aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Vagin <avagin@openvz.org>2016-09-06 03:47:16 -0400
committerEric W. Biederman <ebiederm@xmission.com>2016-09-22 20:59:41 -0400
commit6ad92bf63e45f97e306da48cd1cbce6e4fef1e5d (patch)
tree3a880aea3a869f8ee5261704a7ca5e6f6983db17
parenta7306ed8d94af729ecef8b6e37506a1c6fc14788 (diff)
tools/testing: add a test to check nsfs ioctl-s
There are two new ioctl-s: One ioctl for the user namespace that owns a file descriptor. One ioctl for the parent namespace of a namespace file descriptor. The test checks that these ioctl-s works and that they handle a case when a target namespace is outside of the current process namespace. Signed-off-by: Andrei Vagin <avagin@openvz.org> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/nsfs/Makefile12
-rw-r--r--tools/testing/selftests/nsfs/owner.c91
-rw-r--r--tools/testing/selftests/nsfs/pidns.c78
4 files changed, 182 insertions, 0 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index ff9e5f20a5a7..f770dba2a6f6 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -15,6 +15,7 @@ TARGETS += memory-hotplug
15TARGETS += mount 15TARGETS += mount
16TARGETS += mqueue 16TARGETS += mqueue
17TARGETS += net 17TARGETS += net
18TARGETS += nsfs
18TARGETS += powerpc 19TARGETS += powerpc
19TARGETS += pstore 20TARGETS += pstore
20TARGETS += ptrace 21TARGETS += ptrace
diff --git a/tools/testing/selftests/nsfs/Makefile b/tools/testing/selftests/nsfs/Makefile
new file mode 100644
index 000000000000..2306054a901a
--- /dev/null
+++ b/tools/testing/selftests/nsfs/Makefile
@@ -0,0 +1,12 @@
1TEST_PROGS := owner pidns
2
3CFLAGS := -Wall -Werror
4
5all: owner pidns
6owner: owner.c
7pidns: pidns.c
8
9clean:
10 $(RM) owner pidns
11
12include ../lib.mk
diff --git a/tools/testing/selftests/nsfs/owner.c b/tools/testing/selftests/nsfs/owner.c
new file mode 100644
index 000000000000..437205f8b714
--- /dev/null
+++ b/tools/testing/selftests/nsfs/owner.c
@@ -0,0 +1,91 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <signal.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <sys/ioctl.h>
12#include <sys/prctl.h>
13#include <sys/wait.h>
14
15#define NSIO 0xb7
16#define NS_GET_USERNS _IO(NSIO, 0x1)
17
18#define pr_err(fmt, ...) \
19 ({ \
20 fprintf(stderr, "%s:%d:" fmt ": %m\n", \
21 __func__, __LINE__, ##__VA_ARGS__); \
22 1; \
23 })
24
25int main(int argc, char *argvp[])
26{
27 int pfd[2], ns, uns, init_uns;
28 struct stat st1, st2;
29 char path[128];
30 pid_t pid;
31 char c;
32
33 if (pipe(pfd))
34 return 1;
35
36 pid = fork();
37 if (pid < 0)
38 return pr_err("fork");
39 if (pid == 0) {
40 prctl(PR_SET_PDEATHSIG, SIGKILL);
41 if (unshare(CLONE_NEWUTS | CLONE_NEWUSER))
42 return pr_err("unshare");
43 close(pfd[0]);
44 close(pfd[1]);
45 while (1)
46 sleep(1);
47 return 0;
48 }
49 close(pfd[1]);
50 if (read(pfd[0], &c, 1) != 0)
51 return pr_err("Unable to read from pipe");
52 close(pfd[0]);
53
54 snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid);
55 ns = open(path, O_RDONLY);
56 if (ns < 0)
57 return pr_err("Unable to open %s", path);
58
59 uns = ioctl(ns, NS_GET_USERNS);
60 if (uns < 0)
61 return pr_err("Unable to get an owning user namespace");
62
63 if (fstat(uns, &st1))
64 return pr_err("fstat");
65
66 snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
67 if (stat(path, &st2))
68 return pr_err("stat");
69
70 if (st1.st_ino != st2.st_ino)
71 return pr_err("NS_GET_USERNS returned a wrong namespace");
72
73 init_uns = ioctl(uns, NS_GET_USERNS);
74 if (uns < 0)
75 return pr_err("Unable to get an owning user namespace");
76
77 if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
78 return pr_err("Don't get EPERM");
79
80 if (unshare(CLONE_NEWUSER))
81 return pr_err("unshare");
82
83 if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM)
84 return pr_err("Don't get EPERM");
85 if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
86 return pr_err("Don't get EPERM");
87
88 kill(pid, SIGKILL);
89 wait(NULL);
90 return 0;
91}
diff --git a/tools/testing/selftests/nsfs/pidns.c b/tools/testing/selftests/nsfs/pidns.c
new file mode 100644
index 000000000000..ae3a0d68e966
--- /dev/null
+++ b/tools/testing/selftests/nsfs/pidns.c
@@ -0,0 +1,78 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <signal.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <sys/ioctl.h>
12#include <sys/prctl.h>
13#include <sys/wait.h>
14
15#define pr_err(fmt, ...) \
16 ({ \
17 fprintf(stderr, "%s:%d:" fmt ": %m\n", \
18 __func__, __LINE__, ##__VA_ARGS__); \
19 1; \
20 })
21
22#define NSIO 0xb7
23#define NS_GET_USERNS _IO(NSIO, 0x1)
24#define NS_GET_PARENT _IO(NSIO, 0x2)
25
26#define __stack_aligned__ __attribute__((aligned(16)))
27struct cr_clone_arg {
28 char stack[128] __stack_aligned__;
29 char stack_ptr[0];
30};
31
32static int child(void *args)
33{
34 prctl(PR_SET_PDEATHSIG, SIGKILL);
35 while (1)
36 sleep(1);
37 exit(0);
38}
39
40int main(int argc, char *argv[])
41{
42 char *ns_strs[] = {"pid", "user"};
43 char path[] = "/proc/0123456789/ns/pid";
44 struct cr_clone_arg ca;
45 struct stat st1, st2;
46 int ns, pns, i;
47 pid_t pid;
48
49 pid = clone(child, ca.stack_ptr, CLONE_NEWUSER | CLONE_NEWPID | SIGCHLD, NULL);
50 if (pid < 0)
51 return pr_err("clone");
52
53 for (i = 0; i < 2; i++) {
54 snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns_strs[i]);
55 ns = open(path, O_RDONLY);
56 if (ns < 0)
57 return pr_err("Unable to open %s", path);
58
59 pns = ioctl(ns, NS_GET_PARENT);
60 if (pns < 0)
61 return pr_err("Unable to get a parent pidns");
62
63 snprintf(path, sizeof(path), "/proc/self/ns/%s", ns_strs[i]);
64 if (stat(path, &st2))
65 return pr_err("Unable to stat %s", path);
66 if (fstat(pns, &st1))
67 return pr_err("Unable to stat the parent pidns");
68 if (st1.st_ino != st2.st_ino)
69 return pr_err("NS_GET_PARENT returned a wrong namespace");
70
71 if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != EPERM)
72 return pr_err("Don't get EPERM");;
73 }
74
75 kill(pid, SIGKILL);
76 wait(NULL);
77 return 0;
78}