1 /*- 2 * Copyright (c) 2006 nCircle Network Security, Inc. 3 * All rights reserved. 4 * 5 * This software was developed by Robert N. M. Watson for the TrustedBSD 6 * Project under contract to nCircle Network Security, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 21 * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 /* 33 * Privilege test framework. Each test is encapsulated on a .c file exporting 34 * a function that implements the test. Each test is run from its own child 35 * process, and they are run in sequence one at a time. 36 */ 37 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <sys/wait.h> 41 42 #include <err.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "main.h" 49 50 /* 51 * Common routines used across many tests. 52 */ 53 void 54 assert_root(void) 55 { 56 57 if (getuid() != UID_ROOT || geteuid() != UID_ROOT) 58 err(-1, "must be run as root"); 59 } 60 61 void 62 setup_file(char *fpathp, uid_t uid, gid_t gid, mode_t mode) 63 { 64 int fd; 65 66 strcpy(fpathp, "/tmp/priv.XXXXXXXXXXX"); 67 fd = mkstemp(fpathp); 68 if (fd < 0) 69 err(-1, "mkstemp"); 70 71 if (fchown(fd, uid, gid) < 0) 72 err(-1, "fchown(%s, %d, %d)", fpathp, uid, gid); 73 74 if (fchmod(fd, mode) < 0) 75 err(-1, "chmod(%s, 0%o)", fpathp, mode); 76 77 close(fd); 78 } 79 80 /* 81 * When downgrading privileges, set the gid before the uid; when upgrading, 82 * set uid before gid. 83 */ 84 void 85 set_creds(uid_t uid, gid_t gid) 86 { 87 88 if (setegid(gid) < 0) 89 err(-1, "setegid(%d)", gid); 90 if (seteuid(uid) < 0) 91 err(-1, "seteuid(%d)", uid); 92 } 93 94 void 95 set_euid(uid_t uid) 96 { 97 98 if (seteuid(uid) < 0) 99 err(-1, "seteuid(%d)", uid); 100 } 101 102 void 103 restore_creds(void) 104 { 105 106 if (seteuid(UID_ROOT) < 0) 107 err(-1, "seteuid(%d)", UID_ROOT); 108 if (setegid(GID_WHEEL) < 0) 109 err(-1, "setegid(%d)", GID_WHEEL); 110 } 111 112 /* 113 * Execute tests in a child process so they don't contaminate each other, 114 * especially with regard to file descriptors, credentials, working 115 * directories, and chroot status. 116 */ 117 static void 118 run(const char *funcname, void (*func)(void)) 119 { 120 pid_t childpid, pid; 121 122 printf("running %s\n", funcname); 123 fflush(stdout); 124 fflush(stderr); 125 childpid = fork(); 126 if (childpid == -1) 127 err(-1, "test %s unable to fork", funcname); 128 if (childpid == 0) { 129 setprogname(funcname); 130 func(); 131 fflush(stdout); 132 fflush(stderr); 133 exit(0); 134 } else { 135 while (1) { 136 pid = waitpid(childpid, NULL, 0); 137 if (pid == -1) 138 warn("waitpid %s", funcname); 139 if (pid == childpid) 140 break; 141 } 142 } 143 fflush(stdout); 144 fflush(stderr); 145 } 146 147 int 148 main(int argc, char *argv[]) 149 { 150 151 run("priv_acct", priv_acct); 152 run("priv_adjtime", priv_adjtime); 153 run("priv_clock_settime", priv_clock_settime); 154 run("priv_io", priv_io); 155 run("priv_kenv_set", priv_kenv_set); 156 run("priv_kenv_unset", priv_kenv_unset); 157 run("priv_proc_setlogin", priv_proc_setlogin); 158 run("priv_proc_setrlimit", priv_proc_setrlimit); 159 run("priv_sched_rtprio", priv_sched_rtprio); 160 run("priv_sched_setpriority", priv_sched_setpriority); 161 run("priv_settimeofday", priv_settimeofday); 162 run("priv_sysctl_write", priv_sysctl_write); 163 run("priv_vfs_admin", priv_vfs_admin); 164 run("priv_vfs_chown", priv_vfs_chown); 165 run("priv_vfs_chroot", priv_vfs_chroot); 166 run("priv_vfs_clearsugid", priv_vfs_clearsugid); 167 run("priv_vfs_extattr_system", priv_vfs_extattr_system); 168 run("priv_vfs_fhopen", priv_vfs_fhopen); 169 run("priv_vfs_fhstat", priv_vfs_fhstat); 170 run("priv_vfs_fhstatfs", priv_vfs_fhstatfs); 171 run("priv_vfs_generation", priv_vfs_generation); 172 run("priv_vfs_getfh", priv_vfs_getfh); 173 run("priv_vfs_read", priv_vfs_read); 174 run("priv_vfs_setgid", priv_vfs_setgid); 175 run("priv_vfs_stickyfile", priv_vfs_stickyfile); 176 run("priv_vfs_write", priv_vfs_write); 177 run("priv_vm_madv_protect", priv_vm_madv_protect); 178 run("priv_vm_mlock", priv_vm_mlock); 179 run("priv_vm_munlock", priv_vm_munlock); 180 181 run("test_utimes", test_utimes); 182 183 return (0); 184 } 185