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