• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /*
21  * NAME
22  *	rename09
23  *
24  * DESCRIPTION
25  *      check rename() fails with EACCES
26  *
27  * ALGORITHM
28  *	Setup:
29  *		Setup signal handling.
30  *		Create temporary directory.
31  *		Pause for SIGUSR1 if option specified.
32  *
33  *	Test:
34  *		Loop if the proper options are given.
35  *              fork the first child
36  *                      set to be nobody
37  *                      create old dir with mode 0700
38  *                      creat a file under it
39  *              fork the second child
40  *                      set to bin
41  *                      create new dir with mode 0700
42  *                      create a "new" file under it
43  *                      try to rename file under old dir to file under new dir
44  *                      check the return value, if succeeded (return=0)
45  *			       Issue a FAIL message.
46  *		        Otherwise,
47  *			       Log the errno
48  *			       Verify the errno
49  *			       if equals to EACCESS,
50  *				       Issue Pass message.
51  *			       Otherwise,
52  *				       Issue Fail message.
53  *	Cleanup:
54  *		Print errno log and/or timing stats if options given
55  *		Delete the temporary directory created.
56  *
57  * USAGE
58  *	rename09 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
59  *	where,  -c n : Run n copies concurrently.
60  *		-e   : Turn on errno logging.
61  *		-i n : Execute test n times.
62  *		-I x : Execute test for x seconds.
63  *		-P x : Pause for x seconds between iterations.
64  *		-t   : Turn on syscall timing.
65  *
66  * HISTORY
67  *	07/2001 Ported by Wayne Boyer
68  *
69  * RESTRICTIONS
70  *	Must run test as root.
71  *
72  */
73 #include <errno.h>
74 #include <sys/types.h>
75 #include <sys/stat.h>
76 #include <fcntl.h>
77 #include <pwd.h>
78 #include <sys/wait.h>
79 #include <unistd.h>
80 
81 #include "test.h"
82 #include "safe_macros.h"
83 
84 void setup();
85 void cleanup();
86 
87 #define PERMS		0700
88 
89 char *TCID = "rename09";
90 int TST_TOTAL = 1;
91 
92 char fdir[255], mdir[255];
93 char fname[255], mname[255];
94 uid_t nobody_uid, bin_uid;
95 
main(int ac,char ** av)96 int main(int ac, char **av)
97 {
98 	int lc;
99 	int rval;
100 	pid_t pid, pid1;
101 	int status;
102 
103 	/*
104 	 * parse standard options
105 	 */
106 	tst_parse_opts(ac, av, NULL, NULL);
107 
108 	/*
109 	 * perform global setup for test
110 	 */
111 	setup();
112 
113 	/*
114 	 * check looping state if -i option given
115 	 */
116 	for (lc = 0; TEST_LOOPING(lc); lc++) {
117 
118 		tst_count = 0;
119 
120 		if ((pid = FORK_OR_VFORK()) == -1) {
121 			tst_brkm(TBROK, cleanup, "fork() #1 failed");
122 		}
123 
124 		if (pid == 0) {	/* first child */
125 			/* set to nobody */
126 			rval = setreuid(nobody_uid, nobody_uid);
127 			if (rval < 0) {
128 				tst_resm(TWARN, "setreuid failed to "
129 					 "to set the real uid to %d and "
130 					 "effective uid to %d",
131 					 nobody_uid, nobody_uid);
132 				perror("setreuid");
133 				exit(1);
134 			}
135 
136 			/* create the a directory with 0700 permits */
137 			if (mkdir(fdir, PERMS) == -1) {
138 				tst_resm(TWARN, "mkdir(%s, %#o) Failed",
139 					 fdir, PERMS);
140 				exit(1);
141 			}
142 
143 			/* create "old" file under it */
144 			SAFE_TOUCH(cleanup, fname, 0700, NULL);
145 
146 			exit(0);
147 		}
148 
149 		/* wait for child to exit */
150 		wait(&status);
151 		if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
152 			tst_brkm(TBROK, cleanup, "First child failed to set "
153 				 "up conditions for the test");
154 		}
155 
156 		if ((pid1 = FORK_OR_VFORK()) == -1) {
157 			tst_brkm(TBROK, cleanup, "fork() #2 failed");
158 		}
159 
160 		if (pid1 == 0) {	/* second child */
161 			/* set to bin */
162 			if ((rval = seteuid(bin_uid)) == -1) {
163 				tst_resm(TWARN, "seteuid() failed");
164 				perror("setreuid");
165 				exit(1);
166 			}
167 
168 			/* create "new" directory */
169 			if (mkdir(mdir, PERMS) == -1) {
170 				tst_resm(TWARN, "mkdir(%s, %#o) failed",
171 					 mdir, PERMS);
172 				exit(1);
173 			}
174 
175 			SAFE_TOUCH(cleanup, mname, 0700, NULL);
176 
177 			/* rename "old" to "new" */
178 			TEST(rename(fname, mname));
179 			if (TEST_RETURN != -1) {
180 				tst_resm(TFAIL, "call succeeded unexpectedly");
181 				continue;
182 			}
183 
184 			if (TEST_ERRNO != EACCES) {
185 				tst_resm(TFAIL, "Expected EACCES got %d",
186 					 TEST_ERRNO);
187 			} else {
188 				tst_resm(TPASS, "rename() returned EACCES");
189 			}
190 
191 			/* set the process id back to root */
192 			if (seteuid(0) == -1) {
193 				tst_resm(TWARN, "seteuid(0) failed");
194 				exit(1);
195 			}
196 
197 			/* clean up things in case we are looping */
198 			if (unlink(fname) == -1) {
199 				tst_brkm(TBROK, cleanup, "unlink() #1 failed");
200 			}
201 			if (unlink(mname) == -1) {
202 				tst_brkm(TBROK, cleanup, "unlink() #2 failed");
203 			}
204 			if (rmdir(fdir) == -1) {
205 				tst_brkm(TBROK, cleanup, "rmdir() #1 failed");
206 			}
207 			if (rmdir(mdir) == -1) {
208 				tst_brkm(TBROK, cleanup, "rmdir() #2 failed");
209 			}
210 		} else {
211 			/* parent - let the second child carry on */
212 			waitpid(pid1, &status, 0);
213 			if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
214 				exit(WEXITSTATUS(status));
215 			} else {
216 				exit(0);
217 			}
218 		}
219 	}
220 
221 	/*
222 	 * cleanup and exit
223 	 */
224 	cleanup();
225 	tst_exit();
226 
227 }
228 
229 /*
230  * setup() - performs all ONE TIME setup for this test.
231  */
setup(void)232 void setup(void)
233 {
234 	struct passwd *pw;
235 
236 	tst_require_root();
237 
238 	pw = SAFE_GETPWNAM(NULL, "nobody");
239 	nobody_uid = pw->pw_uid;
240 #ifndef ANDROID
241 	pw = SAFE_GETPWNAM(NULL, "bin");
242 #else
243     // user "bin" does not exist in Android kernel
244     pw = SAFE_GETPWNAM(NULL, "everybody");
245 #endif
246 	bin_uid = pw->pw_uid;
247 
248 	tst_sig(FORK, DEF_HANDLER, cleanup);
249 
250 	TEST_PAUSE;
251 
252 	/* Create a temporary directory and make it current. */
253 	tst_tmpdir();
254 
255 	umask(0);
256 
257 	sprintf(fdir, "tdir_%d", getpid());
258 	sprintf(mdir, "rndir_%d", getpid());
259 	sprintf(fname, "%s/tfile_%d", fdir, getpid());
260 	sprintf(mname, "%s/rnfile_%d", mdir, getpid());
261 }
262 
263 /*
264  * cleanup() - performs all ONE TIME cleanup for this test at
265  *             completion or premature exit.
266  */
cleanup(void)267 void cleanup(void)
268 {
269 
270 	/*
271 	 * Remove the temporary directory.
272 	 */
273 	tst_rmdir();
274 
275 	/*
276 	 * Exit with return code appropriate for results.
277 	 */
278 
279 }
280