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 "accesfile_r"
36 #define FNAME_W "accesfile_w"
37 #define FNAME_X "accesfile_x"
38
39 static uid_t uid;
40
41 static struct tcase {
42 const char *fname;
43 int mode;
44 char *name;
45 int exp_errno;
46 /* 1: nobody expected 2: root expected 3: both */
47 int exp_user;
48 } tcases[] = {
49 {FNAME_RWX, F_OK, "F_OK", 0, 3},
50 {FNAME_RWX, X_OK, "X_OK", 0, 3},
51 {FNAME_RWX, W_OK, "W_OK", 0, 3},
52 {FNAME_RWX, R_OK, "R_OK", 0, 3},
53
54 {FNAME_RWX, R_OK|W_OK, "R_OK|W_OK", 0, 3},
55 {FNAME_RWX, R_OK|X_OK, "R_OK|X_OK", 0, 3},
56 {FNAME_RWX, W_OK|X_OK, "W_OK|X_OK", 0, 3},
57 {FNAME_RWX, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", 0, 3},
58
59 {FNAME_X, X_OK, "X_OK", 0, 3},
60 {FNAME_W, W_OK, "W_OK", 0, 3},
61 {FNAME_R, R_OK, "R_OK", 0, 3},
62
63 {FNAME_R, X_OK, "X_OK", EACCES, 3},
64 {FNAME_R, W_OK, "W_OK", EACCES, 1},
65 {FNAME_W, R_OK, "R_OK", EACCES, 1},
66 {FNAME_W, X_OK, "X_OK", EACCES, 3},
67 {FNAME_X, R_OK, "R_OK", EACCES, 1},
68 {FNAME_X, W_OK, "W_OK", EACCES, 1},
69
70 {FNAME_R, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
71 {FNAME_R, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
72 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
73 {FNAME_R, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
74
75 {FNAME_W, W_OK|X_OK, "W_OK|X_OK", EACCES, 3},
76 {FNAME_W, R_OK|X_OK, "R_OK|X_OK", EACCES, 3},
77 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
78 {FNAME_W, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 3},
79
80 {FNAME_X, W_OK|X_OK, "W_OK|X_OK", EACCES, 1},
81 {FNAME_X, R_OK|X_OK, "R_OK|X_OK", EACCES, 1},
82 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", EACCES, 1},
83 {FNAME_X, R_OK|W_OK|X_OK, "R_OK|W_OK|X_OK", EACCES, 1},
84
85 {FNAME_R, W_OK, "W_OK", 0, 2},
86 {FNAME_R, R_OK|W_OK, "R_OK|W_OK", 0, 2},
87
88 {FNAME_W, R_OK, "R_OK", 0, 2},
89 {FNAME_W, R_OK|W_OK, "R_OK|W_OK", 0, 2},
90
91 {FNAME_X, R_OK, "R_OK", 0, 2},
92 {FNAME_X, W_OK, "W_OK", 0, 2},
93 {FNAME_X, R_OK|W_OK, "R_OK|W_OK", 0, 2}
94 };
95
verify_success(struct tcase * tc,const char * user)96 static void verify_success(struct tcase *tc, const char *user)
97 {
98 if (TEST_RETURN == -1) {
99 tst_res(TFAIL | TTERRNO,
100 "access(%s, %s) as %s failed unexpectedly",
101 tc->fname, tc->name, user);
102 return;
103 }
104
105 tst_res(TPASS, "access(%s, %s) as %s", tc->fname, tc->name, user);
106 }
107
verify_failure(struct tcase * tc,const char * user)108 static void verify_failure(struct tcase *tc, const char *user)
109 {
110 if (TEST_RETURN != -1) {
111 tst_res(TFAIL, "access(%s, %s) as %s succeded unexpectedly",
112 tc->fname, tc->name, user);
113 return;
114 }
115
116 if (TEST_ERRNO != tc->exp_errno) {
117 tst_res(TFAIL | TTERRNO,
118 "access(%s, %s) as %s should fail with %s",
119 tc->fname, tc->name, user,
120 tst_strerrno(tc->exp_errno));
121 return;
122 }
123
124 tst_res(TPASS | TTERRNO, "access(%s, %s) as %s",
125 tc->fname, tc->name, user);
126 }
127
access_test(struct tcase * tc,const char * user)128 static void access_test(struct tcase *tc, const char *user)
129 {
130 TEST(access(tc->fname, tc->mode));
131
132 if (tc->exp_errno)
133 verify_failure(tc, user);
134 else
135 verify_success(tc, user);
136 }
137
verify_access(unsigned int n)138 static void verify_access(unsigned int n)
139 {
140 struct tcase *tc = tcases + n;
141 pid_t pid;
142
143 if (tc->exp_user & 0x02)
144 access_test(tc, "root");
145
146 if (tc->exp_user & 0x01) {
147 pid = SAFE_FORK();
148 if (pid) {
149 SAFE_WAITPID(pid, NULL, 0);
150 } else {
151 SAFE_SETUID(uid);
152 access_test(tc, "nobody");
153 }
154 }
155 }
156
setup(void)157 static void setup(void)
158 {
159 struct passwd *pw;
160
161 pw = SAFE_GETPWNAM("nobody");
162
163 uid = pw->pw_uid;
164
165 SAFE_TOUCH(FNAME_RWX, 0777, NULL);
166 SAFE_TOUCH(FNAME_R, 0444, NULL);
167 SAFE_TOUCH(FNAME_W, 0222, NULL);
168 SAFE_TOUCH(FNAME_X, 0111, NULL);
169 }
170
171 static struct tst_test test = {
172 .tid = "access01",
173 .needs_tmpdir = 1,
174 .needs_root = 1,
175 .forks_child = 1,
176 .setup = setup,
177 .test = verify_access,
178 .tcnt = ARRAY_SIZE(tcases),
179 };
180