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 (at) 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 62 static int dummy_child(void *v) 63 { 64 (void) v; 65 return 0; 66 } 67 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 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 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 110 void zeroize(char *s) 111 { 112 memset(s, 0, HLEN); 113 } 114 115 char *tsttype; 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 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 273 static void setup(void) 274 { 275 gethostname(oldhost, HLEN); 276 tst_require_root(); 277 check_newuts(); 278 } 279 280 static void cleanup(void) 281 { 282 sethostname(oldhost, strlen(oldhost)); 283 } 284 285 #define UNSHARESTR "unshare" 286 #define CLONESTR "clone" 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