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