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