[v2,06/57] net: Do not change net_ns of root_item in create_net_ns()

Submitted by Kirill Tkhai on March 28, 2017, 3:34 p.m.

Details

Message ID 149071528899.12770.3494220167796166118.stgit@localhost.localdomain
State New
Series "Nested pid namespaces support"
Headers show

Commit Message

Kirill Tkhai March 28, 2017, 3:34 p.m.
Currently, we do unshare(CLONE_NEWNET), but do not restore
old net ns. So, net_ns of criu task and root_item becomes
different. Unpredictible net_ns of root_item is not good,
so this patch fixes the problem.

Later, we will use this property to create transport sockets
for tasks items and usernsd in the only net.

Also, disable tun test before "Problem of restoring tun in
nested net namespace" from criu ml is not fixed.

v2: Rebase on new criu

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/net.c                |  119 ++++++++++++++++++++++-----------------------
 test/zdtm/static/tun.desc |    2 -
 2 files changed, 60 insertions(+), 61 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/net.c b/criu/net.c
index e06d32bc..e9e58e32 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1385,18 +1385,25 @@  struct net_link *lookup_net_link(struct ns_id *ns, uint32_t ifindex)
 	return NULL;
 }
 
-static int __restore_links(struct ns_id *nsid, int *nrlinks, int *nrcreated)
+static int __links_nrlinks;
+static int __links_nrcreated;
+
+static int __restore_links(void *arg)
 {
+	struct ns_id *nsid = arg;
 	struct net_link *link, *t;
 	int ret;
 
+	if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL))
+		return -1;
+
 	list_for_each_entry_safe(link, t, &nsid->net.links, node) {
 		struct net_link *mlink = NULL;
 
 		if (link->created)
 			continue;
 
-		(*nrlinks)++;
+		__links_nrlinks++;
 
 		pr_debug("Try to restore a link %d:%d:%s",
 				nsid->id, link->nde->ifindex, link->nde->name);
@@ -1419,7 +1426,7 @@  static int __restore_links(struct ns_id *nsid, int *nrlinks, int *nrcreated)
 			return -1;
 
 		if (ret == 0) {
-			(*nrcreated)++;
+			__links_nrcreated++;
 			link->created = true;
 
 			if (mlink && restore_master_link(nsid->net.nlsk, nsid, link))
@@ -1432,26 +1439,22 @@  static int __restore_links(struct ns_id *nsid, int *nrlinks, int *nrcreated)
 
 static int restore_links()
 {
-	int nrcreated, nrlinks;
 	struct ns_id *nsid;
 
 	while (true) {
-		nrcreated = 0;
-		nrlinks = 0;
+		__links_nrcreated = 0;
+		__links_nrlinks = 0;
 		for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
 			if (nsid->nd != &net_ns_desc)
 				continue;
 
-			if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL))
-				return -1;
-
-			if (__restore_links(nsid, &nrlinks, &nrcreated))
+			if (call_in_child_process(__restore_links, nsid))
 				return -1;
 		}
 
-		if (nrcreated == nrlinks)
+		if (__links_nrcreated == __links_nrlinks)
 			break;
-		if (nrcreated == 0) {
+		if (__links_nrcreated == 0) {
 			pr_err("Unable to restore network links");
 			return -1;
 		}
@@ -1990,26 +1993,39 @@  static int restore_netns_ids(struct ns_id *ns)
 	return exit_code;
 }
 
-static int prepare_net_ns_first_stage(struct ns_id *ns)
+static int prepare_net_ns_first_stage(void *arg)
 {
-	int ret = 0;
+	struct ns_id *ns = arg;
 
-	if (opts.empty_ns & CLONE_NEWNET)
-		return 0;
+	if (switch_ns_by_fd(ns->net.ns_fd, &net_ns_desc, NULL))
+		return -1;
 
-	ret = restore_netns_conf(ns);
-	if (!ret)
-		ret = restore_netns_ids(ns);
-	if (!ret)
-		ret = read_links(ns);
+	if (!(opts.empty_ns & CLONE_NEWNET)) {
+		if (restore_netns_conf(ns))
+			return -1;
+		if (restore_netns_ids(ns))
+			return -1;
+		if (read_links(ns))
+			return -1;
+	}
 
-	return ret;
+	ns->net.nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+	if (ns->net.nlsk < 0) {
+		pr_perror("Can't create nlk socket");
+		return -1;
+	}
+
+	return 0;
 }
 
-static int prepare_net_ns_second_stage(struct ns_id *ns)
+static int prepare_net_ns_second_stage(void *arg)
 {
+	struct ns_id *ns = arg;
 	int ret = 0, nsid = ns->id;
 
+	if (switch_ns_by_fd(ns->net.ns_fd, &net_ns_desc, NULL))
+		return -1;
+
 	if (!(opts.empty_ns & CLONE_NEWNET)) {
 		if (ns->net.netns)
 			netns_entry__free_unpacked(ns->net.netns, NULL);
@@ -2038,6 +2054,7 @@  static int prepare_net_ns_second_stage(struct ns_id *ns)
 		close(fd);
 	}
 
+	close_safe(&ns->net.nlsk);
 	ns->ns_populated = true;
 
 	return ret;
@@ -2073,20 +2090,22 @@  static int create_net_ns(void *arg)
 	int ufd, ret;
 
 	uns = ns->user_ns;
-	ufd = fdstore_get(uns->user.nsfd_id);
-	if (ufd < 0) {
-		pr_err("Can't get user ns\n");
-		exit(1);
-	}
-	if (setns(ufd, CLONE_NEWUSER) < 0) {
-		pr_perror("Can't set user ns");
-		exit(2);
-	}
-	if (prepare_userns_creds() < 0) {
-		pr_err("Can't prepare creds\n");
-		exit(3);
+	if (uns && uns != root_user_ns) {
+		ufd = fdstore_get(uns->user.nsfd_id);
+		if (ufd < 0) {
+			pr_err("Can't get user ns\n");
+			exit(1);
+		}
+		if (setns(ufd, CLONE_NEWUSER) < 0) {
+			pr_perror("Can't set user ns");
+			exit(2);
+		}
+		close(ufd);
+		if (prepare_userns_creds() < 0) {
+			pr_err("Can't prepare creds\n");
+			exit(3);
+		}
 	}
-	close(ufd);
 	ret = do_create_net_ns(ns) ? 3 : 0;
 	exit(ret);
 }
@@ -2103,31 +2122,16 @@  int prepare_net_namespaces()
 		if (nsid->nd != &net_ns_desc)
 			continue;
 
-		if (root_user_ns && nsid->user_ns != root_user_ns) {
-			if (call_in_child_process(create_net_ns, nsid) < 0)
-				goto err;
-		} else {
-			if (do_create_net_ns(nsid))
-				goto err;
-		}
+		if (call_in_child_process(create_net_ns, nsid) < 0)
+			goto err;
 	}
 
 	for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
 		if (nsid->nd != &net_ns_desc)
 			continue;
 
-		if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL))
-			goto err;
-
-		if (prepare_net_ns_first_stage(nsid))
-			goto err;
-
-		nsid->net.nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-		if (nsid->net.nlsk < 0) {
-			pr_perror("Can't create nlk socket");
+		if (call_in_child_process(prepare_net_ns_first_stage, nsid))
 			goto err;
-		}
-
 	}
 
 	if (restore_links())
@@ -2137,13 +2141,8 @@  int prepare_net_namespaces()
 		if (nsid->nd != &net_ns_desc)
 			continue;
 
-		if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL))
+		if (call_in_child_process(prepare_net_ns_second_stage, nsid))
 			goto err;
-
-		if (prepare_net_ns_second_stage(nsid))
-			goto err;
-
-		close_safe(&nsid->net.nlsk);
 	}
 
 	close_service_fd(NS_FD_OFF);
diff --git a/test/zdtm/static/tun.desc b/test/zdtm/static/tun.desc
index 8c7cfe86..eac32c2d 100644
--- a/test/zdtm/static/tun.desc
+++ b/test/zdtm/static/tun.desc
@@ -1 +1 @@ 
-{'flavor': 'ns uns', 'flags': 'suid', 'feature': 'tun'}
+{'flavor': 'ns uns', 'flags': 'suid noauto', 'feature': 'tun'}