2 * Copyright (c) 2001 Networks Associates Technology, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * Written at NAI Labs at Network Associates by Robert Watson for the
29 * Work sponsored by Defense Advanced Research Projects Agency under the
30 * CHATS research program, CBOSS project.
33 #include <sys/types.h>
42 * Regression test to check some basic cases and see if access() and
43 * eaccess() are using the correct portions of the process credential.
44 * This test relies on running with privilege, and on UFS filesystem
45 * semantics. Running the test in other environments may result
46 * in incorrect failure identification.
48 * Note that this may also break if filesystem access control is
49 * broken, or if the ability to check and set credentials is broken.
51 * Note that this test uses two hard-coded non-root UIDs; on multi-user
52 * systems, these UIDs may be in use by an untrusted user, in which
53 * case those users could interfere with the test.
56 #define ROOT_UID (uid_t)0
57 #define WHEEL_GID (gid_t)0
58 #define TEST_UID_ONE (uid_t)500
59 #define TEST_GID_ONE (gid_t)500
60 #define TEST_UID_TWO (uid_t)501
61 #define TEST_GID_TWO (gid_t)501
63 struct file_description {
70 static struct file_description fd_list[] = {
71 {"test1", ROOT_UID, WHEEL_GID, 0400},
72 {"test2", TEST_UID_ONE, WHEEL_GID,0400},
73 {"test3", TEST_UID_TWO, WHEEL_GID, 0400},
74 {"test4", ROOT_UID, WHEEL_GID, 0040},
75 {"test5", ROOT_UID, TEST_GID_ONE, 0040},
76 {"test6", ROOT_UID, TEST_GID_TWO, 0040}};
78 static int fd_list_count = sizeof(fd_list) /
79 sizeof(struct file_description);
86 for (i = 0; i < fd_list_count; i++) {
87 error = open(fd_list[i].fd_name, O_CREAT | O_EXCL, fd_list[i].fd_mode);
93 error = chown(fd_list[i].fd_name, fd_list[i].fd_owner,
104 restoreprivilege(void)
108 error = setreuid(ROOT_UID, ROOT_UID);
112 error = setregid(WHEEL_GID, WHEEL_GID);
120 reportprivilege(char *message)
122 uid_t euid, ruid, suid;
123 gid_t egid, rgid, sgid;
126 error = getresuid(&ruid, &euid, &suid);
132 error = getresgid(&rgid, &egid, &sgid);
139 printf("%s: ", message);
140 printf("ruid: %d, euid: %d, suid: %d, ", ruid, euid, suid);
141 printf("rgid: %d, egid: %d, sgid: %d\n", rgid, egid, sgid);
151 error = restoreprivilege();
153 perror("restoreprivilege");
157 for (i = 0; i < fd_list_count; i++) {
158 error = unlink(fd_list[i].fd_name);
167 main(int argc, char *argv[])
169 int error, errorseen;
171 if (geteuid() != 0) {
172 fprintf(stderr, "testaccess must run as root.\n");
182 /* Make sure saved uid is set appropriately. */
183 error = setresuid(ROOT_UID, ROOT_UID, ROOT_UID);
189 /* Clear out additional groups. */
190 error = setgroups(0, NULL);
196 /* Make sure saved gid is set appropriately. */
197 error = setresgid(WHEEL_GID, WHEEL_GID, WHEEL_GID);
207 /* Check that saved uid is not used */
208 error = setresuid(TEST_UID_ONE, TEST_UID_ONE, ROOT_UID);
210 perror("setresuid.1");
217 error = access("test1", R_OK);
219 fprintf(stderr, "saved uid used instead of real uid\n");
223 #ifdef EACCESS_AVAILABLE
224 error = eaccess("test1", R_OK);
226 fprintf(stderr, "saved uid used instead of effective uid\n");
231 error = restoreprivilege();
233 perror("restoreprivilege");
238 error = setresuid(TEST_UID_ONE, TEST_UID_TWO, ROOT_UID);
240 perror("setresid.2");
245 /* Check that the real uid is used, not the effective uid */
246 error = access("test2", R_OK);
248 fprintf(stderr, "Effective uid was used instead of real uid in access().\n");
252 #ifdef EACCESS_AVAILABLE
253 /* Check that the effective uid is used, not the real uid */
254 error = eaccess("test3", R_OK);
256 fprintf(stderr, "Real uid was used instead of effective uid in eaccess().\n");
261 /* Check that the real uid is used, not the effective uid */
262 error = access("test3", R_OK);
264 fprintf(stderr, "Effective uid was used instead of real uid in access().\n");
268 #ifdef EACCESS_AVAILABLE
269 /* Check that the effective uid is used, not the real uid */
270 error = eaccess("test2", R_OK);
272 fprintf(stderr, "Real uid was used instead of effective uid in eaccess().\n");
277 error = restoreprivilege();
279 perror("restoreprivilege");
284 error = setresgid(TEST_GID_ONE, TEST_GID_TWO, WHEEL_GID);
286 perror("setresgid.1");
291 /* Set non-root effective uid to avoid excess privilege. */
292 error = setresuid(TEST_UID_ONE, TEST_UID_ONE, ROOT_UID);
294 perror("setresuid.3");
299 /* Check that the saved gid is not used */
300 error = access("test4", R_OK);
302 fprintf(stderr, "saved gid used instead of real gid\n");
305 #ifdef EACCESS_AVAILABLE
306 error = eaccess("test4", R_OK);
308 fprintf(stderr, "saved gid used instead of effective gid\n");
313 /* Check that the real gid is used, not the effective gid */
314 error = access("test5", R_OK);
316 fprintf(stderr, "Effective gid was used instead of real gid in access().\n");
320 #ifdef EACCESS_AVAILABLE
321 /* Check that the effective gid is used, not the real gid */
322 error = eaccess("test6", R_OK);
324 fprintf(stderr, "Real gid was used instead of effective gid in eaccess().\n");
329 /* Check that the real gid is used, not the effective gid */
330 error = access("test6", R_OK);
332 fprintf(stderr, "Effective gid was used instead of real gid in access().\n");
336 #ifdef EACCESS_AVAILABLE
337 /* Check that the effective gid is used, not the real gid */
338 error = eaccess("test5", R_OK);
340 fprintf(stderr, "Real gid was used instead of effective gid in eaccess().\n");
345 fprintf(stderr, "%d errors seen.\n", errorseen);
348 * All tests done, restore and clean up