[v2,29/30] net_ns: Set net_ns for child, if it has no permissions to do that

Submitted by Kirill Tkhai on June 7, 2017, 11:32 a.m.

Details

Message ID 149683514260.4663.2077137897031381272.stgit@localhost.localdomain
State Accepted
Series "Support sockets leaked to child user_ns task"
Headers show

Commit Message

Kirill Tkhai June 7, 2017, 11:32 a.m.
Child may be created via clone with CLONE_NEWUSER,
and it may do not have permissions to enter its
net namespace, which is inherited from parent.
So, parent must set it for child like it happens
in real life.

Currently one-level inheritance is supported.

v2: New

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/cr-restore.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index d55ed8fd2..05531cd3d 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -472,7 +472,7 @@  static int restore_task_pfc_before_user_ns(void)
 
 static int setup_child_task_namespaces(struct pstree_item *item, struct ns_id **ret_pid_ns)
 {
-	struct ns_id *pid_ns;
+	struct ns_id *pid_ns, *net_ns;
 
 	pid_ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc);
 	BUG_ON(!pid_ns);
@@ -483,6 +483,16 @@  static int setup_child_task_namespaces(struct pstree_item *item, struct ns_id **
 			item->user_ns = pid_ns->user_ns;
 		else
 			item->user_ns = current->user_ns;
+
+		if (item->ids->net_ns_id != current->net_ns->id) {
+			/* Check, that child can set its net_ns */
+			net_ns = lookup_ns_by_id(item->ids->net_ns_id, &net_ns_desc);
+			if (!is_subns(net_ns->user_ns, item->user_ns) &&
+			    set_netns(net_ns) < 0) {
+				pr_err("Can't set net_ns\n");
+				return -1;
+			}
+		}
 		item->net_ns = current->net_ns;
 	} else {
 		item->user_ns = top_user_ns;