1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * Copyright (c) Linux Test Project, 2003-2023
5 * Author: William Roske
6 */
7
8 /*\
9 * [Description]
10 *
11 * Basic test for access(2) using F_OK, R_OK, W_OK and X_OK
12 */
13
14 #include <errno.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <pwd.h>
18 #include "tst_test.h"
19
20 #define FNAME_RWX "accessfile_rwx"
21 #define FNAME_R "accessfile_r"
22 #define FNAME_W "accessfile_w"
23 #define FNAME_X "accessfile_x"
24
25 #define DNAME_R "accessdir_r"
26 #define DNAME_W "accessdir_w"
27 #define DNAME_X "accessdir_x"
28 #define DNAME_RW "accessdir_rw"
29 #define DNAME_RX "accessdir_rx"
30 #define DNAME_WX "accessdir_wx"
31
32 static uid_t uid;
33
34 static struct tcase {
35 const char *fname;
36 int mode;
37 char *name;
38 int exp_errno;
39 /* 1: nobody expected 2: root expected 3: both */
40 int exp_user;
41 } tcases[] = {
42 {FNAME_RWX, F_OK, "F_OK", 0, 3},
43 {FNAME_RWX, X_OK, "X_OK", 0, 3},
44 {FNAME_RWX, W_OK, "W_OK", 0, 3},
45 {FNAME_RWX, R_OK, "R_OK", 0, 3},
46
47 {FNAME_RWX, R_OK|W_OK, "R_OK|W_OK", 0, 3},
48 {FNAME_RWX, R_OK|X_OK, "R_OK|X_OK", 0, 3},
49 {FNAME_RWX, W_OK|X_OK, "W_OK|X_OK", 0, 3},
50 {FNAME_RWX, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", 0, 3},
51
52 {FNAME_X, X_OK, "X_OK", 0, 3},
53 {FNAME_W, W_OK, "W_OK", 0, 3},
54 {FNAME_R, R_OK, "R_OK", 0, 3},
55
56 {FNAME_R, X_OK, "X_OK", EACCES, 3},
57 {FNAME_R, W_OK, "W_OK", EACCES, 1},
58 {FNAME_W, R_OK, "R_OK", EACCES, 1},
59 {FNAME_W, X_OK, "X_OK", EACCES, 3},
60 {FNAME_X, R_OK, "R_OK", EACCES, 1},
61 {FNAME_X, W_OK, "W_OK", EACCES, 1},
62
63 {FNAME_R, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
64 {FNAME_R, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
65 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
66 {FNAME_R, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
67
68 {FNAME_W, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
69 {FNAME_W, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
70 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
71 {FNAME_W, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
72
73 {FNAME_X, W_OK|X_OK, "W_OK|X_OK", EACCES, 1},
74 {FNAME_X, R_OK|X_OK, "R_OK|X_OK", EACCES, 1},
75 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
76 {FNAME_X, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 1},
77
78 {FNAME_R, W_OK, "W_OK", 0, 2},
79 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", 0, 2},
80
81 {FNAME_W, R_OK, "R_OK", 0, 2},
82 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", 0, 2},
83
84 {FNAME_X, R_OK, "R_OK", 0, 2},
85 {FNAME_X, W_OK, "W_OK", 0, 2},
86 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", 0, 2},
87
88 {DNAME_R"/"FNAME_R, F_OK, "F_OK", 0, 2},
89 {DNAME_R"/"FNAME_R, R_OK, "R_OK", 0, 2},
90 {DNAME_R"/"FNAME_R, W_OK, "W_OK", 0, 2},
91
92 {DNAME_R"/"FNAME_W, F_OK, "F_OK", 0, 2},
93 {DNAME_R"/"FNAME_W, R_OK, "R_OK", 0, 2},
94 {DNAME_R"/"FNAME_W, W_OK, "W_OK", 0, 2},
95
96 {DNAME_R"/"FNAME_X, F_OK, "F_OK", 0, 2},
97 {DNAME_R"/"FNAME_X, R_OK, "R_OK", 0, 2},
98 {DNAME_R"/"FNAME_X, W_OK, "W_OK", 0, 2},
99 {DNAME_R"/"FNAME_X, X_OK, "X_OK", 0, 2},
100
101 {DNAME_W"/"FNAME_R, F_OK, "F_OK", 0, 2},
102 {DNAME_W"/"FNAME_R, R_OK, "R_OK", 0, 2},
103 {DNAME_W"/"FNAME_R, W_OK, "W_OK", 0, 2},
104
105 {DNAME_W"/"FNAME_W, F_OK, "F_OK", 0, 2},
106 {DNAME_W"/"FNAME_W, R_OK, "R_OK", 0, 2},
107 {DNAME_W"/"FNAME_W, W_OK, "W_OK", 0, 2},
108
109 {DNAME_W"/"FNAME_X, F_OK, "F_OK", 0, 2},
110 {DNAME_W"/"FNAME_X, R_OK, "R_OK", 0, 2},
111 {DNAME_W"/"FNAME_X, W_OK, "W_OK", 0, 2},
112 {DNAME_W"/"FNAME_X, X_OK, "X_OK", 0, 2},
113
114 {DNAME_X"/"FNAME_R, F_OK, "F_OK", 0, 3},
115 {DNAME_X"/"FNAME_R, R_OK, "R_OK", 0, 3},
116 {DNAME_X"/"FNAME_R, W_OK, "W_OK", 0, 2},
117
118 {DNAME_X"/"FNAME_W, F_OK, "F_OK", 0, 3},
119 {DNAME_X"/"FNAME_W, R_OK, "R_OK", 0, 2},
120 {DNAME_X"/"FNAME_W, W_OK, "W_OK", 0, 3},
121
122 {DNAME_X"/"FNAME_X, F_OK, "F_OK", 0, 3},
123 {DNAME_X"/"FNAME_X, R_OK, "R_OK", 0, 2},
124 {DNAME_X"/"FNAME_X, W_OK, "W_OK", 0, 2},
125 {DNAME_X"/"FNAME_X, X_OK, "X_OK", 0, 3},
126
127 {DNAME_RW"/"FNAME_R, F_OK, "F_OK", 0, 2},
128 {DNAME_RW"/"FNAME_R, R_OK, "R_OK", 0, 2},
129 {DNAME_RW"/"FNAME_R, W_OK, "W_OK", 0, 2},
130
131 {DNAME_RW"/"FNAME_W, F_OK, "F_OK", 0, 2},
132 {DNAME_RW"/"FNAME_W, R_OK, "R_OK", 0, 2},
133 {DNAME_RW"/"FNAME_W, W_OK, "W_OK", 0, 2},
134
135 {DNAME_RW"/"FNAME_X, F_OK, "F_OK", 0, 2},
136 {DNAME_RW"/"FNAME_X, R_OK, "R_OK", 0, 2},
137 {DNAME_RW"/"FNAME_X, W_OK, "W_OK", 0, 2},
138 {DNAME_RW"/"FNAME_X, X_OK, "X_OK", 0, 2},
139
140 {DNAME_RX"/"FNAME_R, F_OK, "F_OK", 0, 3},
141 {DNAME_RX"/"FNAME_R, R_OK, "R_OK", 0, 3},
142 {DNAME_RX"/"FNAME_R, W_OK, "W_OK", 0, 2},
143
144 {DNAME_RX"/"FNAME_W, F_OK, "F_OK", 0, 3},
145 {DNAME_RX"/"FNAME_W, R_OK, "R_OK", 0, 2},
146 {DNAME_RX"/"FNAME_W, W_OK, "W_OK", 0, 3},
147
148 {DNAME_RX"/"FNAME_X, F_OK, "F_OK", 0, 3},
149 {DNAME_RX"/"FNAME_X, R_OK, "R_OK", 0, 2},
150 {DNAME_RX"/"FNAME_X, W_OK, "W_OK", 0, 2},
151 {DNAME_RX"/"FNAME_X, X_OK, "X_OK", 0, 3},
152
153 {DNAME_WX"/"FNAME_R, F_OK, "F_OK", 0, 3},
154 {DNAME_WX"/"FNAME_R, R_OK, "R_OK", 0, 3},
155 {DNAME_WX"/"FNAME_R, W_OK, "W_OK", 0, 2},
156
157 {DNAME_WX"/"FNAME_W, F_OK, "F_OK", 0, 3},
158 {DNAME_WX"/"FNAME_W, R_OK, "R_OK", 0, 2},
159 {DNAME_WX"/"FNAME_W, W_OK, "W_OK", 0, 3},
160
161 {DNAME_WX"/"FNAME_X, F_OK, "F_OK", 0, 3},
162 {DNAME_WX"/"FNAME_X, R_OK, "R_OK", 0, 2},
163 {DNAME_WX"/"FNAME_X, W_OK, "W_OK", 0, 2},
164 {DNAME_WX"/"FNAME_X, X_OK, "X_OK", 0, 3},
165
166 {DNAME_R"/"FNAME_R, F_OK, "F_OK", EACCES, 1},
167 {DNAME_R"/"FNAME_R, R_OK, "R_OK", EACCES, 1},
168 {DNAME_R"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
169 {DNAME_R"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
170
171 {DNAME_R"/"FNAME_W, F_OK, "F_OK", EACCES, 1},
172 {DNAME_R"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
173 {DNAME_R"/"FNAME_W, W_OK, "W_OK", EACCES, 1},
174 {DNAME_R"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
175
176 {DNAME_R"/"FNAME_X, F_OK, "F_OK", EACCES, 1},
177 {DNAME_R"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
178 {DNAME_R"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
179 {DNAME_R"/"FNAME_X, X_OK, "X_OK", EACCES, 1},
180
181 {DNAME_W"/"FNAME_R, F_OK, "F_OK", EACCES, 1},
182 {DNAME_W"/"FNAME_R, R_OK, "R_OK", EACCES, 1},
183 {DNAME_W"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
184 {DNAME_W"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
185
186 {DNAME_W"/"FNAME_W, F_OK, "F_OK", EACCES, 1},
187 {DNAME_W"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
188 {DNAME_W"/"FNAME_W, W_OK, "W_OK", EACCES, 1},
189 {DNAME_W"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
190
191 {DNAME_W"/"FNAME_X, F_OK, "F_OK", EACCES, 1},
192 {DNAME_W"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
193 {DNAME_W"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
194 {DNAME_W"/"FNAME_X, X_OK, "X_OK", EACCES, 1},
195
196 {DNAME_X"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
197 {DNAME_X"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
198
199 {DNAME_X"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
200 {DNAME_X"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
201
202 {DNAME_X"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
203 {DNAME_X"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
204
205 {DNAME_RW"/"FNAME_R, F_OK, "F_OK", EACCES, 1},
206 {DNAME_RW"/"FNAME_R, R_OK, "R_OK", EACCES, 1},
207 {DNAME_RW"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
208 {DNAME_RW"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
209
210 {DNAME_RW"/"FNAME_W, F_OK, "F_OK", EACCES, 1},
211 {DNAME_RW"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
212 {DNAME_RW"/"FNAME_W, W_OK, "W_OK", EACCES, 1},
213 {DNAME_RW"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
214
215 {DNAME_RW"/"FNAME_X, F_OK, "F_OK", EACCES, 1},
216 {DNAME_RW"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
217 {DNAME_RW"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
218 {DNAME_RW"/"FNAME_X, X_OK, "X_OK", EACCES, 1},
219
220 {DNAME_RX"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
221 {DNAME_RX"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
222
223 {DNAME_RX"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
224 {DNAME_RX"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
225
226 {DNAME_RX"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
227 {DNAME_RX"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
228
229 {DNAME_WX"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
230 {DNAME_WX"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
231
232 {DNAME_WX"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
233 {DNAME_WX"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
234
235 {DNAME_WX"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
236 {DNAME_WX"/"FNAME_X, W_OK, "W_OK", EACCES, 1}
237 };
238
access_test(struct tcase * tc,const char * user)239 static void access_test(struct tcase *tc, const char *user)
240 {
241 if (tc->exp_errno) {
242 TST_EXP_FAIL(access(tc->fname, tc->mode), tc->exp_errno,
243 "access(%s, %s) as %s", tc->fname, tc->name, user);
244 } else {
245 TST_EXP_PASS(access(tc->fname, tc->mode),
246 "access(%s, %s) as %s", tc->fname, tc->name, user);
247 }
248 }
249
verify_access(unsigned int n)250 static void verify_access(unsigned int n)
251 {
252 struct tcase *tc = tcases + n;
253 pid_t pid;
254
255 if (tc->exp_user & 0x02)
256 access_test(tc, "root");
257
258 if (tc->exp_user & 0x01) {
259 pid = SAFE_FORK();
260 if (pid) {
261 SAFE_WAITPID(pid, NULL, 0);
262 } else {
263 SAFE_SETUID(uid);
264 access_test(tc, "nobody");
265 }
266 }
267 }
268
setup(void)269 static void setup(void)
270 {
271 struct passwd *pw;
272
273 umask(0022);
274
275 pw = SAFE_GETPWNAM("nobody");
276
277 uid = pw->pw_uid;
278
279 SAFE_TOUCH(FNAME_RWX, 0777, NULL);
280 SAFE_TOUCH(FNAME_R, 0444, NULL);
281 SAFE_TOUCH(FNAME_W, 0222, NULL);
282 SAFE_TOUCH(FNAME_X, 0111, NULL);
283
284 SAFE_MKDIR(DNAME_R, 0444);
285 SAFE_MKDIR(DNAME_W, 0222);
286 SAFE_MKDIR(DNAME_X, 0111);
287 SAFE_MKDIR(DNAME_RW, 0666);
288 SAFE_MKDIR(DNAME_RX, 0555);
289 SAFE_MKDIR(DNAME_WX, 0333);
290
291 SAFE_TOUCH(DNAME_R"/"FNAME_R, 0444, NULL);
292 SAFE_TOUCH(DNAME_R"/"FNAME_W, 0222, NULL);
293 SAFE_TOUCH(DNAME_R"/"FNAME_X, 0111, NULL);
294
295 SAFE_TOUCH(DNAME_W"/"FNAME_R, 0444, NULL);
296 SAFE_TOUCH(DNAME_W"/"FNAME_W, 0222, NULL);
297 SAFE_TOUCH(DNAME_W"/"FNAME_X, 0111, NULL);
298
299 SAFE_TOUCH(DNAME_X"/"FNAME_R, 0444, NULL);
300 SAFE_TOUCH(DNAME_X"/"FNAME_W, 0222, NULL);
301 SAFE_TOUCH(DNAME_X"/"FNAME_X, 0111, NULL);
302
303 SAFE_TOUCH(DNAME_RW"/"FNAME_R, 0444, NULL);
304 SAFE_TOUCH(DNAME_RW"/"FNAME_W, 0222, NULL);
305 SAFE_TOUCH(DNAME_RW"/"FNAME_X, 0111, NULL);
306
307 SAFE_TOUCH(DNAME_RX"/"FNAME_R, 0444, NULL);
308 SAFE_TOUCH(DNAME_RX"/"FNAME_W, 0222, NULL);
309 SAFE_TOUCH(DNAME_RX"/"FNAME_X, 0111, NULL);
310
311 SAFE_TOUCH(DNAME_WX"/"FNAME_R, 0444, NULL);
312 SAFE_TOUCH(DNAME_WX"/"FNAME_W, 0222, NULL);
313 SAFE_TOUCH(DNAME_WX"/"FNAME_X, 0111, NULL);
314 }
315
316 static struct tst_test test = {
317 .needs_tmpdir = 1,
318 .needs_root = 1,
319 .forks_child = 1,
320 .setup = setup,
321 .test = verify_access,
322 .tcnt = ARRAY_SIZE(tcases),
323 };
324