diff options
Diffstat (limited to 'tools/testing/selftests/nsfs/pidns.c')
-rw-r--r-- | tools/testing/selftests/nsfs/pidns.c | 78 |
1 files changed, 78 insertions, 0 deletions
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))) | ||
27 | struct cr_clone_arg { | ||
28 | char stack[128] __stack_aligned__; | ||
29 | char stack_ptr[0]; | ||
30 | }; | ||
31 | |||
32 | static int child(void *args) | ||
33 | { | ||
34 | prctl(PR_SET_PDEATHSIG, SIGKILL); | ||
35 | while (1) | ||
36 | sleep(1); | ||
37 | exit(0); | ||
38 | } | ||
39 | |||
40 | int 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 | } | ||