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