Home | History | Annotate | Download | only in utsname
      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