diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 5b1254c3e..3da8f39f7 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1564,10 +1564,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 12f544f35..23f3e45c2 100644 --- a/criu/net.c +++ b/criu/net.c @@ -2172,6 +2172,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); @@ -2304,13 +2307,23 @@ static int do_create_net_ns(struct ns_id *ns) static int __prepare_net_namespaces(void *unused) { struct ns_id *nsid; + int root_ns; + 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; - if (do_create_net_ns(nsid)) - goto err; + if (nsid->type == NS_ROOT) { + nsid->net.ns_fd = root_ns; + } else { + if (do_create_net_ns(nsid)) + goto err; + } } for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {