xref: /freebsd/tools/regression/priv/priv_sched_setpriority.c (revision 2b743a9e9ddc6736208dc8ca1ce06ce64ad20a19)
1 /*-
2  * Copyright (c) 2006 nCircle Network Security, Inc.
3  * All rights reserved.
4  *
5  * This software was developed by Robert N. M. Watson for the TrustedBSD
6  * Project under contract to nCircle Network Security, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
21  * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * Test that privilege is required to lower nice value; first test with, then
34  * without.  There are two failure modes associated with privilege: the right
35  * to renice a process with a different uid, and the right to renice to a
36  * lower priority.  Because both the real and effective uid are part of the
37  * permissions test, we have to create two children processes with different
38  * uids.
39  */
40 
41 #include <sys/types.h>
42 #include <sys/resource.h>
43 #include <sys/wait.h>
44 
45 #include <err.h>
46 #include <errno.h>
47 #include <signal.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 
51 #include "main.h"
52 
53 static void
54 dummy(void)
55 {
56 
57 	while (1)
58 		sleep(1);
59 }
60 
61 static void
62 collect(pid_t test_pid, pid_t dummy_pid)
63 {
64 	pid_t pid;
65 
66 	/*
67 	 * First, collect the main test process.  When it has exited, then
68 	 * kill off the dummy process.
69 	 */
70 	if (test_pid > 0) {
71 		while (1) {
72 			pid = waitpid(test_pid, NULL, 0);
73 			if (pid == -1)
74 				warn("waitpid(%d (test), NULL, 0)", test_pid);
75 			if (pid == test_pid)
76 				break;
77 		}
78 	}
79 
80 	if (kill(dummy_pid, SIGKILL) < 0)
81 		err(-1, "kill(%d, SIGKILL)", dummy_pid);
82 
83 	while (1) {
84 		pid = waitpid(dummy_pid, NULL, 0);
85 		if (pid == -1)
86 			warn("waitpid(%d, NULL, 0)", dummy_pid);
87 		if (pid == dummy_pid)
88 			return;
89 	}
90 }
91 
92 static void
93 test(pid_t dummy_pid)
94 {
95 	int error;
96 
97 	/*
98 	 * Tests first as root.
99 	 */
100 	if (setpriority(PRIO_PROCESS, 0, -1) < 0)
101 		err(-1, "setpriority(PRIO_PROCESS, 0, -1) as root");
102 
103 	if (setpriority(PRIO_PROCESS, dummy_pid, -1) < 0)
104 		err(-1, "setpriority(PRIO_PROCESS, %d, -1) as root",
105 		    dummy_pid);
106 
107 	/*
108 	 * Then test again as a different credential.
109 	 */
110 	if (setresuid(UID_OTHER, UID_OTHER, UID_OTHER) < 0)
111 		err(-1, "setresuid(%d)", UID_OTHER);
112 
113 	error = setpriority(PRIO_PROCESS, 0, -2);
114 	if (error == 0)
115 		errx(-1,
116 		    "setpriority(PRIO_PROCESS, 0, -2) succeeded as !root");
117 	if (errno != EACCES)
118 		err(-1, "setpriority(PRIO_PROCESS, 0, 2) wrong errno %d as "
119 		    "!root", errno);
120 
121 	error = setpriority(PRIO_PROCESS, dummy_pid, -2);
122 	if (error == 0)
123 		errx(-1,
124 		    "setpriority(PRIO_PROCESS, %d, -2) succeeded as !root",
125 		    dummy_pid);
126 	if (errno != EPERM)
127 		err(-1, "setpriority(PRIO_PROCESS, %d, 2) wrong errno %d as "
128 		    "!root", dummy_pid, errno);
129 
130 	exit(0);
131 }
132 
133 void
134 priv_sched_setpriority(void)
135 {
136 	pid_t dummy_pid, test_pid;
137 
138 	assert_root();
139 
140 	/*
141 	 * Set up dummy process, which we will kill before exiting.
142 	 */
143 	dummy_pid = fork();
144 	if (dummy_pid < 0)
145 		err(-1, "fork - dummy");
146 	if (dummy_pid == 0) {
147 		if (setresuid(UID_THIRD, UID_THIRD, UID_THIRD) < 0)
148 			err(-1, "setresuid(%d)", UID_THIRD);
149 		dummy();
150 	}
151 	sleep(1);	/* Allow dummy thread to change uids. */
152 
153 	test_pid = fork();
154 	if (test_pid < 0) {
155 		warn("fork - test");
156 		collect(-1, dummy_pid);
157 		return;
158 	}
159 	if (test_pid == 0)
160 		test(dummy_pid);
161 
162 	collect(test_pid, dummy_pid);
163 }
164