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 "safe_macros.h" 96 #include "config.h" 97 98 char *TCID = "unshare01"; 99 int testno; 100 int TST_TOTAL = 1; 101 102 #ifdef HAVE_UNSHARE 103 104 /* Extern Global Functions */ 105 /******************************************************************************/ 106 /* */ 107 /* Function: cleanup */ 108 /* */ 109 /* Description: Performs all one time clean up for this test on successful */ 110 /* completion, premature exit or failure. Closes all temporary */ 111 /* files, removes all temporary directories exits the test with */ 112 /* appropriate return code by calling tst_exit() function. */ 113 /* */ 114 /* Input: None. */ 115 /* */ 116 /* Output: None. */ 117 /* */ 118 /* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ 119 /* On success - Exits calling tst_exit(). With '0' return code. */ 120 /* */ 121 /******************************************************************************/ 122 void cleanup(void) 123 { 124 125 tst_rmdir(); 126 } 127 128 /* Local Functions */ 129 /******************************************************************************/ 130 /* */ 131 /* Function: setup */ 132 /* */ 133 /* Description: Performs all one time setup for this test. This function is */ 134 /* typically used to capture signals, create temporary dirs */ 135 /* and temporary files that may be used in the course of this */ 136 /* test. */ 137 /* */ 138 /* Input: None. */ 139 /* */ 140 /* Output: None. */ 141 /* */ 142 /* Return: On failure - Exits by calling cleanup(). */ 143 /* On success - returns 0. */ 144 /* */ 145 /******************************************************************************/ 146 void setup(void) 147 { 148 tst_require_root(); 149 150 /* Capture signals if any */ 151 /* Create temporary directories */ 152 TEST_PAUSE; 153 tst_tmpdir(); 154 } 155 156 int main(int ac, char **av) 157 { 158 pid_t pid1; 159 int lc; 160 int rval; 161 162 tst_parse_opts(ac, av, NULL, NULL); 163 164 setup(); 165 166 for (lc = 0; TEST_LOOPING(lc); ++lc) { 167 tst_count = 0; 168 for (testno = 0; testno < TST_TOTAL; ++testno) { 169 170 pid1 = fork(); //call to fork() 171 if (pid1 == -1) { 172 tst_brkm(TFAIL | TERRNO, cleanup, 173 "fork failed"); 174 } else if (pid1 == 0) { 175 switch (unshare(CLONE_FILES)) { 176 case 0: 177 printf("unshare with CLONE_FILES call " 178 "succeeded\n"); 179 rval = 0; 180 break; 181 case -1: 182 if (errno == ENOSYS) 183 rval = 1; 184 else { 185 perror("unshare failed"); 186 rval = 2; 187 } 188 } 189 exit(rval); 190 } else { 191 SAFE_WAIT(cleanup, &rval); 192 if (rval != 0 && WIFEXITED(rval)) { 193 switch (WEXITSTATUS(rval)) { 194 case 1: 195 tst_brkm(TCONF, cleanup, 196 "unshare not supported in " 197 "kernel"); 198 break; 199 default: 200 tst_brkm(TFAIL, cleanup, 201 "unshare failed"); 202 } 203 } 204 } 205 206 pid1 = fork(); 207 if (pid1 == -1) { 208 tst_brkm(TFAIL | TERRNO, cleanup, 209 "fork failed"); 210 } else if (pid1 == 0) { 211 switch (unshare(CLONE_FS)) { 212 case 0: 213 printf("unshare with CLONE_FS call " 214 "succeeded\n"); 215 rval = 0; 216 break; 217 case -1: 218 if (errno == ENOSYS) 219 rval = 1; 220 else { 221 perror("unshare failed"); 222 rval = 2; 223 } 224 } 225 exit(rval); 226 } else { 227 SAFE_WAIT(cleanup, &rval); 228 if (rval != 0 && WIFEXITED(rval)) { 229 switch (WEXITSTATUS(rval)) { 230 case 1: 231 tst_brkm(TCONF, cleanup, 232 "unshare not supported in " 233 "kernel"); 234 break; 235 default: 236 tst_brkm(TFAIL, cleanup, 237 "unshare failed"); 238 } 239 } 240 } 241 242 pid1 = fork(); 243 if (pid1 == -1) { 244 tst_brkm(TFAIL | TERRNO, cleanup, 245 "fork() failed."); 246 } else if (pid1 == 0) { 247 switch (unshare(CLONE_NEWNS)) { 248 case 0: 249 printf("unshare call with CLONE_NEWNS " 250 "succeeded\n"); 251 rval = 0; 252 break; 253 case -1: 254 if (errno == ENOSYS) 255 rval = 1; 256 else { 257 perror("unshare failed"); 258 rval = 2; 259 } 260 } 261 exit(rval); 262 } else { 263 SAFE_WAIT(cleanup, &rval); 264 if (rval != 0 && WIFEXITED(rval)) { 265 switch (WEXITSTATUS(rval)) { 266 case 1: 267 tst_brkm(TCONF, cleanup, 268 "unshare not supported in " 269 "kernel"); 270 break; 271 default: 272 tst_brkm(TFAIL, cleanup, 273 "unshare failed"); 274 } 275 276 } 277 278 } 279 280 } 281 282 } 283 cleanup(); 284 tst_exit(); 285 } 286 #else 287 int main(void) 288 { 289 tst_brkm(TCONF, NULL, "unshare is undefined."); 290 } 291 #endif 292