Home | History | Annotate | Download | only in userns
      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 
     38 static void cleanup(void)
     39 {
     40 	tst_rmdir();
     41 }
     42 
     43 /*
     44  * child_fn1() - Inside a new user namespace
     45  */
     46 static int child_fn1(void)
     47 {
     48 	TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
     49 	return 0;
     50 }
     51 
     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 
     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 
    121 static void setup(void)
    122 {
    123 	check_newuser();
    124 
    125 	tst_tmpdir();
    126 	TST_CHECKPOINT_INIT(NULL);
    127 }
    128 
    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