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