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
46static uid_t uid;
47
48static 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
253static 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
265static 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
285static 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
295static 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
314static void setup(void)
315{
316	struct passwd *pw;
317
318	pw = SAFE_GETPWNAM("nobody");
319
320	uid = pw->pw_uid;
321
322	SAFE_TOUCH(FNAME_RWX, 0777, NULL);
323	SAFE_TOUCH(FNAME_R, 0444, NULL);
324	SAFE_TOUCH(FNAME_W, 0222, NULL);
325	SAFE_TOUCH(FNAME_X, 0111, NULL);
326
327	SAFE_MKDIR(DNAME_R, 0444);
328	SAFE_MKDIR(DNAME_W, 0222);
329	SAFE_MKDIR(DNAME_X, 0111);
330	SAFE_MKDIR(DNAME_RW, 0666);
331	SAFE_MKDIR(DNAME_RX, 0555);
332	SAFE_MKDIR(DNAME_WX, 0333);
333
334	SAFE_TOUCH(DNAME_R"/"FNAME_R, 0444, NULL);
335	SAFE_TOUCH(DNAME_R"/"FNAME_W, 0222, NULL);
336	SAFE_TOUCH(DNAME_R"/"FNAME_X, 0111, NULL);
337
338	SAFE_TOUCH(DNAME_W"/"FNAME_R, 0444, NULL);
339	SAFE_TOUCH(DNAME_W"/"FNAME_W, 0222, NULL);
340	SAFE_TOUCH(DNAME_W"/"FNAME_X, 0111, NULL);
341
342	SAFE_TOUCH(DNAME_X"/"FNAME_R, 0444, NULL);
343	SAFE_TOUCH(DNAME_X"/"FNAME_W, 0222, NULL);
344	SAFE_TOUCH(DNAME_X"/"FNAME_X, 0111, NULL);
345
346	SAFE_TOUCH(DNAME_RW"/"FNAME_R, 0444, NULL);
347	SAFE_TOUCH(DNAME_RW"/"FNAME_W, 0222, NULL);
348	SAFE_TOUCH(DNAME_RW"/"FNAME_X, 0111, NULL);
349
350	SAFE_TOUCH(DNAME_RX"/"FNAME_R, 0444, NULL);
351	SAFE_TOUCH(DNAME_RX"/"FNAME_W, 0222, NULL);
352	SAFE_TOUCH(DNAME_RX"/"FNAME_X, 0111, NULL);
353
354	SAFE_TOUCH(DNAME_WX"/"FNAME_R, 0444, NULL);
355	SAFE_TOUCH(DNAME_WX"/"FNAME_W, 0222, NULL);
356	SAFE_TOUCH(DNAME_WX"/"FNAME_X, 0111, NULL);
357}
358
359static struct tst_test test = {
360	.tid = "access01",
361	.needs_tmpdir = 1,
362	.needs_root = 1,
363	.forks_child = 1,
364	.setup = setup,
365	.test = verify_access,
366	.tcnt = ARRAY_SIZE(tcases),
367};
368