blob: f391d2b7fa3912db5df5c892fd83f01488c7d0dc [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * NAME
22 * rmdir03
23 *
24 * DESCRIPTION
25 * check rmdir() fails with EPERM or EACCES
26 *
27 * ALGORITHM
28 * Setup:
29 * Setup signal handling.
30 * Pause for SIGUSR1 if option specified.
31 * Create temporary directory.
32 *
33 * Test:
34 * Loop if the proper options are given.
subrata_modak4bb656a2009-02-26 12:02:09 +000035 * 1. create a directory tstdir1 and set the sticky bit, then
36 * create directory tstdir2 under tstdir1. Fork a
plars865695b2001-08-27 22:15:12 +000037 * child , set to be user nobody. Pass tstdir2 to rmdir(2).
robbiewf6addef2004-04-14 21:42:09 +000038 * Verify the return value is not 0 and the errno is EPERM
39 * or EACCES.
subrata_modak4bb656a2009-02-26 12:02:09 +000040 * 2. Fork a child, set to be user nobody. Create a directory
plars865695b2001-08-27 22:15:12 +000041 * tstdir1 and only give write permission to nobody.
subrata_modak4bb656a2009-02-26 12:02:09 +000042 * Create directory tstdir2 under tstdir1. Fork the second
plars865695b2001-08-27 22:15:12 +000043 * child , set to be user nobody. Pass tstdir2 to rmdir(2).
44 * Verify the return value is not 0 and the errno is EACCES.
45 *
46 * Cleanup:
47 * Print errno log and/or timing stats if options given
48 * Delete the temporary directory created.
49 *
50 * USAGE
51 * rmdir03 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
52 * where, -c n : Run n copies concurrently.
53 * -e : Turn on errno logging.
54 * -i n : Execute test n times.
55 * -I x : Execute test for x seconds.
56 * -P x : Pause for x seconds between iterations.
57 * -t : Turn on syscall timing.
58 *
59 * HISTORY
60 * 07/2001 Ported by Wayne Boyer
61 *
62 * RESTRICTIONS
63 * Test must be run as root.
64 *
65 */
66#include <errno.h>
67#include <string.h>
68#include <sys/stat.h>
69#include <sys/types.h>
plars74948ad2002-11-14 16:16:14 +000070#include <sys/wait.h>
plars865695b2001-08-27 22:15:12 +000071#include <fcntl.h>
72#include <pwd.h>
73#include <unistd.h>
subrata_modak4bb656a2009-02-26 12:02:09 +000074#include "test.h"
plars865695b2001-08-27 22:15:12 +000075
robbiewd34d5812005-07-11 22:28:09 +000076void dochild1();
77void dochild2();
plars865695b2001-08-27 22:15:12 +000078void setup();
79void cleanup();
subrata_modak56207ce2009-03-23 13:35:39 +000080extern struct passwd *my_getpwnam(char *);
plars865695b2001-08-27 22:15:12 +000081
82#define PERMS 0777
83
84char user1name[] = "nobody";
85
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020086char *TCID = "rmdir03";
87int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000088
89char tstdir1[255];
90char tstdir2[255];
91char tstdir3[255];
92char tstdir4[255];
93
subrata_modak56207ce2009-03-23 13:35:39 +000094int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000095{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020096 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020097 const char *msg;
plars865695b2001-08-27 22:15:12 +000098 pid_t pid;
plars865695b2001-08-27 22:15:12 +000099 struct stat buf1;
robbiewd34d5812005-07-11 22:28:09 +0000100 int e_code, status, status2;
plars865695b2001-08-27 22:15:12 +0000101
102 /*
103 * parse standard options
104 */
Garrett Cooper45e285d2010-11-22 12:19:25 -0800105 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
Garrett Cooper60fa8012010-11-22 13:50:58 -0800106 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
plars865695b2001-08-27 22:15:12 +0000107 }
robbiewd34d5812005-07-11 22:28:09 +0000108#ifdef UCLINUX
109 maybe_run_child(&dochild1, "ns", 1, tstdir2);
110 maybe_run_child(&dochild2, "ns", 2, tstdir4);
111#endif
112
plars865695b2001-08-27 22:15:12 +0000113 /*
114 * perform global setup for test
115 */
116 setup();
subrata_modakbdbaec52009-02-26 12:14:51 +0000117
plars865695b2001-08-27 22:15:12 +0000118 /*
119 * check looping state if -i option given
120 */
subrata_modak56207ce2009-03-23 13:35:39 +0000121 for (lc = 0; TEST_LOOPING(lc); lc++) {
plars865695b2001-08-27 22:15:12 +0000122
Caspar Zhangd59a6592013-03-07 14:59:12 +0800123 tst_count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000124
125//test1: $
subrata_modak4bb656a2009-02-26 12:02:09 +0000126 /*
127 * attempt to rmdir a file whose parent directory has
plars865695b2001-08-27 22:15:12 +0000128 * the sticky bit set without the root right
129 * or effective uid
130 */
131
132 if (stat(tstdir1, &buf1) != -1) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000133 tst_brkm(TBROK, cleanup,
plars865695b2001-08-27 22:15:12 +0000134 "tmp directory %s found!", tstdir1);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800135 }
plars865695b2001-08-27 22:15:12 +0000136 /* create a directory */
137 if (mkdir(tstdir1, PERMS) == -1) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000138 tst_brkm(TBROK, cleanup,
subrata_modak56207ce2009-03-23 13:35:39 +0000139 "Couldnot create directory %s", tstdir1);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 }
subrata_modak56207ce2009-03-23 13:35:39 +0000141 if (stat(tstdir1, &buf1) == -1) {
plars865695b2001-08-27 22:15:12 +0000142 perror("stat");
143 tst_brkm(TBROK, cleanup, "failed to stat directory %s "
144 "in rmdir()", tstdir1);
Garrett Cooper2c282152010-12-16 00:55:50 -0800145
plars865695b2001-08-27 22:15:12 +0000146 }
147 /* set the sticky bit */
subrata_modak56207ce2009-03-23 13:35:39 +0000148 if (chmod(tstdir1, buf1.st_mode | S_ISVTX) != 0) {
plars865695b2001-08-27 22:15:12 +0000149 perror("chmod");
150 tst_brkm(TBROK, cleanup,
151 "failed to set the S_ISVTX bit");
Garrett Cooper2c282152010-12-16 00:55:50 -0800152
subrata_modak56207ce2009-03-23 13:35:39 +0000153 }
plars865695b2001-08-27 22:15:12 +0000154 /* create a sub directory under tstdir1 */
155 if (mkdir(tstdir2, PERMS) == -1) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000156 tst_brkm(TBROK, cleanup,
plars865695b2001-08-27 22:15:12 +0000157 "Could not create directory %s", tstdir2);
158 }
159
robbiewd34d5812005-07-11 22:28:09 +0000160 if ((pid = FORK_OR_VFORK()) == -1) {
plars865695b2001-08-27 22:15:12 +0000161 tst_brkm(TBROK, cleanup, "fork() failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800162 }
plars865695b2001-08-27 22:15:12 +0000163
subrata_modak56207ce2009-03-23 13:35:39 +0000164 if (pid == 0) { /* first child */
robbiewd34d5812005-07-11 22:28:09 +0000165#ifdef UCLINUX
166 if (self_exec(av[0], "ns", 1, tstdir2) < 0) {
167 tst_brkm(TBROK, cleanup, "self_exec failed");
plars865695b2001-08-27 22:15:12 +0000168 }
robbiewd34d5812005-07-11 22:28:09 +0000169#else
170 dochild1();
171#endif
plars865695b2001-08-27 22:15:12 +0000172 }
plars8ccf65e2001-09-14 21:56:23 +0000173 /* Parent */
plars865695b2001-08-27 22:15:12 +0000174
subrata_modak56207ce2009-03-23 13:35:39 +0000175//test2: $
plars865695b2001-08-27 22:15:12 +0000176 /* create the a directory with 0700 permits */
177 if (mkdir(tstdir3, 0700) == -1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000178 tst_brkm(TBROK, cleanup, "mkdir(%s, %#o) Failed",
179 tstdir3, PERMS);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800180 }
plars865695b2001-08-27 22:15:12 +0000181 /* create the a directory with 0700 permits */
182 if (mkdir(tstdir4, 0777) == -1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000183 tst_brkm(TBROK, cleanup, "mkdir(%s, %#o) Failed",
184 tstdir4, PERMS);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800185 }
plars865695b2001-08-27 22:15:12 +0000186
vapier62b16cf2007-02-09 20:48:23 +0000187 if ((pid = FORK_OR_VFORK()) == -1) {
plars865695b2001-08-27 22:15:12 +0000188 tst_brkm(TBROK, cleanup, "fork() failed");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800189 }
plars865695b2001-08-27 22:15:12 +0000190
subrata_modak56207ce2009-03-23 13:35:39 +0000191 if (pid == 0) { /* child */
robbiewd34d5812005-07-11 22:28:09 +0000192#ifdef UCLINUX
193 if (self_exec(av[0], "ns", 2, tstdir4) < 0) {
194 tst_brkm(TBROK, cleanup, "self_exec failed");
plars865695b2001-08-27 22:15:12 +0000195 }
robbiewd34d5812005-07-11 22:28:09 +0000196#else
197 dochild2();
198#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000199 } else { /* parent */
200 /* wait for the child to finish */
201 wait(&status);
202 wait(&status2);
203 /* make sure the child returned a good exit status */
204 e_code = status >> 8;
205 if (e_code != 0) {
206 tst_resm(TFAIL, "Failures reported above");
207 } else {
plars8ccf65e2001-09-14 21:56:23 +0000208 /* No error in the 1st one, check the 2nd */
subrata_modak56207ce2009-03-23 13:35:39 +0000209 e_code = status2 >> 8;
210 if (e_code != 0) {
211 tst_resm(TFAIL,
212 "Failures reported above");
plars8ccf65e2001-09-14 21:56:23 +0000213 }
214 }
plars865695b2001-08-27 22:15:12 +0000215 }
216
217 /* clean up things in case we are looping */
218
219 (void)rmdir(tstdir2);
220 (void)rmdir(tstdir1);
221 (void)rmdir(tstdir4);
222 (void)rmdir(tstdir3);
223
Garrett Cooper2c282152010-12-16 00:55:50 -0800224 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000225
plars865695b2001-08-27 22:15:12 +0000226 /*
227 * cleanup and exit
228 */
229 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800230 tst_exit();
subrata_modakbdbaec52009-02-26 12:14:51 +0000231
Garrett Cooper2c282152010-12-16 00:55:50 -0800232}
plars865695b2001-08-27 22:15:12 +0000233
234/*
robbiewd34d5812005-07-11 22:28:09 +0000235 * dochild1()
236 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400237void dochild1(void)
robbiewd34d5812005-07-11 22:28:09 +0000238{
239 int retval = 0;
240 struct passwd *nobody = my_getpwnam(user1name);
241
242 /* set to nobody */
243 if (seteuid(nobody->pw_uid) == -1) {
244 retval = 1;
245 tst_brkm(TBROK, cleanup, "setreuid failed to "
246 "set effective uid to %d", nobody->pw_uid);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800247 }
subrata_modak56207ce2009-03-23 13:35:39 +0000248
249 /* rmdir tstdir2 */
250 TEST(rmdir(tstdir2));
251
252 if (TEST_ERRNO) {
robbiewd34d5812005-07-11 22:28:09 +0000253 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000254
subrata_modak56207ce2009-03-23 13:35:39 +0000255 if (TEST_RETURN != -1) {
256 retval = 1;
257 tst_resm(TFAIL, "call succeeded unexpectedly");
258 } else if ((TEST_ERRNO != EPERM) && (TEST_ERRNO != EACCES)) {
259 retval = 1;
260 tst_resm(TFAIL, "Expected EPERM or EACCES, got %d", TEST_ERRNO);
261 } else {
262 tst_resm(TPASS, "rmdir() produced EPERM or EACCES");
263 }
264
265 if (seteuid(0) == -1) {
266 retval = 1;
267 tst_brkm(TBROK, cleanup, "seteuid(0) failed");
268 }
269 exit(retval);
270 /* END of child 1 (test1) */
271}
272
273/*
274 * dochild1()
275 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400276void dochild2(void)
subrata_modak56207ce2009-03-23 13:35:39 +0000277{
278 int retval = 0;
279 struct passwd *nobody = my_getpwnam(user1name);
280
281 /* set to nobody */
282 if (seteuid(nobody->pw_uid) == -1) {
283 retval = 1;
284 tst_brkm(TBROK, cleanup, "setreuid failed to "
285 "set effective uid to %d", nobody->pw_uid);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800286 }
subrata_modak56207ce2009-03-23 13:35:39 +0000287
288 /* rmdir tstdir4 */
robbiewd34d5812005-07-11 22:28:09 +0000289 TEST(rmdir(tstdir4));
subrata_modakbdbaec52009-02-26 12:14:51 +0000290
robbiewd34d5812005-07-11 22:28:09 +0000291 if (TEST_ERRNO) {
robbiewd34d5812005-07-11 22:28:09 +0000292 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000293
robbiewd34d5812005-07-11 22:28:09 +0000294 if (TEST_RETURN != -1) {
295 retval = 1;
296 tst_resm(TFAIL, "call succeeded unexpectedly");
297 } else if (TEST_ERRNO != EACCES) {
298 retval = 1;
299 tst_resm(TFAIL, "Expected EACCES got %d", TEST_ERRNO);
300 } else {
301 tst_resm(TPASS, "rmdir() produced EACCES");
302 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000303
robbiewd34d5812005-07-11 22:28:09 +0000304 if (seteuid(0) == -1) {
305 retval = 1;
306 tst_brkm(TBROK, cleanup, "seteuid(0) failed");
307 }
308 exit(retval);
309}
310
311/*
plars865695b2001-08-27 22:15:12 +0000312 * setup() - performs all ONE TIME setup for this test.
313 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400314void setup(void)
plars865695b2001-08-27 22:15:12 +0000315{
Nicolas Jolyd4ceb372014-06-22 17:03:57 +0200316 tst_require_root(NULL);
plars865695b2001-08-27 22:15:12 +0000317
plars865695b2001-08-27 22:15:12 +0000318 tst_sig(FORK, DEF_HANDLER, cleanup);
319
plars865695b2001-08-27 22:15:12 +0000320 TEST_PAUSE;
321
322 /* Create a temporary directory and make it current. */
323 tst_tmpdir();
324
plars865695b2001-08-27 22:15:12 +0000325 umask(0);
subrata_modakbdbaec52009-02-26 12:14:51 +0000326
subrata_modak56207ce2009-03-23 13:35:39 +0000327 sprintf(tstdir1, "./tstdir1_%d", getpid());
328 sprintf(tstdir2, "%s/tstdir2_%d", tstdir1, getpid());
329 sprintf(tstdir3, "./tstdir3_%d", getpid());
330 sprintf(tstdir4, "%s/tstdir3_%d", tstdir3, getpid());
plars865695b2001-08-27 22:15:12 +0000331}
332
333/*
334 * cleanup() - performs all ONE TIME cleanup for this test at
335 * completion or premature exit.
336 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400337void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000338{
plars865695b2001-08-27 22:15:12 +0000339
340 /*
341 * Remove the temporary directory.
342 */
343 tst_rmdir();
subrata_modakbdbaec52009-02-26 12:14:51 +0000344
plars865695b2001-08-27 22:15:12 +0000345 /*
346 * Exit with return code appropriate for results.
347 */
Garrett Cooper2c282152010-12-16 00:55:50 -0800348
Chris Dearmanec6edca2012-10-17 19:54:01 -0700349}