1 /*- 2 * Copyright (c) 2006 nCircle Network Security, Inc. 3 * Copyright (c) 2007 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * This software was developed by Robert N. M. Watson for the TrustedBSD 7 * Project under contract to nCircle Network Security, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 22 * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 24 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $FreeBSD$ 31 */ 32 33 /* 34 * Test that privilege is required to lower nice value; first test with, then 35 * without. There are two failure modes associated with privilege: the right 36 * to renice a process with a different uid, and the right to renice to a 37 * lower priority. Because both the real and effective uid are part of the 38 * permissions test, we have to create two children processes with different 39 * uids. 40 */ 41 42 #include <sys/types.h> 43 #include <sys/resource.h> 44 #include <sys/wait.h> 45 46 #include <err.h> 47 #include <errno.h> 48 #include <signal.h> 49 #include <stdlib.h> 50 #include <unistd.h> 51 52 #include "main.h" 53 54 static int childproc_running; 55 static pid_t childproc; 56 57 int 58 priv_sched_setpriority_setup(int asroot, int injail, struct test *test) 59 { 60 int another_uid, need_child; 61 62 /* 63 * Some tests require a second process with specific credentials. 64 * Set that up here, and kill in cleanup. 65 */ 66 need_child = 0; 67 if (test->t_test_func == priv_sched_setpriority_aproc) { 68 need_child = 1; 69 another_uid = 1; 70 } 71 if (test->t_test_func == priv_sched_setpriority_myproc) 72 need_child = 1; 73 74 if (need_child) { 75 childproc = fork(); 76 if (childproc < 0) { 77 warn("priv_sched_setup: fork"); 78 return (-1); 79 } 80 if (childproc == 0) { 81 if (another_uid) { 82 if (setresuid(UID_THIRD, UID_THIRD, 83 UID_THIRD) < 0) 84 err(-1, "setresuid(%d)", UID_THIRD); 85 } 86 while (1) 87 sleep(1); 88 } 89 childproc_running = 1; 90 sleep(1); /* Allow dummy thread to change uids. */ 91 } 92 return (0); 93 } 94 95 void 96 priv_sched_setpriority_curproc(int asroot, int injail, struct test *test) 97 { 98 int error; 99 100 error = setpriority(PRIO_PROCESS, 0, -1); 101 if (asroot && injail) 102 expect("priv_sched_setpriority_curproc(asroot, injail)", 103 error, -1, EACCES); 104 if (asroot && !injail) 105 expect("priv_sched_setpriority_curproc(asroot, !injail)", 106 error, 0, 0); 107 if (!asroot && injail) 108 expect("priv_sched_setpriority_curproc(!asroot, injail)", 109 error, -1, EACCES); 110 if (!asroot && !injail) 111 expect("priv_sched_setpriority_curproc(!asroot, !injail)", 112 error, -1, EACCES); 113 } 114 115 void 116 priv_sched_setpriority_myproc(int asroot, int injail, struct test *test) 117 { 118 int error; 119 120 error = setpriority(PRIO_PROCESS, 0, -1); 121 if (asroot && injail) 122 expect("priv_sched_setpriority_myproc(asroot, injail)", 123 error, -1, EACCES); 124 if (asroot && !injail) 125 expect("priv_sched_setpriority_myproc(asroot, !injail)", 126 error, 0, 0); 127 if (!asroot && injail) 128 expect("priv_sched_setpriority_myproc(!asroot, injail)", 129 error, -1, EACCES); 130 if (!asroot && !injail) 131 expect("priv_sched_setpriority_myproc(!asroot, !injail)", 132 error, -1, EACCES); 133 } 134 135 void 136 priv_sched_setpriority_aproc(int asroot, int injail, struct test *test) 137 { 138 int error; 139 140 error = setpriority(PRIO_PROCESS, 0, -1); 141 if (asroot && injail) 142 expect("priv_sched_setpriority_aproc(asroot, injail)", 143 error, -1, EACCES); 144 if (asroot && !injail) 145 expect("priv_sched_setpriority_aproc(asroot, !injail)", 146 error, 0, 0); 147 if (!asroot && injail) 148 expect("priv_sched_setpriority_aproc(!asroot, injail)", 149 error, -1, EACCES); 150 if (!asroot && !injail) 151 expect("priv_sched_setpriority_aproc(!asroot, !injail)", 152 error, -1, EACCES); 153 } 154 155 void 156 priv_sched_setpriority_cleanup(int asroot, int injail, struct test *test) 157 { 158 pid_t pid; 159 160 if (childproc_running) { 161 (void)kill(childproc, SIGKILL); 162 while (1) { 163 pid = waitpid(childproc, NULL, 0); 164 if (pid == -1) 165 warn("waitpid(%d (test), NULL, 0)", 166 childproc); 167 if (pid == childproc) 168 break; 169 } 170 childproc_running = 0; 171 childproc = -1; 172 } 173 } 174