1 /*
2 * Copyright (c) International Business Machines Corp., 2007
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 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15 *
16 ***************************************************************************
17 * Copyright 2007 IBM
18 * Author: Serge Hallyn <serue@us.ibm.com>
19 *
20 * test1:
21 P1: A=gethostname
22 P2: B=gethostname
23 Ensure(A==B)
24
25 * test2:
26 P1: sethostname(A);
27 P2: (wait); B=gethostname
28 Ensure (A==B)
29
30 * test3:
31 P1: A=gethostname; unshare(utsname); sethostname(newname); C=gethostname
32 P2: B=gethostname; (wait); (wait); D=gethostname
33 Ensure (A==B && A==D && C!=D)
34
35 * test4:
36 P1: A=gethostname; unshare(utsname); (wait); C=gethostname
37 P2: B=gethostname; (wait); sethostname(newname); D=gethostname
38 Ensure (A==B && A==C && C!=D)
39
40 * test5:
41 P1: drop_privs(); unshare(utsname); (wait); C=gethostname
42 P2: (wait); sethostname(B); D=gethostname
43 Ensure (B==C==D) and state is ok.
44 *
45 */
46
47 #define _GNU_SOURCE 1
48 #include <sys/wait.h>
49 #include <assert.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <unistd.h>
53 #include <string.h>
54 #include <errno.h>
55 #include "libclone.h"
56 #include "test.h"
57 #include "safe_macros.h"
58
59 char *TCID = "uts_namespace";
60 int TST_TOTAL = 1;
61
dummy_child(void * v)62 static int dummy_child(void *v)
63 {
64 (void) v;
65 return 0;
66 }
67
check_newuts(void)68 static void check_newuts(void)
69 {
70 int pid, status;
71
72 if (tst_kvercmp(2, 6, 19) < 0)
73 tst_brkm(TCONF, NULL, "CLONE_NEWUTS not supported");
74
75 pid = do_clone_unshare_test(T_CLONE, CLONE_NEWUTS, dummy_child, NULL);
76 if (pid == -1)
77 tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWUTS not supported");
78
79 SAFE_WAIT(NULL, &status);
80 }
81
drop_root(void)82 int drop_root(void)
83 {
84 int ret;
85 ret = setresuid(1000, 1000, 1000);
86 if (ret) {
87 perror("setresuid");
88 exit(4);
89 }
90 return 1;
91 }
92
93 #define HLEN 100
94 #define NAME1 "serge1"
95 #define NAME2 "serge2"
96
97 int p1fd[2], p2fd[2];
98 static char oldhost[HLEN];
99 pid_t cpid;
100
picknewhostname(char * orig,char * new)101 void picknewhostname(char *orig, char *new)
102 {
103 memset(new, 0, HLEN);
104 if (strcmp(orig, NAME1) == 0)
105 strcpy(new, NAME2);
106 else
107 strcpy(new, NAME1);
108 }
109
zeroize(char * s)110 void zeroize(char *s)
111 {
112 memset(s, 0, HLEN);
113 }
114
115 char *tsttype;
P1(void * vtest)116 int P1(void *vtest)
117 {
118 char hostname[HLEN], newhostname[HLEN], rhostname[HLEN];
119 int err;
120 int len;
121 int testnum;
122
123 testnum = atoi((char *)vtest);
124
125 close(p1fd[1]);
126 close(p2fd[0]);
127
128 switch (testnum) {
129 case 1:
130 gethostname(hostname, HLEN);
131 zeroize(rhostname);
132 len = read(p1fd[0], rhostname, HLEN);
133 if (strcmp(hostname, rhostname) == 0) {
134 tst_resm(TPASS, "test 1 (%s): success", tsttype);
135 tst_exit();
136 }
137 tst_brkm(TFAIL, NULL,
138 "test 1 (%s): hostname 1 %s, hostname 2 %s",
139 tsttype, hostname, rhostname);
140 case 2:
141 gethostname(hostname, HLEN);
142 picknewhostname(hostname, newhostname);
143 err = sethostname(newhostname, strlen(newhostname));
144 write(p2fd[1], "1", 1);
145 if (err == -1) {
146 tst_brkm(TFAIL, NULL,
147 "test 2 (%s): failed to sethostname",
148 tsttype);
149 }
150 zeroize(rhostname);
151 len = read(p1fd[0], rhostname, HLEN);
152 if (strcmp(newhostname, rhostname) == 0) {
153 tst_resm(TPASS, "test 2 (%s): success", tsttype);
154 tst_exit();
155 }
156 tst_brkm(TFAIL, NULL,
157 "test 2 (%s) hostname 1 %s, hostname 2 %s",
158 tsttype, newhostname, rhostname);
159 case 3:
160 gethostname(hostname, HLEN);
161 picknewhostname(hostname, newhostname);
162 err = sethostname(newhostname, strlen(newhostname));
163 write(p2fd[1], "1", 1);
164 if (err == -1) {
165 tst_brkm(TFAIL, NULL,
166 "test 3 (%s): failed to sethostname",
167 tsttype);
168 }
169
170 zeroize(rhostname);
171 len = read(p1fd[0], rhostname, HLEN);
172 if (strcmp(newhostname, rhostname) == 0) {
173 tst_brkm(TFAIL,
174 NULL,
175 "test 3 (%s): hostname 1 %s, hostname 2 %s, these should have been different",
176 tsttype, newhostname, rhostname);
177 }
178 if (strcmp(hostname, rhostname) == 0) {
179 tst_resm(TPASS, "test 3 (%s): success", tsttype);
180 tst_exit();
181 }
182 tst_brkm(TFAIL,
183 NULL,
184 "test 3 (%s): hostname 1 %s, hostname 2 %s, should have been same",
185 tsttype, hostname, rhostname);
186
187 case 4:
188 gethostname(hostname, HLEN);
189 write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
190 zeroize(rhostname);
191 len = read(p1fd[0], rhostname, HLEN);
192 gethostname(newhostname, HLEN);
193 if (strcmp(hostname, newhostname) != 0) {
194 tst_brkm(TFAIL,
195 NULL,
196 "test 4 (%s): hostname 1 %s, hostname 2 %s, should be same",
197 tsttype, hostname, newhostname);
198 }
199 if (strcmp(hostname, rhostname) == 0) {
200 tst_brkm(TFAIL,
201 NULL,
202 "test 4 (%s): hostname 1 %s, hostname 2 %s, should be different",
203 tsttype, hostname, rhostname);
204 }
205 tst_resm(TPASS, "test 4 (%s): successful", tsttype);
206 tst_exit();
207 case 5:
208 write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
209 zeroize(rhostname);
210 len = read(p1fd[0], rhostname, HLEN);
211 gethostname(newhostname, HLEN);
212 if (strcmp(rhostname, newhostname) != 0) {
213 tst_brkm(TFAIL,
214 NULL,
215 "test 5 (%s): hostnames %s and %s should be same",
216 tsttype, rhostname, newhostname);
217 }
218 tst_resm(TPASS, "test 5 (%s): successful", tsttype);
219 tst_exit();
220 default:
221 break;
222 }
223 tst_exit();
224 }
225
P2(void * vtest)226 int P2(void *vtest)
227 {
228 char hostname[HLEN], newhostname[HLEN];
229 int len;
230 int testnum;
231
232 testnum = atoi((char *)vtest);
233
234 close(p1fd[0]);
235 close(p2fd[1]);
236
237 switch (testnum) {
238 case 1:
239 gethostname(hostname, HLEN);
240 write(p1fd[1], hostname, strlen(hostname));
241 break;
242 case 2:
243 case 3:
244 len = 0;
245 while (!len) {
246 len = read(p2fd[0], hostname, 1);
247 }
248 gethostname(hostname, HLEN);
249 write(p1fd[1], hostname, strlen(hostname));
250 break;
251 case 4:
252 case 5:
253 len = 0;
254 while (!len) {
255 len = read(p2fd[0], hostname, 1);
256 }
257 if (hostname[0] == '0') {
258 tst_resm(TPASS, "P2: P1 claims error");
259 return 0;
260 }
261 gethostname(hostname, HLEN);
262 picknewhostname(hostname, newhostname);
263 sethostname(newhostname, strlen(newhostname));
264 write(p1fd[1], newhostname, strlen(newhostname));
265 break;
266 default:
267 tst_resm(TFAIL, "undefined test: %d", testnum);
268 break;
269 }
270 return 0;
271 }
272
setup(void)273 static void setup(void)
274 {
275 gethostname(oldhost, HLEN);
276 tst_require_root();
277 check_newuts();
278 }
279
cleanup(void)280 static void cleanup(void)
281 {
282 sethostname(oldhost, strlen(oldhost));
283 }
284
285 #define UNSHARESTR "unshare"
286 #define CLONESTR "clone"
main(int argc,char * argv[])287 int main(int argc, char *argv[])
288 {
289 int r, pid, use_clone = T_UNSHARE;
290 int testnum;
291 void *vtest;
292
293 setup();
294 if (argc != 3) {
295 tst_resm(TFAIL, "Usage: %s <clone|unshare> <testnum>",
296 argv[0]);
297 tst_resm(TFAIL,
298 " where clone or unshare specifies unshare method,");
299 tst_resm(TFAIL, " and testnum is between 1 and 5 inclusive");
300 exit(2);
301 }
302 if (pipe(p1fd) == -1) {
303 perror("pipe");
304 exit(EXIT_FAILURE);
305 }
306 if (pipe(p2fd) == -1) {
307 perror("pipe");
308 exit(EXIT_FAILURE);
309 }
310
311 tsttype = UNSHARESTR;
312 if (strcmp(argv[1], "clone") == 0) {
313 use_clone = T_CLONE;
314 tsttype = CLONESTR;
315 }
316
317 testnum = atoi(argv[2]);
318
319 vtest = (void *)argv[2];
320 switch (testnum) {
321 case 1:
322 case 2:
323 r = do_clone_unshare_tests(T_NONE, 0, P1, vtest, P2, vtest);
324 break;
325 case 3:
326 case 4:
327 r = do_clone_unshare_tests(use_clone, CLONE_NEWUTS,
328 P1, vtest, P2, vtest);
329 break;
330 case 5:
331 pid = fork();
332 if (pid == -1) {
333 perror("fork");
334 exit(2);
335 }
336 if (pid == 0) {
337 if (!drop_root()) {
338 tst_brkm(TFAIL, NULL, "failed to drop root.");
339 }
340 r = do_clone_unshare_test(use_clone, CLONE_NEWUTS,
341 P1, vtest);
342 write(p2fd[1], "0", 1); /* don't let p2 hang */
343 exit(0);
344 } else {
345 P2(vtest);
346 }
347 break;
348 default:
349 tst_resm(TFAIL,
350 "testnum should be between 1 and 5 inclusive.");
351 break;
352 }
353
354 cleanup();
355 tst_exit();
356 }
357