1 /*************************************************************************/ 2 /* Copyright (c) Crackerjack Project., 2007 */ 3 /* */ 4 /* This program is free software; you can redistribute it and/or modify */ 5 /* it under the terms of the GNU General Public License as published by */ 6 /* the Free Software Foundation; either version 2 of the License, or */ 7 /* (at your option) any later version. */ 8 /* */ 9 /* This program is distributed in the hope that it will be useful, */ 10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 12 /* the GNU General Public License for more details. */ 13 /* */ 14 /* You should have received a copy of the GNU General Public License */ 15 /* along with this program; if not, write to the Free Software */ 16 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/ 17 /* */ 18 /*************************************************************************/ 19 /*************************************************************************/ 20 /* */ 21 /* File: unshare01.c */ 22 /* */ 23 /* Description: This tests the unshare() syscall. */ 24 /* unshare() allows a process to disassociate parts of its */ 25 /* execution context that are currently being shared with other */ 26 /* processes. Part of the execution context, such as the namespace */ 27 /* ,is shared implicitly when a new process is created using */ 28 /* fork(2) or vfork(2), while other parts, such as virtual memory */ 29 /* , may be shared by explicit request when creating a process */ 30 /* using clone(2). */ 31 /* */ 32 /* The main use of unshare() is to allow a process to control its */ 33 /* shared execution context without creating a new process. */ 34 /* */ 35 /* */ 36 /* The flags argument is a bit mask that specifies which parts of */ 37 /* the execution context should be unshared. This argument is */ 38 /* specified by ORing together zero or more of the following cons- */ 39 /* tants: */ 40 /* */ 41 /* CLONE_FILES: */ 42 /* Reverse the effect of the clone(2) CLONE_FILES flag. */ 43 /* Unshare the file descriptor table, so that the calling */ 44 /* process no longer shares its file descriptors with any */ 45 /* other process. */ 46 /* CLONE_FS: */ 47 /* Reverse the effect of the clone(2) CLONE_FS flag.Unshare*/ 48 /* file system attributes, so that the calling process no */ 49 /* longer shares its root directory, current directory, or */ 50 /* umask attributes with any other process. */ 51 /* CLONE_NEWNS: */ 52 /* This flag has the same effect as the clone(2) CLONE_NEWNS*/ 53 /* flag. Unshare the namespace, so that the calling process*/ 54 /* has a private copy of its namespacei which is not shared*/ 55 /* with any other process. Specifying this flag automat- */ 56 /* ically implies CLONE_FS as well. */ 57 /* */ 58 /* If flags is specified as zero, then unshare() is a no-op; no */ 59 /* changes are made to the calling process's execution context. */ 60 /* */ 61 /* Usage: <for command-line> */ 62 /* unshare01 [-c n] [-e][-i n] [-I x] [-p x] [-t] */ 63 /* where, -c n : Run n copies concurrently. */ 64 /* -e : Turn on errno logging. */ 65 /* -i n : Execute test n times. */ 66 /* -I x : Execute test for x seconds. */ 67 /* -P x : Pause for x seconds between iterations. */ 68 /* -t : Turn on syscall timing. */ 69 /* */ 70 /* Total Tests: 1 */ 71 /* */ 72 /* Test Name: unshare01 */ 73 /* History: Porting from Crackerjack to LTP is done by */ 74 /* Manas Kumar Nayak maknayak (at) in.ibm.com> */ 75 /********************************************************************************/ 76 77 #define _GNU_SOURCE 78 79 #include <stdio.h> 80 #include <sys/wait.h> 81 #include <sys/types.h> 82 #include <sched.h> 83 #include <limits.h> 84 #include <unistd.h> 85 #include <sys/types.h> 86 #include <sys/syscall.h> 87 #include <errno.h> 88 #include <pwd.h> 89 #include <grp.h> 90 #include <string.h> 91 #include <sys/param.h> 92 #include <stdio.h> 93 94 #include "test.h" 95 #include "config.h" 96 97 char *TCID = "unshare01"; 98 int testno; 99 int TST_TOTAL = 1; 100 101 #ifdef HAVE_UNSHARE 102 103 /* Extern Global Functions */ 104 /******************************************************************************/ 105 /* */ 106 /* Function: cleanup */ 107 /* */ 108 /* Description: Performs all one time clean up for this test on successful */ 109 /* completion, premature exit or failure. Closes all temporary */ 110 /* files, removes all temporary directories exits the test with */ 111 /* appropriate return code by calling tst_exit() function. */ 112 /* */ 113 /* Input: None. */ 114 /* */ 115 /* Output: None. */ 116 /* */ 117 /* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ 118 /* On success - Exits calling tst_exit(). With '0' return code. */ 119 /* */ 120 /******************************************************************************/ 121 void cleanup(void) 122 { 123 124 tst_rmdir(); 125 } 126 127 /* Local Functions */ 128 /******************************************************************************/ 129 /* */ 130 /* Function: setup */ 131 /* */ 132 /* Description: Performs all one time setup for this test. This function is */ 133 /* typically used to capture signals, create temporary dirs */ 134 /* and temporary files that may be used in the course of this */ 135 /* test. */ 136 /* */ 137 /* Input: None. */ 138 /* */ 139 /* Output: None. */ 140 /* */ 141 /* Return: On failure - Exits by calling cleanup(). */ 142 /* On success - returns 0. */ 143 /* */ 144 /******************************************************************************/ 145 void setup(void) 146 { 147 tst_require_root(); 148 149 /* Capture signals if any */ 150 /* Create temporary directories */ 151 TEST_PAUSE; 152 tst_tmpdir(); 153 } 154 155 int main(int ac, char **av) 156 { 157 pid_t pid1; 158 int lc; 159 int rval; 160 161 tst_parse_opts(ac, av, NULL, NULL); 162 163 setup(); 164 165 for (lc = 0; TEST_LOOPING(lc); ++lc) { 166 tst_count = 0; 167 for (testno = 0; testno < TST_TOTAL; ++testno) { 168 169 pid1 = fork(); //call to fork() 170 if (pid1 == -1) { 171 tst_brkm(TFAIL | TERRNO, cleanup, 172 "fork failed"); 173 } else if (pid1 == 0) { 174 switch (unshare(CLONE_FILES)) { 175 case 0: 176 printf("unshare with CLONE_FILES call " 177 "succeeded\n"); 178 rval = 0; 179 break; 180 case -1: 181 if (errno == ENOSYS) 182 rval = 1; 183 else { 184 perror("unshare failed"); 185 rval = 2; 186 } 187 } 188 exit(rval); 189 } else { 190 if (wait(&rval) == -1) 191 tst_brkm(TBROK | TERRNO, cleanup, 192 "wait failed"); 193 if (rval != 0 && WIFEXITED(rval)) { 194 switch (WEXITSTATUS(rval)) { 195 case 1: 196 tst_brkm(TCONF, cleanup, 197 "unshare not supported in " 198 "kernel"); 199 break; 200 default: 201 tst_brkm(TFAIL, cleanup, 202 "unshare failed"); 203 } 204 } 205 } 206 207 pid1 = fork(); 208 if (pid1 == -1) { 209 tst_brkm(TFAIL | TERRNO, cleanup, 210 "fork failed"); 211 } else if (pid1 == 0) { 212 switch (unshare(CLONE_FS)) { 213 case 0: 214 printf("unshare with CLONE_FS call " 215 "succeeded\n"); 216 rval = 0; 217 break; 218 case -1: 219 if (errno == ENOSYS) 220 rval = 1; 221 else { 222 perror("unshare failed"); 223 rval = 2; 224 } 225 } 226 exit(rval); 227 } else { 228 if (wait(&rval) == -1) 229 tst_brkm(TBROK | TERRNO, cleanup, 230 "wait failed"); 231 if (rval != 0 && WIFEXITED(rval)) { 232 switch (WEXITSTATUS(rval)) { 233 case 1: 234 tst_brkm(TCONF, cleanup, 235 "unshare not supported in " 236 "kernel"); 237 break; 238 default: 239 tst_brkm(TFAIL, cleanup, 240 "unshare failed"); 241 } 242 } 243 } 244 245 pid1 = fork(); 246 if (pid1 == -1) { 247 tst_brkm(TFAIL | TERRNO, cleanup, 248 "fork() failed."); 249 } else if (pid1 == 0) { 250 switch (unshare(CLONE_NEWNS)) { 251 case 0: 252 printf("unshare call with CLONE_NEWNS " 253 "succeeded\n"); 254 rval = 0; 255 break; 256 case -1: 257 if (errno == ENOSYS) 258 rval = 1; 259 else { 260 perror("unshare failed"); 261 rval = 2; 262 } 263 } 264 exit(rval); 265 } else { 266 if (wait(&rval) == -1) 267 tst_brkm(TBROK | TERRNO, cleanup, 268 "wait failed"); 269 if (rval != 0 && WIFEXITED(rval)) { 270 switch (WEXITSTATUS(rval)) { 271 case 1: 272 tst_brkm(TCONF, cleanup, 273 "unshare not supported in " 274 "kernel"); 275 break; 276 default: 277 tst_brkm(TFAIL, cleanup, 278 "unshare failed"); 279 } 280 281 } 282 283 } 284 285 } 286 287 } 288 cleanup(); 289 tst_exit(); 290 } 291 #else 292 int main(void) 293 { 294 tst_brkm(TCONF, NULL, "unshare is undefined."); 295 } 296 #endif 297