diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-06-20 15:53:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-20 17:39:36 -0400 |
commit | 50d75f8daead8a1f850c40a3b6c6575ab19b48cf (patch) | |
tree | 1917eec9deadded31869372207772d9a3d3ca11a /kernel/exit.c | |
parent | 6347e90091041e34bea625370794c92f4ce71228 (diff) |
pidns: find_new_reaper() can no longer switch to init_pid_ns.child_reaper
find_new_reaper() changes pid_ns->child_reaper, see add0d4df ("pid_ns:
zap_pid_ns_processes: fix the ->child_reaper changing").
The original reason has gone away after the previous patch, ->children
list must be empty after zap_pid_ns_processes().
However now we can not switch to init_pid_ns.child_reaper.
__unhash_process() relies on the "->child_reaper == parent" check, but
this check does not work if the last exiting task is also the child
reaper.
As Eric sugested, we can change __unhash_process() to use the parent's
pid_ns and remove this code.
Also, with this change we can move detach_pid(PIDTYPE_PID) back, where it
was before the previous fix.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Louis Rilling <louis.rilling@kerlabs.com>
Cc: Mike Galbraith <efault@gmx.de>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Tested-by: Andrew Wagin <avagin@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 10 |
1 files changed, 2 insertions, 8 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index a85efd2348bd..2f59cc334516 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -64,6 +64,7 @@ static void exit_mm(struct task_struct * tsk); | |||
64 | static void __unhash_process(struct task_struct *p, bool group_dead) | 64 | static void __unhash_process(struct task_struct *p, bool group_dead) |
65 | { | 65 | { |
66 | nr_threads--; | 66 | nr_threads--; |
67 | detach_pid(p, PIDTYPE_PID); | ||
67 | if (group_dead) { | 68 | if (group_dead) { |
68 | detach_pid(p, PIDTYPE_PGID); | 69 | detach_pid(p, PIDTYPE_PGID); |
69 | detach_pid(p, PIDTYPE_SID); | 70 | detach_pid(p, PIDTYPE_SID); |
@@ -78,13 +79,12 @@ static void __unhash_process(struct task_struct *p, bool group_dead) | |||
78 | if (IS_ENABLED(CONFIG_PID_NS)) { | 79 | if (IS_ENABLED(CONFIG_PID_NS)) { |
79 | struct task_struct *parent = p->real_parent; | 80 | struct task_struct *parent = p->real_parent; |
80 | 81 | ||
81 | if ((task_active_pid_ns(p)->child_reaper == parent) && | 82 | if ((task_active_pid_ns(parent)->child_reaper == parent) && |
82 | list_empty(&parent->children) && | 83 | list_empty(&parent->children) && |
83 | (parent->flags & PF_EXITING)) | 84 | (parent->flags & PF_EXITING)) |
84 | wake_up_process(parent); | 85 | wake_up_process(parent); |
85 | } | 86 | } |
86 | } | 87 | } |
87 | detach_pid(p, PIDTYPE_PID); | ||
88 | list_del_rcu(&p->thread_group); | 88 | list_del_rcu(&p->thread_group); |
89 | } | 89 | } |
90 | 90 | ||
@@ -732,12 +732,6 @@ static struct task_struct *find_new_reaper(struct task_struct *father) | |||
732 | 732 | ||
733 | zap_pid_ns_processes(pid_ns); | 733 | zap_pid_ns_processes(pid_ns); |
734 | write_lock_irq(&tasklist_lock); | 734 | write_lock_irq(&tasklist_lock); |
735 | /* | ||
736 | * We can not clear ->child_reaper or leave it alone. | ||
737 | * There may by stealth EXIT_DEAD tasks on ->children, | ||
738 | * forget_original_parent() must move them somewhere. | ||
739 | */ | ||
740 | pid_ns->child_reaper = init_pid_ns.child_reaper; | ||
741 | } else if (father->signal->has_child_subreaper) { | 735 | } else if (father->signal->has_child_subreaper) { |
742 | struct task_struct *reaper; | 736 | struct task_struct *reaper; |
743 | 737 | ||