• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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