diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 580da79e38ee..9960accbf2ab 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -607,15 +607,18 @@ static struct task_struct *find_new_reaper(struct task_struct *father, | |||
607 | return thread; | 607 | return thread; |
608 | 608 | ||
609 | if (father->signal->has_child_subreaper) { | 609 | if (father->signal->has_child_subreaper) { |
610 | unsigned int ns_level = task_pid(father)->level; | ||
610 | /* | 611 | /* |
611 | * Find the first ->is_child_subreaper ancestor in our pid_ns. | 612 | * Find the first ->is_child_subreaper ancestor in our pid_ns. |
612 | * We start from father to ensure we can not look into another | 613 | * We can't check reaper != child_reaper to ensure we do not |
613 | * namespace, this is safe because all its threads are dead. | 614 | * cross the namespaces, the exiting parent could be injected |
615 | * by setns() + fork(). | ||
616 | * We check pid->level, this is slightly more efficient than | ||
617 | * task_active_pid_ns(reaper) != task_active_pid_ns(father). | ||
614 | */ | 618 | */ |
615 | for (reaper = father; | 619 | for (reaper = father->real_parent; |
616 | !same_thread_group(reaper, child_reaper); | 620 | task_pid(reaper)->level == ns_level; |
617 | reaper = reaper->real_parent) { | 621 | reaper = reaper->real_parent) { |
618 | /* call_usermodehelper() descendants need this check */ | ||
619 | if (reaper == &init_task) | 622 | if (reaper == &init_task) |
620 | break; | 623 | break; |
621 | if (!reaper->signal->is_child_subreaper) | 624 | if (!reaper->signal->is_child_subreaper) |