[Devel] [PATCH RHEL7 COMMIT] ms/exit: fix the setns() && PR_SET_CHILD_SUBREAPER interaction
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Jun 20 21:12:50 MSK 2022
The commit is pushed to "branch-rh7-3.10.0-1160.62.1.vz7.187.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.62.1.vz7.187.5
------>
commit a9cf6573bf2285eca795c8aac3ad60304c0d87b9
Author: Oleg Nesterov <oleg at redhat.com>
Date: Wed Jun 15 17:54:20 2022 +0300
ms/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 at redhat.com>
Signed-off-by: Eric W. Biederman <ebiederm at xmission.com>
(cherry picked from ms commit c6c70f4455d1eda91065e93cc4f7eddf4499b105)
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
=================
Patchset description:
vz7: fix child-reaper reparenting
Forth patch is needed as kernel can reparent process to a dead thread
which is wrong.
Third patch is needed as kernel could reparent process from father from
one pidns to process from different pidns, which creates configurations
not supported by CRIU. Found it when reproducing problem from CRIU
mainstream issue in VZ7 ct.
https://github.com/checkpoint-restore/criu/issues/1914
First and Second are just to make it apply cleaner.
Oleg Nesterov (4):
exit: reparent: fix the cross-namespace PR_SET_CHILD_SUBREAPER
reparenting
exit: reparent: document the ->has_child_subreaper checks
exit: fix the setns() && PR_SET_CHILD_SUBREAPER interaction
exit: reparent: fix the dead-parent PR_SET_CHILD_SUBREAPER reparenting
---
kernel/exit.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/kernel/exit.c b/kernel/exit.c
index b87564b77011..4ba3a108d449 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -642,16 +642,19 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
}
if (father->signal->has_child_subreaper) {
+ unsigned int ns_level = task_pid(father)->level;
struct task_struct *reaper;
/*
* Find the first ->is_child_subreaper ancestor in our pid_ns.
- * We start from father to ensure we can not look into another
- * namespace, this is safe because all its threads are dead.
+ * We can't check reaper != child_reaper to ensure we do not
+ * 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;
- !same_thread_group(reaper, pid_ns->child_reaper);
+ for (reaper = father->real_parent;
+ task_pid(reaper)->level == ns_level;
reaper = reaper->real_parent) {
- /* call_usermodehelper() descendants need this check */
if (reaper == &init_task)
break;
if (!reaper->signal->is_child_subreaper)
More information about the Devel
mailing list