1 /* $NetBSD: t_access.c,v 2.2 2017/01/10 22:36:29 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_access.c,v 1.2 2017/01/10 22:36:29 christos Exp $");
33
34 #include <atf-c.h>
35
36 #include <sys/stat.h>
37 #include <sys/sysctl.h>
38
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <limits.h>
42 #include <stdint.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46
47 static const char path[] = "access";
48 static const int mode[4] = { R_OK, W_OK, X_OK, F_OK };
49
50 ATF_TC_WITH_CLEANUP(access_access);
ATF_TC_HEAD(access_access,tc)51 ATF_TC_HEAD(access_access, tc)
52 {
53 atf_tc_set_md_var(tc, "descr", "Test access(2) for EACCES");
54 atf_tc_set_md_var(tc, "require.user", "unprivileged");
55 }
56
ATF_TC_BODY(access_access,tc)57 ATF_TC_BODY(access_access, tc)
58 {
59 const int perm[3] = { 0200, 0400, 0000 };
60 size_t i;
61 int fd;
62
63 fd = open(path, O_RDONLY | O_CREAT, 0600);
64
65 if (fd < 0)
66 return;
67
68 for (i = 0; i < __arraycount(mode) - 1; i++) {
69
70 ATF_REQUIRE(fchmod(fd, perm[i]) == 0);
71
72 errno = 0;
73
74 ATF_REQUIRE(access(path, mode[i]) != 0);
75 ATF_REQUIRE(errno == EACCES);
76 }
77
78 ATF_REQUIRE(close(fd) == 0);
79 }
80
ATF_TC_CLEANUP(access_access,tc)81 ATF_TC_CLEANUP(access_access, tc)
82 {
83 (void)unlink(path);
84 }
85
86 ATF_TC(access_fault);
ATF_TC_HEAD(access_fault,tc)87 ATF_TC_HEAD(access_fault, tc)
88 {
89 atf_tc_set_md_var(tc, "descr", "Test access(2) for EFAULT");
90 }
91
ATF_TC_BODY(access_fault,tc)92 ATF_TC_BODY(access_fault, tc)
93 {
94 size_t i;
95
96 for (i = 0; i < __arraycount(mode); i++) {
97
98 errno = 0;
99
100 ATF_REQUIRE(access(NULL, mode[i]) != 0);
101 ATF_REQUIRE(errno == EFAULT);
102
103 errno = 0;
104
105 ATF_REQUIRE(access((char *)-1, mode[i]) != 0);
106 ATF_REQUIRE(errno == EFAULT);
107 }
108 }
109
110 ATF_TC(access_inval);
ATF_TC_HEAD(access_inval,tc)111 ATF_TC_HEAD(access_inval, tc)
112 {
113 atf_tc_set_md_var(tc, "descr", "Test access(2) for EINVAL");
114 }
115
ATF_TC_BODY(access_inval,tc)116 ATF_TC_BODY(access_inval, tc)
117 {
118
119 errno = 0;
120
121 ATF_REQUIRE(access("/usr", -1) != 0);
122 ATF_REQUIRE(errno == EINVAL);
123 }
124
125 ATF_TC(access_notdir);
ATF_TC_HEAD(access_notdir,tc)126 ATF_TC_HEAD(access_notdir, tc)
127 {
128 atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOTDIR");
129 }
130
ATF_TC_BODY(access_notdir,tc)131 ATF_TC_BODY(access_notdir, tc)
132 {
133 size_t i;
134
135 for (i = 0; i < __arraycount(mode); i++) {
136
137 errno = 0;
138
139 /*
140 * IEEE Std 1003.1-2008 about ENOTDIR:
141 *
142 * "A component of the path prefix is not a directory,
143 * or the path argument contains at least one non-<slash>
144 * character and ends with one or more trailing <slash>
145 * characters and the last pathname component names an
146 * existing file that is neither a directory nor a symbolic
147 * link to a directory."
148 */
149 ATF_REQUIRE(access("/etc/passwd//", mode[i]) != 0);
150 ATF_REQUIRE(errno == ENOTDIR);
151 }
152 }
153
154 ATF_TC(access_notexist);
ATF_TC_HEAD(access_notexist,tc)155 ATF_TC_HEAD(access_notexist, tc)
156 {
157 atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOENT");
158 }
159
ATF_TC_BODY(access_notexist,tc)160 ATF_TC_BODY(access_notexist, tc)
161 {
162 size_t i;
163
164 for (i = 0; i < __arraycount(mode); i++) {
165
166 errno = 0;
167
168 ATF_REQUIRE(access("", mode[i]) != 0);
169 ATF_REQUIRE(errno == ENOENT);
170 }
171 }
172
173 ATF_TC(access_text);
ATF_TC_HEAD(access_text,tc)174 ATF_TC_HEAD(access_text, tc)
175 {
176 atf_tc_set_md_var(tc, "descr", "Test access(2) for ETXTBSY");
177 }
178
ATF_TC_BODY(access_text,tc)179 ATF_TC_BODY(access_text, tc)
180 {
181 char path[PATH_MAX];
182 size_t sz;
183 int fd, name[4];
184
185 name[0] = CTL_KERN;
186 name[1] = KERN_PROC;
187 name[2] = KERN_PROC_PATHNAME;
188 name[3] = -1;
189
190 sz = sizeof(path);
191 ATF_REQUIRE(sysctl(name, 4, path, &sz, NULL, 0) == 0);
192
193 fd = open(path, O_RDONLY);
194 ATF_REQUIRE(fd >= 0);
195
196 ATF_REQUIRE(access(path, W_OK) != 0);
197 ATF_REQUIRE(errno == ETXTBSY);
198
199 ATF_REQUIRE(faccessat(AT_FDCWD, path, W_OK, 0) != 0);
200 ATF_REQUIRE(errno == ETXTBSY);
201
202 ATF_REQUIRE(close(fd) == 0);
203 }
204
205 ATF_TC(access_toolong);
ATF_TC_HEAD(access_toolong,tc)206 ATF_TC_HEAD(access_toolong, tc)
207 {
208 atf_tc_set_md_var(tc, "descr", "Test access(2) for ENAMETOOLONG");
209 }
210
ATF_TC_BODY(access_toolong,tc)211 ATF_TC_BODY(access_toolong, tc)
212 {
213 char *buf;
214 size_t i;
215
216 buf = malloc(PATH_MAX);
217
218 if (buf == NULL)
219 return;
220
221 for (i = 0; i < PATH_MAX; i++)
222 buf[i] = 'x';
223
224 for (i = 0; i < __arraycount(mode); i++) {
225
226 errno = 0;
227
228 ATF_REQUIRE(access(buf, mode[i]) != 0);
229 ATF_REQUIRE(errno == ENAMETOOLONG);
230 }
231
232 free(buf);
233 }
234
ATF_TP_ADD_TCS(tp)235 ATF_TP_ADD_TCS(tp)
236 {
237
238 ATF_TP_ADD_TC(tp, access_access);
239 ATF_TP_ADD_TC(tp, access_fault);
240 ATF_TP_ADD_TC(tp, access_inval);
241 ATF_TP_ADD_TC(tp, access_notdir);
242 ATF_TP_ADD_TC(tp, access_notexist);
243 ATF_TP_ADD_TC(tp, access_text);
244 ATF_TP_ADD_TC(tp, access_toolong);
245
246 return atf_no_error();
247 }
248