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 31 /* 32 * Test that privilege is required to lower nice value; first test with, then 33 * without. There are two failure modes associated with privilege: the right 34 * to renice a process with a different uid, and the right to renice to a 35 * lower priority. Because both the real and effective uid are part of the 36 * permissions test, we have to create two children processes with different 37 * uids. 38 */ 39 40 #include <sys/types.h> 41 #include <sys/resource.h> 42 #include <sys/wait.h> 43 44 #include <err.h> 45 #include <errno.h> 46 #include <signal.h> 47 #include <stdlib.h> 48 #include <unistd.h> 49 50 #include "main.h" 51 52 static int childproc_running; 53 static pid_t childproc; 54 55 int 56 priv_sched_setpriority_setup(int asroot, int injail, struct test *test) 57 { 58 int another_uid, need_child; 59 60 /* 61 * Some tests require a second process with specific credentials. 62 * Set that up here, and kill in cleanup. 63 */ 64 need_child = 0; 65 if (test->t_test_func == priv_sched_setpriority_aproc) { 66 need_child = 1; 67 another_uid = 1; 68 } 69 if (test->t_test_func == priv_sched_setpriority_myproc) 70 need_child = 1; 71 72 if (need_child) { 73 childproc = fork(); 74 if (childproc < 0) { 75 warn("priv_sched_setup: fork"); 76 return (-1); 77 } 78 if (childproc == 0) { 79 if (another_uid) { 80 if (setresuid(UID_THIRD, UID_THIRD, 81 UID_THIRD) < 0) 82 err(-1, "setresuid(%d)", UID_THIRD); 83 } 84 while (1) 85 sleep(1); 86 } 87 childproc_running = 1; 88 sleep(1); /* Allow dummy thread to change uids. */ 89 } 90 return (0); 91 } 92 93 void 94 priv_sched_setpriority_curproc(int asroot, int injail, struct test *test) 95 { 96 int error; 97 98 error = setpriority(PRIO_PROCESS, 0, -1); 99 if (asroot && injail) 100 expect("priv_sched_setpriority_curproc(asroot, injail)", 101 error, -1, EACCES); 102 if (asroot && !injail) 103 expect("priv_sched_setpriority_curproc(asroot, !injail)", 104 error, 0, 0); 105 if (!asroot && injail) 106 expect("priv_sched_setpriority_curproc(!asroot, injail)", 107 error, -1, EACCES); 108 if (!asroot && !injail) 109 expect("priv_sched_setpriority_curproc(!asroot, !injail)", 110 error, -1, EACCES); 111 } 112 113 void 114 priv_sched_setpriority_myproc(int asroot, int injail, struct test *test) 115 { 116 int error; 117 118 error = setpriority(PRIO_PROCESS, 0, -1); 119 if (asroot && injail) 120 expect("priv_sched_setpriority_myproc(asroot, injail)", 121 error, -1, EACCES); 122 if (asroot && !injail) 123 expect("priv_sched_setpriority_myproc(asroot, !injail)", 124 error, 0, 0); 125 if (!asroot && injail) 126 expect("priv_sched_setpriority_myproc(!asroot, injail)", 127 error, -1, EACCES); 128 if (!asroot && !injail) 129 expect("priv_sched_setpriority_myproc(!asroot, !injail)", 130 error, -1, EACCES); 131 } 132 133 void 134 priv_sched_setpriority_aproc(int asroot, int injail, struct test *test) 135 { 136 int error; 137 138 error = setpriority(PRIO_PROCESS, 0, -1); 139 if (asroot && injail) 140 expect("priv_sched_setpriority_aproc(asroot, injail)", 141 error, -1, EACCES); 142 if (asroot && !injail) 143 expect("priv_sched_setpriority_aproc(asroot, !injail)", 144 error, 0, 0); 145 if (!asroot && injail) 146 expect("priv_sched_setpriority_aproc(!asroot, injail)", 147 error, -1, EACCES); 148 if (!asroot && !injail) 149 expect("priv_sched_setpriority_aproc(!asroot, !injail)", 150 error, -1, EACCES); 151 } 152 153 void 154 priv_sched_setpriority_cleanup(int asroot, int injail, struct test *test) 155 { 156 pid_t pid; 157 158 if (childproc_running) { 159 (void)kill(childproc, SIGKILL); 160 while (1) { 161 pid = waitpid(childproc, NULL, 0); 162 if (pid == -1) 163 warn("waitpid(%d (test), NULL, 0)", 164 childproc); 165 if (pid == childproc) 166 break; 167 } 168 childproc_running = 0; 169 childproc = -1; 170 } 171 } 172