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