1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd., 2015
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11 * the GNU General Public License for more details.
12 */
13
14 /*
15 * Verify that:
16 * A process created via fork(2) or clone(2) without the
17 * CLONE_NEWUSER flag is a member of the same user namespace as its
18 * parent.
19 * When unshare an user namespace, the calling process is moved into
20 * a new user namespace which is not shared with any previously
21 * existing process.
22 */
23
24 #define _GNU_SOURCE
25 #include <sys/wait.h>
26 #include <assert.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include "userns_helper.h"
33 #include "test.h"
34
35 char *TCID = "user_namespace5";
36 int TST_TOTAL = 1;
37
cleanup(void)38 static void cleanup(void)
39 {
40 tst_rmdir();
41 }
42
43 /*
44 * child_fn1() - Inside a new user namespace
45 */
child_fn1(void)46 static int child_fn1(void)
47 {
48 TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
49 return 0;
50 }
51
getusernsidbypid(int pid)52 static unsigned int getusernsidbypid(int pid)
53 {
54 char path[BUFSIZ];
55 char userid[BUFSIZ];
56 unsigned int id = 0;
57
58 sprintf(path, "/proc/%d/ns/user", pid);
59
60 if (readlink(path, userid, BUFSIZ) == -1)
61 tst_resm(TFAIL | TERRNO, "readlink failure.");
62
63 if (sscanf(userid, "user:[%u]", &id) != 1)
64 tst_resm(TFAIL, "sscanf failure.");
65 return id;
66 }
67
test_userns_id(void)68 static void test_userns_id(void)
69 {
70 int cpid1, cpid2, cpid3;
71 unsigned int parentuserns, cpid1userns, cpid2userns, newparentuserns;
72
73 parentuserns = getusernsidbypid(getpid());
74 cpid1 = ltp_clone_quick(SIGCHLD, (void *)child_fn1,
75 NULL);
76 if (cpid1 < 0)
77 tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
78 cpid1userns = getusernsidbypid(cpid1);
79 TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
80
81 /* A process created via fork(2) or clone(2) without the
82 CLONE_NEWUSER flag is a member of the same user namespace as its
83 parent.*/
84 if (parentuserns != cpid1userns)
85 tst_resm(TFAIL, "userns:parent should be equal to cpid1");
86
87 cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD,
88 (void *)child_fn1, NULL);
89 if (cpid2 < 0)
90 tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
91 cpid2userns = getusernsidbypid(cpid2);
92 TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
93
94 if (parentuserns == cpid2userns)
95 tst_resm(TFAIL, "userns:parent should be not equal to cpid2");
96
97 switch (cpid3 = fork()) {
98 case -1:
99 tst_brkm(TBROK | TERRNO, cleanup, "fork");
100 case 0:
101 if (unshare(CLONE_NEWUSER) == -1) {
102 printf("parent pid unshare failure: (%d) %s",
103 errno, strerror(errno));
104 exit(1);
105 }
106 newparentuserns = getusernsidbypid(getpid());
107
108 /* When unshare an user namespace, the calling process
109 is moved into a new user namespace which is not shared
110 with any previously existing process.*/
111 if (parentuserns == newparentuserns)
112 exit(1);
113 exit(0);
114 }
115
116 tst_record_childstatus(cleanup, cpid1);
117 tst_record_childstatus(cleanup, cpid2);
118 tst_record_childstatus(cleanup, cpid3);
119 }
120
setup(void)121 static void setup(void)
122 {
123 check_newuser();
124
125 tst_tmpdir();
126 TST_CHECKPOINT_INIT(NULL);
127 }
128
main(int argc,char * argv[])129 int main(int argc, char *argv[])
130 {
131 int lc;
132
133 tst_parse_opts(argc, argv, NULL, NULL);
134 setup();
135
136 for (lc = 0; TEST_LOOPING(lc); lc++) {
137 tst_count = 0;
138 test_userns_id();
139 }
140 cleanup();
141 tst_exit();
142 }
143