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