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$
31162271Srwatson */
32162271Srwatson
33162271Srwatson/*
34172106Srwatson * Privilege test framework.  Each test is encapsulated on a .c file
35172106Srwatson * exporting a function that implements the test.  Each test is run from its
36172106Srwatson * own child process, and they are run in sequence one at a time.
37162271Srwatson */
38162271Srwatson
39172106Srwatson#include <sys/param.h>
40172106Srwatson#include <sys/jail.h>
41162271Srwatson#include <sys/stat.h>
42162271Srwatson#include <sys/wait.h>
43162271Srwatson
44172106Srwatson#include <netinet/in.h>
45172106Srwatson
46162271Srwatson#include <err.h>
47172106Srwatson#include <errno.h>
48162271Srwatson#include <stdio.h>
49162271Srwatson#include <stdlib.h>
50162271Srwatson#include <string.h>
51162271Srwatson#include <unistd.h>
52162271Srwatson
53162271Srwatson#include "main.h"
54162271Srwatson
55162271Srwatson/*
56264457Sjmmv * If true, some test or preparatory step failed along the execution of this
57264457Sjmmv * program.
58264457Sjmmv *
59264457Sjmmv * Intuitively, we would define a counter instead of a boolean.  However,
60264457Sjmmv * we fork to run the subtests and keeping proper track of the number of
61264457Sjmmv * failed tests would be tricky and not provide any real value.
62264457Sjmmv */
63264457Sjmmvstatic int something_failed = 0;
64264457Sjmmv
65264457Sjmmv/*
66172106Srwatson * Registration table of privilege tests.  Each test registers a name, a test
67172106Srwatson * function, and a cleanup function to run after the test has completed,
68172106Srwatson * regardless of success/failure.
69162271Srwatson */
70172106Srwatsonstatic struct test tests[] = {
71172106Srwatson	{ "priv_acct_enable", priv_acct_setup, priv_acct_enable,
72172106Srwatson	    priv_acct_cleanup },
73172106Srwatson
74172106Srwatson	{ "priv_acct_disable", priv_acct_setup, priv_acct_disable,
75172106Srwatson	    priv_acct_cleanup },
76172106Srwatson
77172106Srwatson	{ "priv_acct_rotate", priv_acct_setup, priv_acct_rotate,
78172106Srwatson	    priv_acct_cleanup },
79172106Srwatson
80172106Srwatson	{ "priv_acct_noopdisable", priv_acct_setup, priv_acct_noopdisable,
81172106Srwatson	    priv_acct_cleanup },
82172106Srwatson
83172106Srwatson	{ "priv_adjtime_set", priv_adjtime_setup, priv_adjtime_set,
84172106Srwatson	    priv_adjtime_cleanup },
85172106Srwatson
86172106Srwatson	{ "priv_audit_submit", priv_audit_submit_setup, priv_audit_submit,
87172106Srwatson	    priv_audit_submit_cleanup },
88172106Srwatson
89172106Srwatson	{ "priv_audit_control", priv_audit_control_setup, priv_audit_control,
90172106Srwatson	    priv_audit_control_cleanup },
91172106Srwatson
92172106Srwatson	{ "priv_audit_getaudit", priv_audit_getaudit_setup,
93172106Srwatson	    priv_audit_getaudit, priv_audit_getaudit_cleanup },
94172106Srwatson
95172106Srwatson	{ "priv_audit_getaudit_addr", priv_audit_getaudit_setup,
96172106Srwatson	    priv_audit_getaudit_addr, priv_audit_getaudit_cleanup },
97172106Srwatson
98172106Srwatson	{ "priv_audit_setaudit", priv_audit_setaudit_setup,
99172106Srwatson	    priv_audit_setaudit, priv_audit_setaudit_cleanup },
100172106Srwatson
101172106Srwatson	{ "priv_audit_setaudit_addr", priv_audit_setaudit_setup,
102172106Srwatson	    priv_audit_setaudit_addr, priv_audit_setaudit_cleanup },
103172106Srwatson
104172106Srwatson	{ "priv_clock_settime", priv_clock_settime_setup, priv_clock_settime,
105172106Srwatson	    priv_clock_settime_cleanup },
106172106Srwatson
107172106Srwatson	{ "priv_cred_setuid", priv_cred_setup, priv_cred_setuid,
108172106Srwatson	    priv_cred_cleanup },
109172106Srwatson
110172106Srwatson	{ "priv_cred_seteuid", priv_cred_setup, priv_cred_seteuid,
111172106Srwatson	    priv_cred_cleanup },
112172106Srwatson
113172106Srwatson	{ "priv_cred_setgid", priv_cred_setup, priv_cred_setgid,
114172106Srwatson	    priv_cred_cleanup },
115172106Srwatson
116172106Srwatson	{ "priv_cred_setegid", priv_cred_setup, priv_cred_setegid,
117172106Srwatson	    priv_cred_cleanup },
118172106Srwatson
119172106Srwatson	{ "priv_cred_setgroups", priv_cred_setup, priv_cred_setgroups,
120172106Srwatson	    priv_cred_cleanup },
121172106Srwatson
122172106Srwatson	{ "priv_cred_setreuid", priv_cred_setup, priv_cred_setreuid,
123172106Srwatson	    priv_cred_cleanup },
124172106Srwatson
125172106Srwatson	{ "priv_cred_setregid", priv_cred_setup, priv_cred_setregid,
126172106Srwatson	    priv_cred_cleanup },
127172106Srwatson
128172106Srwatson	{ "priv_cred_setresuid", priv_cred_setup, priv_cred_setresuid,
129172106Srwatson	    priv_cred_cleanup },
130172106Srwatson
131172106Srwatson	{ "priv_cred_setresgid", priv_cred_setup, priv_cred_setresgid,
132172106Srwatson	    priv_cred_cleanup },
133172106Srwatson
134172106Srwatson	{ "priv_io", priv_io_setup, priv_io, priv_io_cleanup },
135172106Srwatson
136172106Srwatson	{ "priv_kenv_set", priv_kenv_set_setup, priv_kenv_set,
137172106Srwatson	    priv_kenv_set_cleanup },
138172106Srwatson
139172106Srwatson	{ "priv_kenv_unset", priv_kenv_unset_setup, priv_kenv_unset,
140172106Srwatson	    priv_kenv_unset_cleanup },
141172106Srwatson
142172106Srwatson	{ "priv_msgbuf_privonly", priv_msgbuf_privonly_setup,
143172106Srwatson	    priv_msgbuf_privonly, priv_msgbuf_cleanup },
144172106Srwatson
145172106Srwatson	{ "priv_msgbuf_unprivok", priv_msgbuf_unprivok_setup,
146172106Srwatson	   priv_msgbuf_unprivok, priv_msgbuf_cleanup },
147172106Srwatson
148173679Sbz	{ "priv_netinet_ipsec_pfkey", NULL, priv_netinet_ipsec_pfkey, NULL },
149173578Sbz
150173679Sbz	{ "priv_netinet_ipsec_policy4_bypass",
151173679Sbz	    priv_netinet_ipsec_policy4_bypass_setup,
152173679Sbz	    priv_netinet_ipsec_policy4_bypass,
153173679Sbz	    priv_netinet_ipsec_policy_bypass_cleanup },
154173679Sbz
155196172Sbz#ifdef INET6
156173679Sbz	{ "priv_netinet_ipsec_policy6_bypass",
157173679Sbz	    priv_netinet_ipsec_policy6_bypass_setup,
158173679Sbz	    priv_netinet_ipsec_policy6_bypass,
159173679Sbz	    priv_netinet_ipsec_policy_bypass_cleanup },
160196172Sbz#endif
161173679Sbz
162173679Sbz	{ "priv_netinet_ipsec_policy4_entrust",
163173679Sbz	    priv_netinet_ipsec_policy4_entrust_setup,
164173679Sbz	    priv_netinet_ipsec_policy4_entrust,
165173679Sbz	    priv_netinet_ipsec_policy_entrust_cleanup },
166173679Sbz
167196172Sbz#ifdef INET6
168173679Sbz	{ "priv_netinet_ipsec_policy6_entrust",
169173679Sbz	    priv_netinet_ipsec_policy6_entrust_setup,
170173679Sbz	    priv_netinet_ipsec_policy6_entrust,
171173679Sbz	    priv_netinet_ipsec_policy_entrust_cleanup },
172196172Sbz#endif
173173679Sbz
174172106Srwatson	{ "priv_netinet_raw", priv_netinet_raw_setup, priv_netinet_raw,
175172106Srwatson	    priv_netinet_raw_cleanup },
176172106Srwatson
177172106Srwatson	{ "priv_proc_setlogin", priv_proc_setlogin_setup, priv_proc_setlogin,
178172106Srwatson	    priv_proc_setlogin_cleanup },
179172106Srwatson
180172106Srwatson	{ "priv_proc_setrlimit_raisemax", priv_proc_setrlimit_setup,
181172106Srwatson	    priv_proc_setrlimit_raisemax, priv_proc_setrlimit_cleanup },
182172106Srwatson
183172106Srwatson	{ "priv_proc_setrlimit_raisecur", priv_proc_setrlimit_setup,
184172106Srwatson	    priv_proc_setrlimit_raisecur, priv_proc_setrlimit_cleanup },
185172106Srwatson
186172106Srwatson	{ "priv_proc_setrlimit_raisecur_nopriv", priv_proc_setrlimit_setup,
187172106Srwatson	    priv_proc_setrlimit_raisecur_nopriv,
188172106Srwatson	    priv_proc_setrlimit_cleanup },
189172106Srwatson
190172106Srwatson	{ "priv_sched_rtprio_curproc_normal", priv_sched_rtprio_setup,
191172106Srwatson	    priv_sched_rtprio_curproc_normal, priv_sched_rtprio_cleanup },
192172106Srwatson
193172106Srwatson	{ "priv_sched_rtprio_curproc_idle", priv_sched_rtprio_setup,
194172106Srwatson	    priv_sched_rtprio_curproc_idle, priv_sched_rtprio_cleanup },
195172106Srwatson
196172106Srwatson	{ "priv_sched_rtprio_curproc_realtime", priv_sched_rtprio_setup,
197172106Srwatson	    priv_sched_rtprio_curproc_realtime, priv_sched_rtprio_cleanup },
198172106Srwatson
199172106Srwatson	{ "priv_sched_rtprio_myproc_normal", priv_sched_rtprio_setup,
200172106Srwatson	    priv_sched_rtprio_myproc_normal, priv_sched_rtprio_cleanup },
201172106Srwatson
202172106Srwatson	{ "priv_sched_rtprio_myproc_idle", priv_sched_rtprio_setup,
203172106Srwatson	    priv_sched_rtprio_myproc_idle, priv_sched_rtprio_cleanup },
204172106Srwatson
205172106Srwatson	{ "priv_sched_rtprio_myproc_realtime", priv_sched_rtprio_setup,
206172106Srwatson	    priv_sched_rtprio_myproc_realtime, priv_sched_rtprio_cleanup },
207172106Srwatson
208172106Srwatson	{ "priv_sched_rtprio_aproc_normal", priv_sched_rtprio_setup,
209172106Srwatson	    priv_sched_rtprio_aproc_normal, priv_sched_rtprio_cleanup },
210172106Srwatson
211172106Srwatson	{ "priv_sched_rtprio_aproc_idle", priv_sched_rtprio_setup,
212172106Srwatson	    priv_sched_rtprio_aproc_idle, priv_sched_rtprio_cleanup },
213172106Srwatson
214172106Srwatson	{ "priv_sched_rtprio_aproc_realtime", priv_sched_rtprio_setup,
215172106Srwatson	    priv_sched_rtprio_aproc_realtime, priv_sched_rtprio_cleanup },
216172106Srwatson
217172106Srwatson	{ "priv_sched_setpriority_curproc", priv_sched_setpriority_setup,
218172106Srwatson	    priv_sched_setpriority_curproc, priv_sched_setpriority_cleanup },
219172106Srwatson
220172106Srwatson	{ "priv_sched_setpriority_myproc", priv_sched_setpriority_setup,
221172106Srwatson	    priv_sched_setpriority_myproc, priv_sched_setpriority_cleanup },
222172106Srwatson
223172106Srwatson	{ "priv_sched_setpriority_aproc", priv_sched_setpriority_setup,
224172106Srwatson	    priv_sched_setpriority_aproc, priv_sched_setpriority_cleanup },
225172106Srwatson
226172106Srwatson	{ "priv_settimeofday", priv_settimeofday_setup, priv_settimeofday,
227172106Srwatson	    priv_settimeofday_cleanup },
228172106Srwatson
229172106Srwatson	{ "priv_sysctl_write", priv_sysctl_write_setup, priv_sysctl_write,
230172106Srwatson	    priv_sysctl_write_cleanup },
231172106Srwatson
232172106Srwatson	{ "priv_sysctl_writejail", priv_sysctl_write_setup,
233172106Srwatson	    priv_sysctl_writejail, priv_sysctl_write_cleanup },
234172106Srwatson
235172106Srwatson	{ "priv_vfs_chflags_froot_uflags", priv_vfs_chflags_froot_setup,
236172106Srwatson	    priv_vfs_chflags_froot_uflags, priv_vfs_chflags_cleanup },
237172106Srwatson
238172106Srwatson	{ "priv_vfs_chflags_froot_sflags", priv_vfs_chflags_froot_setup,
239172106Srwatson	    priv_vfs_chflags_froot_sflags, priv_vfs_chflags_cleanup },
240172106Srwatson
241172106Srwatson	{ "priv_vfs_chflags_fowner_uflags", priv_vfs_chflags_fowner_setup,
242172106Srwatson	    priv_vfs_chflags_fowner_uflags, priv_vfs_chflags_cleanup },
243172106Srwatson
244172106Srwatson	{ "priv_vfs_chflags_fowner_sflags", priv_vfs_chflags_fowner_setup,
245172106Srwatson	    priv_vfs_chflags_fowner_sflags, priv_vfs_chflags_cleanup },
246172106Srwatson
247172106Srwatson	{ "priv_vfs_chflags_fother_uflags", priv_vfs_chflags_fother_setup,
248172106Srwatson	    priv_vfs_chflags_fother_uflags, priv_vfs_chflags_cleanup },
249172106Srwatson
250172106Srwatson	{ "priv_vfs_chflags_fother_sflags", priv_vfs_chflags_fother_setup,
251172106Srwatson	    priv_vfs_chflags_fother_sflags, priv_vfs_chflags_cleanup },
252172106Srwatson
253172106Srwatson	{ "priv_vfs_chmod_froot", priv_vfs_chmod_froot_setup,
254172106Srwatson	     priv_vfs_chmod_froot, priv_vfs_chmod_cleanup },
255172106Srwatson
256172106Srwatson	{ "priv_vfs_chmod_fowner", priv_vfs_chmod_fowner_setup,
257172106Srwatson	     priv_vfs_chmod_fowner, priv_vfs_chmod_cleanup },
258172106Srwatson
259172106Srwatson	{ "priv_vfs_chmod_fother", priv_vfs_chmod_fother_setup,
260172106Srwatson	     priv_vfs_chmod_fother, priv_vfs_chmod_cleanup },
261172106Srwatson
262172106Srwatson	{ "priv_vfs_chown_uid", priv_vfs_chown_uid_setup, priv_vfs_chown_uid,
263172106Srwatson	    priv_vfs_chown_cleanup },
264172106Srwatson
265172106Srwatson	{ "priv_vfs_chown_mygid", priv_vfs_chown_mygid_setup,
266172106Srwatson	    priv_vfs_chown_mygid, priv_vfs_chown_cleanup },
267172106Srwatson
268172106Srwatson	{ "priv_vfs_chown_othergid", priv_vfs_chown_othergid_setup,
269172106Srwatson	    priv_vfs_chown_othergid, priv_vfs_chown_cleanup },
270172106Srwatson
271172106Srwatson	{ "priv_vfs_chroot", priv_vfs_chroot_setup, priv_vfs_chroot,
272172106Srwatson	    priv_vfs_chroot_cleanup },
273172106Srwatson
274172106Srwatson	{ "priv_vfs_clearsugid_chgrp", priv_vfs_clearsugid_setup,
275172106Srwatson	    priv_vfs_clearsugid_chgrp, priv_vfs_clearsugid_cleanup },
276172106Srwatson
277172106Srwatson	{ "priv_vfs_clearsugid_extattr", priv_vfs_clearsugid_setup,
278172106Srwatson	    priv_vfs_clearsugid_extattr, priv_vfs_clearsugid_cleanup },
279172106Srwatson
280172106Srwatson	{ "priv_vfs_clearsugid_write", priv_vfs_clearsugid_setup,
281172106Srwatson	    priv_vfs_clearsugid_write, priv_vfs_clearsugid_cleanup },
282172106Srwatson
283172106Srwatson	{ "priv_vfs_extattr_system", priv_vfs_extattr_system_setup,
284172106Srwatson	    priv_vfs_extattr_system, priv_vfs_extattr_system_cleanup },
285172106Srwatson
286172106Srwatson	{ "priv_vfs_fhopen", priv_vfs_fhopen_setup, priv_vfs_fhopen,
287172106Srwatson	    priv_vfs_fhopen_cleanup },
288172106Srwatson
289172106Srwatson	{ "priv_vfs_fhstat", priv_vfs_fhstat_setup, priv_vfs_fhstat,
290172106Srwatson	    priv_vfs_fhstat_cleanup },
291172106Srwatson
292172106Srwatson	{ "priv_vfs_fhstatfs", priv_vfs_fhstatfs_setup, priv_vfs_fhstatfs,
293172106Srwatson	    priv_vfs_fhstatfs_cleanup },
294172106Srwatson
295172106Srwatson	{ "priv_vfs_generation", priv_vfs_generation_setup,
296172106Srwatson	    priv_vfs_generation, priv_vfs_generation_cleanup },
297172106Srwatson
298172106Srwatson	{ "priv_vfs_getfh", priv_vfs_getfh_setup, priv_vfs_getfh,
299172106Srwatson	    priv_vfs_getfh_cleanup },
300172106Srwatson
301172106Srwatson	{ "priv_vfs_readwrite_fowner", priv_vfs_readwrite_fowner_setup,
302172106Srwatson	    priv_vfs_readwrite_fowner, priv_vfs_readwrite_cleanup },
303172106Srwatson
304172106Srwatson	{ "priv_vfs_readwrite_fgroup", priv_vfs_readwrite_fgroup_setup,
305172106Srwatson	    priv_vfs_readwrite_fgroup, priv_vfs_readwrite_cleanup },
306172106Srwatson
307172106Srwatson	{ "priv_vfs_readwrite_fother", priv_vfs_readwrite_fother_setup,
308172106Srwatson	    priv_vfs_readwrite_fother, priv_vfs_readwrite_cleanup },
309172106Srwatson
310172106Srwatson	{ "priv_vfs_setgid_fowner", priv_vfs_setgid_fowner_setup,
311172106Srwatson	    priv_vfs_setgid_fowner, priv_vfs_setgid_cleanup },
312172106Srwatson
313172106Srwatson	{ "priv_vfs_setgid_fother", priv_vfs_setgid_fother_setup,
314172106Srwatson	    priv_vfs_setgid_fother, priv_vfs_setgid_cleanup },
315172106Srwatson
316172106Srwatson	{ "priv_vfs_stickyfile_dir_fowner",
317172106Srwatson	    priv_vfs_stickyfile_dir_fowner_setup,
318172106Srwatson	    priv_vfs_stickyfile_dir_fowner,
319172106Srwatson	    priv_vfs_stickyfile_dir_cleanup },
320172106Srwatson
321172106Srwatson	{ "priv_vfs_stickyfile_dir_fother",
322172106Srwatson	    priv_vfs_stickyfile_dir_fother_setup,
323172106Srwatson	    priv_vfs_stickyfile_dir_fother,
324172106Srwatson	    priv_vfs_stickyfile_dir_cleanup },
325172106Srwatson
326172106Srwatson	{ "priv_vfs_stickyfile_file_fowner",
327172106Srwatson	    priv_vfs_stickyfile_file_fowner_setup,
328172106Srwatson	    priv_vfs_stickyfile_file_fowner,
329172106Srwatson	    priv_vfs_stickyfile_file_cleanup },
330172106Srwatson
331172106Srwatson	{ "priv_vfs_stickyfile_file_fother",
332172106Srwatson	    priv_vfs_stickyfile_file_fother_setup,
333172106Srwatson	    priv_vfs_stickyfile_file_fother,
334172106Srwatson	    priv_vfs_stickyfile_file_cleanup },
335172106Srwatson
336172106Srwatson	{ "priv_vfs_utimes_froot", priv_vfs_utimes_froot_setup,
337172106Srwatson	    priv_vfs_utimes_froot, priv_vfs_utimes_cleanup },
338172106Srwatson
339172106Srwatson	{ "priv_vfs_utimes_froot_null", priv_vfs_utimes_froot_setup,
340172106Srwatson	    priv_vfs_utimes_froot_null, priv_vfs_utimes_cleanup },
341172106Srwatson
342172106Srwatson	{ "priv_vfs_utimes_fowner", priv_vfs_utimes_fowner_setup,
343172106Srwatson	    priv_vfs_utimes_fowner, priv_vfs_utimes_cleanup },
344172106Srwatson
345172106Srwatson	{ "priv_vfs_utimes_fowner_null", priv_vfs_utimes_fowner_setup,
346172106Srwatson	    priv_vfs_utimes_fowner_null, priv_vfs_utimes_cleanup },
347172106Srwatson
348172106Srwatson	{ "priv_vfs_utimes_fother", priv_vfs_utimes_fother_setup,
349172106Srwatson	    priv_vfs_utimes_fother, priv_vfs_utimes_cleanup },
350172106Srwatson
351172106Srwatson	{ "priv_vfs_utimes_fother_null", priv_vfs_utimes_fother_setup,
352172106Srwatson	    priv_vfs_utimes_fother_null, priv_vfs_utimes_cleanup },
353172106Srwatson
354172106Srwatson	{ "priv_vm_madv_protect", priv_vm_madv_protect_setup,
355172106Srwatson	    priv_vm_madv_protect, priv_vm_madv_protect_cleanup },
356172106Srwatson
357172106Srwatson	{ "priv_vm_mlock", priv_vm_mlock_setup, priv_vm_mlock,
358172106Srwatson	    priv_vm_mlock_cleanup },
359172106Srwatson
360172106Srwatson	{ "priv_vm_munlock", priv_vm_munlock_setup, priv_vm_munlock,
361172106Srwatson	    priv_vm_munlock_cleanup },
362172106Srwatson
363172106Srwatson};
364172106Srwatsonstatic int tests_count = sizeof(tests) / sizeof(struct test);
365172106Srwatson
366162271Srwatsonvoid
367172106Srwatsonexpect(const char *test, int error, int expected_error, int expected_errno)
368162271Srwatson{
369162271Srwatson
370172106Srwatson	if (error == 0) {
371264457Sjmmv		if (expected_error != 0) {
372264457Sjmmv			something_failed = 1;
373172106Srwatson			warnx("%s: returned 0", test);
374264457Sjmmv		}
375172106Srwatson	} else {
376264457Sjmmv		if (expected_error == 0) {
377264457Sjmmv			something_failed = 1;
378172106Srwatson			warn("%s: returned (%d, %d)", test, error, errno);
379264457Sjmmv		} else if (expected_errno != errno) {
380264457Sjmmv			something_failed = 1;
381172106Srwatson			warn("%s: returned (%d, %d)", test, error, errno);
382264457Sjmmv		}
383172106Srwatson	}
384162271Srwatson}
385162271Srwatson
386162271Srwatsonvoid
387172106Srwatsonsetup_dir(const char *test, char *dpathp, uid_t uid, gid_t gid, mode_t mode)
388162271Srwatson{
389172106Srwatson
390172106Srwatson	strcpy(dpathp, "/tmp/priv.XXXXXXXXXXX");
391172106Srwatson	if (mkdtemp(dpathp) == NULL)
392172106Srwatson		err(-1, "test %s: mkdtemp", test);
393172106Srwatson
394172106Srwatson	if (chown(dpathp, uid, gid) < 0)
395172106Srwatson		err(-1, "test %s: chown(%s, %d, %d)", test, dpathp, uid,
396172106Srwatson		    gid);
397172106Srwatson
398172106Srwatson	if (chmod(dpathp, mode) < 0)
399172106Srwatson		err(-1, "test %s: chmod(%s, 0%o)", test, dpathp, mode);
400172106Srwatson}
401172106Srwatson
402172106Srwatsonvoid
403172106Srwatsonsetup_file(const char *test, char *fpathp, uid_t uid, gid_t gid, mode_t mode)
404172106Srwatson{
405162271Srwatson	int fd;
406162271Srwatson
407162271Srwatson	strcpy(fpathp, "/tmp/priv.XXXXXXXXXXX");
408162271Srwatson	fd = mkstemp(fpathp);
409162271Srwatson	if (fd < 0)
410172106Srwatson		err(-1, "test %s: mkstemp", test);
411162271Srwatson
412162271Srwatson	if (fchown(fd, uid, gid) < 0)
413172106Srwatson		err(-1, "test %s: fchown(%s, %d, %d)", test, fpathp, uid,
414172106Srwatson		    gid);
415162271Srwatson
416162271Srwatson	if (fchmod(fd, mode) < 0)
417172106Srwatson		err(-1, "test %s: chmod(%s, 0%o)", test, fpathp, mode);
418162271Srwatson
419162271Srwatson	close(fd);
420162271Srwatson}
421162271Srwatson
422162271Srwatson/*
423172106Srwatson * Irrevocably set credentials to specific uid and gid.
424162271Srwatson */
425172106Srwatsonstatic void
426172106Srwatsonset_creds(const char *test, uid_t uid, gid_t gid)
427162271Srwatson{
428172106Srwatson	gid_t gids[1] = { gid };
429162271Srwatson
430172106Srwatson	if (setgid(gid) < 0)
431172106Srwatson		err(-1, "test %s: setegid(%d)", test, gid);
432172106Srwatson	if (setgroups(sizeof(gids)/sizeof(gid_t), gids) < 0)
433172106Srwatson		err(-1, "test %s: setgroups(%d)", test, gid);
434172106Srwatson	if (setuid(uid) < 0)
435172106Srwatson		err(-1, "test %s: seteuid(%d)", test, uid);
436162271Srwatson}
437162271Srwatson
438172106Srwatsonstatic void
439172106Srwatsonenter_jail(const char *test)
440162271Srwatson{
441172106Srwatson	struct jail j;
442196172Sbz	struct in_addr ia4;
443196172Sbz#ifdef INET6
444196172Sbz	struct in6_addr ia6 = IN6ADDR_LOOPBACK_INIT;
445196172Sbz#endif
446162271Srwatson
447172106Srwatson	bzero(&j, sizeof(j));
448196172Sbz	j.version = JAIL_API_VERSION;
449172106Srwatson	j.path = "/";
450172106Srwatson	j.hostname = "test";
451196172Sbz	j.jailname = "regressions/priv";
452196172Sbz	ia4.s_addr = htonl(INADDR_LOOPBACK);
453196172Sbz	j.ip4s = 1;
454196172Sbz	j.ip4 = &ia4;
455196172Sbz#ifdef INET6
456196172Sbz	j.ip6s = 1;
457196172Sbz	j.ip6 = &ia6;
458196172Sbz#endif
459172106Srwatson	if (jail(&j) < 0)
460172106Srwatson		err(-1, "test %s: jail", test);
461162271Srwatson}
462162271Srwatson
463172106Srwatsonstatic void
464172106Srwatsonrun_child(struct test *test, int asroot, int injail)
465162271Srwatson{
466162271Srwatson
467172106Srwatson	setprogname(test->t_name);
468172106Srwatson	if (injail)
469172106Srwatson		enter_jail(test->t_name);
470172106Srwatson	if (!asroot)
471172106Srwatson		set_creds(test->t_name, UID_OWNER, GID_OWNER);
472172106Srwatson	test->t_test_func(asroot, injail, test);
473162271Srwatson}
474162271Srwatson
475162271Srwatson/*
476172106Srwatson * Run a test in a particular credential context -- always call the setup and
477172106Srwatson * cleanup routines; if setup succeeds, also run the test.  Test cleanup must
478172106Srwatson * handle cases where the setup has failed, so may need to maintain their own
479172106Srwatson * state in order to know what needs cleaning up (such as whether temporary
480172106Srwatson * files were created).
481162271Srwatson */
482162271Srwatsonstatic void
483172106Srwatsonrun(struct test *test, int asroot, int injail)
484162271Srwatson{
485162271Srwatson	pid_t childpid, pid;
486162271Srwatson
487172106Srwatson	if (test->t_setup_func != NULL) {
488172106Srwatson		if ((test->t_setup_func)(asroot, injail, test) != 0) {
489172106Srwatson			warnx("run(%s, %d, %d) setup failed", test->t_name,
490172106Srwatson			    asroot, injail);
491172106Srwatson			goto cleanup;
492172106Srwatson		}
493172106Srwatson	}
494162271Srwatson	fflush(stdout);
495162271Srwatson	fflush(stderr);
496162271Srwatson	childpid = fork();
497172106Srwatson	if (childpid == -1) {
498172106Srwatson		warn("run(%s, %d, %d) fork failed", test->t_name, asroot,
499172106Srwatson		    injail);
500172106Srwatson		goto cleanup;
501172106Srwatson	}
502162271Srwatson	if (childpid == 0) {
503172106Srwatson		run_child(test, asroot, injail);
504162271Srwatson		fflush(stdout);
505162271Srwatson		fflush(stderr);
506264457Sjmmv		exit(something_failed ? EXIT_FAILURE : EXIT_SUCCESS);
507162271Srwatson	} else {
508162271Srwatson		while (1) {
509264457Sjmmv			int status;
510264457Sjmmv			pid = waitpid(childpid, &status, 0);
511264457Sjmmv			if (pid == -1) {
512264457Sjmmv				something_failed = 1;
513172106Srwatson				warn("test: waitpid %s", test->t_name);
514264457Sjmmv			}
515264457Sjmmv			if (pid == childpid) {
516264457Sjmmv				if (WIFEXITED(status) &&
517264457Sjmmv				    WEXITSTATUS(status) == EXIT_SUCCESS) {
518264457Sjmmv					/* All good in the subprocess! */
519264457Sjmmv				} else {
520264457Sjmmv					something_failed = 1;
521264457Sjmmv				}
522162271Srwatson				break;
523264457Sjmmv			}
524162271Srwatson		}
525162271Srwatson	}
526162271Srwatson	fflush(stdout);
527162271Srwatson	fflush(stderr);
528172106Srwatsoncleanup:
529172106Srwatson	if (test->t_cleanup_func != NULL)
530172106Srwatson		test->t_cleanup_func(asroot, injail, test);
531162271Srwatson}
532162271Srwatson
533162271Srwatsonint
534162271Srwatsonmain(int argc, char *argv[])
535162271Srwatson{
536172106Srwatson	int i;
537162271Srwatson
538172106Srwatson	/*
539172106Srwatson	 * This test suite will need to become quite a bit more enlightened
540172106Srwatson	 * if the notion of privilege is truly separated from root, as tests
541172106Srwatson	 * make assumptions about when privilege will be present.  In
542172106Srwatson	 * particular, VFS-related tests need to manage uids in order to
543172106Srwatson	 * force the use of privilege, and will likely need checking.
544172106Srwatson	 */
545172106Srwatson	if (getuid() != 0 && geteuid() != 0)
546264457Sjmmv		errx(-1, "must be run as root");
547162271Srwatson
548172106Srwatson	/*
549172106Srwatson	 * Run each test four times, varying whether the process is running
550172106Srwatson	 * as root and in jail in order to test all possible combinations.
551172106Srwatson	 */
552172106Srwatson	for (i = 0; i < tests_count; i++) {
553172106Srwatson		run(&tests[i], 0, 0);
554172106Srwatson		run(&tests[i], 0, 1);
555172106Srwatson		run(&tests[i], 1, 0);
556172106Srwatson		run(&tests[i], 1, 1);
557172106Srwatson	}
558264457Sjmmv	return (something_failed ? EXIT_FAILURE : EXIT_SUCCESS);
559162271Srwatson}
560