[CRIU] [PATCH 1/2] restore: create the root netns before executin setup-namespaces scripts

Andrei Vagin avagin at openvz.org
Thu May 4 13:27:46 PDT 2017


From: Andrei Vagin <avagin at virtuozzo.com>

runc restore executes criu with --emptyns network and set
a setup-namespaces script to restore a network namespace.

https://github.com/xemul/criu/issues/314

Fixes: 2189b9c71d3d ("net: allow to dump and restore more than one network namespace")
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/cr-restore.c | 21 +++++++++++++++++----
 criu/net.c        | 12 +++++++++++-
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index afdc9eb..d088ef9 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1515,10 +1515,23 @@ static int restore_task_with_children(void *_arg)
 			goto err;
 	}
 
-	/* Wait prepare_userns */
-	if (current->parent == NULL &&
-			restore_finish_ns_stage(CR_STATE_ROOT_TASK, CR_STATE_PREPARE_NAMESPACES) < 0)
-		goto err;
+	if (current->parent == NULL) {
+		/*
+		 * The root task has to be in its namespaces before executing
+		 * ACT_SETUP_NS scripts, so the root netns has to be created here
+		 */
+		if (root_ns_mask & CLONE_NEWNET) {
+			ret = unshare(CLONE_NEWNET);
+			if (ret) {
+				pr_perror("Can't unshare net-namespace");
+				goto err;
+			}
+		}
+
+		/* Wait prepare_userns */
+		if (restore_finish_ns_stage(CR_STATE_ROOT_TASK, CR_STATE_PREPARE_NAMESPACES) < 0)
+			goto err;
+	}
 
 	/*
 	 * Call this _before_ forking to optimize cgroups
diff --git a/criu/net.c b/criu/net.c
index b423000..aabc666 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1938,6 +1938,9 @@ int dump_net_ns(struct ns_id *ns)
 			ret = dump_iptables(fds);
 		if (!ret)
 			ret = dump_netns_conf(ns, fds);
+	} else if (ns->type != NS_ROOT) {
+		pr_err("Unable to dump more than one netns if the --emptyns is set\n");
+		ret = -1;
 	}
 	if (!ret)
 		ret = dump_nf_ct(fds, CR_FD_NETNF_CT);
@@ -2094,11 +2097,16 @@ static int create_net_ns(void *arg)
 int prepare_net_namespaces()
 {
 	struct ns_id *nsid;
-	int ret = -1;
+	int ret = -1, root_ns;
 
 	if (!(root_ns_mask & CLONE_NEWNET))
 		return 0;
 
+	root_ns = open_proc(PROC_SELF, "ns/net");
+	if (root_ns < 0)
+		return -1;
+
+	/* Pin one with a file descriptor */
 	for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
 		if (nsid->nd != &net_ns_desc)
 			continue;
@@ -2106,6 +2114,8 @@ int prepare_net_namespaces()
 		if (root_user_ns && nsid->user_ns != root_user_ns) {
 			if (call_in_child_process(create_net_ns, nsid) < 0)
 				goto err;
+		} else if (nsid->type == NS_ROOT) {
+			nsid->net.ns_fd = root_ns;
 		} else {
 			if (do_create_net_ns(nsid))
 				goto err;
-- 
2.9.3



More information about the CRIU mailing list