mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
exit: fix the setns() && PR_SET_CHILD_SUBREAPER interaction
find_new_reaper() checks same_thread_group(reaper, child_reaper) to prevent the cross-namespace reparenting but this is not enough if the exiting parent was injected by setns() + fork(). Suppose we have a process P in the root namespace and some namespace X. P does setns() to enter the X namespace, and forks the child C. C forks a grandchild G and exits. The grandchild G should be re-parented to X->child_reaper, but in this case the ->real_parent chain does not lead to ->child_reaper, so it will be wrongly reparanted to P's sub-reaper or a global init. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
This commit is contained in:
parent
1328c72700
commit
c6c70f4455
1 changed files with 8 additions and 5 deletions
|
@ -578,15 +578,18 @@ static struct task_struct *find_new_reaper(struct task_struct *father,
|
||||||
return thread;
|
return thread;
|
||||||
|
|
||||||
if (father->signal->has_child_subreaper) {
|
if (father->signal->has_child_subreaper) {
|
||||||
|
unsigned int ns_level = task_pid(father)->level;
|
||||||
/*
|
/*
|
||||||
* Find the first ->is_child_subreaper ancestor in our pid_ns.
|
* Find the first ->is_child_subreaper ancestor in our pid_ns.
|
||||||
* We start from father to ensure we can not look into another
|
* We can't check reaper != child_reaper to ensure we do not
|
||||||
* namespace, this is safe because all its threads are dead.
|
* cross the namespaces, the exiting parent could be injected
|
||||||
|
* by setns() + fork().
|
||||||
|
* We check pid->level, this is slightly more efficient than
|
||||||
|
* task_active_pid_ns(reaper) != task_active_pid_ns(father).
|
||||||
*/
|
*/
|
||||||
for (reaper = father;
|
for (reaper = father->real_parent;
|
||||||
!same_thread_group(reaper, child_reaper);
|
task_pid(reaper)->level == ns_level;
|
||||||
reaper = reaper->real_parent) {
|
reaper = reaper->real_parent) {
|
||||||
/* call_usermodehelper() descendants need this check */
|
|
||||||
if (reaper == &init_task)
|
if (reaper == &init_task)
|
||||||
break;
|
break;
|
||||||
if (!reaper->signal->is_child_subreaper)
|
if (!reaper->signal->is_child_subreaper)
|
||||||
|
|
Loading…
Add table
Reference in a new issue