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 /*
32d903306aSRobert Watson * Privilege test framework. Each test is encapsulated on a .c file
33d903306aSRobert Watson * exporting a function that implements the test. Each test is run from its
34d903306aSRobert Watson * own child process, and they are run in sequence one at a time.
359fa5f6b4SRobert Watson */
369fa5f6b4SRobert Watson
37d903306aSRobert Watson #include <sys/param.h>
38d903306aSRobert Watson #include <sys/jail.h>
399fa5f6b4SRobert Watson #include <sys/stat.h>
409fa5f6b4SRobert Watson #include <sys/wait.h>
419fa5f6b4SRobert Watson
42d903306aSRobert Watson #include <netinet/in.h>
43d903306aSRobert Watson
449fa5f6b4SRobert Watson #include <err.h>
45d903306aSRobert Watson #include <errno.h>
469fa5f6b4SRobert Watson #include <stdio.h>
479fa5f6b4SRobert Watson #include <stdlib.h>
489fa5f6b4SRobert Watson #include <string.h>
499fa5f6b4SRobert Watson #include <unistd.h>
509fa5f6b4SRobert Watson
519fa5f6b4SRobert Watson #include "main.h"
529fa5f6b4SRobert Watson
539fa5f6b4SRobert Watson /*
5434ed5572SJulio Merino * If true, some test or preparatory step failed along the execution of this
5534ed5572SJulio Merino * program.
5634ed5572SJulio Merino *
5734ed5572SJulio Merino * Intuitively, we would define a counter instead of a boolean. However,
5834ed5572SJulio Merino * we fork to run the subtests and keeping proper track of the number of
5934ed5572SJulio Merino * failed tests would be tricky and not provide any real value.
6034ed5572SJulio Merino */
6134ed5572SJulio Merino static int something_failed = 0;
6234ed5572SJulio Merino
6334ed5572SJulio Merino /*
64d903306aSRobert Watson * Registration table of privilege tests. Each test registers a name, a test
65d903306aSRobert Watson * function, and a cleanup function to run after the test has completed,
66d903306aSRobert Watson * regardless of success/failure.
679fa5f6b4SRobert Watson */
68d903306aSRobert Watson static struct test tests[] = {
69d903306aSRobert Watson { "priv_acct_enable", priv_acct_setup, priv_acct_enable,
70d903306aSRobert Watson priv_acct_cleanup },
71d903306aSRobert Watson
72d903306aSRobert Watson { "priv_acct_disable", priv_acct_setup, priv_acct_disable,
73d903306aSRobert Watson priv_acct_cleanup },
74d903306aSRobert Watson
75d903306aSRobert Watson { "priv_acct_rotate", priv_acct_setup, priv_acct_rotate,
76d903306aSRobert Watson priv_acct_cleanup },
77d903306aSRobert Watson
78d903306aSRobert Watson { "priv_acct_noopdisable", priv_acct_setup, priv_acct_noopdisable,
79d903306aSRobert Watson priv_acct_cleanup },
80d903306aSRobert Watson
81d903306aSRobert Watson { "priv_adjtime_set", priv_adjtime_setup, priv_adjtime_set,
82d903306aSRobert Watson priv_adjtime_cleanup },
83d903306aSRobert Watson
84d903306aSRobert Watson { "priv_audit_submit", priv_audit_submit_setup, priv_audit_submit,
85d903306aSRobert Watson priv_audit_submit_cleanup },
86d903306aSRobert Watson
87d903306aSRobert Watson { "priv_audit_control", priv_audit_control_setup, priv_audit_control,
88d903306aSRobert Watson priv_audit_control_cleanup },
89d903306aSRobert Watson
90d903306aSRobert Watson { "priv_audit_getaudit", priv_audit_getaudit_setup,
91d903306aSRobert Watson priv_audit_getaudit, priv_audit_getaudit_cleanup },
92d903306aSRobert Watson
93d903306aSRobert Watson { "priv_audit_getaudit_addr", priv_audit_getaudit_setup,
94d903306aSRobert Watson priv_audit_getaudit_addr, priv_audit_getaudit_cleanup },
95d903306aSRobert Watson
96d903306aSRobert Watson { "priv_audit_setaudit", priv_audit_setaudit_setup,
97d903306aSRobert Watson priv_audit_setaudit, priv_audit_setaudit_cleanup },
98d903306aSRobert Watson
99d903306aSRobert Watson { "priv_audit_setaudit_addr", priv_audit_setaudit_setup,
100d903306aSRobert Watson priv_audit_setaudit_addr, priv_audit_setaudit_cleanup },
101d903306aSRobert Watson
102d903306aSRobert Watson { "priv_clock_settime", priv_clock_settime_setup, priv_clock_settime,
103d903306aSRobert Watson priv_clock_settime_cleanup },
104d903306aSRobert Watson
105d903306aSRobert Watson { "priv_cred_setuid", priv_cred_setup, priv_cred_setuid,
106d903306aSRobert Watson priv_cred_cleanup },
107d903306aSRobert Watson
108d903306aSRobert Watson { "priv_cred_seteuid", priv_cred_setup, priv_cred_seteuid,
109d903306aSRobert Watson priv_cred_cleanup },
110d903306aSRobert Watson
111d903306aSRobert Watson { "priv_cred_setgid", priv_cred_setup, priv_cred_setgid,
112d903306aSRobert Watson priv_cred_cleanup },
113d903306aSRobert Watson
114d903306aSRobert Watson { "priv_cred_setegid", priv_cred_setup, priv_cred_setegid,
115d903306aSRobert Watson priv_cred_cleanup },
116d903306aSRobert Watson
117d903306aSRobert Watson { "priv_cred_setgroups", priv_cred_setup, priv_cred_setgroups,
118d903306aSRobert Watson priv_cred_cleanup },
119d903306aSRobert Watson
120d903306aSRobert Watson { "priv_cred_setreuid", priv_cred_setup, priv_cred_setreuid,
121d903306aSRobert Watson priv_cred_cleanup },
122d903306aSRobert Watson
123d903306aSRobert Watson { "priv_cred_setregid", priv_cred_setup, priv_cred_setregid,
124d903306aSRobert Watson priv_cred_cleanup },
125d903306aSRobert Watson
126d903306aSRobert Watson { "priv_cred_setresuid", priv_cred_setup, priv_cred_setresuid,
127d903306aSRobert Watson priv_cred_cleanup },
128d903306aSRobert Watson
129d903306aSRobert Watson { "priv_cred_setresgid", priv_cred_setup, priv_cred_setresgid,
130d903306aSRobert Watson priv_cred_cleanup },
131d903306aSRobert Watson
132d903306aSRobert Watson { "priv_io", priv_io_setup, priv_io, priv_io_cleanup },
133d903306aSRobert Watson
134d903306aSRobert Watson { "priv_kenv_set", priv_kenv_set_setup, priv_kenv_set,
135d903306aSRobert Watson priv_kenv_set_cleanup },
136d903306aSRobert Watson
137d903306aSRobert Watson { "priv_kenv_unset", priv_kenv_unset_setup, priv_kenv_unset,
138d903306aSRobert Watson priv_kenv_unset_cleanup },
139d903306aSRobert Watson
140d903306aSRobert Watson { "priv_msgbuf_privonly", priv_msgbuf_privonly_setup,
141d903306aSRobert Watson priv_msgbuf_privonly, priv_msgbuf_cleanup },
142d903306aSRobert Watson
143d903306aSRobert Watson { "priv_msgbuf_unprivok", priv_msgbuf_unprivok_setup,
144d903306aSRobert Watson priv_msgbuf_unprivok, priv_msgbuf_cleanup },
145d903306aSRobert Watson
146f3d220fbSBjoern A. Zeeb { "priv_netinet_ipsec_pfkey", NULL, priv_netinet_ipsec_pfkey, NULL },
147f3d220fbSBjoern A. Zeeb
148f3d220fbSBjoern A. Zeeb { "priv_netinet_ipsec_policy4_bypass",
149f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_bypass_setup,
150f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_bypass,
151f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_cleanup },
152f3d220fbSBjoern A. Zeeb
153e7fba5c7SBjoern A. Zeeb #ifdef INET6
154f3d220fbSBjoern A. Zeeb { "priv_netinet_ipsec_policy6_bypass",
155f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_bypass_setup,
156f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_bypass,
157f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_cleanup },
158e7fba5c7SBjoern A. Zeeb #endif
159f3d220fbSBjoern A. Zeeb
160f3d220fbSBjoern A. Zeeb { "priv_netinet_ipsec_policy4_entrust",
161f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_entrust_setup,
162f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_entrust,
163f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_cleanup },
164f3d220fbSBjoern A. Zeeb
165e7fba5c7SBjoern A. Zeeb #ifdef INET6
166f3d220fbSBjoern A. Zeeb { "priv_netinet_ipsec_policy6_entrust",
167f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_entrust_setup,
168f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_entrust,
169f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_cleanup },
170e7fba5c7SBjoern A. Zeeb #endif
1716007da5fSBjoern A. Zeeb
172d903306aSRobert Watson { "priv_netinet_raw", priv_netinet_raw_setup, priv_netinet_raw,
173d903306aSRobert Watson priv_netinet_raw_cleanup },
174d903306aSRobert Watson
175d903306aSRobert Watson { "priv_proc_setlogin", priv_proc_setlogin_setup, priv_proc_setlogin,
176d903306aSRobert Watson priv_proc_setlogin_cleanup },
177d903306aSRobert Watson
178d903306aSRobert Watson { "priv_proc_setrlimit_raisemax", priv_proc_setrlimit_setup,
179d903306aSRobert Watson priv_proc_setrlimit_raisemax, priv_proc_setrlimit_cleanup },
180d903306aSRobert Watson
181d903306aSRobert Watson { "priv_proc_setrlimit_raisecur", priv_proc_setrlimit_setup,
182d903306aSRobert Watson priv_proc_setrlimit_raisecur, priv_proc_setrlimit_cleanup },
183d903306aSRobert Watson
184d903306aSRobert Watson { "priv_proc_setrlimit_raisecur_nopriv", priv_proc_setrlimit_setup,
185d903306aSRobert Watson priv_proc_setrlimit_raisecur_nopriv,
186d903306aSRobert Watson priv_proc_setrlimit_cleanup },
187d903306aSRobert Watson
188d903306aSRobert Watson { "priv_sched_rtprio_curproc_normal", priv_sched_rtprio_setup,
189d903306aSRobert Watson priv_sched_rtprio_curproc_normal, priv_sched_rtprio_cleanup },
190d903306aSRobert Watson
191d903306aSRobert Watson { "priv_sched_rtprio_curproc_idle", priv_sched_rtprio_setup,
192d903306aSRobert Watson priv_sched_rtprio_curproc_idle, priv_sched_rtprio_cleanup },
193d903306aSRobert Watson
194d903306aSRobert Watson { "priv_sched_rtprio_curproc_realtime", priv_sched_rtprio_setup,
195d903306aSRobert Watson priv_sched_rtprio_curproc_realtime, priv_sched_rtprio_cleanup },
196d903306aSRobert Watson
197d903306aSRobert Watson { "priv_sched_rtprio_myproc_normal", priv_sched_rtprio_setup,
198d903306aSRobert Watson priv_sched_rtprio_myproc_normal, priv_sched_rtprio_cleanup },
199d903306aSRobert Watson
200d903306aSRobert Watson { "priv_sched_rtprio_myproc_idle", priv_sched_rtprio_setup,
201d903306aSRobert Watson priv_sched_rtprio_myproc_idle, priv_sched_rtprio_cleanup },
202d903306aSRobert Watson
203d903306aSRobert Watson { "priv_sched_rtprio_myproc_realtime", priv_sched_rtprio_setup,
204d903306aSRobert Watson priv_sched_rtprio_myproc_realtime, priv_sched_rtprio_cleanup },
205d903306aSRobert Watson
206d903306aSRobert Watson { "priv_sched_rtprio_aproc_normal", priv_sched_rtprio_setup,
207d903306aSRobert Watson priv_sched_rtprio_aproc_normal, priv_sched_rtprio_cleanup },
208d903306aSRobert Watson
209d903306aSRobert Watson { "priv_sched_rtprio_aproc_idle", priv_sched_rtprio_setup,
210d903306aSRobert Watson priv_sched_rtprio_aproc_idle, priv_sched_rtprio_cleanup },
211d903306aSRobert Watson
212d903306aSRobert Watson { "priv_sched_rtprio_aproc_realtime", priv_sched_rtprio_setup,
213d903306aSRobert Watson priv_sched_rtprio_aproc_realtime, priv_sched_rtprio_cleanup },
214d903306aSRobert Watson
215d903306aSRobert Watson { "priv_sched_setpriority_curproc", priv_sched_setpriority_setup,
216d903306aSRobert Watson priv_sched_setpriority_curproc, priv_sched_setpriority_cleanup },
217d903306aSRobert Watson
218d903306aSRobert Watson { "priv_sched_setpriority_myproc", priv_sched_setpriority_setup,
219d903306aSRobert Watson priv_sched_setpriority_myproc, priv_sched_setpriority_cleanup },
220d903306aSRobert Watson
221d903306aSRobert Watson { "priv_sched_setpriority_aproc", priv_sched_setpriority_setup,
222d903306aSRobert Watson priv_sched_setpriority_aproc, priv_sched_setpriority_cleanup },
223d903306aSRobert Watson
224d903306aSRobert Watson { "priv_settimeofday", priv_settimeofday_setup, priv_settimeofday,
225d903306aSRobert Watson priv_settimeofday_cleanup },
226d903306aSRobert Watson
227d903306aSRobert Watson { "priv_sysctl_write", priv_sysctl_write_setup, priv_sysctl_write,
228d903306aSRobert Watson priv_sysctl_write_cleanup },
229d903306aSRobert Watson
230d903306aSRobert Watson { "priv_sysctl_writejail", priv_sysctl_write_setup,
231d903306aSRobert Watson priv_sysctl_writejail, priv_sysctl_write_cleanup },
232d903306aSRobert Watson
233d903306aSRobert Watson { "priv_vfs_chflags_froot_uflags", priv_vfs_chflags_froot_setup,
234d903306aSRobert Watson priv_vfs_chflags_froot_uflags, priv_vfs_chflags_cleanup },
235d903306aSRobert Watson
236d903306aSRobert Watson { "priv_vfs_chflags_froot_sflags", priv_vfs_chflags_froot_setup,
237d903306aSRobert Watson priv_vfs_chflags_froot_sflags, priv_vfs_chflags_cleanup },
238d903306aSRobert Watson
239d903306aSRobert Watson { "priv_vfs_chflags_fowner_uflags", priv_vfs_chflags_fowner_setup,
240d903306aSRobert Watson priv_vfs_chflags_fowner_uflags, priv_vfs_chflags_cleanup },
241d903306aSRobert Watson
242d903306aSRobert Watson { "priv_vfs_chflags_fowner_sflags", priv_vfs_chflags_fowner_setup,
243d903306aSRobert Watson priv_vfs_chflags_fowner_sflags, priv_vfs_chflags_cleanup },
244d903306aSRobert Watson
245d903306aSRobert Watson { "priv_vfs_chflags_fother_uflags", priv_vfs_chflags_fother_setup,
246d903306aSRobert Watson priv_vfs_chflags_fother_uflags, priv_vfs_chflags_cleanup },
247d903306aSRobert Watson
248d903306aSRobert Watson { "priv_vfs_chflags_fother_sflags", priv_vfs_chflags_fother_setup,
249d903306aSRobert Watson priv_vfs_chflags_fother_sflags, priv_vfs_chflags_cleanup },
250d903306aSRobert Watson
251d903306aSRobert Watson { "priv_vfs_chmod_froot", priv_vfs_chmod_froot_setup,
252d903306aSRobert Watson priv_vfs_chmod_froot, priv_vfs_chmod_cleanup },
253d903306aSRobert Watson
254d903306aSRobert Watson { "priv_vfs_chmod_fowner", priv_vfs_chmod_fowner_setup,
255d903306aSRobert Watson priv_vfs_chmod_fowner, priv_vfs_chmod_cleanup },
256d903306aSRobert Watson
257d903306aSRobert Watson { "priv_vfs_chmod_fother", priv_vfs_chmod_fother_setup,
258d903306aSRobert Watson priv_vfs_chmod_fother, priv_vfs_chmod_cleanup },
259d903306aSRobert Watson
260d903306aSRobert Watson { "priv_vfs_chown_uid", priv_vfs_chown_uid_setup, priv_vfs_chown_uid,
261d903306aSRobert Watson priv_vfs_chown_cleanup },
262d903306aSRobert Watson
263d903306aSRobert Watson { "priv_vfs_chown_mygid", priv_vfs_chown_mygid_setup,
264d903306aSRobert Watson priv_vfs_chown_mygid, priv_vfs_chown_cleanup },
265d903306aSRobert Watson
266d903306aSRobert Watson { "priv_vfs_chown_othergid", priv_vfs_chown_othergid_setup,
267d903306aSRobert Watson priv_vfs_chown_othergid, priv_vfs_chown_cleanup },
268d903306aSRobert Watson
269d903306aSRobert Watson { "priv_vfs_chroot", priv_vfs_chroot_setup, priv_vfs_chroot,
270d903306aSRobert Watson priv_vfs_chroot_cleanup },
271d903306aSRobert Watson
272d903306aSRobert Watson { "priv_vfs_clearsugid_chgrp", priv_vfs_clearsugid_setup,
273d903306aSRobert Watson priv_vfs_clearsugid_chgrp, priv_vfs_clearsugid_cleanup },
274d903306aSRobert Watson
275d903306aSRobert Watson { "priv_vfs_clearsugid_extattr", priv_vfs_clearsugid_setup,
276d903306aSRobert Watson priv_vfs_clearsugid_extattr, priv_vfs_clearsugid_cleanup },
277d903306aSRobert Watson
278d903306aSRobert Watson { "priv_vfs_clearsugid_write", priv_vfs_clearsugid_setup,
279d903306aSRobert Watson priv_vfs_clearsugid_write, priv_vfs_clearsugid_cleanup },
280d903306aSRobert Watson
281d903306aSRobert Watson { "priv_vfs_extattr_system", priv_vfs_extattr_system_setup,
282d903306aSRobert Watson priv_vfs_extattr_system, priv_vfs_extattr_system_cleanup },
283d903306aSRobert Watson
284d903306aSRobert Watson { "priv_vfs_fhopen", priv_vfs_fhopen_setup, priv_vfs_fhopen,
285d903306aSRobert Watson priv_vfs_fhopen_cleanup },
286d903306aSRobert Watson
287d903306aSRobert Watson { "priv_vfs_fhstat", priv_vfs_fhstat_setup, priv_vfs_fhstat,
288d903306aSRobert Watson priv_vfs_fhstat_cleanup },
289d903306aSRobert Watson
290d903306aSRobert Watson { "priv_vfs_fhstatfs", priv_vfs_fhstatfs_setup, priv_vfs_fhstatfs,
291d903306aSRobert Watson priv_vfs_fhstatfs_cleanup },
292d903306aSRobert Watson
293d903306aSRobert Watson { "priv_vfs_generation", priv_vfs_generation_setup,
294d903306aSRobert Watson priv_vfs_generation, priv_vfs_generation_cleanup },
295d903306aSRobert Watson
296d903306aSRobert Watson { "priv_vfs_getfh", priv_vfs_getfh_setup, priv_vfs_getfh,
297d903306aSRobert Watson priv_vfs_getfh_cleanup },
298d903306aSRobert Watson
299d903306aSRobert Watson { "priv_vfs_readwrite_fowner", priv_vfs_readwrite_fowner_setup,
300d903306aSRobert Watson priv_vfs_readwrite_fowner, priv_vfs_readwrite_cleanup },
301d903306aSRobert Watson
302d903306aSRobert Watson { "priv_vfs_readwrite_fgroup", priv_vfs_readwrite_fgroup_setup,
303d903306aSRobert Watson priv_vfs_readwrite_fgroup, priv_vfs_readwrite_cleanup },
304d903306aSRobert Watson
305d903306aSRobert Watson { "priv_vfs_readwrite_fother", priv_vfs_readwrite_fother_setup,
306d903306aSRobert Watson priv_vfs_readwrite_fother, priv_vfs_readwrite_cleanup },
307d903306aSRobert Watson
308d903306aSRobert Watson { "priv_vfs_setgid_fowner", priv_vfs_setgid_fowner_setup,
309d903306aSRobert Watson priv_vfs_setgid_fowner, priv_vfs_setgid_cleanup },
310d903306aSRobert Watson
311d903306aSRobert Watson { "priv_vfs_setgid_fother", priv_vfs_setgid_fother_setup,
312d903306aSRobert Watson priv_vfs_setgid_fother, priv_vfs_setgid_cleanup },
313d903306aSRobert Watson
314d903306aSRobert Watson { "priv_vfs_stickyfile_dir_fowner",
315d903306aSRobert Watson priv_vfs_stickyfile_dir_fowner_setup,
316d903306aSRobert Watson priv_vfs_stickyfile_dir_fowner,
317d903306aSRobert Watson priv_vfs_stickyfile_dir_cleanup },
318d903306aSRobert Watson
319d903306aSRobert Watson { "priv_vfs_stickyfile_dir_fother",
320d903306aSRobert Watson priv_vfs_stickyfile_dir_fother_setup,
321d903306aSRobert Watson priv_vfs_stickyfile_dir_fother,
322d903306aSRobert Watson priv_vfs_stickyfile_dir_cleanup },
323d903306aSRobert Watson
324d903306aSRobert Watson { "priv_vfs_stickyfile_file_fowner",
325d903306aSRobert Watson priv_vfs_stickyfile_file_fowner_setup,
326d903306aSRobert Watson priv_vfs_stickyfile_file_fowner,
327d903306aSRobert Watson priv_vfs_stickyfile_file_cleanup },
328d903306aSRobert Watson
329d903306aSRobert Watson { "priv_vfs_stickyfile_file_fother",
330d903306aSRobert Watson priv_vfs_stickyfile_file_fother_setup,
331d903306aSRobert Watson priv_vfs_stickyfile_file_fother,
332d903306aSRobert Watson priv_vfs_stickyfile_file_cleanup },
333d903306aSRobert Watson
334d903306aSRobert Watson { "priv_vfs_utimes_froot", priv_vfs_utimes_froot_setup,
335d903306aSRobert Watson priv_vfs_utimes_froot, priv_vfs_utimes_cleanup },
336d903306aSRobert Watson
337d903306aSRobert Watson { "priv_vfs_utimes_froot_null", priv_vfs_utimes_froot_setup,
338d903306aSRobert Watson priv_vfs_utimes_froot_null, priv_vfs_utimes_cleanup },
339d903306aSRobert Watson
340d903306aSRobert Watson { "priv_vfs_utimes_fowner", priv_vfs_utimes_fowner_setup,
341d903306aSRobert Watson priv_vfs_utimes_fowner, priv_vfs_utimes_cleanup },
342d903306aSRobert Watson
343d903306aSRobert Watson { "priv_vfs_utimes_fowner_null", priv_vfs_utimes_fowner_setup,
344d903306aSRobert Watson priv_vfs_utimes_fowner_null, priv_vfs_utimes_cleanup },
345d903306aSRobert Watson
346d903306aSRobert Watson { "priv_vfs_utimes_fother", priv_vfs_utimes_fother_setup,
347d903306aSRobert Watson priv_vfs_utimes_fother, priv_vfs_utimes_cleanup },
348d903306aSRobert Watson
349d903306aSRobert Watson { "priv_vfs_utimes_fother_null", priv_vfs_utimes_fother_setup,
350d903306aSRobert Watson priv_vfs_utimes_fother_null, priv_vfs_utimes_cleanup },
351d903306aSRobert Watson
352d903306aSRobert Watson { "priv_vm_madv_protect", priv_vm_madv_protect_setup,
353d903306aSRobert Watson priv_vm_madv_protect, priv_vm_madv_protect_cleanup },
354d903306aSRobert Watson
355d903306aSRobert Watson { "priv_vm_mlock", priv_vm_mlock_setup, priv_vm_mlock,
356d903306aSRobert Watson priv_vm_mlock_cleanup },
357d903306aSRobert Watson
358d903306aSRobert Watson { "priv_vm_munlock", priv_vm_munlock_setup, priv_vm_munlock,
359d903306aSRobert Watson priv_vm_munlock_cleanup },
360d903306aSRobert Watson
361d903306aSRobert Watson };
362d903306aSRobert Watson static int tests_count = sizeof(tests) / sizeof(struct test);
363d903306aSRobert Watson
3649fa5f6b4SRobert Watson void
expect(const char * test,int error,int expected_error,int expected_errno)365d903306aSRobert Watson expect(const char *test, int error, int expected_error, int expected_errno)
3669fa5f6b4SRobert Watson {
3679fa5f6b4SRobert Watson
368d903306aSRobert Watson if (error == 0) {
36934ed5572SJulio Merino if (expected_error != 0) {
37034ed5572SJulio Merino something_failed = 1;
371d903306aSRobert Watson warnx("%s: returned 0", test);
37234ed5572SJulio Merino }
373d903306aSRobert Watson } else {
37434ed5572SJulio Merino if (expected_error == 0) {
37534ed5572SJulio Merino something_failed = 1;
376d903306aSRobert Watson warn("%s: returned (%d, %d)", test, error, errno);
37734ed5572SJulio Merino } else if (expected_errno != errno) {
37834ed5572SJulio Merino something_failed = 1;
379d903306aSRobert Watson warn("%s: returned (%d, %d)", test, error, errno);
380d903306aSRobert Watson }
3819fa5f6b4SRobert Watson }
38234ed5572SJulio Merino }
3839fa5f6b4SRobert Watson
3849fa5f6b4SRobert Watson void
setup_dir(const char * test,char * dpathp,uid_t uid,gid_t gid,mode_t mode)385d903306aSRobert Watson setup_dir(const char *test, char *dpathp, uid_t uid, gid_t gid, mode_t mode)
386d903306aSRobert Watson {
387d903306aSRobert Watson
388d903306aSRobert Watson strcpy(dpathp, "/tmp/priv.XXXXXXXXXXX");
389d903306aSRobert Watson if (mkdtemp(dpathp) == NULL)
390d903306aSRobert Watson err(-1, "test %s: mkdtemp", test);
391d903306aSRobert Watson
392d903306aSRobert Watson if (chown(dpathp, uid, gid) < 0)
393d903306aSRobert Watson err(-1, "test %s: chown(%s, %d, %d)", test, dpathp, uid,
394d903306aSRobert Watson gid);
395d903306aSRobert Watson
396d903306aSRobert Watson if (chmod(dpathp, mode) < 0)
397d903306aSRobert Watson err(-1, "test %s: chmod(%s, 0%o)", test, dpathp, mode);
398d903306aSRobert Watson }
399d903306aSRobert Watson
400d903306aSRobert Watson void
setup_file(const char * test,char * fpathp,uid_t uid,gid_t gid,mode_t mode)401d903306aSRobert Watson setup_file(const char *test, char *fpathp, uid_t uid, gid_t gid, mode_t mode)
4029fa5f6b4SRobert Watson {
4039fa5f6b4SRobert Watson int fd;
4049fa5f6b4SRobert Watson
4059fa5f6b4SRobert Watson strcpy(fpathp, "/tmp/priv.XXXXXXXXXXX");
4069fa5f6b4SRobert Watson fd = mkstemp(fpathp);
4079fa5f6b4SRobert Watson if (fd < 0)
408d903306aSRobert Watson err(-1, "test %s: mkstemp", test);
4099fa5f6b4SRobert Watson
4109fa5f6b4SRobert Watson if (fchown(fd, uid, gid) < 0)
411d903306aSRobert Watson err(-1, "test %s: fchown(%s, %d, %d)", test, fpathp, uid,
412d903306aSRobert Watson gid);
4139fa5f6b4SRobert Watson
4149fa5f6b4SRobert Watson if (fchmod(fd, mode) < 0)
415d903306aSRobert Watson err(-1, "test %s: chmod(%s, 0%o)", test, fpathp, mode);
4169fa5f6b4SRobert Watson
4179fa5f6b4SRobert Watson close(fd);
4189fa5f6b4SRobert Watson }
4199fa5f6b4SRobert Watson
4209fa5f6b4SRobert Watson /*
421d903306aSRobert Watson * Irrevocably set credentials to specific uid and gid.
4229fa5f6b4SRobert Watson */
423d903306aSRobert Watson static void
set_creds(const char * test,uid_t uid,gid_t gid)424d903306aSRobert Watson set_creds(const char *test, uid_t uid, gid_t gid)
4259fa5f6b4SRobert Watson {
426d903306aSRobert Watson gid_t gids[1] = { gid };
4279fa5f6b4SRobert Watson
428d903306aSRobert Watson if (setgid(gid) < 0)
429d903306aSRobert Watson err(-1, "test %s: setegid(%d)", test, gid);
430d903306aSRobert Watson if (setgroups(sizeof(gids)/sizeof(gid_t), gids) < 0)
431d903306aSRobert Watson err(-1, "test %s: setgroups(%d)", test, gid);
432d903306aSRobert Watson if (setuid(uid) < 0)
433d903306aSRobert Watson err(-1, "test %s: seteuid(%d)", test, uid);
4349fa5f6b4SRobert Watson }
4359fa5f6b4SRobert Watson
436d903306aSRobert Watson static void
enter_jail(const char * test)437d903306aSRobert Watson enter_jail(const char *test)
4389fa5f6b4SRobert Watson {
439d903306aSRobert Watson struct jail j;
440e7fba5c7SBjoern A. Zeeb struct in_addr ia4;
441e7fba5c7SBjoern A. Zeeb #ifdef INET6
442e7fba5c7SBjoern A. Zeeb struct in6_addr ia6 = IN6ADDR_LOOPBACK_INIT;
443e7fba5c7SBjoern A. Zeeb #endif
4449fa5f6b4SRobert Watson
445d903306aSRobert Watson bzero(&j, sizeof(j));
446e7fba5c7SBjoern A. Zeeb j.version = JAIL_API_VERSION;
447d903306aSRobert Watson j.path = "/";
448d903306aSRobert Watson j.hostname = "test";
449e7fba5c7SBjoern A. Zeeb j.jailname = "regressions/priv";
450e7fba5c7SBjoern A. Zeeb ia4.s_addr = htonl(INADDR_LOOPBACK);
451e7fba5c7SBjoern A. Zeeb j.ip4s = 1;
452e7fba5c7SBjoern A. Zeeb j.ip4 = &ia4;
453e7fba5c7SBjoern A. Zeeb #ifdef INET6
454e7fba5c7SBjoern A. Zeeb j.ip6s = 1;
455e7fba5c7SBjoern A. Zeeb j.ip6 = &ia6;
456e7fba5c7SBjoern A. Zeeb #endif
457d903306aSRobert Watson if (jail(&j) < 0)
458d903306aSRobert Watson err(-1, "test %s: jail", test);
4599fa5f6b4SRobert Watson }
4609fa5f6b4SRobert Watson
461d903306aSRobert Watson static void
run_child(struct test * test,int asroot,int injail)462d903306aSRobert Watson run_child(struct test *test, int asroot, int injail)
4639fa5f6b4SRobert Watson {
4649fa5f6b4SRobert Watson
465d903306aSRobert Watson setprogname(test->t_name);
466d903306aSRobert Watson if (injail)
467d903306aSRobert Watson enter_jail(test->t_name);
468d903306aSRobert Watson if (!asroot)
469d903306aSRobert Watson set_creds(test->t_name, UID_OWNER, GID_OWNER);
470d903306aSRobert Watson test->t_test_func(asroot, injail, test);
4719fa5f6b4SRobert Watson }
4729fa5f6b4SRobert Watson
4739fa5f6b4SRobert Watson /*
474d903306aSRobert Watson * Run a test in a particular credential context -- always call the setup and
475d903306aSRobert Watson * cleanup routines; if setup succeeds, also run the test. Test cleanup must
476d903306aSRobert Watson * handle cases where the setup has failed, so may need to maintain their own
477d903306aSRobert Watson * state in order to know what needs cleaning up (such as whether temporary
478d903306aSRobert Watson * files were created).
4799fa5f6b4SRobert Watson */
4809fa5f6b4SRobert Watson static void
run(struct test * test,int asroot,int injail)481d903306aSRobert Watson run(struct test *test, int asroot, int injail)
4829fa5f6b4SRobert Watson {
4839fa5f6b4SRobert Watson pid_t childpid, pid;
4849fa5f6b4SRobert Watson
485d903306aSRobert Watson if (test->t_setup_func != NULL) {
486d903306aSRobert Watson if ((test->t_setup_func)(asroot, injail, test) != 0) {
487d903306aSRobert Watson warnx("run(%s, %d, %d) setup failed", test->t_name,
488d903306aSRobert Watson asroot, injail);
489d903306aSRobert Watson goto cleanup;
490d903306aSRobert Watson }
491d903306aSRobert Watson }
4929fa5f6b4SRobert Watson fflush(stdout);
4939fa5f6b4SRobert Watson fflush(stderr);
4949fa5f6b4SRobert Watson childpid = fork();
495d903306aSRobert Watson if (childpid == -1) {
496d903306aSRobert Watson warn("run(%s, %d, %d) fork failed", test->t_name, asroot,
497d903306aSRobert Watson injail);
498d903306aSRobert Watson goto cleanup;
499d903306aSRobert Watson }
5009fa5f6b4SRobert Watson if (childpid == 0) {
501d903306aSRobert Watson run_child(test, asroot, injail);
5029fa5f6b4SRobert Watson fflush(stdout);
5039fa5f6b4SRobert Watson fflush(stderr);
50434ed5572SJulio Merino exit(something_failed ? EXIT_FAILURE : EXIT_SUCCESS);
5059fa5f6b4SRobert Watson } else {
5069fa5f6b4SRobert Watson while (1) {
50734ed5572SJulio Merino int status;
50834ed5572SJulio Merino pid = waitpid(childpid, &status, 0);
50934ed5572SJulio Merino if (pid == -1) {
51034ed5572SJulio Merino something_failed = 1;
511d903306aSRobert Watson warn("test: waitpid %s", test->t_name);
51234ed5572SJulio Merino }
51334ed5572SJulio Merino if (pid == childpid) {
51434ed5572SJulio Merino if (WIFEXITED(status) &&
51534ed5572SJulio Merino WEXITSTATUS(status) == EXIT_SUCCESS) {
51634ed5572SJulio Merino /* All good in the subprocess! */
51734ed5572SJulio Merino } else {
51834ed5572SJulio Merino something_failed = 1;
51934ed5572SJulio Merino }
5209fa5f6b4SRobert Watson break;
5219fa5f6b4SRobert Watson }
5229fa5f6b4SRobert Watson }
52334ed5572SJulio Merino }
5249fa5f6b4SRobert Watson fflush(stdout);
5259fa5f6b4SRobert Watson fflush(stderr);
526d903306aSRobert Watson cleanup:
527d903306aSRobert Watson if (test->t_cleanup_func != NULL)
528d903306aSRobert Watson test->t_cleanup_func(asroot, injail, test);
5299fa5f6b4SRobert Watson }
5309fa5f6b4SRobert Watson
5319fa5f6b4SRobert Watson int
main(int argc,char * argv[])5329fa5f6b4SRobert Watson main(int argc, char *argv[])
5339fa5f6b4SRobert Watson {
534d903306aSRobert Watson int i;
5359fa5f6b4SRobert Watson
536d903306aSRobert Watson /*
537d903306aSRobert Watson * This test suite will need to become quite a bit more enlightened
538d903306aSRobert Watson * if the notion of privilege is truly separated from root, as tests
539d903306aSRobert Watson * make assumptions about when privilege will be present. In
540d903306aSRobert Watson * particular, VFS-related tests need to manage uids in order to
541d903306aSRobert Watson * force the use of privilege, and will likely need checking.
542d903306aSRobert Watson */
543d903306aSRobert Watson if (getuid() != 0 && geteuid() != 0)
544*2111435bSJulio Merino errx(-1, "must be run as root");
5459fa5f6b4SRobert Watson
546d903306aSRobert Watson /*
547d903306aSRobert Watson * Run each test four times, varying whether the process is running
548d903306aSRobert Watson * as root and in jail in order to test all possible combinations.
549d903306aSRobert Watson */
550d903306aSRobert Watson for (i = 0; i < tests_count; i++) {
551d903306aSRobert Watson run(&tests[i], 0, 0);
552d903306aSRobert Watson run(&tests[i], 0, 1);
553d903306aSRobert Watson run(&tests[i], 1, 0);
554d903306aSRobert Watson run(&tests[i], 1, 1);
555d903306aSRobert Watson }
55634ed5572SJulio Merino return (something_failed ? EXIT_FAILURE : EXIT_SUCCESS);
5579fa5f6b4SRobert Watson }
558