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
priv_sched_setpriority_setup(int asroot,int injail,struct test * test)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
priv_sched_setpriority_curproc(int asroot,int injail,struct test * test)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
priv_sched_setpriority_myproc(int asroot,int injail,struct test * test)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
priv_sched_setpriority_aproc(int asroot,int injail,struct test * test)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
priv_sched_setpriority_cleanup(int asroot,int injail,struct test * test)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