19fa5f6b4SRobert Watson /*- 29fa5f6b4SRobert Watson * Copyright (c) 2006 nCircle Network Security, Inc. 3d903306aSRobert Watson * Copyright (c) 2007 Robert N. M. Watson 49fa5f6b4SRobert Watson * All rights reserved. 59fa5f6b4SRobert Watson * 69fa5f6b4SRobert Watson * This software was developed by Robert N. M. Watson for the TrustedBSD 79fa5f6b4SRobert Watson * Project under contract to nCircle Network Security, Inc. 89fa5f6b4SRobert Watson * 99fa5f6b4SRobert Watson * Redistribution and use in source and binary forms, with or without 109fa5f6b4SRobert Watson * modification, are permitted provided that the following conditions 119fa5f6b4SRobert Watson * are met: 129fa5f6b4SRobert Watson * 1. Redistributions of source code must retain the above copyright 139fa5f6b4SRobert Watson * notice, this list of conditions and the following disclaimer. 149fa5f6b4SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 159fa5f6b4SRobert Watson * notice, this list of conditions and the following disclaimer in the 169fa5f6b4SRobert Watson * documentation and/or other materials provided with the distribution. 179fa5f6b4SRobert Watson * 189fa5f6b4SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 199fa5f6b4SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 209fa5f6b4SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 219fa5f6b4SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 229fa5f6b4SRobert Watson * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 239fa5f6b4SRobert Watson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 249fa5f6b4SRobert Watson * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 259fa5f6b4SRobert Watson * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 269fa5f6b4SRobert Watson * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 279fa5f6b4SRobert Watson * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 289fa5f6b4SRobert Watson * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 299fa5f6b4SRobert Watson * 309fa5f6b4SRobert Watson * $FreeBSD$ 319fa5f6b4SRobert Watson */ 329fa5f6b4SRobert Watson 339fa5f6b4SRobert Watson /* 349fa5f6b4SRobert Watson * Test that privilege is required to lower nice value; first test with, then 359fa5f6b4SRobert Watson * without. There are two failure modes associated with privilege: the right 369fa5f6b4SRobert Watson * to renice a process with a different uid, and the right to renice to a 379fa5f6b4SRobert Watson * lower priority. Because both the real and effective uid are part of the 389fa5f6b4SRobert Watson * permissions test, we have to create two children processes with different 399fa5f6b4SRobert Watson * uids. 409fa5f6b4SRobert Watson */ 419fa5f6b4SRobert Watson 429fa5f6b4SRobert Watson #include <sys/types.h> 439fa5f6b4SRobert Watson #include <sys/resource.h> 449fa5f6b4SRobert Watson #include <sys/wait.h> 459fa5f6b4SRobert Watson 469fa5f6b4SRobert Watson #include <err.h> 479fa5f6b4SRobert Watson #include <errno.h> 489fa5f6b4SRobert Watson #include <signal.h> 499fa5f6b4SRobert Watson #include <stdlib.h> 509fa5f6b4SRobert Watson #include <unistd.h> 519fa5f6b4SRobert Watson 529fa5f6b4SRobert Watson #include "main.h" 539fa5f6b4SRobert Watson 54d903306aSRobert Watson static int childproc_running; 55d903306aSRobert Watson static pid_t childproc; 569fa5f6b4SRobert Watson 57d903306aSRobert Watson int 58d903306aSRobert Watson priv_sched_setpriority_setup(int asroot, int injail, struct test *test) 59d903306aSRobert Watson { 60d903306aSRobert Watson int another_uid, need_child; 61d903306aSRobert Watson 62d903306aSRobert Watson /* 63d903306aSRobert Watson * Some tests require a second process with specific credentials. 64d903306aSRobert Watson * Set that up here, and kill in cleanup. 65d903306aSRobert Watson */ 66d903306aSRobert Watson need_child = 0; 67d903306aSRobert Watson if (test->t_test_func == priv_sched_setpriority_aproc) { 68d903306aSRobert Watson need_child = 1; 69d903306aSRobert Watson another_uid = 1; 70d903306aSRobert Watson } 71d903306aSRobert Watson if (test->t_test_func == priv_sched_setpriority_myproc) 72d903306aSRobert Watson need_child = 1; 73d903306aSRobert Watson 74d903306aSRobert Watson if (need_child) { 75d903306aSRobert Watson childproc = fork(); 76d903306aSRobert Watson if (childproc < 0) { 77d903306aSRobert Watson warn("priv_sched_setup: fork"); 78d903306aSRobert Watson return (-1); 79d903306aSRobert Watson } 80d903306aSRobert Watson if (childproc == 0) { 81d903306aSRobert Watson if (another_uid) { 82d903306aSRobert Watson if (setresuid(UID_THIRD, UID_THIRD, 83d903306aSRobert Watson UID_THIRD) < 0) 84d903306aSRobert Watson err(-1, "setresuid(%d)", UID_THIRD); 85d903306aSRobert Watson } 869fa5f6b4SRobert Watson while (1) 879fa5f6b4SRobert Watson sleep(1); 889fa5f6b4SRobert Watson } 89d903306aSRobert Watson childproc_running = 1; 90d903306aSRobert Watson sleep(1); /* Allow dummy thread to change uids. */ 919fa5f6b4SRobert Watson } 92d903306aSRobert Watson return (0); 939fa5f6b4SRobert Watson } 949fa5f6b4SRobert Watson 959fa5f6b4SRobert Watson void 96d903306aSRobert Watson priv_sched_setpriority_curproc(int asroot, int injail, struct test *test) 979fa5f6b4SRobert Watson { 98d903306aSRobert Watson int error; 999fa5f6b4SRobert Watson 100d903306aSRobert Watson error = setpriority(PRIO_PROCESS, 0, -1); 101d903306aSRobert Watson if (asroot && injail) 102d903306aSRobert Watson expect("priv_sched_setpriority_curproc(asroot, injail)", 103d903306aSRobert Watson error, -1, EACCES); 104d903306aSRobert Watson if (asroot && !injail) 105d903306aSRobert Watson expect("priv_sched_setpriority_curproc(asroot, !injail)", 106d903306aSRobert Watson error, 0, 0); 107d903306aSRobert Watson if (!asroot && injail) 108d903306aSRobert Watson expect("priv_sched_setpriority_curproc(!asroot, injail)", 109d903306aSRobert Watson error, -1, EACCES); 110d903306aSRobert Watson if (!asroot && !injail) 111d903306aSRobert Watson expect("priv_sched_setpriority_curproc(!asroot, !injail)", 112d903306aSRobert Watson error, -1, EACCES); 1139fa5f6b4SRobert Watson } 1149fa5f6b4SRobert Watson 115d903306aSRobert Watson void 116d903306aSRobert Watson priv_sched_setpriority_myproc(int asroot, int injail, struct test *test) 117d903306aSRobert Watson { 118d903306aSRobert Watson int error; 119d903306aSRobert Watson 120d903306aSRobert Watson error = setpriority(PRIO_PROCESS, 0, -1); 121d903306aSRobert Watson if (asroot && injail) 122d903306aSRobert Watson expect("priv_sched_setpriority_myproc(asroot, injail)", 123d903306aSRobert Watson error, -1, EACCES); 124d903306aSRobert Watson if (asroot && !injail) 125d903306aSRobert Watson expect("priv_sched_setpriority_myproc(asroot, !injail)", 126d903306aSRobert Watson error, 0, 0); 127d903306aSRobert Watson if (!asroot && injail) 128d903306aSRobert Watson expect("priv_sched_setpriority_myproc(!asroot, injail)", 129d903306aSRobert Watson error, -1, EACCES); 130d903306aSRobert Watson if (!asroot && !injail) 131d903306aSRobert Watson expect("priv_sched_setpriority_myproc(!asroot, !injail)", 132d903306aSRobert Watson error, -1, EACCES); 1339fa5f6b4SRobert Watson } 1349fa5f6b4SRobert Watson 135d903306aSRobert Watson void 136d903306aSRobert Watson priv_sched_setpriority_aproc(int asroot, int injail, struct test *test) 137d903306aSRobert Watson { 138d903306aSRobert Watson int error; 139d903306aSRobert Watson 140d903306aSRobert Watson error = setpriority(PRIO_PROCESS, 0, -1); 141d903306aSRobert Watson if (asroot && injail) 142d903306aSRobert Watson expect("priv_sched_setpriority_aproc(asroot, injail)", 143d903306aSRobert Watson error, -1, EACCES); 144d903306aSRobert Watson if (asroot && !injail) 145d903306aSRobert Watson expect("priv_sched_setpriority_aproc(asroot, !injail)", 146d903306aSRobert Watson error, 0, 0); 147d903306aSRobert Watson if (!asroot && injail) 148d903306aSRobert Watson expect("priv_sched_setpriority_aproc(!asroot, injail)", 149d903306aSRobert Watson error, -1, EACCES); 150d903306aSRobert Watson if (!asroot && !injail) 151d903306aSRobert Watson expect("priv_sched_setpriority_aproc(!asroot, !injail)", 152d903306aSRobert Watson error, -1, EACCES); 153d903306aSRobert Watson } 154d903306aSRobert Watson 155d903306aSRobert Watson void 156d903306aSRobert Watson priv_sched_setpriority_cleanup(int asroot, int injail, struct test *test) 157d903306aSRobert Watson { 158d903306aSRobert Watson pid_t pid; 159d903306aSRobert Watson 160d903306aSRobert Watson if (childproc_running) { 161d903306aSRobert Watson (void)kill(childproc, SIGKILL); 162d903306aSRobert Watson while (1) { 163d903306aSRobert Watson pid = waitpid(childproc, NULL, 0); 164d903306aSRobert Watson if (pid == -1) 165d903306aSRobert Watson warn("waitpid(%d (test), NULL, 0)", 166d903306aSRobert Watson childproc); 167d903306aSRobert Watson if (pid == childproc) 168d903306aSRobert Watson break; 169d903306aSRobert Watson } 170d903306aSRobert Watson childproc_running = 0; 171d903306aSRobert Watson childproc = -1; 172d903306aSRobert Watson } 1739fa5f6b4SRobert Watson } 174