• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 /******************************************************************************/
cleanup(void)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 /******************************************************************************/
setup(void)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 
main(int ac,char ** av)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
main(void)287 int main(void)
288 {
289 	tst_brkm(TCONF, NULL, "unshare is undefined.");
290 }
291 #endif
292