Commit f358166a authored by Linus Torvalds's avatar Linus Torvalds

ptrace_attach: fix possible deadlock schenario with irqs

Eric Biederman points out that we can't take the task_lock while holding
tasklist_lock for writing, because another CPU that holds the task lock
might take an interrupt that then tries to take tasklist_lock for writing.

Which would be a nasty deadlock, with one CPU spinning forever in an
interrupt handler (although admittedly you need to really work at
triggering it ;)

Since the ptrace_attach() code is special and very unusual, just make it
be extra careful, and use trylock+repeat to avoid the possible deadlock.

Cc: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0e44dc38
...@@ -155,8 +155,26 @@ int ptrace_attach(struct task_struct *task) ...@@ -155,8 +155,26 @@ int ptrace_attach(struct task_struct *task)
if (task->tgid == current->tgid) if (task->tgid == current->tgid)
goto out; goto out;
write_lock_irq(&tasklist_lock); repeat:
/*
* Nasty, nasty.
*
* We want to hold both the task-lock and the
* tasklist_lock for writing at the same time.
* But that's against the rules (tasklist_lock
* is taken for reading by interrupts on other
* cpu's that may have task_lock).
*/
task_lock(task); task_lock(task);
local_irq_disable();
if (!write_trylock(&tasklist_lock)) {
local_irq_enable();
task_unlock(task);
do {
cpu_relax();
} while (!write_can_lock(&tasklist_lock));
goto repeat;
}
/* the same process cannot be attached many times */ /* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED) if (task->ptrace & PT_PTRACED)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment