[8/8] zdtm: Add userns-no-child-setns test

Submitted by Kirill Tkhai on June 28, 2017, 11:51 a.m.

Details

Message ID 149865066267.12218.6939296322544130416.stgit@localhost.localdomain
State New
Series "One-level leaked net_ns support"
Headers show

Commit Message

Kirill Tkhai June 28, 2017, 11:51 a.m.
1)Create a child with CLONE_NEWNET|CLONE_NEWUSER.
2)setns() to its net_ns.
3)Create second child with CLONE_NEWUSER|CLONE_NEWPID
  (and it inherits net_ns of first child).
4)Restore original net_ns.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 test/zdtm/static/Makefile                       |    1 
 test/zdtm/static/userns-denied-child-setns.c    |  146 +++++++++++++++++++++++
 test/zdtm/static/userns-denied-child-setns.desc |    1 
 3 files changed, 148 insertions(+)
 create mode 100644 test/zdtm/static/userns-denied-child-setns.c
 create mode 100644 test/zdtm/static/userns-denied-child-setns.desc

Patch hide | download patch | download mbox

diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 2c6353ee8..71ef71811 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -180,6 +180,7 @@  TST_NOFILE	:=				\
 		userns01			\
 		userns02			\
 		userns-leaked-sock		\
+		userns-denied-child-setns	\
 		netns_sub_veth			\
 		pidns00				\
 		pidns01				\
diff --git a/test/zdtm/static/userns-denied-child-setns.c b/test/zdtm/static/userns-denied-child-setns.c
new file mode 100644
index 000000000..6f6e9c127
--- /dev/null
+++ b/test/zdtm/static/userns-denied-child-setns.c
@@ -0,0 +1,146 @@ 
+#include <stdbool.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <limits.h>
+
+#include "zdtmtst.h"
+#include "lock.h"
+#include "ns.h"
+
+const char *test_doc	= "Check that namespaces are correctly inherited";
+const char *test_author	= "Kirill Tkhai <ktkhai@virtuozzo.com>";
+
+/*
+ *  1)Create a child with CLONE_NEWNET|CLONE_NEWUSER.
+ *  2)setns() to its net_ns.
+ *  3)Create second child with CLONE_NEWUSER|CLONE_NEWPID
+ *    (and it inherits net_ns of first child).
+ *  4)Restore original net_ns.
+ */
+
+enum {
+	FUTEX_INITIALIZED = 0,
+	MAPS_SET,
+	CHILD_PREPARED,
+	POST_RESTORE_CHECK,
+	EMERGENCY_ABORT,
+};
+
+futex_t *futex;
+
+static int child_fn(void *arg)
+{
+	futex_wait_while_lt(futex, MAPS_SET);
+	setuid(0);
+	setgid(0);
+	futex_set_and_wake(futex, CHILD_PREPARED);
+	return pause();
+}
+
+int main(int argc, char **argv)
+{
+	int i, net_ns_fd, fd;
+	char path[64];
+	pid_t pid[2];
+	int status;
+
+	test_init(argc, argv);
+	futex = mmap(NULL, sizeof(*futex), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+	if (futex == MAP_FAILED) {
+		fail("mmap futex\n");
+		return 1;
+	}
+	futex_init(futex);
+
+	/* save original net namespace fd */
+	net_ns_fd = open("/proc/self/ns/net", O_RDONLY);
+	if (net_ns_fd < 0) {
+		fail("open");
+		return 1;
+	}
+
+	{
+		/* Create first child */
+		char stack;
+		pid[0] = clone(child_fn, &stack - 256, CLONE_NEWUSER|CLONE_NEWNET, NULL);
+		if (pid[0] == -1) {
+			fail("clone");
+			return 1;
+		}
+	}
+
+	if (write_map(pid[0], "uid_map", "0 10 1") < 0 ||
+	    write_map(pid[0], "gid_map", "0 12 1") < 0) {
+		fail("write map");
+		goto out_kill;
+	}
+	futex_set_and_wake(futex, MAPS_SET);
+	futex_wait_while_lt(futex, CHILD_PREPARED);
+
+	sprintf(path, "/proc/%d/ns/net", pid[0]);
+	fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		fail("open");
+		goto out_kill;
+	}
+
+	if (setns(fd, CLONE_NEWNET)) {
+		fail("setns");
+		goto out_kill;
+	}
+
+	futex_init(futex);
+	{
+		/* Create second child */
+		char stack;
+		pid[1] = clone(child_fn, &stack - 256, CLONE_NEWUSER|CLONE_NEWPID, NULL);
+		if (pid[1] == -1) {
+			fail("clone");
+			goto out_kill;
+		}
+	}
+
+	if (write_map(pid[1], "uid_map", "0 10 1") < 0 ||
+	    write_map(pid[1], "gid_map", "0 12 1") < 0) {
+		fail("write map");
+		goto out_kill2;
+	}
+
+	futex_set_and_wake(futex, MAPS_SET);
+	futex_wait_while_lt(futex, CHILD_PREPARED);
+
+	if (setns(net_ns_fd, CLONE_NEWNET)) {
+		fail("setns");
+		goto out_kill2;
+	}
+
+	close(fd);
+	close(net_ns_fd);
+
+	test_daemon();
+	test_waitsig();
+
+	for (i = 0; i < 2; i++) {
+		kill(pid[i], SIGKILL);
+		wait(&status);
+	}
+
+	/* If we restore, test is passed */
+	pass();
+	return 0;
+out_kill2:
+	kill(pid[1], SIGKILL);
+	wait(&status);
+out_kill:
+	kill(pid[0], SIGKILL);
+	wait(&status);
+	return 1;
+}
diff --git a/test/zdtm/static/userns-denied-child-setns.desc b/test/zdtm/static/userns-denied-child-setns.desc
new file mode 100644
index 000000000..703c925e2
--- /dev/null
+++ b/test/zdtm/static/userns-denied-child-setns.desc
@@ -0,0 +1 @@ 
+{'flavor': 'uns', 'flags': 'suid', 'feature': 'ns_pid ns_get_parent ns_get_userns'}