[v3,06/55] kerndat: Check that "/proc/[pid]/status" file has NS{pid, ..} lines

Submitted by Kirill Tkhai on April 10, 2017, 8:16 a.m.

Details

Message ID 149181216340.17342.12606484782334273195.stgit@localhost.localdomain
State New
Series "Nested pid namespaces support"
Headers show

Commit Message

Kirill Tkhai April 10, 2017, 8:16 a.m.
If there is nested pid_ns, we need to be able to get pid in
the whole pid hierarhy. This may be taken from "/proc/[pid]/status"
file only. Check, that kernel has support for it.

v3: Add criu feature check

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/cr-check.c        |   13 +++++++++++++
 criu/include/kerndat.h |    2 ++
 criu/kerndat.c         |   28 ++++++++++++++++++++++++++++
 criu/namespaces.c      |    5 +++++
 4 files changed, 48 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/cr-check.c b/criu/cr-check.c
index 28e8db15a..7415de39e 100644
--- a/criu/cr-check.c
+++ b/criu/cr-check.c
@@ -1094,6 +1094,17 @@  static int check_sk_netns(void)
 	return 0;
 }
 
+static int check_ns_pid(void)
+{
+	if (kerndat_has_nspid() < 0)
+		return -1;
+
+	if (!kdat.has_nspid)
+		return -1;
+
+	return 0;
+}
+
 static int (*chk_feature)(void);
 
 /*
@@ -1198,6 +1209,7 @@  int cr_check(void)
 		ret |= check_userns();
 		ret |= check_loginuid();
 		ret |= check_sk_netns();
+		ret |= check_ns_pid();
 	}
 
 	/*
@@ -1278,6 +1290,7 @@  static struct feature_list feature_list[] = {
 	{ "sk_ns", check_sk_netns },
 	{ "nsid", check_nsid },
 	{ "link_nsid", check_link_nsid},
+	{ "ns_pid", check_ns_pid},
 	{ NULL, NULL },
 };
 
diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index 60c69c3e1..eacd4c73d 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -43,6 +43,7 @@  struct kerndat_s {
 	unsigned long uffd_features;
 	bool has_nsid;
 	bool has_link_nsid;
+	bool has_nspid;
 };
 
 extern struct kerndat_s kdat;
@@ -65,5 +66,6 @@  extern int kerndat_fs_virtualized(unsigned int which, u32 kdev);
 
 extern int kerndat_tcp_repair();
 extern int kerndat_uffd(bool need_uffd);
+extern int kerndat_has_nspid(void);
 
 #endif /* __CR_KERNDAT_H__ */
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 22dd1e8c4..a10247930 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -627,6 +627,32 @@  int kerndat_uffd(bool need_uffd)
 	return 0;
 }
 
+int kerndat_has_nspid(void)
+{
+	struct bfd f;
+	int ret = -1;
+	char *str;
+
+	f.fd = open("/proc/self/status", O_RDONLY);
+	if (f.fd < 0) {
+		pr_perror("Can't open /proc/self/status");
+		return -1;
+	}
+	if (bfdopenr(&f))
+		return -1;
+	while ((str = breadline(&f)) != NULL) {
+		if (IS_ERR(str))
+			goto close;
+		if (!strncmp(str, "NSpid:", 6)) {
+			kdat.has_nspid = true;
+			break;
+		}
+	}
+	ret = 0;
+close:
+	bclose(&f);
+	return ret;
+}
 int kerndat_init(void)
 {
 	int ret;
@@ -658,6 +684,8 @@  int kerndat_init(void)
 		ret = kerndat_socket_netns();
 	if (!ret)
 		ret = kerndat_nsid();
+	if (!ret)
+		ret = kerndat_has_nspid();
 
 	kerndat_lsm();
 	kerndat_mmap_min_addr();
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 910fc0e0a..a1088e426 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -26,6 +26,7 @@ 
 #include "namespaces.h"
 #include "net.h"
 #include "cgroup.h"
+#include "kerndat.h"
 
 #include "protobuf.h"
 #include "util.h"
@@ -789,6 +790,10 @@  static int set_ns_hookups(struct ns_id *ns)
 			pr_err("Wrong determined NS_ROOT, or root_item has NS_OTHER user_ns\n");
 			goto out;
 		}
+		if (nd == &pid_ns_desc && !kdat.has_nspid) {
+			pr_err("Can't dump nested pid ns\n");
+			goto out;
+		}
 		list_add(&ns->siblings, &ns->parent->children);
 	}