[6/8] files: Create transport socket via usernsd, when it's need

Submitted by Kirill Tkhai on June 28, 2017, 11:50 a.m.

Details

Message ID 149865061297.12218.18372183930082880089.stgit@localhost.localdomain
State New
Series "One-level leaked net_ns support"
Headers show

Commit Message

Kirill Tkhai June 28, 2017, 11:50 a.m.
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@virtuozzo.com>
---
 criu/files.c              |   11 ++++++++++-
 criu/include/namespaces.h |    1 +
 criu/namespaces.c         |   27 +++++++++++++++++++++++++++
 3 files changed, 38 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

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");