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 privilege associated with real time process settings. There are
35 * three relevant notions of privilege:
36 *
37 * - Privilege to set the real-time priority of the current process.
38 * - Privilege to set the real-time priority of another process.
39 * - Privilege to set the idle priority of another process.
40 * - No privilege to set the idle priority of the current process.
41 *
42 * This requires a test process and a target (dummy) process running with
43 * various uids. This test is based on the code in the setpriority() test.
44 */
45
46 #include <sys/types.h>
47 #include <sys/rtprio.h>
48 #include <sys/wait.h>
49
50 #include <err.h>
51 #include <errno.h>
52 #include <signal.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55
56 #include "main.h"
57
58 static int childproc_running;
59 static pid_t childproc;
60
61 int
priv_sched_rtprio_setup(int asroot,int injail,struct test * test)62 priv_sched_rtprio_setup(int asroot, int injail, struct test *test)
63 {
64 int another_uid, need_child;
65
66 /*
67 * Some tests require a second process with specific credentials.
68 * Set that up here, and kill in cleanup.
69 */
70 need_child = 0;
71 if (test->t_test_func == priv_sched_rtprio_aproc_normal ||
72 test->t_test_func == priv_sched_rtprio_aproc_idle ||
73 test->t_test_func == priv_sched_rtprio_aproc_realtime) {
74 need_child = 1;
75 another_uid = 1;
76 }
77 if (test->t_test_func == priv_sched_rtprio_myproc_normal ||
78 test->t_test_func == priv_sched_rtprio_myproc_idle ||
79 test->t_test_func == priv_sched_rtprio_myproc_realtime) {
80 need_child = 1;
81 }
82
83 if (need_child) {
84 childproc = fork();
85 if (childproc < 0) {
86 warn("priv_sched_setup: fork");
87 return (-1);
88 }
89 if (childproc == 0) {
90 if (another_uid) {
91 if (setresuid(UID_THIRD, UID_THIRD,
92 UID_THIRD) < 0)
93 err(-1, "setresuid(%d)", UID_THIRD);
94 }
95 while (1)
96 sleep(1);
97 }
98 childproc_running = 1;
99 sleep(1); /* Allow dummy thread to change uids. */
100 }
101 return (0);
102 }
103
104 void
priv_sched_rtprio_curproc_normal(int asroot,int injail,struct test * test)105 priv_sched_rtprio_curproc_normal(int asroot, int injail, struct test *test)
106 {
107 struct rtprio rtp;
108 int error;
109
110 rtp.type = RTP_PRIO_NORMAL;
111 rtp.prio = 0;
112 error = rtprio(RTP_SET, 0, &rtp);
113 if (asroot && injail)
114 expect("priv_sched_rtprio_curproc_normal(asroot, injail)",
115 error, 0, 0);
116 if (asroot && !injail)
117 expect("priv_sched_rtprio_curproc_normal(asroot, !injail)",
118 error, 0, 0);
119 if (!asroot && injail)
120 expect("priv_sched_rtprio_curproc_normal(!asroot, injail)",
121 error, 0, 0);
122 if (!asroot && !injail)
123 expect("priv_sched_rtprio_curproc_normal(!asroot, !injail)",
124 error, 0, 0);
125 }
126
127 void
priv_sched_rtprio_curproc_idle(int asroot,int injail,struct test * test)128 priv_sched_rtprio_curproc_idle(int asroot, int injail, struct test *test)
129 {
130 struct rtprio rtp;
131 int error;
132
133 rtp.type = RTP_PRIO_IDLE;
134 rtp.prio = 0;
135 error = rtprio(RTP_SET, 0, &rtp);
136 if (asroot && injail)
137 expect("priv_sched_rtprio_curproc_idle(asroot, injail)",
138 error, -1, EPERM);
139 if (asroot && !injail)
140 expect("priv_sched_rtprio_curproc_idle(asroot, !injail)",
141 error, 0, 0);
142 if (!asroot && injail)
143 expect("priv_sched_rtprio_curproc_idle(!asroot, injail)",
144 error, -1, EPERM);
145 if (!asroot && !injail)
146 expect("priv_sched_rtprio_curproc_idle(!asroot, !injail)",
147 error, -1, EPERM);
148 }
149
150 void
priv_sched_rtprio_curproc_realtime(int asroot,int injail,struct test * test)151 priv_sched_rtprio_curproc_realtime(int asroot, int injail, struct test *test)
152 {
153 struct rtprio rtp;
154 int error;
155
156 rtp.type = RTP_PRIO_REALTIME;
157 rtp.prio = 0;
158 error = rtprio(RTP_SET, 0, &rtp);
159 if (asroot && injail)
160 expect("priv_sched_rtprio_curproc_realtime(asroot, injail)",
161 error, -1, EPERM);
162 if (asroot && !injail)
163 expect("priv_sched_rtprio_curproc_realtime(asroot, !injail)",
164 error, 0, 0);
165 if (!asroot && injail)
166 expect("priv_sched_rtprio_curproc_realtime(!asroot, injail)",
167 error, -1, EPERM);
168 if (!asroot && !injail)
169 expect("priv_sched_rtprio_curproc_realtime(!asroot, !injail)",
170 error, -1, EPERM);
171 }
172
173 void
priv_sched_rtprio_myproc_normal(int asroot,int injail,struct test * test)174 priv_sched_rtprio_myproc_normal(int asroot, int injail, struct test *test)
175 {
176 struct rtprio rtp;
177 int error;
178
179 rtp.type = RTP_PRIO_NORMAL;
180 rtp.prio = 0;
181 error = rtprio(RTP_SET, 0, &rtp);
182 if (asroot && injail)
183 expect("priv_sched_rtprio_myproc_normal(asroot, injail)",
184 error, 0, 0);
185 if (asroot && !injail)
186 expect("priv_sched_rtprio_myproc_normal(asroot, !injail)",
187 error, 0, 0);
188 if (!asroot && injail)
189 expect("priv_sched_rtprio_myproc_normal(!asroot, injail)",
190 error, 0, 0);
191 if (!asroot && !injail)
192 expect("priv_sched_rtprio_myproc_normal(!asroot, !injail)",
193 error, 0, 0);
194 }
195
196 void
priv_sched_rtprio_myproc_idle(int asroot,int injail,struct test * test)197 priv_sched_rtprio_myproc_idle(int asroot, int injail, struct test *test)
198 {
199 struct rtprio rtp;
200 int error;
201
202 rtp.type = RTP_PRIO_IDLE;
203 rtp.prio = 0;
204 error = rtprio(RTP_SET, 0, &rtp);
205 if (asroot && injail)
206 expect("priv_sched_rtprio_myproc_idle(asroot, injail)",
207 error, -1, EPERM);
208 if (asroot && !injail)
209 expect("priv_sched_rtprio_myproc_idle(asroot, !injail)",
210 error, 0, 0);
211 if (!asroot && injail)
212 expect("priv_sched_rtprio_myproc_idle(!asroot, injail)",
213 error, -1, EPERM);
214 if (!asroot && !injail)
215 expect("priv_sched_rtprio_myproc_idle(!asroot, !injail)",
216 error, -1, EPERM);
217 }
218
219 void
priv_sched_rtprio_myproc_realtime(int asroot,int injail,struct test * test)220 priv_sched_rtprio_myproc_realtime(int asroot, int injail, struct test *test)
221 {
222 struct rtprio rtp;
223 int error;
224
225 rtp.type = RTP_PRIO_REALTIME;
226 rtp.prio = 0;
227 error = rtprio(RTP_SET, 0, &rtp);
228 if (asroot && injail)
229 expect("priv_sched_rtprio_myproc_realtime(asroot, injail)",
230 error, -1, EPERM);
231 if (asroot && !injail)
232 expect("priv_sched_rtprio_myproc_realtime(asroot, !injail)",
233 error, 0, 0);
234 if (!asroot && injail)
235 expect("priv_sched_rtprio_myproc_realtime(!asroot, injail)",
236 error, -1, EPERM);
237 if (!asroot && !injail)
238 expect("priv_sched_rtprio_myproc_realtime(!asroot, !injail)",
239 error, -1, EPERM);
240 }
241
242 void
priv_sched_rtprio_aproc_normal(int asroot,int injail,struct test * test)243 priv_sched_rtprio_aproc_normal(int asroot, int injail, struct test *test)
244 {
245 struct rtprio rtp;
246 int error;
247
248 rtp.type = RTP_PRIO_NORMAL;
249 rtp.prio = 0;
250 error = rtprio(RTP_SET, childproc, &rtp);
251 if (asroot && injail)
252 expect("priv_sched_rtprio_aproc_normal(asroot, injail)",
253 error, -1, ESRCH);
254 if (asroot && !injail)
255 expect("priv_sched_rtprio_aproc_normal(asroot, !injail)",
256 error, 0, 0);
257 if (!asroot && injail)
258 expect("priv_sched_rtprio_aproc_normal(!asroot, injail)",
259 error, -1, ESRCH);
260 if (!asroot && !injail)
261 expect("priv_sched_rtprio_aproc_normal(!asroot, !injail)",
262 error, -1, EPERM);
263 }
264
265 void
priv_sched_rtprio_aproc_idle(int asroot,int injail,struct test * test)266 priv_sched_rtprio_aproc_idle(int asroot, int injail, struct test *test)
267 {
268 struct rtprio rtp;
269 int error;
270
271 rtp.type = RTP_PRIO_IDLE;
272 rtp.prio = 0;
273 error = rtprio(RTP_SET, childproc, &rtp);
274 if (asroot && injail)
275 expect("priv_sched_rtprio_aproc_idle(asroot, injail)",
276 error, -1, ESRCH);
277 if (asroot && !injail)
278 expect("priv_sched_rtprio_aproc_idle(asroot, !injail)",
279 error, 0, 0);
280 if (!asroot && injail)
281 expect("priv_sched_rtprio_aproc_idle(!asroot, injail)",
282 error, -1, ESRCH);
283 if (!asroot && !injail)
284 expect("priv_sched_rtprio_aroc_idle(!asroot, !injail)",
285 error, -1, EPERM);
286 }
287
288 void
priv_sched_rtprio_aproc_realtime(int asroot,int injail,struct test * test)289 priv_sched_rtprio_aproc_realtime(int asroot, int injail, struct test *test)
290 {
291 struct rtprio rtp;
292 int error;
293
294 rtp.type = RTP_PRIO_REALTIME;
295 rtp.prio = 0;
296 error = rtprio(RTP_SET, childproc, &rtp);
297 if (asroot && injail)
298 expect("priv_sched_rtprio_aproc_realtime(asroot, injail)",
299 error, -1, ESRCH);
300 if (asroot && !injail)
301 expect("priv_sched_rtprio_aproc_realtime(asroot, !injail)",
302 error, 0, 0);
303 if (!asroot && injail)
304 expect("priv_sched_rtprio_aproc_realtime(!asroot, injail)",
305 error, -1, ESRCH);
306 if (!asroot && !injail)
307 expect("priv_sched_rtprio_aproc_realtime(!asroot, !injail)",
308 error, -1, EPERM);
309 }
310
311 void
priv_sched_rtprio_cleanup(int asroot,int injail,struct test * test)312 priv_sched_rtprio_cleanup(int asroot, int injail, struct test *test)
313 {
314 pid_t pid;
315
316 if (childproc_running) {
317 (void)kill(childproc, SIGKILL);
318 while (1) {
319 pid = waitpid(childproc, NULL, 0);
320 if (pid == -1)
321 warn("waitpid(%d (test), NULL, 0)",
322 childproc);
323 if (pid == childproc)
324 break;
325 }
326 childproc_running = 0;
327 childproc = -1;
328 }
329 }
330