Commit a7f0765edfd53aed09cb7b0e15863688b39447de
Committed by
Linus Torvalds
1 parent
1dd3a27326
Exists in
master
and in
7 other branches
ptrace: __ptrace_detach: do __wake_up_parent() if we reap the tracee
The bug is old, it wasn't cause by recent changes. Test case: static void *tfunc(void *arg) { int pid = (long)arg; assert(ptrace(PTRACE_ATTACH, pid, NULL, NULL) == 0); kill(pid, SIGKILL); sleep(1); return NULL; } int main(void) { pthread_t th; long pid = fork(); if (!pid) pause(); signal(SIGCHLD, SIG_IGN); assert(pthread_create(&th, NULL, tfunc, (void*)pid) == 0); int r = waitpid(-1, NULL, __WNOTHREAD); printf("waitpid: %d %m\n", r); return 0; } Before the patch this program hangs, after this patch waitpid() correctly fails with errno == -ECHILD. The problem is, __ptrace_detach() reaps the EXIT_ZOMBIE tracee if its ->real_parent is our sub-thread and we ignore SIGCHLD. But in this case we should wake up other threads which can sleep in do_wait(). Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Roland McGrath <roland@redhat.com> Cc: Vitaly Mayatskikh <vmayatsk@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 4 changed files with 13 additions and 13 deletions Side-by-side Diff
include/linux/sched.h
... | ... | @@ -2059,6 +2059,7 @@ |
2059 | 2059 | extern int kill_pid(struct pid *pid, int sig, int priv); |
2060 | 2060 | extern int kill_proc_info(int, struct siginfo *, pid_t); |
2061 | 2061 | extern int do_notify_parent(struct task_struct *, int); |
2062 | +extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); | |
2062 | 2063 | extern void force_sig(int, struct task_struct *); |
2063 | 2064 | extern void force_sig_specific(int, struct task_struct *); |
2064 | 2065 | extern int send_sig(int, struct task_struct *, int); |
kernel/exit.c
... | ... | @@ -1575,6 +1575,11 @@ |
1575 | 1575 | return 0; |
1576 | 1576 | } |
1577 | 1577 | |
1578 | +void __wake_up_parent(struct task_struct *p, struct task_struct *parent) | |
1579 | +{ | |
1580 | + wake_up_interruptible_sync(&parent->signal->wait_chldexit); | |
1581 | +} | |
1582 | + | |
1578 | 1583 | static long do_wait(struct wait_opts *wo) |
1579 | 1584 | { |
1580 | 1585 | DECLARE_WAITQUEUE(wait, current); |
kernel/ptrace.c
... | ... | @@ -266,9 +266,10 @@ |
266 | 266 | * or self-reaping. Do notification now if it would have happened earlier. |
267 | 267 | * If it should reap itself, return true. |
268 | 268 | * |
269 | - * If it's our own child, there is no notification to do. | |
270 | - * But if our normal children self-reap, then this child | |
271 | - * was prevented by ptrace and we must reap it now. | |
269 | + * If it's our own child, there is no notification to do. But if our normal | |
270 | + * children self-reap, then this child was prevented by ptrace and we must | |
271 | + * reap it now, in that case we must also wake up sub-threads sleeping in | |
272 | + * do_wait(). | |
272 | 273 | */ |
273 | 274 | static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) |
274 | 275 | { |
275 | 276 | |
... | ... | @@ -278,8 +279,10 @@ |
278 | 279 | if (!task_detached(p) && thread_group_empty(p)) { |
279 | 280 | if (!same_thread_group(p->real_parent, tracer)) |
280 | 281 | do_notify_parent(p, p->exit_signal); |
281 | - else if (ignoring_children(tracer->sighand)) | |
282 | + else if (ignoring_children(tracer->sighand)) { | |
283 | + __wake_up_parent(p, tracer); | |
282 | 284 | p->exit_signal = -1; |
285 | + } | |
283 | 286 | } |
284 | 287 | if (task_detached(p)) { |
285 | 288 | /* Mark it as in the process of being reaped. */ |
kernel/signal.c
... | ... | @@ -1383,15 +1383,6 @@ |
1383 | 1383 | } |
1384 | 1384 | |
1385 | 1385 | /* |
1386 | - * Wake up any threads in the parent blocked in wait* syscalls. | |
1387 | - */ | |
1388 | -static inline void __wake_up_parent(struct task_struct *p, | |
1389 | - struct task_struct *parent) | |
1390 | -{ | |
1391 | - wake_up_interruptible_sync(&parent->signal->wait_chldexit); | |
1392 | -} | |
1393 | - | |
1394 | -/* | |
1395 | 1386 | * Let a parent know about the death of a child. |
1396 | 1387 | * For a stopped/continued status change, use do_notify_parent_cldstop instead. |
1397 | 1388 | * |