[CRIU] [PATCH 3/7] pie: better detection of /proc belonging to pid ns

Tycho Andersen tycho.andersen at canonical.com
Thu Feb 18 08:08:52 PST 2016


While this commit is logically part of the "implement cgns support" commit,
it's worth noting this separately I think: since cgns requires each task to
look at its own proc file, we can now no longer dump unprivileged tasks
whose /proc doesn't belong to them.

This is because unprivileged tasks can't mount /proc, so if their /proc
doesn't belong to them and they need to read it (because they're in a
cgns), the pie code can't do anything about it.

For cgns, we could solve this problem by simply fork()ing and setns()ing to
the tasks pid and cgroup namespaces, and then reading the /proc from that
task instead. (And perhaps we should implement it that way so we can still
dump tasks whose /proc doesn't belong to them, although I don't think
that's a common case.)

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 criu/pie/parasite.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index c3271b1..53ef609 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -284,21 +284,35 @@ static int dump_thread(struct parasite_dump_thread *args)
 }
 
 static char proc_mountpoint[] = "proc.crtools";
-static int get_proc_fd(void)
+
+static int pie_atoi(char *str)
+{
+	int ret = 0;
+
+	while (*str) {
+		ret *= 10;
+		ret += *str - '0';
+		str++;
+	}
+
+	return ret;
+}
+
+static int get_proc_fd()
 {
 	int ret;
-	char buf[2];
+	char buf[10];
 
 	ret = sys_readlinkat(AT_FDCWD, "/proc/self", buf, sizeof(buf));
 	if (ret < 0 && ret != -ENOENT) {
 		pr_err("Can't readlink /proc/self (%d)\n", ret);
 		return ret;
 	}
+	buf[ret] = 0;
 
 	/* Fast path -- if /proc belongs to this pidns */
-	if (ret == 1 && buf[0] == '1') {
+	if (pie_atoi(buf) == sys_getpid())
 		return sys_open("/proc", O_RDONLY, 0);
-	}
 
 	ret = sys_mkdir(proc_mountpoint, 0700);
 	if (ret) {
@@ -308,7 +322,10 @@ static int get_proc_fd(void)
 
 	ret = sys_mount("proc", proc_mountpoint, "proc", MS_MGC_VAL, NULL);
 	if (ret) {
-		pr_err("mount failed (%d)\n", ret);
+		if (ret == -EPERM)
+			pr_err("can't dump unpriviliged task whose /proc doesn't belong to it\n");
+		else
+			pr_err("mount failed (%d)\n", ret);
 		sys_rmdir(proc_mountpoint);
 		return -1;
 	}
-- 
2.6.4



More information about the CRIU mailing list