1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Linux Test Project, 2002-2022
4 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
5 */
6
7 /*\
8 * [Description]
9 *
10 * Verify that unlink(2) fails with
11 *
12 * - EACCES when no write access to the directory containing pathname
13 * - EACCES when one of the directories in pathname did not allow search
14 * - EISDIR when deleting directory as root user
15 * - EISDIR when deleting directory as non-root user
16 */
17
18 #include <errno.h>
19 #include <pwd.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include "tst_test.h"
23
24 static struct passwd *pw;
25
26 static struct test_case_t {
27 char *name;
28 char *desc;
29 int exp_errno;
30 int exp_user;
31 } tcases[] = {
32 {"unwrite_dir/file", "unwritable directory", EACCES, 1},
33 {"unsearch_dir/file", "unsearchable directory", EACCES, 1},
34 {"regdir", "directory", EISDIR, 0},
35 {"regdir", "directory", EISDIR, 1},
36 };
37
verify_unlink(struct test_case_t * tc)38 static void verify_unlink(struct test_case_t *tc)
39 {
40 TST_EXP_FAIL(unlink(tc->name), tc->exp_errno, "%s", tc->desc);
41 }
42
do_unlink(unsigned int n)43 static void do_unlink(unsigned int n)
44 {
45 struct test_case_t *cases = &tcases[n];
46 pid_t pid;
47
48 if (cases->exp_user) {
49 pid = SAFE_FORK();
50 if (!pid) {
51 SAFE_SETUID(pw->pw_uid);
52 verify_unlink(cases);
53 exit(0);
54 }
55 SAFE_WAITPID(pid, NULL, 0);
56 } else {
57 verify_unlink(cases);
58 }
59 }
60
setup(void)61 static void setup(void)
62 {
63 SAFE_MKDIR("unwrite_dir", 0777);
64 SAFE_TOUCH("unwrite_dir/file", 0777, NULL);
65 SAFE_CHMOD("unwrite_dir", 0555);
66
67 SAFE_MKDIR("unsearch_dir", 0777);
68 SAFE_TOUCH("unsearch_dir/file", 0777, NULL);
69 SAFE_CHMOD("unsearch_dir", 0666);
70
71 SAFE_MKDIR("regdir", 0777);
72
73 pw = SAFE_GETPWNAM("nobody");
74 }
75
76 static struct tst_test test = {
77 .needs_root = 1,
78 .forks_child = 1,
79 .needs_tmpdir = 1,
80 .setup = setup,
81 .tcnt = ARRAY_SIZE(tcases),
82 .test = do_unlink,
83 };
84