[CRIU] [PATCH 3/4] restore: create tansport socket for pidns helpers from the root task
Andrei Vagin
avagin at openvz.org
Fri May 5 22:56:50 PDT 2017
From: Andrei Vagin <avagin at virtuozzo.com>
The root task can live in another netns and it has to be restored
before executing setup-namespaces scripts.
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
criu/cr-restore.c | 3 ++
criu/include/namespaces.h | 3 ++
criu/namespaces.c | 75 +++++++++++++++++++++++++++++++----------------
3 files changed, 55 insertions(+), 26 deletions(-)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 3687dd5..3481362 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1746,6 +1746,9 @@ static int restore_task_with_children(void *_arg)
/* Wait prepare_userns */
if (restore_finish_ns_stage(CR_STATE_ROOT_TASK, CR_STATE_PREPARE_NAMESPACES) < 0)
goto err;
+
+ if (prep_usernsd_transport())
+ goto err;
}
/*
diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 52072a6..ec22887 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -207,6 +207,7 @@ extern int prepare_userns(pid_t real_pid, UsernsEntry *e);
extern int __set_user_ns(struct ns_id *ns);
extern int set_user_ns(u32 id);
extern int stop_usernsd(void);
+extern int prep_usernsd_transport(void);
extern uid_t userns_uid(uid_t uid);
extern gid_t userns_gid(gid_t gid);
@@ -271,4 +272,6 @@ extern int create_pid_ns_helper(struct ns_id *ns);
extern int destroy_pid_ns_helpers(void);
extern int request_set_next_pid(int pid_ns_id, pid_t pid, int sk);
+extern int pid_ns_helper_sock(struct ns_id *ns);
+
#endif /* __CR_NS_H__ */
diff --git a/criu/namespaces.c b/criu/namespaces.c
index f65f060..3d75317 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -1539,14 +1539,24 @@ static void usernsd_handler(int signal, siginfo_t *siginfo, void *data)
}
}
-static int usernsd(int sk)
+static int usernsd_recv_transport(void *arg, int fd, pid_t pid)
+{
+ if (install_service_fd(TRANSPORT_FD_OFF, fd) < 0) {
+ pr_perror("Can't install transport fd\n");
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+int prep_usernsd_transport()
{
struct sockaddr_un addr;
- int transport_fd;
+ int transport_fd, ret;
socklen_t len;
- pr_info("uns: Daemon started\n");
-
transport_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (transport_fd < 0) {
pr_perror("Can't create transport socket");
@@ -1560,13 +1570,17 @@ static int usernsd(int sk)
if (bind(transport_fd, (struct sockaddr *)&addr, len) < 0) {
pr_perror("Can't bind transport sock");
+ close(transport_fd);
return -1;
}
+ ret = userns_call(usernsd_recv_transport, 0, NULL, 0, transport_fd);
+ close(transport_fd);
+ return ret;
+}
- if (install_service_fd(TRANSPORT_FD_OFF, transport_fd) < 0) {
- pr_perror("Can't install transport fd\n");
- return -1;
- }
+static int usernsd(int sk)
+{
+ pr_info("uns: Daemon started\n");
if (criu_signals_setup(usernsd_handler) < 0) {
pr_err("Can't setup handler\n");
@@ -2540,7 +2554,7 @@ int reserve_pid_ns_helpers(void)
return walk_namespaces(&pid_ns_desc, do_reserve_pid_ns_helpers, NULL);
}
-static int pid_ns_helper_sock(struct ns_id *ns)
+int pid_ns_helper_sock(struct ns_id *ns)
{
struct sockaddr_un addr;
socklen_t len;
@@ -2604,9 +2618,9 @@ static int pid_ns_helper(struct ns_id *ns, int sk)
return -1;
}
-static int do_create_pid_ns_helper(void *arg, int unused_fd, pid_t unused_pid)
+static int do_create_pid_ns_helper(void *arg, int sk, pid_t unused_pid)
{
- int pid_ns_fd, mnt_ns_fd, sk, fd, i, lock_fd, transport_fd;
+ int pid_ns_fd, mnt_ns_fd, fd, i, lock_fd, transport_fd;
struct ns_id *ns, *tmp;
struct pid *pid;
pid_t child;
@@ -2614,29 +2628,25 @@ static int do_create_pid_ns_helper(void *arg, int unused_fd, pid_t unused_pid)
pid_ns_fd = open_proc(PROC_SELF, "ns/pid");
if (pid_ns_fd < 0) {
pr_perror("Can't open pid ns");
- return -1;
+ goto err;
}
ns = *(struct ns_id **)arg;
fd = fdstore_get(ns->pid.nsfd_id);
if (fd < 0) {
pr_err("Can't get pid_ns fd\n");
- return -1;
+ goto err;
}
if (setns(fd, CLONE_NEWPID) < 0) {
pr_perror("Can't setns");
- return -1;
+ goto err;
}
close(fd);
- sk = pid_ns_helper_sock(ns);
- if (sk < 0)
- return -1;
-
pid = __pstree_pid_by_virt(ns, ns->ns_pid);
if (!pid) {
pr_err("Can't find helper reserved pid\n");
- return -1;
+ goto err;
}
tmp = ns->parent;
@@ -2647,22 +2657,23 @@ static int do_create_pid_ns_helper(void *arg, int unused_fd, pid_t unused_pid)
if (switch_ns(root_item->pid->real, &mnt_ns_desc, &mnt_ns_fd) < 0) {
pr_err("Can't set mnt_ns\n");
- return -1;
+ goto err;
}
lock_fd = open("/proc/" LAST_PID_PATH, O_RDONLY);
- if (lock_fd < 0)
- return -1;
+ if (lock_fd < 0) {
+ pr_perror("Unable to open /proc/" LAST_PID_PATH);
+ goto err;
+ }
if (restore_ns(mnt_ns_fd, &mnt_ns_desc) < 0) {
pr_err("Can't restore ns\n");
- return -1;
+ goto err;
}
if (flock(lock_fd, LOCK_EX)) {
close(lock_fd);
pr_perror("Can't lock %s", LAST_PID_PATH);
- return -1;
}
transport_fd = get_service_fd(TRANSPORT_FD_OFF);
@@ -2676,7 +2687,7 @@ static int do_create_pid_ns_helper(void *arg, int unused_fd, pid_t unused_pid)
pr_err("Can't set next pid using helper\n");
flock(lock_fd, LOCK_UN);
close(lock_fd);
- return -1;
+ goto err;
}
child = fork();
if (child < 0) {
@@ -2699,6 +2710,9 @@ static int do_create_pid_ns_helper(void *arg, int unused_fd, pid_t unused_pid)
return -1;
}
return 0;
+err:
+ close_safe(&sk);
+ return -1;
}
/*
@@ -2718,16 +2732,25 @@ static int do_create_pid_ns_helper(void *arg, int unused_fd, pid_t unused_pid)
*/
int create_pid_ns_helper(struct ns_id *ns)
{
+ int sk;
+
BUG_ON(getpid() != INIT_PID);
if (__set_next_pid(ns->ns_pid) < 0) {
pr_err("Can't set next fd\n");
return -1;
}
- if (userns_call(do_create_pid_ns_helper, 0, &ns, sizeof(ns), -1) < 0) {
+
+ sk = pid_ns_helper_sock(ns);
+ if (sk < 0)
+ return -1;
+
+ if (userns_call(do_create_pid_ns_helper, 0, &ns, sizeof(ns), sk) < 0) {
pr_err("Can't create pid_ns helper\n");
+ close(sk);
return -1;
}
+ close(sk);
return 0;
}
--
2.9.3
More information about the CRIU
mailing list