aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2011-07-21 14:00:43 -0400
committerOleg Nesterov <oleg@redhat.com>2011-07-22 09:10:49 -0400
commiteac1b5e57d7abc836e78fd3fbcf77dbeed01edc9 (patch)
tree50d267e7a4edd645543abfeb33d12eb18d84d00e
parent8a35241803eeb0e9fd3fe27835d6b2775c73b641 (diff)
ptrace: do_wait(traced_leader_killed_by_mt_exec) can block forever
Test-case: void *tfunc(void *arg) { execvp("true", NULL); return NULL; } int main(void) { int pid; if (fork()) { pthread_t t; kill(getpid(), SIGSTOP); pthread_create(&t, NULL, tfunc, NULL); for (;;) pause(); } pid = getppid(); assert(ptrace(PTRACE_ATTACH, pid, 0,0) == 0); while (wait(NULL) > 0) ptrace(PTRACE_CONT, pid, 0,0); return 0; } It is racy, exit_notify() does __wake_up_parent() too. But in the likely case it triggers the problem: de_thread() does release_task() and the old leader goes away without the notification, the tracer sleeps in do_wait() without children/tracees. Change de_thread() to do __wake_up_parent(traced_leader->parent). Since it is already EXIT_DEAD we can do this without ptrace_unlink(), EXIT_DEAD threads do not exist from do_wait's pov. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Tejun Heo <tj@kernel.org>
-rw-r--r--fs/exec.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/exec.c b/fs/exec.c
index b08367abf30e..d219541db06c 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -967,6 +967,14 @@ static int de_thread(struct task_struct *tsk)
967 967
968 BUG_ON(leader->exit_state != EXIT_ZOMBIE); 968 BUG_ON(leader->exit_state != EXIT_ZOMBIE);
969 leader->exit_state = EXIT_DEAD; 969 leader->exit_state = EXIT_DEAD;
970
971 /*
972 * We are going to release_task()->ptrace_unlink() silently,
973 * the tracer can sleep in do_wait(). EXIT_DEAD guarantees
974 * the tracer wont't block again waiting for this thread.
975 */
976 if (unlikely(leader->ptrace))
977 __wake_up_parent(leader, leader->parent);
970 write_unlock_irq(&tasklist_lock); 978 write_unlock_irq(&tasklist_lock);
971 979
972 release_task(leader); 980 release_task(leader);