[CRIU] [PATCH 7/9] kerndat: check the SIOCGSKNS ioctl

Andrei Vagin avagin at openvz.org
Tue Feb 14 15:59:30 PST 2017


From: Andrei Vagin <avagin at virtuozzo.com>

This ioctl is called for a socket and returns a file descriptor
for network namespace where a socket has been created.

Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/cr-check.c        | 13 +++++++++++++
 criu/include/kerndat.h |  1 +
 criu/include/sockets.h |  6 ++++++
 criu/kerndat.c         |  5 +++++
 criu/net.c             | 24 ++++++++++++++++++++++++
 5 files changed, 49 insertions(+)

diff --git a/criu/cr-check.c b/criu/cr-check.c
index 04c2cd1..c826125 100644
--- a/criu/cr-check.c
+++ b/criu/cr-check.c
@@ -1079,6 +1079,17 @@ static int check_uffd(void)
 	return 0;
 }
 
+static int check_sk_netns(void)
+{
+	if (kerndat_socket_netns() < 0)
+		return -1;
+
+	if (!kdat.sk_ns)
+		return -1;
+
+	return 0;
+}
+
 static int check_compat_cr(void)
 {
 	if (kdat_compat_sigreturn_test())
@@ -1190,6 +1201,7 @@ int cr_check(void)
 		ret |= check_tcp_halt_closed();
 		ret |= check_userns();
 		ret |= check_loginuid();
+		ret |= check_sk_netns();
 	}
 
 	/*
@@ -1241,6 +1253,7 @@ static struct feature_list feature_list[] = {
 	{ "tcp_half_closed", check_tcp_halt_closed },
 	{ "lazy_pages", check_uffd },
 	{ "compat_cr", check_compat_cr },
+	{ "sk_ns", check_sk_netns },
 	{ NULL, NULL },
 };
 
diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index 8f8db78..e41768f 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -35,6 +35,7 @@ struct kerndat_s {
 	bool ipv6;
 	bool has_loginuid;
 	bool has_compat_sigreturn;
+	bool sk_ns;
 	enum pagemap_func pmap;
 	unsigned int has_xtlocks;
 	unsigned long mmap_min_addr;
diff --git a/criu/include/sockets.h b/criu/include/sockets.h
index 28bf91e..93f9ca3 100644
--- a/criu/include/sockets.h
+++ b/criu/include/sockets.h
@@ -84,4 +84,10 @@ static inline int sk_decode_shutdown(int val)
 
 extern int set_netns(uint32_t ns_id);
 
+#ifndef SIOCGSKNS
+#define SIOCGSKNS      0x894C          /* get socket network namespace */
+#endif
+
+extern int kerndat_socket_netns(void);
+
 #endif /* __CR_SOCKETS_H__ */
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 88feac3..162ac28 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -27,6 +27,7 @@
 #include "proc_parse.h"
 #include "config.h"
 #include "sk-inet.h"
+#include "sockets.h"
 #include <compel/plugins/std/syscall-codes.h>
 #include <compel/compel.h>
 #include "linux/userfaultfd.h"
@@ -634,6 +635,8 @@ int kerndat_init(void)
 		ret = kerndat_tcp_repair();
 	if (!ret)
 		ret = kerndat_compat_restore();
+	if (!ret)
+		ret = kerndat_socket_netns();
 
 	kerndat_lsm();
 	kerndat_mmap_min_addr();
@@ -670,6 +673,8 @@ int kerndat_init_rst(void)
 		ret = kerndat_compat_restore();
 	if (!ret)
 		ret = kerndat_uffd(opts.lazy_pages);
+	if (!ret)
+		ret = kerndat_socket_netns();
 
 	kerndat_lsm();
 	kerndat_mmap_min_addr();
diff --git a/criu/net.c b/criu/net.c
index 25abd6f..7000923 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -2061,6 +2061,30 @@ struct ns_id *get_socket_ns(int lfd)
 	return NULL;
 }
 
+int kerndat_socket_netns(void)
+{
+	int sk, ns_fd;
+
+	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		pr_perror("Unable to create socket");
+		return -1;
+	}
+	ns_fd = ioctl(sk, SIOCGSKNS);
+	if (ns_fd < 0) {
+		pr_warn("Unable to get a socket network namespace\n");
+		kdat.sk_ns = false;
+		close(sk);
+		return 0;
+	}
+	close(sk);
+	close(ns_fd);
+
+	kdat.sk_ns = true;
+
+	return 0;
+}
+
 static int move_to_bridge(struct external *ext, void *arg)
 {
 	int s = *(int *)arg;
-- 
2.7.4



More information about the CRIU mailing list