Subject: [merged] wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race.patch
removed from -mm tree
To:
[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected]
From: [email protected]
Date: Tue, 08 Apr 2014 14:19:33 -0700
The patch titled
Subject: wait: fix reparent_leader() vs EXIT_DEAD->EXIT_ZOMBIE race
has been removed from the -mm tree. Its filename was
wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race.patch
This patch was dropped because it was merged into mainline or a subsystem tree
------------------------------------------------------
From: Oleg Nesterov <[email protected]>
Subject: wait: fix reparent_leader() vs EXIT_DEAD->EXIT_ZOMBIE race
wait_task_zombie() first does EXIT_ZOMBIE->EXIT_DEAD transition and drops
tasklist_lock. If this task is not the natural child and it is traced, we
change its state back to EXIT_ZOMBIE for ->real_parent.
The last transition is racy, this is even documented in 50b8d257486a
"ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE
race". wait_consider_task() tries to detect this transition and clear
->notask_error but we can't rely on ptrace_reparented(), debugger can exit
and do ptrace_unlink() before its sub-thread sets EXIT_ZOMBIE.
And there is another problem which were missed before: this transition can
also race with reparent_leader() which doesn't reset >exit_signal if
EXIT_DEAD, assuming that this task must be reaped by someone else. So the
tracee can be re-parented with ->exit_signal != SIGCHLD, and if /sbin/init
doesn't use __WALL it becomes unreapable.
Change reparent_leader() to update ->exit_signal even if EXIT_DEAD. Note:
this is the simple temporary hack for -stable, it doesn't try to solve all
problems, it will be reverted by the next changes.
Signed-off-by: Oleg Nesterov <[email protected]>
Reported-by: Jan Kratochvil <[email protected]>
Reported-by: Michal Schmidt <[email protected]>
Tested-by: Michal Schmidt <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Lennart Poettering <[email protected]>
Cc: Roland McGrath <[email protected]>
Cc: Tejun Heo <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
---
kernel/exit.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff -puN kernel/exit.c~wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race
kernel/exit.c
--- a/kernel/exit.c~wait-fix-reparent_leader-vs-exit_dead-exit_zombie-race
+++ a/kernel/exit.c
@@ -560,9 +560,6 @@ static void reparent_leader(struct task_
struct list_head *dead)
{
list_move_tail(&p->sibling, &p->real_parent->children);
-
- if (p->exit_state == EXIT_DEAD)
- return;
/*
* If this is a threaded reparent there is no need to
* notify anyone anything has happened.
@@ -570,9 +567,19 @@ static void reparent_leader(struct task_
if (same_thread_group(p->real_parent, father))
return;
- /* We don't want people slaying init. */
+ /*
+ * We don't want people slaying init.
+ *
+ * Note: we do this even if it is EXIT_DEAD, wait_task_zombie()
+ * can change ->exit_state to EXIT_ZOMBIE. If this is the final
+ * state, do_notify_parent() was already called and ->exit_signal
+ * doesn't matter.
+ */
p->exit_signal = SIGCHLD;
+ if (p->exit_state == EXIT_DEAD)
+ return;
+
/* If it has exited notify the new parent about this child's death. */
if (!p->ptrace &&
p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) {
_
Patches currently in -mm which might be from [email protected] are
origin.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html