[CRIU] [PATCH 08/10] net: set a proper network namespace to create a socket

Andrei Vagin avagin at openvz.org
Fri Oct 28 10:41:54 PDT 2016


From: Andrei Vagin <avagin at virtuozzo.com>

Each socket has to be restored from a proper network namespaces
where it was created.

Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/files.c           |  2 ++
 criu/include/sockets.h |  2 ++
 criu/sk-inet.c         |  3 +++
 criu/sk-netlink.c      |  3 +++
 criu/sk-packet.c       |  3 +++
 criu/sk-unix.c         |  7 ++++++-
 criu/sockets.c         | 36 ++++++++++++++++++++++++++++++++++++
 7 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/criu/files.c b/criu/files.c
index 9227c90..169a2ba 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -993,6 +993,8 @@ static int open_transport_fd(int pid, struct fdinfo_list_entry *fle)
 
 	pr_info("\t\tCreate transport fd %s\n", saddr.sun_path + 1);
 
+	if (root_item->ids && set_netns(root_item->ids->net_ns_id))
+		return -1;
 
 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (sock < 0) {
diff --git a/criu/include/sockets.h b/criu/include/sockets.h
index 7685eeb..28bf91e 100644
--- a/criu/include/sockets.h
+++ b/criu/include/sockets.h
@@ -82,4 +82,6 @@ static inline int sk_decode_shutdown(int val)
 #define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
 #endif
 
+extern int set_netns(uint32_t ns_id);
+
 #endif /* __CR_SOCKETS_H__ */
diff --git a/criu/sk-inet.c b/criu/sk-inet.c
index e3dac6e..8d1285d 100644
--- a/criu/sk-inet.c
+++ b/criu/sk-inet.c
@@ -585,6 +585,9 @@ static int open_inet_sk(struct file_desc *d)
 	if (inet_validate_address(ie))
 		return -1;
 
+	if (set_netns(ie->ns_id))
+		return -1;
+
 	sk = socket(ie->family, ie->type, ie->proto);
 	if (sk < 0) {
 		pr_perror("Can't create inet socket");
diff --git a/criu/sk-netlink.c b/criu/sk-netlink.c
index 849c48b..0868a4e 100644
--- a/criu/sk-netlink.c
+++ b/criu/sk-netlink.c
@@ -179,6 +179,9 @@ static int open_netlink_sk(struct file_desc *d)
 
 	pr_info("Opening netlink socket id %#x\n", nse->id);
 
+	if (set_netns(nse->ns_id))
+		return -1;
+
 	sk = socket(PF_NETLINK, SOCK_RAW, nse->protocol);
 	if (sk < 0) {
 		pr_perror("Can't create netlink sock");
diff --git a/criu/sk-packet.c b/criu/sk-packet.c
index 0a5306d..d7719b4 100644
--- a/criu/sk-packet.c
+++ b/criu/sk-packet.c
@@ -418,6 +418,9 @@ static int open_packet_sk(struct file_desc *d)
 
 	pr_info("Opening packet socket id %#x\n", pse->id);
 
+	if (set_netns(pse->ns_id))
+		return -1;
+
 	sk = socket(PF_PACKET, pse->type, pse->protocol);
 	if (sk < 0) {
 		pr_perror("Can't create packet sock");
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index dec7a0c..d22df2b 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -1053,6 +1053,9 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui)
 	pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
 			ui->ue->id, ui->ue->ino, ui->ue->peer);
 
+	if (set_netns(ui->ue->ns_id))
+		return -1;
+
 	if (socketpair(PF_UNIX, ui->ue->type, 0, sk) < 0) {
 		pr_perror("Can't make socketpair");
 		return -1;
@@ -1127,6 +1130,9 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 	pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
 			ui->ue->id, ui->ue->ino, ui->ue->peer);
 
+	if (set_netns(ui->ue->ns_id))
+		return -1;
+
 	/*
 	 * Check if this socket was connected to criu service.
 	 * If so, put response, that dumping and restoring
@@ -1230,7 +1236,6 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 			return -1;
 		}
 
-
 		sk = socket(PF_UNIX, ui->ue->type, 0);
 		if (sk < 0) {
 			pr_perror("Can't make unix socket");
diff --git a/criu/sockets.c b/criu/sockets.c
index 8aa6706..c925c9f 100644
--- a/criu/sockets.c
+++ b/criu/sockets.c
@@ -1,3 +1,4 @@
+#include <sched.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <linux/netlink.h>
@@ -24,6 +25,8 @@
 #include "net.h"
 #include "xmalloc.h"
 #include "fs-magic.h"
+#include "pstree.h"
+#include "util.h"
 
 #ifndef SOCK_DIAG_BY_FAMILY
 #define SOCK_DIAG_BY_FAMILY 20
@@ -734,3 +737,36 @@ int collect_sockets(struct ns_id *ns)
 
 	return err;
 }
+
+static uint32_t last_ns_id = 0;
+
+int set_netns(uint32_t ns_id)
+{
+	struct ns_id *ns;
+	int nsfd;
+
+	if (!(root_ns_mask & CLONE_NEWNET))
+		return 0;
+
+	if (ns_id == last_ns_id)
+		return 0;
+
+	ns = lookup_ns_by_id(ns_id, &net_ns_desc);
+	if (ns == NULL) {
+		pr_err("Unable to find a network namespace");
+		return -1;
+	}
+	nsfd = open_proc(root_item->pid.virt, "fd/%d", ns->net.ns_fd);
+	if (nsfd < 0)
+		return -1;
+	if (setns(nsfd, CLONE_NEWNET)) {
+		pr_perror("Unable to switch a network namespace");
+		close(nsfd);
+		return -1;
+	}
+	last_ns_id = ns_id;
+	close(nsfd);
+	close_pid_proc();
+
+	return 0;
+}
-- 
2.7.4



More information about the CRIU mailing list