[CRIU] [PATCH 08/11] zdtm: extent zdtm to execute tests in userns

Andrey Vagin avagin at openvz.org
Wed Aug 13 00:51:35 PDT 2014


time bash test/zdtm.sh  -i 0 -x cwd -x maps -x sched -x sock -x fanot ns/.*

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm/lib/ns.c | 146 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 117 insertions(+), 29 deletions(-)

diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
index 8afec5b..f5fd72d 100644
--- a/test/zdtm/lib/ns.c
+++ b/test/zdtm/lib/ns.c
@@ -13,14 +13,16 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <sched.h>
+#include <sys/socket.h>
 
 #include "ns.h"
 
 extern int pivot_root(const char *new_root, const char *put_old);
 static int prepare_mntns()
 {
-	int dfd;
+	int dfd, ret;
 	char *root;
+	char path[PATH_MAX];
 
 	root = getenv("ZDTM_ROOT");
 	if (!root) {
@@ -34,6 +36,16 @@ static int prepare_mntns()
 			return -1;
 		}
 
+		if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) {
+			fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n");
+			return -1;
+		}
+
+		if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) {
+			fprintf(stderr, "Can't bind-mount root: %m\n");
+			return -1;
+		}
+
 		if (chdir(root)) {
 			fprintf(stderr, "chdir(%s) failed: %m\n", root);
 			return -1;
@@ -43,19 +55,11 @@ static int prepare_mntns()
 			return -1;
 		}
 
-		if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) {
-			fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n");
-			return -1;
-		}
-
 		if (pivot_root(".", "./old")) {
 			fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
 			return -1;
 		}
-		if (umount2("./old", MNT_DETACH)) {
-			fprintf(stderr, "umount(./old) failed: %m\n");
-			return -1;
-		}
+		chdir("/");
 		if (mkdir("proc", 0777) && errno != EEXIST) {
 			fprintf(stderr, "mkdir(proc) failed: %m\n");
 			return -1;
@@ -68,21 +72,23 @@ static int prepare_mntns()
 			fprintf(stderr, "mkdir(/dev) failed: %m\n");
 			return -1;
 		}
+
 		if (mkdir("/dev/pts", 0755) && errno != EEXIST) {
 			fprintf(stderr, "mkdir(/dev/pts) failed: %m\n");
 			return -1;
 		}
+		if (mount("pts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance,mode=666,ptmxmode=666")) {
+			fprintf(stderr, "mount(/dev/pts) failed: %m\n");
+			return -1;
+		}
 		if (symlink("/dev/pts/ptmx", "/dev/ptmx") && errno != EEXIST) {
 			fprintf(stderr, "mknod(/dev/ptmx) failed: %m\n");
 			return -1;
 		}
 		chmod("/dev/ptmx", 0666);
-		if (mount("pts", "/dev/pts", "devpts", MS_MGC_VAL, "mode=666,ptmxmode=666,newinstance")) {
-			fprintf(stderr, "mount(/dev/pts) failed: %m\n");
-			return -1;
-		}
-		if (mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL)) {
-			fprintf(stderr, "mount(/dev/pts) failed: %m\n");
+		if (umount2("./old", MNT_DETACH)) {
+			fprintf(stderr, "umount(./old) failed: %m\n");
+			sleep(1000);
 			return -1;
 		}
 		if (fchdir(dfd)) {
@@ -91,14 +97,14 @@ static int prepare_mntns()
 		}
 		close(dfd);
 
-	mkdir("/dev", 0777);
-	mknod("/dev/null", 0777 | S_IFCHR, makedev(1, 3));
-	chmod("/dev/null", 0777);
-	mkdir("/dev/net", 0777);
-	mknod("/dev/net/tun", 0777 | S_IFCHR, makedev(10, 200));
-	chmod("/dev/net/tun", 0777);
-	mknod("/dev/rtc", 0777 | S_IFCHR, makedev(254, 0));
-	chmod("/dev/rtc", 0777);
+	ret = readlink("/proc/self/cwd", path, sizeof(path) - 1);
+	if (ret < 0)
+		return -1;
+
+	path[ret] = 0;
+
+	chdir(path);
+
 	return 0;
 }
 
