1 /*
2 * Copyright (c) International Business Machines Corp., 2001
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, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * DESCRIPTION
20 * check rmdir() fails with EPERM or EACCES
21 *
22 * 1. Create a directory tstdir1 and set the sticky bit, then
23 * create directory tstdir2 under tstdir1. Call rmdir(),
24 * set to be user nobody. Pass tstdir2 to rmdir(2), verify
25 * the return value is not 0 and the errno is EPERM or EACCES.
26 *
27 * 2. Create a directory tstdir1 and doesn't give execute/search
28 * permission to nobody, then create directory tstdir2 under
29 * tstdir1. Call rmdir(), set to be user nobody. Pass
30 * tstdir2 to rmdir(2), verify the return value is not 0 and
31 * the errno is EACCES.
32 */
33 #include <errno.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <pwd.h>
37 #include <unistd.h>
38 #include "tst_test.h"
39
40 #define DIR_MODE 0777
41 #define NOEXCUTE_MODE 0766
42 #define TESTDIR "testdir"
43 #define TESTDIR2 "testdir/testdir2"
44 #define TESTDIR3 "testdir3"
45 #define TESTDIR4 "testdir3/testdir4"
46
47 static struct testcase {
48 mode_t dir_mode;
49 char *subdir;
50 } tcases[] = {
51 {DIR_MODE | S_ISVTX, TESTDIR2},
52 {NOEXCUTE_MODE, TESTDIR4},
53 };
54
do_rmdir(unsigned int n)55 static void do_rmdir(unsigned int n)
56 {
57 struct testcase *tc = &tcases[n];
58
59 TEST(rmdir(tc->subdir));
60 if (TST_RET != -1) {
61 tst_res(TFAIL, "rmdir() succeeded unexpectedly");
62 return;
63 }
64
65 if (TST_ERR != EACCES) {
66 if (tc->dir_mode & S_ISVTX && TST_ERR == EPERM)
67 tst_res(TPASS | TTERRNO, "rmdir() got expected errno");
68 else
69 tst_res(TFAIL | TTERRNO, "expected EPERM, but got");
70 return;
71 }
72
73 tst_res(TPASS | TTERRNO, "rmdir() got expected errno");
74 }
75
76
setup(void)77 static void setup(void)
78 {
79 struct passwd *pw;
80 pw = SAFE_GETPWNAM("nobody");
81
82 umask(0);
83
84 SAFE_MKDIR(TESTDIR, DIR_MODE | S_ISVTX);
85 SAFE_MKDIR(TESTDIR2, DIR_MODE);
86 SAFE_MKDIR(TESTDIR3, NOEXCUTE_MODE);
87 SAFE_MKDIR(TESTDIR4, DIR_MODE);
88
89 SAFE_SETEUID(pw->pw_uid);
90 }
91
cleanup(void)92 static void cleanup(void)
93 {
94 SAFE_SETEUID(0);
95 }
96
97 static struct tst_test test = {
98 .setup = setup,
99 .cleanup = cleanup,
100 .tcnt = ARRAY_SIZE(tcases),
101 .test = do_rmdir,
102 .needs_root = 1,
103 .needs_tmpdir = 1,
104 };
105
106