Thread (33 messages) 33 messages, 5 authors, 2017-06-07

[PATCH 16/26] exit: Fix reporting a ptraced !reparented leader has exited

STALE3405d

From: Eric W. Biederman <hidden>
Date: 2017-06-06 19:14:42
Also in: lkml
Subsystem: the rest · Maintainer: Linus Torvalds

When a task exits and uses do_notify_parent to send tsk->exit_signal
or SIGCHLD this has one of two possible meanings.
- The ptraced task has exited
- The thread group has exited

Linux resolves this ambiguity by preferring the thread group exit
interpretation if it is possible.  As the exit of a thread group
containing a task is a superset of the exit of a task.

The code attempts to implement this in it's selection of signal
before calling do_notify_parent for a ptraced task.  Unfortunately
it fails to properly handle the case when the thread_group is still
running (but it's leader has exited).

Fix this for a ptraced child leader by skipping the notification
instead of changing the exit signal.  If we skip sending the signal in
exit_noitfy, when the last of the other threads are reaped
release_task will send the signal for us.

Signed-off-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
---
 kernel/exit.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/kernel/exit.c b/kernel/exit.c
index 85b34eff8807..72591eb5e361 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -639,7 +639,7 @@ static void forget_original_parent(struct task_struct *father,
  */
 static void exit_notify(struct task_struct *tsk, int group_dead)
 {
-	bool autoreap;
+	bool autoreap = true;
 	struct task_struct *p, *n;
 	LIST_HEAD(dead);
 
@@ -649,17 +649,12 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
 	if (group_dead)
 		kill_orphaned_pgrp(tsk->group_leader, NULL);
 
-	if (unlikely(tsk->ptrace)) {
-		int sig = thread_group_leader(tsk) &&
-				thread_group_empty(tsk) &&
-				!ptrace_reparented(tsk) ?
-			tsk->exit_signal : SIGCHLD;
-		autoreap = do_notify_parent(tsk, sig);
-	} else if (thread_group_leader(tsk)) {
+	if (thread_group_leader(tsk) && !ptrace_reparented(tsk)) {
 		autoreap = thread_group_empty(tsk) &&
 			do_notify_parent(tsk, tsk->exit_signal);
-	} else {
-		autoreap = true;
+	}
+	else if (unlikely(tsk->ptrace)) {
+		autoreap = do_notify_parent(tsk, SIGCHLD);
 	}
 
 	tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
-- 
2.10.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help