@@ -156,6 +162,7 @@ write_out:
 int ns_exec(void *_arg)
 {
 	struct ns_exec_args *args = (struct ns_exec_args *) _arg;
+	char buf[4096];
 	int ret;
 
 	close(args->status_pipe[0]);
@@ -170,6 +177,13 @@ int ns_exec(void *_arg)
 		return -1;
 	}
 	close(args->status_pipe[1]);
+	read(STATUS_FD, buf, sizeof(buf));
+	shutdown(STATUS_FD, SHUT_RD);
+	if (setuid(0) || setgid(0)) {
+		fprintf(stderr, "set*id failed: %m\n");
+		return -1;
+	}
+
 	if (prepare_mntns())
 		return -1;
 
@@ -290,30 +304,104 @@ int ns_init(int argc, char **argv)
 	exit(1);
 }
 
+static int construct_root()
+{
+	char *root;
+	int dfd;
+
+	root = getenv("ZDTM_ROOT");
+	if (!root) {
+		fprintf(stderr, "ZDTM_ROOT isn't set\n");
+		return -1;
+	}
+
+	dfd = open(".", O_RDONLY);
+	if (dfd == -1) {
+		fprintf(stderr, "open(.) failed: %m\n");
+		return -1;
+	}
+	if (chdir(root)) {
+		fprintf(stderr, "chdir(%s): %m\n", root);
+		return -1;
+	}
+
+	mkdir("dev", 0777);
+	chmod("dev", 0777);
+	mknod("dev/null", 0777 | S_IFCHR, makedev(1, 3));
+	chmod("dev/null", 0777);
+	mkdir("dev/net", 0777);
+	mknod("dev/net/tun", 0777 | S_IFCHR, makedev(10, 200));
+	chmod("dev/net/tun", 0777);
+	mknod("dev/rtc", 0777 | S_IFCHR, makedev(254, 0));
+	chmod("dev/rtc", 0777);
+
+	if (fchdir(dfd)) {
+		fprintf(stderr, "fchdir() failed: %m\n");
+		return -1;
+	}
+	close(dfd);
+
+	return 0;
+}
+
+#define ID_MAP "0 10000 100000"
 void ns_create(int argc, char **argv)
 {
 	pid_t pid;
+	char pname[PATH_MAX];
 	int ret, status;
 	struct ns_exec_args args;
-	int fd;
+	int fd, flags;
 
 	args.argc = argc;
 	args.argv = argv;
 
-	ret = pipe(args.status_pipe);
+	ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, args.status_pipe);
 	if (ret) {
 		fprintf(stderr, "Pipe() failed %m\n");
 		exit(1);
 	}
-	pid = clone(ns_exec, args.stack_ptr,
-			CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUTS |
-			CLONE_NEWNET | CLONE_NEWIPC | SIGCHLD, &args);
+
+	flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUTS |
+		CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUSER | SIGCHLD;
+
+	if (construct_root())
+		exit(1);
+
+	pid = clone(ns_exec, args.stack_ptr, flags, &args);
 	if (pid < 0) {
 		fprintf(stderr, "clone() failed: %m\n");
 		exit(1);
 	}
+
 	close(args.status_pipe[1]);
 
+	snprintf(pname, sizeof(pname), "/proc/%d/uid_map", pid);
+	fd = open(pname, O_WRONLY);
+	if (fd < 0) {
+		fprintf(stderr, "open(%s): %m\n", pname);
+		exit(1);
+	}
+	if (write(fd, ID_MAP, sizeof(ID_MAP)) < 0) {
+		fprintf(stderr, "write(" ID_MAP "): %m\n");
+		exit(1);
+	}
+	close(fd);
+
+	snprintf(pname, sizeof(pname), "/proc/%d/gid_map", pid);
+	fd = open(pname, O_WRONLY);
+	if (fd < 0) {
+		fprintf(stderr, "open(%s): %m\n", pname);
+		exit(1);
+	}
+	if (write(fd, ID_MAP, sizeof(ID_MAP)) < 0) {
+		fprintf(stderr, "write(" ID_MAP "): %m\n");
+		exit(1);
+	}
+	close(fd);
+
+	shutdown(args.status_pipe[0], SHUT_WR);
+
 	status = 1;
 	ret = read(args.status_pipe[0], &status, sizeof(status));
 	if (ret != sizeof(status) || status) {
-- 
1.9.3



More information about the CRIU mailing list