[CRIU] [PATCH 13/14] zdtm: add ability to execute tests in another user namespace

Andrey Vagin avagin at openvz.org
Tue Oct 14 04:38:27 PDT 2014


Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm.sh       | 11 +++++++++-
 test/zdtm/lib/ns.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/test/zdtm.sh b/test/zdtm.sh
index 9a2c188..16777a6 100755
--- a/test/zdtm.sh
+++ b/test/zdtm.sh
@@ -410,6 +410,12 @@ start_test()
 		chmod a+w $tdir
 	fi
 
+	if [ -z "$USERNS" ]; then
+		unset ZDTM_USERNS
+	else
+		export ZDTM_USERNS=1
+	fi
+
 	if [ -z "$PIDNS" ]; then
 		TPID="$test.pid"
 		unset ZDTM_NEWNS
@@ -493,7 +499,10 @@ run_test()
 	fi
 
 	expr "$test" : 'ns/' > /dev/null && PIDNS=1 || PIDNS=""
-	test=${ZP}/${test#ns/}
+	test=${test#ns/}
+	expr "$test" : 'user/' > /dev/null && USERNS=1 || USERNS=""
+	test=${test#user/}
+	test=${ZP}/${test}
 
 	shift
 	local gen_args=$*
diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
index 9901f5f..411040d 100644
--- a/test/zdtm/lib/ns.c
+++ b/test/zdtm/lib/ns.c
@@ -13,6 +13,7 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <sched.h>
+#include <sys/socket.h>
 
 #include "ns.h"
 
@@ -183,6 +184,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]);
@@ -197,6 +199,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;
 
@@ -357,34 +366,76 @@ static int construct_root()
 	return 0;
 }
 
+#define UID_MAP "0 100000 100000\n100000 200000 50000"
+#define GID_MAP "0 400000 50000\n50000 500000 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;
+	char *val;
 
 	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);
 	}
 
+	val = getenv("ZDTM_USERNS");
+	if (val)
+		/*
+		 * CLONE_NEWIPC and CLONE_NEWUTS are excluded, because
+		 * their sysctl-s are protected by CAP_SYS_ADMIN
+		 */
+		flags = CLONE_NEWPID | CLONE_NEWNS  |
+			CLONE_NEWNET | CLONE_NEWUSER | SIGCHLD;
+	else
+		flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUTS |
+			CLONE_NEWNET | CLONE_NEWIPC | SIGCHLD;
+
 	if (construct_root())
 		exit(1);
 
-	pid = clone(ns_exec, args.stack_ptr,
-			CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUTS |
-			CLONE_NEWNET | CLONE_NEWIPC | SIGCHLD, &args);
+	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]);
 
+	if (val) {
+		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, UID_MAP, sizeof(UID_MAP)) < 0) {
+			fprintf(stderr, "write(" UID_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, GID_MAP, sizeof(GID_MAP)) < 0) {
+			fprintf(stderr, "write(" GID_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