[CRIU] [PATCH 6/8] files: Create transport socket via usernsd, when it's need
Kirill Tkhai
ktkhai at virtuozzo.com
Wed Jun 28 14:50:12 MSK 2017
If net_ns is inherited from parent, and a task has no
permissions to change it or to enter top_net_ns,
we should create transport socket via usernsd.
See next patch for the details, how net_ns may be inherited.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/files.c | 11 ++++++++++-
criu/include/namespaces.h | 1 +
criu/namespaces.c | 27 +++++++++++++++++++++++++++
3 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/criu/files.c b/criu/files.c
index 1b0e02626..a095f7bb2 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -1728,7 +1728,14 @@ int open_transport_socket(void)
struct sockaddr_un saddr;
int sock, slen, ret = -1;
- sock = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (current->user_ns != top_user_ns) {
+ sock = userns_call(uns_create_dgram_sock, UNS_FDOUT,
+ &top_net_ns, sizeof(top_net_ns), -1);
+ } else {
+ if (set_netns(top_net_ns))
+ goto out;
+ sock = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ }
if (sock < 0) {
pr_perror("Can't create socket");
goto out;
@@ -1748,6 +1755,8 @@ int open_transport_socket(void)
close(sock);
ret = 0;
out:
+ if (ret)
+ pr_err("Can't create transport socket\n");
return ret;
}
diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index b9e10e4e5..f5d777aaf 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -216,6 +216,7 @@ extern int set_userns(struct ns_id *ns);
extern int set_userns_by_id(u32 id);
extern int stop_usernsd(void);
extern int prep_usernsd_transport(void);
+extern int uns_create_dgram_sock(void *arg, int fd, pid_t pid);
extern uid_t userns_uid(uid_t uid);
extern gid_t userns_gid(gid_t gid);
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 27e353fc3..a1be94a87 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -1647,6 +1647,33 @@ int prep_usernsd_transport()
return ret;
}
+static struct ns_id *last_net_ns = NULL;
+
+int uns_create_dgram_sock(void *arg, int fd, pid_t pid)
+{
+ struct ns_id *ns = *(struct ns_id **)arg;
+
+ if (last_net_ns != ns) {
+ fd = fdstore_get(ns->net.nsfd_id);
+ if (fd < 0) {
+ pr_err("Can't get net_ns\n");
+ return -1;
+ }
+ if (setns(fd, CLONE_NEWNET) < 0) {
+ pr_perror("Can't setns");
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ last_net_ns = ns;
+ }
+
+ fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (fd < 0)
+ pr_perror("Can't create sock");
+ return fd;
+}
+
static int usernsd(int sk)
{
pr_info("uns: Daemon started\n");
More information about the CRIU
mailing list