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