xref: /freebsd/tools/regression/priv/main.c (revision 3157ba21)
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  * Privilege test framework.  Each test is encapsulated on a .c file
35  * exporting a function that implements the test.  Each test is run from its
36  * own child process, and they are run in sequence one at a time.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/jail.h>
41 #include <sys/stat.h>
42 #include <sys/wait.h>
43 
44 #include <netinet/in.h>
45 
46 #include <err.h>
47 #include <errno.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 
53 #include "main.h"
54 
55 /*
56  * Registration table of privilege tests.  Each test registers a name, a test
57  * function, and a cleanup function to run after the test has completed,
58  * regardless of success/failure.
59  */
60 static struct test tests[] = {
61 	{ "priv_acct_enable", priv_acct_setup, priv_acct_enable,
62 	    priv_acct_cleanup },
63 
64 	{ "priv_acct_disable", priv_acct_setup, priv_acct_disable,
65 	    priv_acct_cleanup },
66 
67 	{ "priv_acct_rotate", priv_acct_setup, priv_acct_rotate,
68 	    priv_acct_cleanup },
69 
70 	{ "priv_acct_noopdisable", priv_acct_setup, priv_acct_noopdisable,
71 	    priv_acct_cleanup },
72 
73 	{ "priv_adjtime_set", priv_adjtime_setup, priv_adjtime_set,
74 	    priv_adjtime_cleanup },
75 
76 	{ "priv_audit_submit", priv_audit_submit_setup, priv_audit_submit,
77 	    priv_audit_submit_cleanup },
78 
79 	{ "priv_audit_control", priv_audit_control_setup, priv_audit_control,
80 	    priv_audit_control_cleanup },
81 
82 	{ "priv_audit_getaudit", priv_audit_getaudit_setup,
83 	    priv_audit_getaudit, priv_audit_getaudit_cleanup },
84 
85 	{ "priv_audit_getaudit_addr", priv_audit_getaudit_setup,
86 	    priv_audit_getaudit_addr, priv_audit_getaudit_cleanup },
87 
88 	{ "priv_audit_setaudit", priv_audit_setaudit_setup,
89 	    priv_audit_setaudit, priv_audit_setaudit_cleanup },
90 
91 	{ "priv_audit_setaudit_addr", priv_audit_setaudit_setup,
92 	    priv_audit_setaudit_addr, priv_audit_setaudit_cleanup },
93 
94 	{ "priv_clock_settime", priv_clock_settime_setup, priv_clock_settime,
95 	    priv_clock_settime_cleanup },
96 
97 	{ "priv_cred_setuid", priv_cred_setup, priv_cred_setuid,
98 	    priv_cred_cleanup },
99 
100 	{ "priv_cred_seteuid", priv_cred_setup, priv_cred_seteuid,
101 	    priv_cred_cleanup },
102 
103 	{ "priv_cred_setgid", priv_cred_setup, priv_cred_setgid,
104 	    priv_cred_cleanup },
105 
106 	{ "priv_cred_setegid", priv_cred_setup, priv_cred_setegid,
107 	    priv_cred_cleanup },
108 
109 	{ "priv_cred_setgroups", priv_cred_setup, priv_cred_setgroups,
110 	    priv_cred_cleanup },
111 
112 	{ "priv_cred_setreuid", priv_cred_setup, priv_cred_setreuid,
113 	    priv_cred_cleanup },
114 
115 	{ "priv_cred_setregid", priv_cred_setup, priv_cred_setregid,
116 	    priv_cred_cleanup },
117 
118 	{ "priv_cred_setresuid", priv_cred_setup, priv_cred_setresuid,
119 	    priv_cred_cleanup },
120 
121 	{ "priv_cred_setresgid", priv_cred_setup, priv_cred_setresgid,
122 	    priv_cred_cleanup },
123 
124 	{ "priv_io", priv_io_setup, priv_io, priv_io_cleanup },
125 
126 	{ "priv_kenv_set", priv_kenv_set_setup, priv_kenv_set,
127 	    priv_kenv_set_cleanup },
128 
129 	{ "priv_kenv_unset", priv_kenv_unset_setup, priv_kenv_unset,
130 	    priv_kenv_unset_cleanup },
131 
132 	{ "priv_msgbuf_privonly", priv_msgbuf_privonly_setup,
133 	    priv_msgbuf_privonly, priv_msgbuf_cleanup },
134 
135 	{ "priv_msgbuf_unprivok", priv_msgbuf_unprivok_setup,
136 	   priv_msgbuf_unprivok, priv_msgbuf_cleanup },
137 
138 	{ "priv_netinet_ipsec_pfkey", NULL, priv_netinet_ipsec_pfkey, NULL },
139 
140 	{ "priv_netinet_ipsec_policy4_bypass",
141 	    priv_netinet_ipsec_policy4_bypass_setup,
142 	    priv_netinet_ipsec_policy4_bypass,
143 	    priv_netinet_ipsec_policy_bypass_cleanup },
144 
145 #ifdef INET6
146 	{ "priv_netinet_ipsec_policy6_bypass",
147 	    priv_netinet_ipsec_policy6_bypass_setup,
148 	    priv_netinet_ipsec_policy6_bypass,
149 	    priv_netinet_ipsec_policy_bypass_cleanup },
150 #endif
151 
152 	{ "priv_netinet_ipsec_policy4_entrust",
153 	    priv_netinet_ipsec_policy4_entrust_setup,
154 	    priv_netinet_ipsec_policy4_entrust,
155 	    priv_netinet_ipsec_policy_entrust_cleanup },
156 
157 #ifdef INET6
158 	{ "priv_netinet_ipsec_policy6_entrust",
159 	    priv_netinet_ipsec_policy6_entrust_setup,
160 	    priv_netinet_ipsec_policy6_entrust,
161 	    priv_netinet_ipsec_policy_entrust_cleanup },
162 #endif
163 
164 	{ "priv_netinet_raw", priv_netinet_raw_setup, priv_netinet_raw,
165 	    priv_netinet_raw_cleanup },
166 
167 	{ "priv_proc_setlogin", priv_proc_setlogin_setup, priv_proc_setlogin,
168 	    priv_proc_setlogin_cleanup },
169 
170 	{ "priv_proc_setrlimit_raisemax", priv_proc_setrlimit_setup,
171 	    priv_proc_setrlimit_raisemax, priv_proc_setrlimit_cleanup },
172 
173 	{ "priv_proc_setrlimit_raisecur", priv_proc_setrlimit_setup,
174 	    priv_proc_setrlimit_raisecur, priv_proc_setrlimit_cleanup },
175 
176 	{ "priv_proc_setrlimit_raisecur_nopriv", priv_proc_setrlimit_setup,
177 	    priv_proc_setrlimit_raisecur_nopriv,
178 	    priv_proc_setrlimit_cleanup },
179 
180 	{ "priv_sched_rtprio_curproc_normal", priv_sched_rtprio_setup,
181 	    priv_sched_rtprio_curproc_normal, priv_sched_rtprio_cleanup },
182 
183 	{ "priv_sched_rtprio_curproc_idle", priv_sched_rtprio_setup,
184 	    priv_sched_rtprio_curproc_idle, priv_sched_rtprio_cleanup },
185 
186 	{ "priv_sched_rtprio_curproc_realtime", priv_sched_rtprio_setup,
187 	    priv_sched_rtprio_curproc_realtime, priv_sched_rtprio_cleanup },
188 
189 	{ "priv_sched_rtprio_myproc_normal", priv_sched_rtprio_setup,
190 	    priv_sched_rtprio_myproc_normal, priv_sched_rtprio_cleanup },
191 
192 	{ "priv_sched_rtprio_myproc_idle", priv_sched_rtprio_setup,
193 	    priv_sched_rtprio_myproc_idle, priv_sched_rtprio_cleanup },
194 
195 	{ "priv_sched_rtprio_myproc_realtime", priv_sched_rtprio_setup,
196 	    priv_sched_rtprio_myproc_realtime, priv_sched_rtprio_cleanup },
197 
198 	{ "priv_sched_rtprio_aproc_normal", priv_sched_rtprio_setup,
199 	    priv_sched_rtprio_aproc_normal, priv_sched_rtprio_cleanup },
200 
201 	{ "priv_sched_rtprio_aproc_idle", priv_sched_rtprio_setup,
202 	    priv_sched_rtprio_aproc_idle, priv_sched_rtprio_cleanup },
203 
204 	{ "priv_sched_rtprio_aproc_realtime", priv_sched_rtprio_setup,
205 	    priv_sched_rtprio_aproc_realtime, priv_sched_rtprio_cleanup },
206 
207 	{ "priv_sched_setpriority_curproc", priv_sched_setpriority_setup,
208 	    priv_sched_setpriority_curproc, priv_sched_setpriority_cleanup },
209 
210 	{ "priv_sched_setpriority_myproc", priv_sched_setpriority_setup,
211 	    priv_sched_setpriority_myproc, priv_sched_setpriority_cleanup },
212 
213 	{ "priv_sched_setpriority_aproc", priv_sched_setpriority_setup,
214 	    priv_sched_setpriority_aproc, priv_sched_setpriority_cleanup },
215 
216 	{ "priv_settimeofday", priv_settimeofday_setup, priv_settimeofday,
217 	    priv_settimeofday_cleanup },
218 
219 	{ "priv_sysctl_write", priv_sysctl_write_setup, priv_sysctl_write,
220 	    priv_sysctl_write_cleanup },
221 
222 	{ "priv_sysctl_writejail", priv_sysctl_write_setup,
223 	    priv_sysctl_writejail, priv_sysctl_write_cleanup },
224 
225 	{ "priv_vfs_chflags_froot_uflags", priv_vfs_chflags_froot_setup,
226 	    priv_vfs_chflags_froot_uflags, priv_vfs_chflags_cleanup },
227 
228 	{ "priv_vfs_chflags_froot_sflags", priv_vfs_chflags_froot_setup,
229 	    priv_vfs_chflags_froot_sflags, priv_vfs_chflags_cleanup },
230 
231 	{ "priv_vfs_chflags_fowner_uflags", priv_vfs_chflags_fowner_setup,
232 	    priv_vfs_chflags_fowner_uflags, priv_vfs_chflags_cleanup },
233 
234 	{ "priv_vfs_chflags_fowner_sflags", priv_vfs_chflags_fowner_setup,
235 	    priv_vfs_chflags_fowner_sflags, priv_vfs_chflags_cleanup },
236 
237 	{ "priv_vfs_chflags_fother_uflags", priv_vfs_chflags_fother_setup,
238 	    priv_vfs_chflags_fother_uflags, priv_vfs_chflags_cleanup },
239 
240 	{ "priv_vfs_chflags_fother_sflags", priv_vfs_chflags_fother_setup,
241 	    priv_vfs_chflags_fother_sflags, priv_vfs_chflags_cleanup },
242 
243 	{ "priv_vfs_chmod_froot", priv_vfs_chmod_froot_setup,
244 	     priv_vfs_chmod_froot, priv_vfs_chmod_cleanup },
245 
246 	{ "priv_vfs_chmod_fowner", priv_vfs_chmod_fowner_setup,
247 	     priv_vfs_chmod_fowner, priv_vfs_chmod_cleanup },
248 
249 	{ "priv_vfs_chmod_fother", priv_vfs_chmod_fother_setup,
250 	     priv_vfs_chmod_fother, priv_vfs_chmod_cleanup },
251 
252 	{ "priv_vfs_chown_uid", priv_vfs_chown_uid_setup, priv_vfs_chown_uid,
253 	    priv_vfs_chown_cleanup },
254 
255 	{ "priv_vfs_chown_mygid", priv_vfs_chown_mygid_setup,
256 	    priv_vfs_chown_mygid, priv_vfs_chown_cleanup },
257 
258 	{ "priv_vfs_chown_othergid", priv_vfs_chown_othergid_setup,
259 	    priv_vfs_chown_othergid, priv_vfs_chown_cleanup },
260 
261 	{ "priv_vfs_chroot", priv_vfs_chroot_setup, priv_vfs_chroot,
262 	    priv_vfs_chroot_cleanup },
263 
264 	{ "priv_vfs_clearsugid_chgrp", priv_vfs_clearsugid_setup,
265 	    priv_vfs_clearsugid_chgrp, priv_vfs_clearsugid_cleanup },
266 
267 	{ "priv_vfs_clearsugid_extattr", priv_vfs_clearsugid_setup,
268 	    priv_vfs_clearsugid_extattr, priv_vfs_clearsugid_cleanup },
269 
270 	{ "priv_vfs_clearsugid_write", priv_vfs_clearsugid_setup,
271 	    priv_vfs_clearsugid_write, priv_vfs_clearsugid_cleanup },
272 
273 	{ "priv_vfs_extattr_system", priv_vfs_extattr_system_setup,
274 	    priv_vfs_extattr_system, priv_vfs_extattr_system_cleanup },
275 
276 	{ "priv_vfs_fhopen", priv_vfs_fhopen_setup, priv_vfs_fhopen,
277 	    priv_vfs_fhopen_cleanup },
278 
279 	{ "priv_vfs_fhstat", priv_vfs_fhstat_setup, priv_vfs_fhstat,
280 	    priv_vfs_fhstat_cleanup },
281 
282 	{ "priv_vfs_fhstatfs", priv_vfs_fhstatfs_setup, priv_vfs_fhstatfs,
283 	    priv_vfs_fhstatfs_cleanup },
284 
285 	{ "priv_vfs_generation", priv_vfs_generation_setup,
286 	    priv_vfs_generation, priv_vfs_generation_cleanup },
287 
288 	{ "priv_vfs_getfh", priv_vfs_getfh_setup, priv_vfs_getfh,
289 	    priv_vfs_getfh_cleanup },
290 
291 	{ "priv_vfs_readwrite_fowner", priv_vfs_readwrite_fowner_setup,
292 	    priv_vfs_readwrite_fowner, priv_vfs_readwrite_cleanup },
293 
294 	{ "priv_vfs_readwrite_fgroup", priv_vfs_readwrite_fgroup_setup,
295 	    priv_vfs_readwrite_fgroup, priv_vfs_readwrite_cleanup },
296 
297 	{ "priv_vfs_readwrite_fother", priv_vfs_readwrite_fother_setup,
298 	    priv_vfs_readwrite_fother, priv_vfs_readwrite_cleanup },
299 
300 	{ "priv_vfs_setgid_fowner", priv_vfs_setgid_fowner_setup,
301 	    priv_vfs_setgid_fowner, priv_vfs_setgid_cleanup },
302 
303 	{ "priv_vfs_setgid_fother", priv_vfs_setgid_fother_setup,
304 	    priv_vfs_setgid_fother, priv_vfs_setgid_cleanup },
305 
306 	{ "priv_vfs_stickyfile_dir_fowner",
307 	    priv_vfs_stickyfile_dir_fowner_setup,
308 	    priv_vfs_stickyfile_dir_fowner,
309 	    priv_vfs_stickyfile_dir_cleanup },
310 
311 	{ "priv_vfs_stickyfile_dir_fother",
312 	    priv_vfs_stickyfile_dir_fother_setup,
313 	    priv_vfs_stickyfile_dir_fother,
314 	    priv_vfs_stickyfile_dir_cleanup },
315 
316 	{ "priv_vfs_stickyfile_file_fowner",
317 	    priv_vfs_stickyfile_file_fowner_setup,
318 	    priv_vfs_stickyfile_file_fowner,
319 	    priv_vfs_stickyfile_file_cleanup },
320 
321 	{ "priv_vfs_stickyfile_file_fother",
322 	    priv_vfs_stickyfile_file_fother_setup,
323 	    priv_vfs_stickyfile_file_fother,
324 	    priv_vfs_stickyfile_file_cleanup },
325 
326 	{ "priv_vfs_utimes_froot", priv_vfs_utimes_froot_setup,
327 	    priv_vfs_utimes_froot, priv_vfs_utimes_cleanup },
328 
329 	{ "priv_vfs_utimes_froot_null", priv_vfs_utimes_froot_setup,
330 	    priv_vfs_utimes_froot_null, priv_vfs_utimes_cleanup },
331 
332 	{ "priv_vfs_utimes_fowner", priv_vfs_utimes_fowner_setup,
333 	    priv_vfs_utimes_fowner, priv_vfs_utimes_cleanup },
334 
335 	{ "priv_vfs_utimes_fowner_null", priv_vfs_utimes_fowner_setup,
336 	    priv_vfs_utimes_fowner_null, priv_vfs_utimes_cleanup },
337 
338 	{ "priv_vfs_utimes_fother", priv_vfs_utimes_fother_setup,
339 	    priv_vfs_utimes_fother, priv_vfs_utimes_cleanup },
340 
341 	{ "priv_vfs_utimes_fother_null", priv_vfs_utimes_fother_setup,
342 	    priv_vfs_utimes_fother_null, priv_vfs_utimes_cleanup },
343 
344 	{ "priv_vm_madv_protect", priv_vm_madv_protect_setup,
345 	    priv_vm_madv_protect, priv_vm_madv_protect_cleanup },
346 
347 	{ "priv_vm_mlock", priv_vm_mlock_setup, priv_vm_mlock,
348 	    priv_vm_mlock_cleanup },
349 
350 	{ "priv_vm_munlock", priv_vm_munlock_setup, priv_vm_munlock,
351 	    priv_vm_munlock_cleanup },
352 
353 };
354 static int tests_count = sizeof(tests) / sizeof(struct test);
355 
356 void
357 expect(const char *test, int error, int expected_error, int expected_errno)
358 {
359 
360 	if (error == 0) {
361 		if (expected_error != 0)
362 			warnx("%s: returned 0", test);
363 	} else {
364 		if (expected_error == 0)
365 			warn("%s: returned (%d, %d)", test, error, errno);
366 		else if (expected_errno != errno)
367 			warn("%s: returned (%d, %d)", test, error, errno);
368 	}
369 }
370 
371 void
372 setup_dir(const char *test, char *dpathp, uid_t uid, gid_t gid, mode_t mode)
373 {
374 
375 	strcpy(dpathp, "/tmp/priv.XXXXXXXXXXX");
376 	if (mkdtemp(dpathp) == NULL)
377 		err(-1, "test %s: mkdtemp", test);
378 
379 	if (chown(dpathp, uid, gid) < 0)
380 		err(-1, "test %s: chown(%s, %d, %d)", test, dpathp, uid,
381 		    gid);
382 
383 	if (chmod(dpathp, mode) < 0)
384 		err(-1, "test %s: chmod(%s, 0%o)", test, dpathp, mode);
385 }
386 
387 void
388 setup_file(const char *test, char *fpathp, uid_t uid, gid_t gid, mode_t mode)
389 {
390 	int fd;
391 
392 	strcpy(fpathp, "/tmp/priv.XXXXXXXXXXX");
393 	fd = mkstemp(fpathp);
394 	if (fd < 0)
395 		err(-1, "test %s: mkstemp", test);
396 
397 	if (fchown(fd, uid, gid) < 0)
398 		err(-1, "test %s: fchown(%s, %d, %d)", test, fpathp, uid,
399 		    gid);
400 
401 	if (fchmod(fd, mode) < 0)
402 		err(-1, "test %s: chmod(%s, 0%o)", test, fpathp, mode);
403 
404 	close(fd);
405 }
406 
407 /*
408  * Irrevocably set credentials to specific uid and gid.
409  */
410 static void
411 set_creds(const char *test, uid_t uid, gid_t gid)
412 {
413 	gid_t gids[1] = { gid };
414 
415 	if (setgid(gid) < 0)
416 		err(-1, "test %s: setegid(%d)", test, gid);
417 	if (setgroups(sizeof(gids)/sizeof(gid_t), gids) < 0)
418 		err(-1, "test %s: setgroups(%d)", test, gid);
419 	if (setuid(uid) < 0)
420 		err(-1, "test %s: seteuid(%d)", test, uid);
421 }
422 
423 static void
424 enter_jail(const char *test)
425 {
426 	struct jail j;
427 	struct in_addr ia4;
428 #ifdef INET6
429 	struct in6_addr ia6 = IN6ADDR_LOOPBACK_INIT;
430 #endif
431 
432 	bzero(&j, sizeof(j));
433 	j.version = JAIL_API_VERSION;
434 	j.path = "/";
435 	j.hostname = "test";
436 	j.jailname = "regressions/priv";
437 	ia4.s_addr = htonl(INADDR_LOOPBACK);
438 	j.ip4s = 1;
439 	j.ip4 = &ia4;
440 #ifdef INET6
441 	j.ip6s = 1;
442 	j.ip6 = &ia6;
443 #endif
444 	if (jail(&j) < 0)
445 		err(-1, "test %s: jail", test);
446 }
447 
448 static void
449 run_child(struct test *test, int asroot, int injail)
450 {
451 
452 	setprogname(test->t_name);
453 	if (injail)
454 		enter_jail(test->t_name);
455 	if (!asroot)
456 		set_creds(test->t_name, UID_OWNER, GID_OWNER);
457 	test->t_test_func(asroot, injail, test);
458 }
459 
460 /*
461  * Run a test in a particular credential context -- always call the setup and
462  * cleanup routines; if setup succeeds, also run the test.  Test cleanup must
463  * handle cases where the setup has failed, so may need to maintain their own
464  * state in order to know what needs cleaning up (such as whether temporary
465  * files were created).
466  */
467 static void
468 run(struct test *test, int asroot, int injail)
469 {
470 	pid_t childpid, pid;
471 
472 	if (test->t_setup_func != NULL) {
473 		if ((test->t_setup_func)(asroot, injail, test) != 0) {
474 			warnx("run(%s, %d, %d) setup failed", test->t_name,
475 			    asroot, injail);
476 			goto cleanup;
477 		}
478 	}
479 	fflush(stdout);
480 	fflush(stderr);
481 	childpid = fork();
482 	if (childpid == -1) {
483 		warn("run(%s, %d, %d) fork failed", test->t_name, asroot,
484 		    injail);
485 		goto cleanup;
486 	}
487 	if (childpid == 0) {
488 		run_child(test, asroot, injail);
489 		fflush(stdout);
490 		fflush(stderr);
491 		exit(0);
492 	} else {
493 		while (1) {
494 			pid = waitpid(childpid, NULL, 0);
495 			if (pid == -1)
496 				warn("test: waitpid %s", test->t_name);
497 			if (pid == childpid)
498 				break;
499 		}
500 	}
501 	fflush(stdout);
502 	fflush(stderr);
503 cleanup:
504 	if (test->t_cleanup_func != NULL)
505 		test->t_cleanup_func(asroot, injail, test);
506 }
507 
508 int
509 main(int argc, char *argv[])
510 {
511 	int i;
512 
513 	/*
514 	 * This test suite will need to become quite a bit more enlightened
515 	 * if the notion of privilege is truly separated from root, as tests
516 	 * make assumptions about when privilege will be present.  In
517 	 * particular, VFS-related tests need to manage uids in order to
518 	 * force the use of privilege, and will likely need checking.
519 	 */
520 	if (getuid() != 0 && geteuid() != 0)
521 		errx(-1, "priv: must be run as root");
522 
523 	/*
524 	 * Run each test four times, varying whether the process is running
525 	 * as root and in jail in order to test all possible combinations.
526 	 */
527 	for (i = 0; i < tests_count; i++) {
528 		run(&tests[i], 0, 0);
529 		run(&tests[i], 0, 1);
530 		run(&tests[i], 1, 0);
531 		run(&tests[i], 1, 1);
532 	}
533 	return (0);
534 }
535