1162271Srwatson/*-
2162271Srwatson * Copyright (c) 2006 nCircle Network Security, Inc.
3172106Srwatson * Copyright (c) 2007 Robert N. M. Watson
4162271Srwatson * All rights reserved.
5162271Srwatson *
6162271Srwatson * This software was developed by Robert N. M. Watson for the TrustedBSD
7162271Srwatson * Project under contract to nCircle Network Security, Inc.
8162271Srwatson *
9162271Srwatson * Redistribution and use in source and binary forms, with or without
10162271Srwatson * modification, are permitted provided that the following conditions
11162271Srwatson * are met:
12162271Srwatson * 1. Redistributions of source code must retain the above copyright
13162271Srwatson *    notice, this list of conditions and the following disclaimer.
14162271Srwatson * 2. Redistributions in binary form must reproduce the above copyright
15162271Srwatson *    notice, this list of conditions and the following disclaimer in the
16162271Srwatson *    documentation and/or other materials provided with the distribution.
17162271Srwatson *
18162271Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19162271Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20162271Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21162271Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
22162271Srwatson * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23162271Srwatson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24162271Srwatson * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25162271Srwatson * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26162271Srwatson * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27162271Srwatson * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28162271Srwatson * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29162271Srwatson *
30162271Srwatson * $FreeBSD: releng/10.3/tools/regression/priv/priv_sched_rtprio.c 172106 2007-09-09 23:08:39Z rwatson $
31162271Srwatson */
32162271Srwatson
33162271Srwatson/*
34162271Srwatson * Test privilege associated with real time process settings.  There are
35162271Srwatson * three relevant notions of privilege:
36162271Srwatson *
37162271Srwatson * - Privilege to set the real-time priority of the current process.
38162271Srwatson * - Privilege to set the real-time priority of another process.
39162271Srwatson * - Privilege to set the idle priority of another process.
40162271Srwatson * - No privilege to set the idle priority of the current process.
41162271Srwatson *
42162271Srwatson * This requires a test process and a target (dummy) process running with
43162271Srwatson * various uids.  This test is based on the code in the setpriority() test.
44162271Srwatson */
45162271Srwatson
46162271Srwatson#include <sys/types.h>
47162271Srwatson#include <sys/rtprio.h>
48162271Srwatson#include <sys/wait.h>
49162271Srwatson
50162271Srwatson#include <err.h>
51162271Srwatson#include <errno.h>
52162271Srwatson#include <signal.h>
53162271Srwatson#include <stdlib.h>
54162271Srwatson#include <unistd.h>
55162271Srwatson
56162271Srwatson#include "main.h"
57162271Srwatson
58172106Srwatsonstatic int	childproc_running;
59172106Srwatsonstatic pid_t	childproc;
60162271Srwatson
61172106Srwatsonint
62172106Srwatsonpriv_sched_rtprio_setup(int asroot, int injail, struct test *test)
63162271Srwatson{
64172106Srwatson	int another_uid, need_child;
65162271Srwatson
66162271Srwatson	/*
67172106Srwatson	 * Some tests require a second process with specific credentials.
68172106Srwatson	 * Set that up here, and kill in cleanup.
69162271Srwatson	 */
70172106Srwatson	need_child = 0;
71172106Srwatson	if (test->t_test_func == priv_sched_rtprio_aproc_normal ||
72172106Srwatson	    test->t_test_func == priv_sched_rtprio_aproc_idle ||
73172106Srwatson	    test->t_test_func == priv_sched_rtprio_aproc_realtime) {
74172106Srwatson		need_child = 1;
75172106Srwatson		another_uid = 1;
76162271Srwatson	}
77172106Srwatson	if (test->t_test_func == priv_sched_rtprio_myproc_normal ||
78172106Srwatson	    test->t_test_func == priv_sched_rtprio_myproc_idle ||
79172106Srwatson	    test->t_test_func == priv_sched_rtprio_myproc_realtime) {
80172106Srwatson		need_child = 1;
81172106Srwatson	}
82162271Srwatson
83172106Srwatson	if (need_child) {
84172106Srwatson		childproc = fork();
85172106Srwatson		if (childproc < 0) {
86172106Srwatson			warn("priv_sched_setup: fork");
87172106Srwatson			return (-1);
88172106Srwatson		}
89172106Srwatson		if (childproc == 0) {
90172106Srwatson			if (another_uid) {
91172106Srwatson				if (setresuid(UID_THIRD, UID_THIRD,
92172106Srwatson				    UID_THIRD) < 0)
93172106Srwatson				err(-1, "setresuid(%d)", UID_THIRD);
94172106Srwatson			}
95172106Srwatson			while (1)
96172106Srwatson				sleep(1);
97172106Srwatson		}
98172106Srwatson		childproc_running = 1;
99172106Srwatson		sleep(1);	/* Allow dummy thread to change uids. */
100162271Srwatson	}
101172106Srwatson	return (0);
102162271Srwatson}
103162271Srwatson
104172106Srwatsonvoid
105172106Srwatsonpriv_sched_rtprio_curproc_normal(int asroot, int injail, struct test *test)
106162271Srwatson{
107162271Srwatson	struct rtprio rtp;
108162271Srwatson	int error;
109162271Srwatson
110172106Srwatson	rtp.type = RTP_PRIO_NORMAL;
111162271Srwatson	rtp.prio = 0;
112172106Srwatson	error = rtprio(RTP_SET, 0, &rtp);
113172106Srwatson	if (asroot && injail)
114172106Srwatson		expect("priv_sched_rtprio_curproc_normal(asroot, injail)",
115172106Srwatson		    error, 0, 0);
116172106Srwatson	if (asroot && !injail)
117172106Srwatson		expect("priv_sched_rtprio_curproc_normal(asroot, !injail)",
118172106Srwatson		    error, 0, 0);
119172106Srwatson	if (!asroot && injail)
120172106Srwatson		expect("priv_sched_rtprio_curproc_normal(!asroot, injail)",
121172106Srwatson		    error, 0, 0);
122172106Srwatson	if (!asroot && !injail)
123172106Srwatson		expect("priv_sched_rtprio_curproc_normal(!asroot, !injail)",
124172106Srwatson		    error, 0, 0);
125172106Srwatson}
126162271Srwatson
127172106Srwatsonvoid
128172106Srwatsonpriv_sched_rtprio_curproc_idle(int asroot, int injail, struct test *test)
129172106Srwatson{
130172106Srwatson	struct rtprio rtp;
131172106Srwatson	int error;
132172106Srwatson
133162271Srwatson	rtp.type = RTP_PRIO_IDLE;
134162271Srwatson	rtp.prio = 0;
135172106Srwatson	error = rtprio(RTP_SET, 0, &rtp);
136172106Srwatson	if (asroot && injail)
137172106Srwatson		expect("priv_sched_rtprio_curproc_idle(asroot, injail)",
138172106Srwatson		    error, -1, EPERM);
139172106Srwatson	if (asroot && !injail)
140172106Srwatson		expect("priv_sched_rtprio_curproc_idle(asroot, !injail)",
141172106Srwatson		    error, 0, 0);
142172106Srwatson	if (!asroot && injail)
143172106Srwatson		expect("priv_sched_rtprio_curproc_idle(!asroot, injail)",
144172106Srwatson		    error, -1, EPERM);
145172106Srwatson	if (!asroot && !injail)
146172106Srwatson		expect("priv_sched_rtprio_curproc_idle(!asroot, !injail)",
147172106Srwatson		    error, -1, EPERM);
148172106Srwatson}
149162271Srwatson
150172106Srwatsonvoid
151172106Srwatsonpriv_sched_rtprio_curproc_realtime(int asroot, int injail, struct test *test)
152172106Srwatson{
153172106Srwatson	struct rtprio rtp;
154172106Srwatson	int error;
155162271Srwatson
156162271Srwatson	rtp.type = RTP_PRIO_REALTIME;
157162271Srwatson	rtp.prio = 0;
158172106Srwatson	error = rtprio(RTP_SET, 0, &rtp);
159172106Srwatson	if (asroot && injail)
160172106Srwatson		expect("priv_sched_rtprio_curproc_realtime(asroot, injail)",
161172106Srwatson		    error, -1, EPERM);
162172106Srwatson	if (asroot && !injail)
163172106Srwatson		expect("priv_sched_rtprio_curproc_realtime(asroot, !injail)",
164172106Srwatson		    error, 0, 0);
165172106Srwatson	if (!asroot && injail)
166172106Srwatson		expect("priv_sched_rtprio_curproc_realtime(!asroot, injail)",
167172106Srwatson		    error, -1, EPERM);
168172106Srwatson	if (!asroot && !injail)
169172106Srwatson		expect("priv_sched_rtprio_curproc_realtime(!asroot, !injail)",
170172106Srwatson		    error, -1, EPERM);
171172106Srwatson}
172162271Srwatson
173172106Srwatsonvoid
174172106Srwatsonpriv_sched_rtprio_myproc_normal(int asroot, int injail, struct test *test)
175172106Srwatson{
176172106Srwatson	struct rtprio rtp;
177172106Srwatson	int error;
178162271Srwatson
179162271Srwatson	rtp.type = RTP_PRIO_NORMAL;
180162271Srwatson	rtp.prio = 0;
181172106Srwatson	error = rtprio(RTP_SET, 0, &rtp);
182172106Srwatson	if (asroot && injail)
183172106Srwatson		expect("priv_sched_rtprio_myproc_normal(asroot, injail)",
184172106Srwatson		    error, 0, 0);
185172106Srwatson	if (asroot && !injail)
186172106Srwatson		expect("priv_sched_rtprio_myproc_normal(asroot, !injail)",
187172106Srwatson		    error, 0, 0);
188172106Srwatson	if (!asroot && injail)
189172106Srwatson		expect("priv_sched_rtprio_myproc_normal(!asroot, injail)",
190172106Srwatson		    error, 0, 0);
191172106Srwatson	if (!asroot && !injail)
192172106Srwatson		expect("priv_sched_rtprio_myproc_normal(!asroot, !injail)",
193172106Srwatson		    error, 0, 0);
194172106Srwatson}
195162271Srwatson
196172106Srwatsonvoid
197172106Srwatsonpriv_sched_rtprio_myproc_idle(int asroot, int injail, struct test *test)
198172106Srwatson{
199172106Srwatson	struct rtprio rtp;
200172106Srwatson	int error;
201162271Srwatson
202172106Srwatson	rtp.type = RTP_PRIO_IDLE;
203162271Srwatson	rtp.prio = 0;
204162271Srwatson	error = rtprio(RTP_SET, 0, &rtp);
205172106Srwatson	if (asroot && injail)
206172106Srwatson		expect("priv_sched_rtprio_myproc_idle(asroot, injail)",
207172106Srwatson		    error, -1, EPERM);
208172106Srwatson	if (asroot && !injail)
209172106Srwatson		expect("priv_sched_rtprio_myproc_idle(asroot, !injail)",
210172106Srwatson		    error, 0, 0);
211172106Srwatson	if (!asroot && injail)
212172106Srwatson		expect("priv_sched_rtprio_myproc_idle(!asroot, injail)",
213172106Srwatson		    error, -1, EPERM);
214172106Srwatson	if (!asroot && !injail)
215172106Srwatson		expect("priv_sched_rtprio_myproc_idle(!asroot, !injail)",
216172106Srwatson		    error, -1, EPERM);
217172106Srwatson}
218162271Srwatson
219172106Srwatsonvoid
220172106Srwatsonpriv_sched_rtprio_myproc_realtime(int asroot, int injail, struct test *test)
221172106Srwatson{
222172106Srwatson	struct rtprio rtp;
223172106Srwatson	int error;
224172106Srwatson
225172106Srwatson	rtp.type = RTP_PRIO_REALTIME;
226162271Srwatson	rtp.prio = 0;
227162271Srwatson	error = rtprio(RTP_SET, 0, &rtp);
228172106Srwatson	if (asroot && injail)
229172106Srwatson		expect("priv_sched_rtprio_myproc_realtime(asroot, injail)",
230172106Srwatson		    error, -1, EPERM);
231172106Srwatson	if (asroot && !injail)
232172106Srwatson		expect("priv_sched_rtprio_myproc_realtime(asroot, !injail)",
233172106Srwatson		    error, 0, 0);
234172106Srwatson	if (!asroot && injail)
235172106Srwatson		expect("priv_sched_rtprio_myproc_realtime(!asroot, injail)",
236172106Srwatson		    error, -1, EPERM);
237172106Srwatson	if (!asroot && !injail)
238172106Srwatson		expect("priv_sched_rtprio_myproc_realtime(!asroot, !injail)",
239172106Srwatson		    error, -1, EPERM);
240172106Srwatson}
241162271Srwatson
242172106Srwatsonvoid
243172106Srwatsonpriv_sched_rtprio_aproc_normal(int asroot, int injail, struct test *test)
244172106Srwatson{
245172106Srwatson	struct rtprio rtp;
246172106Srwatson	int error;
247172106Srwatson
248162271Srwatson	rtp.type = RTP_PRIO_NORMAL;
249162271Srwatson	rtp.prio = 0;
250172106Srwatson	error = rtprio(RTP_SET, childproc, &rtp);
251172106Srwatson	if (asroot && injail)
252172106Srwatson		expect("priv_sched_rtprio_aproc_normal(asroot, injail)",
253172106Srwatson		    error, -1, ESRCH);
254172106Srwatson	if (asroot && !injail)
255172106Srwatson		expect("priv_sched_rtprio_aproc_normal(asroot, !injail)",
256172106Srwatson		    error, 0, 0);
257172106Srwatson	if (!asroot && injail)
258172106Srwatson		expect("priv_sched_rtprio_aproc_normal(!asroot, injail)",
259172106Srwatson		    error, -1, ESRCH);
260172106Srwatson	if (!asroot && !injail)
261172106Srwatson		expect("priv_sched_rtprio_aproc_normal(!asroot, !injail)",
262172106Srwatson		    error, -1, EPERM);
263172106Srwatson}
264162271Srwatson
265172106Srwatsonvoid
266172106Srwatsonpriv_sched_rtprio_aproc_idle(int asroot, int injail, struct test *test)
267172106Srwatson{
268172106Srwatson	struct rtprio rtp;
269172106Srwatson	int error;
270162271Srwatson
271162271Srwatson	rtp.type = RTP_PRIO_IDLE;
272162271Srwatson	rtp.prio = 0;
273172106Srwatson	error = rtprio(RTP_SET, childproc, &rtp);
274172106Srwatson	if (asroot && injail)
275172106Srwatson		expect("priv_sched_rtprio_aproc_idle(asroot, injail)",
276172106Srwatson		    error, -1, ESRCH);
277172106Srwatson	if (asroot && !injail)
278172106Srwatson		expect("priv_sched_rtprio_aproc_idle(asroot, !injail)",
279172106Srwatson		    error, 0, 0);
280172106Srwatson	if (!asroot && injail)
281172106Srwatson		expect("priv_sched_rtprio_aproc_idle(!asroot, injail)",
282172106Srwatson		    error, -1, ESRCH);
283172106Srwatson	if (!asroot && !injail)
284172106Srwatson		expect("priv_sched_rtprio_aroc_idle(!asroot, !injail)",
285172106Srwatson		    error, -1, EPERM);
286172106Srwatson}
287162271Srwatson
288172106Srwatsonvoid
289172106Srwatsonpriv_sched_rtprio_aproc_realtime(int asroot, int injail, struct test *test)
290172106Srwatson{
291172106Srwatson	struct rtprio rtp;
292172106Srwatson	int error;
293172106Srwatson
294172106Srwatson	rtp.type = RTP_PRIO_REALTIME;
295162271Srwatson	rtp.prio = 0;
296172106Srwatson	error = rtprio(RTP_SET, childproc, &rtp);
297172106Srwatson	if (asroot && injail)
298172106Srwatson		expect("priv_sched_rtprio_aproc_realtime(asroot, injail)",
299172106Srwatson		    error, -1, ESRCH);
300172106Srwatson	if (asroot && !injail)
301172106Srwatson		expect("priv_sched_rtprio_aproc_realtime(asroot, !injail)",
302172106Srwatson		    error, 0, 0);
303172106Srwatson	if (!asroot && injail)
304172106Srwatson		expect("priv_sched_rtprio_aproc_realtime(!asroot, injail)",
305172106Srwatson		    error, -1, ESRCH);
306172106Srwatson	if (!asroot && !injail)
307172106Srwatson		expect("priv_sched_rtprio_aproc_realtime(!asroot, !injail)",
308172106Srwatson		    error, -1, EPERM);
309162271Srwatson}
310162271Srwatson
311162271Srwatsonvoid
312172106Srwatsonpriv_sched_rtprio_cleanup(int asroot, int injail, struct test *test)
313162271Srwatson{
314172106Srwatson	pid_t pid;
315162271Srwatson
316172106Srwatson	if (childproc_running) {
317172106Srwatson		(void)kill(childproc, SIGKILL);
318172106Srwatson		while (1) {
319172106Srwatson			pid = waitpid(childproc, NULL, 0);
320172106Srwatson			if (pid == -1)
321172106Srwatson				warn("waitpid(%d (test), NULL, 0)",
322172106Srwatson				    childproc);
323172106Srwatson			if (pid == childproc)
324172106Srwatson				break;
325172106Srwatson		}
326172106Srwatson		childproc_running = 0;
327172106Srwatson		childproc = -1;
328162271Srwatson	}
329162271Srwatson}
330