From: Roland McGrath In the oddball situation where one thread is using ptrace on another thread sharing the same mm, and then someone sharing that mm causes a coredump, there is a deadlock possible if the traced thread is in TASK_TRACED state. It leaves all the threads sharing that mm wedged and permanently unkillable. This patch checks for that situation and brings a thread out of TASK_TRACED if its tracer is part of the same coredump (i.e. shares the same mm). It's not pretty, but it does the job. Signed-off-by: Roland McGrath Signed-off-by: Andrew Morton --- 25-akpm/fs/exec.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+) diff -puN fs/exec.c~fix-coredump_wait-deadlock-with-ptracer-tracee-on-shared-mm fs/exec.c --- 25/fs/exec.c~fix-coredump_wait-deadlock-with-ptracer-tracee-on-shared-mm Tue Jan 11 13:56:27 2005 +++ 25-akpm/fs/exec.c Tue Jan 11 13:56:27 2005 @@ -1338,6 +1338,7 @@ static void zap_threads (struct mm_struc struct task_struct *g, *p; struct task_struct *tsk = current; struct completion *vfork_done = tsk->vfork_done; + int traced = 0; /* * Make sure nobody is waiting for us to release the VM, @@ -1353,10 +1354,30 @@ static void zap_threads (struct mm_struc if (mm == p->mm && p != tsk) { force_sig_specific(SIGKILL, p); mm->core_waiters++; + if (unlikely(p->ptrace) && + unlikely(p->parent->mm == mm)) + traced = 1; } while_each_thread(g,p); read_unlock(&tasklist_lock); + + if (unlikely(traced)) { + /* + * We are zapping a thread and the thread it ptraces. + * If the tracee went into a ptrace stop for exit tracing, + * we could deadlock since the tracer is waiting for this + * coredump to finish. Detach them so they can both die. + */ + write_lock_irq(&tasklist_lock); + do_each_thread(g,p) { + if (mm == p->mm && p != tsk && + p->ptrace && p->parent->mm == mm) { + __ptrace_unlink(p); + } + } while_each_thread(g,p); + write_unlock_irq(&tasklist_lock); + } } static void coredump_wait(struct mm_struct *mm) _