Commit f358166a9405e4f1d8e50d8f415c26d95505b6de

Authored by Linus Torvalds
1 parent 0e44dc3837

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: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 19 additions and 1 deletions Side-by-side Diff

... ... @@ -155,8 +155,26 @@
155 155 if (task->tgid == current->tgid)
156 156 goto out;
157 157  
158   - write_lock_irq(&tasklist_lock);
  158 +repeat:
  159 + /*
  160 + * Nasty, nasty.
  161 + *
  162 + * We want to hold both the task-lock and the
  163 + * tasklist_lock for writing at the same time.
  164 + * But that's against the rules (tasklist_lock
  165 + * is taken for reading by interrupts on other
  166 + * cpu's that may have task_lock).
  167 + */
159 168 task_lock(task);
  169 + local_irq_disable();
  170 + if (!write_trylock(&tasklist_lock)) {
  171 + local_irq_enable();
  172 + task_unlock(task);
  173 + do {
  174 + cpu_relax();
  175 + } while (!write_can_lock(&tasklist_lock));
  176 + goto repeat;
  177 + }
160 178  
161 179 /* the same process cannot be attached many times */
162 180 if (task->ptrace & PT_PTRACED)