1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 * AUTHOR : William Roske
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * Further, this software is distributed without any warranty that it is
14 * free of the rightful claim of any third person regarding infringement
15 * or the like. Any license provided herein, whether implied or
16 * otherwise, applies only to this software file. Patent licenses, if
17 * any, provided herein do not apply to combinations of this program with
18 * other software, or any other product whatsoever.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25 /*
26 * Basic test for access(2) using F_OK, R_OK, W_OK and X_OK
27 */
28 #include <errno.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <pwd.h>
32 #include "tst_test.h"
33
34 #define FNAME_RWX "accessfile_rwx"
35 #define FNAME_R "accessfile_r"
36 #define FNAME_W "accessfile_w"
37 #define FNAME_X "accessfile_x"
38
39 #define DNAME_R "accessdir_r"
40 #define DNAME_W "accessdir_w"
41 #define DNAME_X "accessdir_x"
42 #define DNAME_RW "accessdir_rw"
43 #define DNAME_RX "accessdir_rx"
44 #define DNAME_WX "accessdir_wx"
45
46 static uid_t uid;
47
48 static struct tcase {
49 const char *fname;
50 int mode;
51 char *name;
52 int exp_errno;
53 /* 1: nobody expected 2: root expected 3: both */
54 int exp_user;
55 } tcases[] = {
56 {FNAME_RWX, F_OK, "F_OK", 0, 3},
57 {FNAME_RWX, X_OK, "X_OK", 0, 3},
58 {FNAME_RWX, W_OK, "W_OK", 0, 3},
59 {FNAME_RWX, R_OK, "R_OK", 0, 3},
60
61 {FNAME_RWX, R_OK|W_OK, "R_OK|W_OK", 0, 3},
62 {FNAME_RWX, R_OK|X_OK, "R_OK|X_OK", 0, 3},
63 {FNAME_RWX, W_OK|X_OK, "W_OK|X_OK", 0, 3},
64 {FNAME_RWX, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", 0, 3},
65
66 {FNAME_X, X_OK, "X_OK", 0, 3},
67 {FNAME_W, W_OK, "W_OK", 0, 3},
68 {FNAME_R, R_OK, "R_OK", 0, 3},
69
70 {FNAME_R, X_OK, "X_OK", EACCES, 3},
71 {FNAME_R, W_OK, "W_OK", EACCES, 1},
72 {FNAME_W, R_OK, "R_OK", EACCES, 1},
73 {FNAME_W, X_OK, "X_OK", EACCES, 3},
74 {FNAME_X, R_OK, "R_OK", EACCES, 1},
75 {FNAME_X, W_OK, "W_OK", EACCES, 1},
76
77 {FNAME_R, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
78 {FNAME_R, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
79 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
80 {FNAME_R, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
81
82 {FNAME_W, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
83 {FNAME_W, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
84 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
85 {FNAME_W, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
86
87 {FNAME_X, W_OK|X_OK, "W_OK|X_OK", EACCES, 1},
88 {FNAME_X, R_OK|X_OK, "R_OK|X_OK", EACCES, 1},
89 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
90 {FNAME_X, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 1},
91
92 {FNAME_R, W_OK, "W_OK", 0, 2},
93 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", 0, 2},
94
95 {FNAME_W, R_OK, "R_OK", 0, 2},
96 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", 0, 2},
97
98 {FNAME_X, R_OK, "R_OK", 0, 2},
99 {FNAME_X, W_OK, "W_OK", 0, 2},
100 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", 0, 2},
101
102 {DNAME_R"/"FNAME_R, F_OK, "F_OK", 0, 2},
103 {DNAME_R"/"FNAME_R, R_OK, "R_OK", 0, 2},
104 {DNAME_R"/"FNAME_R, W_OK, "W_OK", 0, 2},
105
106 {DNAME_R"/"FNAME_W, F_OK, "F_OK", 0, 2},
107 {DNAME_R"/"FNAME_W, R_OK, "R_OK", 0, 2},
108 {DNAME_R"/"FNAME_W, W_OK, "W_OK", 0, 2},
109
110 {DNAME_R"/"FNAME_X, F_OK, "F_OK", 0, 2},
111 {DNAME_R"/"FNAME_X, R_OK, "R_OK", 0, 2},
112 {DNAME_R"/"FNAME_X, W_OK, "W_OK", 0, 2},
113 {DNAME_R"/"FNAME_X, X_OK, "X_OK", 0, 2},
114
115 {DNAME_W"/"FNAME_R, F_OK, "F_OK", 0, 2},
116 {DNAME_W"/"FNAME_R, R_OK, "R_OK", 0, 2},
117 {DNAME_W"/"FNAME_R, W_OK, "W_OK", 0, 2},
118
119 {DNAME_W"/"FNAME_W, F_OK, "F_OK", 0, 2},
120 {DNAME_W"/"FNAME_W, R_OK, "R_OK", 0, 2},
121 {DNAME_W"/"FNAME_W, W_OK, "W_OK", 0, 2},
122
123 {DNAME_W"/"FNAME_X, F_OK, "F_OK", 0, 2},
124 {DNAME_W"/"FNAME_X, R_OK, "R_OK", 0, 2},
125 {DNAME_W"/"FNAME_X, W_OK, "W_OK", 0, 2},
126 {DNAME_W"/"FNAME_X, X_OK, "X_OK", 0, 2},
127
128 {DNAME_X"/"FNAME_R, F_OK, "F_OK", 0, 3},
129 {DNAME_X"/"FNAME_R, R_OK, "R_OK", 0, 3},
130 {DNAME_X"/"FNAME_R, W_OK, "W_OK", 0, 2},
131
132 {DNAME_X"/"FNAME_W, F_OK, "F_OK", 0, 3},
133 {DNAME_X"/"FNAME_W, R_OK, "R_OK", 0, 2},
134 {DNAME_X"/"FNAME_W, W_OK, "W_OK", 0, 3},
135
136 {DNAME_X"/"FNAME_X, F_OK, "F_OK", 0, 3},
137 {DNAME_X"/"FNAME_X, R_OK, "R_OK", 0, 2},
138 {DNAME_X"/"FNAME_X, W_OK, "W_OK", 0, 2},
139 {DNAME_X"/"FNAME_X, X_OK, "X_OK", 0, 3},
140
141 {DNAME_RW"/"FNAME_R, F_OK, "F_OK", 0, 2},
142 {DNAME_RW"/"FNAME_R, R_OK, "R_OK", 0, 2},
143 {DNAME_RW"/"FNAME_R, W_OK, "W_OK", 0, 2},
144
145 {DNAME_RW"/"FNAME_W, F_OK, "F_OK", 0, 2},
146 {DNAME_RW"/"FNAME_W, R_OK, "R_OK", 0, 2},
147 {DNAME_RW"/"FNAME_W, W_OK, "W_OK", 0, 2},
148
149 {DNAME_RW"/"FNAME_X, F_OK, "F_OK", 0, 2},
150 {DNAME_RW"/"FNAME_X, R_OK, "R_OK", 0, 2},
151 {DNAME_RW"/"FNAME_X, W_OK, "W_OK", 0, 2},
152 {DNAME_RW"/"FNAME_X, X_OK, "X_OK", 0, 2},
153
154 {DNAME_RX"/"FNAME_R, F_OK, "F_OK", 0, 3},
155 {DNAME_RX"/"FNAME_R, R_OK, "R_OK", 0, 3},
156 {DNAME_RX"/"FNAME_R, W_OK, "W_OK", 0, 2},
157
158 {DNAME_RX"/"FNAME_W, F_OK, "F_OK", 0, 3},
159 {DNAME_RX"/"FNAME_W, R_OK, "R_OK", 0, 2},
160 {DNAME_RX"/"FNAME_W, W_OK, "W_OK", 0, 3},
161
162 {DNAME_RX"/"FNAME_X, F_OK, "F_OK", 0, 3},
163 {DNAME_RX"/"FNAME_X, R_OK, "R_OK", 0, 2},
164 {DNAME_RX"/"FNAME_X, W_OK, "W_OK", 0, 2},
165 {DNAME_RX"/"FNAME_X, X_OK, "X_OK", 0, 3},
166
167 {DNAME_WX"/"FNAME_R, F_OK, "F_OK", 0, 3},
168 {DNAME_WX"/"FNAME_R, R_OK, "R_OK", 0, 3},
169 {DNAME_WX"/"FNAME_R, W_OK, "W_OK", 0, 2},
170
171 {DNAME_WX"/"FNAME_W, F_OK, "F_OK", 0, 3},
172 {DNAME_WX"/"FNAME_W, R_OK, "R_OK", 0, 2},
173 {DNAME_WX"/"FNAME_W, W_OK, "W_OK", 0, 3},
174
175 {DNAME_WX"/"FNAME_X, F_OK, "F_OK", 0, 3},
176 {DNAME_WX"/"FNAME_X, R_OK, "R_OK", 0, 2},
177 {DNAME_WX"/"FNAME_X, W_OK, "W_OK", 0, 2},
178 {DNAME_WX"/"FNAME_X, X_OK, "X_OK", 0, 3},
179
180 {DNAME_R"/"FNAME_R, F_OK, "F_OK", EACCES, 1},
181 {DNAME_R"/"FNAME_R, R_OK, "R_OK", EACCES, 1},
182 {DNAME_R"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
183 {DNAME_R"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
184
185 {DNAME_R"/"FNAME_W, F_OK, "F_OK", EACCES, 1},
186 {DNAME_R"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
187 {DNAME_R"/"FNAME_W, W_OK, "W_OK", EACCES, 1},
188 {DNAME_R"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
189
190 {DNAME_R"/"FNAME_X, F_OK, "F_OK", EACCES, 1},
191 {DNAME_R"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
192 {DNAME_R"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
193 {DNAME_R"/"FNAME_X, X_OK, "X_OK", EACCES, 1},
194
195 {DNAME_W"/"FNAME_R, F_OK, "F_OK", EACCES, 1},
196 {DNAME_W"/"FNAME_R, R_OK, "R_OK", EACCES, 1},
197 {DNAME_W"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
198 {DNAME_W"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
199
200 {DNAME_W"/"FNAME_W, F_OK, "F_OK", EACCES, 1},
201 {DNAME_W"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
202 {DNAME_W"/"FNAME_W, W_OK, "W_OK", EACCES, 1},
203 {DNAME_W"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
204
205 {DNAME_W"/"FNAME_X, F_OK, "F_OK", EACCES, 1},
206 {DNAME_W"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
207 {DNAME_W"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
208 {DNAME_W"/"FNAME_X, X_OK, "X_OK", EACCES, 1},
209
210 {DNAME_X"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
211 {DNAME_X"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
212
213 {DNAME_X"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
214 {DNAME_X"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
215
216 {DNAME_X"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
217 {DNAME_X"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
218
219 {DNAME_RW"/"FNAME_R, F_OK, "F_OK", EACCES, 1},
220 {DNAME_RW"/"FNAME_R, R_OK, "R_OK", EACCES, 1},
221 {DNAME_RW"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
222 {DNAME_RW"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
223
224 {DNAME_RW"/"FNAME_W, F_OK, "F_OK", EACCES, 1},
225 {DNAME_RW"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
226 {DNAME_RW"/"FNAME_W, W_OK, "W_OK", EACCES, 1},
227 {DNAME_RW"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
228
229 {DNAME_RW"/"FNAME_X, F_OK, "F_OK", EACCES, 1},
230 {DNAME_RW"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
231 {DNAME_RW"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
232 {DNAME_RW"/"FNAME_X, X_OK, "X_OK", EACCES, 1},
233
234 {DNAME_RX"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
235 {DNAME_RX"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
236
237 {DNAME_RX"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
238 {DNAME_RX"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
239
240 {DNAME_RX"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
241 {DNAME_RX"/"FNAME_X, W_OK, "W_OK", EACCES, 1},
242
243 {DNAME_WX"/"FNAME_R, W_OK, "W_OK", EACCES, 1},
244 {DNAME_WX"/"FNAME_R, X_OK, "X_OK", EACCES, 3},
245
246 {DNAME_WX"/"FNAME_W, R_OK, "R_OK", EACCES, 1},
247 {DNAME_WX"/"FNAME_W, X_OK, "X_OK", EACCES, 3},
248
249 {DNAME_WX"/"FNAME_X, R_OK, "R_OK", EACCES, 1},
250 {DNAME_WX"/"FNAME_X, W_OK, "W_OK", EACCES, 1}
251 };
252
verify_success(struct tcase * tc,const char * user)253 static void verify_success(struct tcase *tc, const char *user)
254 {
255 if (TEST_RETURN == -1) {
256 tst_res(TFAIL | TTERRNO,
257 "access(%s, %s) as %s failed unexpectedly",
258 tc->fname, tc->name, user);
259 return;
260 }
261
262 tst_res(TPASS, "access(%s, %s) as %s", tc->fname, tc->name, user);
263 }
264
verify_failure(struct tcase * tc,const char * user)265 static void verify_failure(struct tcase *tc, const char *user)
266 {
267 if (TEST_RETURN != -1) {
268 tst_res(TFAIL, "access(%s, %s) as %s succeded unexpectedly",
269 tc->fname, tc->name, user);
270 return;
271 }
272
273 if (TEST_ERRNO != tc->exp_errno) {
274 tst_res(TFAIL | TTERRNO,
275 "access(%s, %s) as %s should fail with %s",
276 tc->fname, tc->name, user,
277 tst_strerrno(tc->exp_errno));
278 return;
279 }
280
281 tst_res(TPASS | TTERRNO, "access(%s, %s) as %s",
282 tc->fname, tc->name, user);
283 }
284
access_test(struct tcase * tc,const char * user)285 static void access_test(struct tcase *tc, const char *user)
286 {
287 TEST(access(tc->fname, tc->mode));
288
289 if (tc->exp_errno)
290 verify_failure(tc, user);
291 else
292 verify_success(tc, user);
293 }
294
verify_access(unsigned int n)295 static void verify_access(unsigned int n)
296 {
297 struct tcase *tc = tcases + n;
298 pid_t pid;
299
300 if (tc->exp_user & 0x02)
301 access_test(tc, "root");
302
303 if (tc->exp_user & 0x01) {
304 pid = SAFE_FORK();
305 if (pid) {
306 SAFE_WAITPID(pid, NULL, 0);
307 } else {
308 SAFE_SETUID(uid);
309 access_test(tc, "nobody");
310 }
311 }
312 }
313
setup(void)314 static void setup(void)
315 {
316 struct passwd *pw;
317
318 umask(0022);
319
320 pw = SAFE_GETPWNAM("nobody");
321
322 uid = pw->pw_uid;
323
324 SAFE_TOUCH(FNAME_RWX, 0777, NULL);
325 SAFE_TOUCH(FNAME_R, 0444, NULL);
326 SAFE_TOUCH(FNAME_W, 0222, NULL);
327 SAFE_TOUCH(FNAME_X, 0111, NULL);
328
329 SAFE_MKDIR(DNAME_R, 0444);
330 SAFE_MKDIR(DNAME_W, 0222);
331 SAFE_MKDIR(DNAME_X, 0111);
332 SAFE_MKDIR(DNAME_RW, 0666);
333 SAFE_MKDIR(DNAME_RX, 0555);
334 SAFE_MKDIR(DNAME_WX, 0333);
335
336 SAFE_TOUCH(DNAME_R"/"FNAME_R, 0444, NULL);
337 SAFE_TOUCH(DNAME_R"/"FNAME_W, 0222, NULL);
338 SAFE_TOUCH(DNAME_R"/"FNAME_X, 0111, NULL);
339
340 SAFE_TOUCH(DNAME_W"/"FNAME_R, 0444, NULL);
341 SAFE_TOUCH(DNAME_W"/"FNAME_W, 0222, NULL);
342 SAFE_TOUCH(DNAME_W"/"FNAME_X, 0111, NULL);
343
344 SAFE_TOUCH(DNAME_X"/"FNAME_R, 0444, NULL);
345 SAFE_TOUCH(DNAME_X"/"FNAME_W, 0222, NULL);
346 SAFE_TOUCH(DNAME_X"/"FNAME_X, 0111, NULL);
347
348 SAFE_TOUCH(DNAME_RW"/"FNAME_R, 0444, NULL);
349 SAFE_TOUCH(DNAME_RW"/"FNAME_W, 0222, NULL);
350 SAFE_TOUCH(DNAME_RW"/"FNAME_X, 0111, NULL);
351
352 SAFE_TOUCH(DNAME_RX"/"FNAME_R, 0444, NULL);
353 SAFE_TOUCH(DNAME_RX"/"FNAME_W, 0222, NULL);
354 SAFE_TOUCH(DNAME_RX"/"FNAME_X, 0111, NULL);
355
356 SAFE_TOUCH(DNAME_WX"/"FNAME_R, 0444, NULL);
357 SAFE_TOUCH(DNAME_WX"/"FNAME_W, 0222, NULL);
358 SAFE_TOUCH(DNAME_WX"/"FNAME_X, 0111, NULL);
359 }
360
361 static struct tst_test test = {
362 .needs_tmpdir = 1,
363 .needs_root = 1,
364 .forks_child = 1,
365 .setup = setup,
366 .test = verify_access,
367 .tcnt = ARRAY_SIZE(tcases),
368 };
369