summaryrefslogtreecommitdiffstats
path: root/tools/regression
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2007-09-09 23:08:39 +0000
committerrwatson <rwatson@FreeBSD.org>2007-09-09 23:08:39 +0000
commit2f5eb093a49d608441a859f9e1771c6dbbc128e0 (patch)
tree31905091a75e03080d113f8836c9872dcff17a5f /tools/regression
parent5e60afe4dd87cca48fda764041753bfa24da562b (diff)
downloadFreeBSD-src-2f5eb093a49d608441a859f9e1771c6dbbc128e0.zip
FreeBSD-src-2f5eb093a49d608441a859f9e1771c6dbbc128e0.tar.gz
Enhance and expand kernel privilege regression tests in support of
work present in FreeBSD 7.0 to refine the kernel privilege model: - Introduce support for jail as a testing variable, in order to confirm that privileges are properly restricted in the jail environment. - Restructure overall testing approach so that privilege and jail conditions are set in the testing infrastructure before tests are invoked, and done so in a custom-created process to isolate the impact of tests from each other in a more consistent way. - Tests now provide setup and cleanup hooks that occur before and after the test runs. - New privilege tests are now present for several audit privileges, several credential management privileges, dmesg buffer reading privilege, and netinet raw socket creation. - Other existing tests are restructured and generally improved as a result of better framework structure and jail as a variable. For exampe, we now test that certain sysctls are writable only outside jail, while others are writable within jail. On a similar note, privileges relating to setting UFS file flags are now better exercised, as with the right to chmod and utimes files. Approved by: re (bmah) Obtained from: TrustedBSD Project
Diffstat (limited to 'tools/regression')
-rw-r--r--tools/regression/priv/Makefile20
-rw-r--r--tools/regression/priv/main.c455
-rw-r--r--tools/regression/priv/main.h299
-rw-r--r--tools/regression/priv/priv_acct.c220
-rw-r--r--tools/regression/priv/priv_adjtime.c59
-rw-r--r--tools/regression/priv/priv_audit_control.c85
-rw-r--r--tools/regression/priv/priv_audit_getaudit.c102
-rw-r--r--tools/regression/priv/priv_audit_setaudit.c109
-rw-r--r--tools/regression/priv/priv_audit_submit.c88
-rw-r--r--tools/regression/priv/priv_clock_settime.c56
-rw-r--r--tools/regression/priv/priv_cred.c208
-rw-r--r--tools/regression/priv/priv_io.c115
-rw-r--r--tools/regression/priv/priv_kenv_set.c42
-rw-r--r--tools/regression/priv/priv_kenv_unset.c52
-rw-r--r--tools/regression/priv/priv_msgbuf.c152
-rw-r--r--tools/regression/priv/priv_netinet_raw.c82
-rw-r--r--tools/regression/priv/priv_proc_setlogin.c65
-rw-r--r--tools/regression/priv/priv_proc_setrlimit.c189
-rw-r--r--tools/regression/priv/priv_sched_rtprio.c353
-rw-r--r--tools/regression/priv/priv_sched_setpriority.c186
-rw-r--r--tools/regression/priv/priv_settimeofday.c55
-rw-r--r--tools/regression/priv/priv_sysctl_write.c109
-rw-r--r--tools/regression/priv/priv_vfs_admin.c328
-rw-r--r--tools/regression/priv/priv_vfs_chflags.c254
-rw-r--r--tools/regression/priv/priv_vfs_chmod.c146
-rw-r--r--tools/regression/priv/priv_vfs_chown.c194
-rw-r--r--tools/regression/priv/priv_vfs_chroot.c36
-rw-r--r--tools/regression/priv/priv_vfs_clearsugid.c209
-rw-r--r--tools/regression/priv/priv_vfs_extattr_system.c78
-rw-r--r--tools/regression/priv/priv_vfs_fhopen.c79
-rw-r--r--tools/regression/priv/priv_vfs_fhstat.c74
-rw-r--r--tools/regression/priv/priv_vfs_fhstatfs.c78
-rw-r--r--tools/regression/priv/priv_vfs_generation.c115
-rw-r--r--tools/regression/priv/priv_vfs_getfh.c51
-rw-r--r--tools/regression/priv/priv_vfs_read_write.c475
-rw-r--r--tools/regression/priv/priv_vfs_setgid.c148
-rw-r--r--tools/regression/priv/priv_vfs_stickyfile.c210
-rw-r--r--tools/regression/priv/priv_vfs_utimes.c224
-rw-r--r--tools/regression/priv/priv_vm_madv_protect.c38
-rw-r--r--tools/regression/priv/priv_vm_mlock.c35
-rw-r--r--tools/regression/priv/priv_vm_munlock.c36
-rw-r--r--tools/regression/priv/test_utimes.c153
42 files changed, 3850 insertions, 2212 deletions
diff --git a/tools/regression/priv/Makefile b/tools/regression/priv/Makefile
index 7a8d7a0..2a63ecc 100644
--- a/tools/regression/priv/Makefile
+++ b/tools/regression/priv/Makefile
@@ -2,21 +2,29 @@
# $FreeBSD$
#
-PROG= main
+PROG= priv
SRCS= main.c \
priv_acct.c \
priv_adjtime.c \
+ priv_audit_control.c \
+ priv_audit_getaudit.c \
+ priv_audit_setaudit.c \
+ priv_audit_submit.c \
priv_clock_settime.c \
+ priv_cred.c \
priv_io.c \
priv_kenv_set.c \
priv_kenv_unset.c \
+ priv_msgbuf.c \
+ priv_netinet_raw.c \
priv_proc_setlogin.c \
priv_proc_setrlimit.c \
priv_sched_rtprio.c \
priv_sched_setpriority.c \
priv_settimeofday.c \
priv_sysctl_write.c \
- priv_vfs_admin.c \
+ priv_vfs_chflags.c \
+ priv_vfs_chmod.c \
priv_vfs_chown.c \
priv_vfs_chroot.c \
priv_vfs_clearsugid.c \
@@ -29,11 +37,11 @@ SRCS= main.c \
priv_vfs_read_write.c \
priv_vfs_setgid.c \
priv_vfs_stickyfile.c \
- priv_vm_mlock.c \
- priv_vm_munlock.c \
+ priv_vfs_utimes.c \
priv_vm_madv_protect.c \
- \
- test_utimes.c
+ priv_vm_mlock.c \
+ priv_vm_munlock.c
+
NO_MAN=
WARNS= 3
diff --git a/tools/regression/priv/main.c b/tools/regression/priv/main.c
index 90622ad..a9faa98 100644
--- a/tools/regression/priv/main.c
+++ b/tools/regression/priv/main.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,16 +31,20 @@
*/
/*
- * Privilege test framework. Each test is encapsulated on a .c file exporting
- * a function that implements the test. Each test is run from its own child
- * process, and they are run in sequence one at a time.
+ * Privilege test framework. Each test is encapsulated on a .c file
+ * exporting a function that implements the test. Each test is run from its
+ * own child process, and they are run in sequence one at a time.
*/
-#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/jail.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <netinet/in.h>
+
#include <err.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -48,86 +53,402 @@
#include "main.h"
/*
- * Common routines used across many tests.
+ * Registration table of privilege tests. Each test registers a name, a test
+ * function, and a cleanup function to run after the test has completed,
+ * regardless of success/failure.
*/
+static struct test tests[] = {
+ { "priv_acct_enable", priv_acct_setup, priv_acct_enable,
+ priv_acct_cleanup },
+
+ { "priv_acct_disable", priv_acct_setup, priv_acct_disable,
+ priv_acct_cleanup },
+
+ { "priv_acct_rotate", priv_acct_setup, priv_acct_rotate,
+ priv_acct_cleanup },
+
+ { "priv_acct_noopdisable", priv_acct_setup, priv_acct_noopdisable,
+ priv_acct_cleanup },
+
+ { "priv_adjtime_set", priv_adjtime_setup, priv_adjtime_set,
+ priv_adjtime_cleanup },
+
+ { "priv_audit_submit", priv_audit_submit_setup, priv_audit_submit,
+ priv_audit_submit_cleanup },
+
+ { "priv_audit_control", priv_audit_control_setup, priv_audit_control,
+ priv_audit_control_cleanup },
+
+ { "priv_audit_getaudit", priv_audit_getaudit_setup,
+ priv_audit_getaudit, priv_audit_getaudit_cleanup },
+
+ { "priv_audit_getaudit_addr", priv_audit_getaudit_setup,
+ priv_audit_getaudit_addr, priv_audit_getaudit_cleanup },
+
+ { "priv_audit_setaudit", priv_audit_setaudit_setup,
+ priv_audit_setaudit, priv_audit_setaudit_cleanup },
+
+ { "priv_audit_setaudit_addr", priv_audit_setaudit_setup,
+ priv_audit_setaudit_addr, priv_audit_setaudit_cleanup },
+
+ { "priv_clock_settime", priv_clock_settime_setup, priv_clock_settime,
+ priv_clock_settime_cleanup },
+
+ { "priv_cred_setuid", priv_cred_setup, priv_cred_setuid,
+ priv_cred_cleanup },
+
+ { "priv_cred_seteuid", priv_cred_setup, priv_cred_seteuid,
+ priv_cred_cleanup },
+
+ { "priv_cred_setgid", priv_cred_setup, priv_cred_setgid,
+ priv_cred_cleanup },
+
+ { "priv_cred_setegid", priv_cred_setup, priv_cred_setegid,
+ priv_cred_cleanup },
+
+ { "priv_cred_setgroups", priv_cred_setup, priv_cred_setgroups,
+ priv_cred_cleanup },
+
+ { "priv_cred_setreuid", priv_cred_setup, priv_cred_setreuid,
+ priv_cred_cleanup },
+
+ { "priv_cred_setregid", priv_cred_setup, priv_cred_setregid,
+ priv_cred_cleanup },
+
+ { "priv_cred_setresuid", priv_cred_setup, priv_cred_setresuid,
+ priv_cred_cleanup },
+
+ { "priv_cred_setresgid", priv_cred_setup, priv_cred_setresgid,
+ priv_cred_cleanup },
+
+ { "priv_io", priv_io_setup, priv_io, priv_io_cleanup },
+
+ { "priv_kenv_set", priv_kenv_set_setup, priv_kenv_set,
+ priv_kenv_set_cleanup },
+
+ { "priv_kenv_unset", priv_kenv_unset_setup, priv_kenv_unset,
+ priv_kenv_unset_cleanup },
+
+ { "priv_msgbuf_privonly", priv_msgbuf_privonly_setup,
+ priv_msgbuf_privonly, priv_msgbuf_cleanup },
+
+ { "priv_msgbuf_unprivok", priv_msgbuf_unprivok_setup,
+ priv_msgbuf_unprivok, priv_msgbuf_cleanup },
+
+ { "priv_netinet_raw", priv_netinet_raw_setup, priv_netinet_raw,
+ priv_netinet_raw_cleanup },
+
+ { "priv_proc_setlogin", priv_proc_setlogin_setup, priv_proc_setlogin,
+ priv_proc_setlogin_cleanup },
+
+ { "priv_proc_setrlimit_raisemax", priv_proc_setrlimit_setup,
+ priv_proc_setrlimit_raisemax, priv_proc_setrlimit_cleanup },
+
+ { "priv_proc_setrlimit_raisecur", priv_proc_setrlimit_setup,
+ priv_proc_setrlimit_raisecur, priv_proc_setrlimit_cleanup },
+
+ { "priv_proc_setrlimit_raisecur_nopriv", priv_proc_setrlimit_setup,
+ priv_proc_setrlimit_raisecur_nopriv,
+ priv_proc_setrlimit_cleanup },
+
+ { "priv_sched_rtprio_curproc_normal", priv_sched_rtprio_setup,
+ priv_sched_rtprio_curproc_normal, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_curproc_idle", priv_sched_rtprio_setup,
+ priv_sched_rtprio_curproc_idle, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_curproc_realtime", priv_sched_rtprio_setup,
+ priv_sched_rtprio_curproc_realtime, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_myproc_normal", priv_sched_rtprio_setup,
+ priv_sched_rtprio_myproc_normal, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_myproc_idle", priv_sched_rtprio_setup,
+ priv_sched_rtprio_myproc_idle, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_myproc_realtime", priv_sched_rtprio_setup,
+ priv_sched_rtprio_myproc_realtime, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_aproc_normal", priv_sched_rtprio_setup,
+ priv_sched_rtprio_aproc_normal, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_aproc_idle", priv_sched_rtprio_setup,
+ priv_sched_rtprio_aproc_idle, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_rtprio_aproc_realtime", priv_sched_rtprio_setup,
+ priv_sched_rtprio_aproc_realtime, priv_sched_rtprio_cleanup },
+
+ { "priv_sched_setpriority_curproc", priv_sched_setpriority_setup,
+ priv_sched_setpriority_curproc, priv_sched_setpriority_cleanup },
+
+ { "priv_sched_setpriority_myproc", priv_sched_setpriority_setup,
+ priv_sched_setpriority_myproc, priv_sched_setpriority_cleanup },
+
+ { "priv_sched_setpriority_aproc", priv_sched_setpriority_setup,
+ priv_sched_setpriority_aproc, priv_sched_setpriority_cleanup },
+
+ { "priv_settimeofday", priv_settimeofday_setup, priv_settimeofday,
+ priv_settimeofday_cleanup },
+
+ { "priv_sysctl_write", priv_sysctl_write_setup, priv_sysctl_write,
+ priv_sysctl_write_cleanup },
+
+ { "priv_sysctl_writejail", priv_sysctl_write_setup,
+ priv_sysctl_writejail, priv_sysctl_write_cleanup },
+
+ { "priv_vfs_chflags_froot_uflags", priv_vfs_chflags_froot_setup,
+ priv_vfs_chflags_froot_uflags, priv_vfs_chflags_cleanup },
+
+ { "priv_vfs_chflags_froot_sflags", priv_vfs_chflags_froot_setup,
+ priv_vfs_chflags_froot_sflags, priv_vfs_chflags_cleanup },
+
+ { "priv_vfs_chflags_fowner_uflags", priv_vfs_chflags_fowner_setup,
+ priv_vfs_chflags_fowner_uflags, priv_vfs_chflags_cleanup },
+
+ { "priv_vfs_chflags_fowner_sflags", priv_vfs_chflags_fowner_setup,
+ priv_vfs_chflags_fowner_sflags, priv_vfs_chflags_cleanup },
+
+ { "priv_vfs_chflags_fother_uflags", priv_vfs_chflags_fother_setup,
+ priv_vfs_chflags_fother_uflags, priv_vfs_chflags_cleanup },
+
+ { "priv_vfs_chflags_fother_sflags", priv_vfs_chflags_fother_setup,
+ priv_vfs_chflags_fother_sflags, priv_vfs_chflags_cleanup },
+
+ { "priv_vfs_chmod_froot", priv_vfs_chmod_froot_setup,
+ priv_vfs_chmod_froot, priv_vfs_chmod_cleanup },
+
+ { "priv_vfs_chmod_fowner", priv_vfs_chmod_fowner_setup,
+ priv_vfs_chmod_fowner, priv_vfs_chmod_cleanup },
+
+ { "priv_vfs_chmod_fother", priv_vfs_chmod_fother_setup,
+ priv_vfs_chmod_fother, priv_vfs_chmod_cleanup },
+
+ { "priv_vfs_chown_uid", priv_vfs_chown_uid_setup, priv_vfs_chown_uid,
+ priv_vfs_chown_cleanup },
+
+ { "priv_vfs_chown_mygid", priv_vfs_chown_mygid_setup,
+ priv_vfs_chown_mygid, priv_vfs_chown_cleanup },
+
+ { "priv_vfs_chown_othergid", priv_vfs_chown_othergid_setup,
+ priv_vfs_chown_othergid, priv_vfs_chown_cleanup },
+
+ { "priv_vfs_chroot", priv_vfs_chroot_setup, priv_vfs_chroot,
+ priv_vfs_chroot_cleanup },
+
+ { "priv_vfs_clearsugid_chgrp", priv_vfs_clearsugid_setup,
+ priv_vfs_clearsugid_chgrp, priv_vfs_clearsugid_cleanup },
+
+ { "priv_vfs_clearsugid_extattr", priv_vfs_clearsugid_setup,
+ priv_vfs_clearsugid_extattr, priv_vfs_clearsugid_cleanup },
+
+ { "priv_vfs_clearsugid_write", priv_vfs_clearsugid_setup,
+ priv_vfs_clearsugid_write, priv_vfs_clearsugid_cleanup },
+
+ { "priv_vfs_extattr_system", priv_vfs_extattr_system_setup,
+ priv_vfs_extattr_system, priv_vfs_extattr_system_cleanup },
+
+ { "priv_vfs_fhopen", priv_vfs_fhopen_setup, priv_vfs_fhopen,
+ priv_vfs_fhopen_cleanup },
+
+ { "priv_vfs_fhstat", priv_vfs_fhstat_setup, priv_vfs_fhstat,
+ priv_vfs_fhstat_cleanup },
+
+ { "priv_vfs_fhstatfs", priv_vfs_fhstatfs_setup, priv_vfs_fhstatfs,
+ priv_vfs_fhstatfs_cleanup },
+
+ { "priv_vfs_generation", priv_vfs_generation_setup,
+ priv_vfs_generation, priv_vfs_generation_cleanup },
+
+ { "priv_vfs_getfh", priv_vfs_getfh_setup, priv_vfs_getfh,
+ priv_vfs_getfh_cleanup },
+
+ { "priv_vfs_readwrite_fowner", priv_vfs_readwrite_fowner_setup,
+ priv_vfs_readwrite_fowner, priv_vfs_readwrite_cleanup },
+
+ { "priv_vfs_readwrite_fgroup", priv_vfs_readwrite_fgroup_setup,
+ priv_vfs_readwrite_fgroup, priv_vfs_readwrite_cleanup },
+
+ { "priv_vfs_readwrite_fother", priv_vfs_readwrite_fother_setup,
+ priv_vfs_readwrite_fother, priv_vfs_readwrite_cleanup },
+
+ { "priv_vfs_setgid_fowner", priv_vfs_setgid_fowner_setup,
+ priv_vfs_setgid_fowner, priv_vfs_setgid_cleanup },
+
+ { "priv_vfs_setgid_fother", priv_vfs_setgid_fother_setup,
+ priv_vfs_setgid_fother, priv_vfs_setgid_cleanup },
+
+ { "priv_vfs_stickyfile_dir_fowner",
+ priv_vfs_stickyfile_dir_fowner_setup,
+ priv_vfs_stickyfile_dir_fowner,
+ priv_vfs_stickyfile_dir_cleanup },
+
+ { "priv_vfs_stickyfile_dir_fother",
+ priv_vfs_stickyfile_dir_fother_setup,
+ priv_vfs_stickyfile_dir_fother,
+ priv_vfs_stickyfile_dir_cleanup },
+
+ { "priv_vfs_stickyfile_file_fowner",
+ priv_vfs_stickyfile_file_fowner_setup,
+ priv_vfs_stickyfile_file_fowner,
+ priv_vfs_stickyfile_file_cleanup },
+
+ { "priv_vfs_stickyfile_file_fother",
+ priv_vfs_stickyfile_file_fother_setup,
+ priv_vfs_stickyfile_file_fother,
+ priv_vfs_stickyfile_file_cleanup },
+
+ { "priv_vfs_utimes_froot", priv_vfs_utimes_froot_setup,
+ priv_vfs_utimes_froot, priv_vfs_utimes_cleanup },
+
+ { "priv_vfs_utimes_froot_null", priv_vfs_utimes_froot_setup,
+ priv_vfs_utimes_froot_null, priv_vfs_utimes_cleanup },
+
+ { "priv_vfs_utimes_fowner", priv_vfs_utimes_fowner_setup,
+ priv_vfs_utimes_fowner, priv_vfs_utimes_cleanup },
+
+ { "priv_vfs_utimes_fowner_null", priv_vfs_utimes_fowner_setup,
+ priv_vfs_utimes_fowner_null, priv_vfs_utimes_cleanup },
+
+ { "priv_vfs_utimes_fother", priv_vfs_utimes_fother_setup,
+ priv_vfs_utimes_fother, priv_vfs_utimes_cleanup },
+
+ { "priv_vfs_utimes_fother_null", priv_vfs_utimes_fother_setup,
+ priv_vfs_utimes_fother_null, priv_vfs_utimes_cleanup },
+
+ { "priv_vm_madv_protect", priv_vm_madv_protect_setup,
+ priv_vm_madv_protect, priv_vm_madv_protect_cleanup },
+
+ { "priv_vm_mlock", priv_vm_mlock_setup, priv_vm_mlock,
+ priv_vm_mlock_cleanup },
+
+ { "priv_vm_munlock", priv_vm_munlock_setup, priv_vm_munlock,
+ priv_vm_munlock_cleanup },
+
+};
+static int tests_count = sizeof(tests) / sizeof(struct test);
+
+void
+expect(const char *test, int error, int expected_error, int expected_errno)
+{
+
+ if (error == 0) {
+ if (expected_error != 0)
+ warnx("%s: returned 0", test);
+ } else {
+ if (expected_error == 0)
+ warn("%s: returned (%d, %d)", test, error, errno);
+ else if (expected_errno != errno)
+ warn("%s: returned (%d, %d)", test, error, errno);
+ }
+}
+
void
-assert_root(void)
+setup_dir(const char *test, char *dpathp, uid_t uid, gid_t gid, mode_t mode)
{
- if (getuid() != UID_ROOT || geteuid() != UID_ROOT)
- err(-1, "must be run as root");
+ strcpy(dpathp, "/tmp/priv.XXXXXXXXXXX");
+ if (mkdtemp(dpathp) == NULL)
+ err(-1, "test %s: mkdtemp", test);
+
+ if (chown(dpathp, uid, gid) < 0)
+ err(-1, "test %s: chown(%s, %d, %d)", test, dpathp, uid,
+ gid);
+
+ if (chmod(dpathp, mode) < 0)
+ err(-1, "test %s: chmod(%s, 0%o)", test, dpathp, mode);
}
void
-setup_file(char *fpathp, uid_t uid, gid_t gid, mode_t mode)
+setup_file(const char *test, char *fpathp, uid_t uid, gid_t gid, mode_t mode)
{
int fd;
strcpy(fpathp, "/tmp/priv.XXXXXXXXXXX");
fd = mkstemp(fpathp);
if (fd < 0)
- err(-1, "mkstemp");
+ err(-1, "test %s: mkstemp", test);
if (fchown(fd, uid, gid) < 0)
- err(-1, "fchown(%s, %d, %d)", fpathp, uid, gid);
+ err(-1, "test %s: fchown(%s, %d, %d)", test, fpathp, uid,
+ gid);
if (fchmod(fd, mode) < 0)
- err(-1, "chmod(%s, 0%o)", fpathp, mode);
+ err(-1, "test %s: chmod(%s, 0%o)", test, fpathp, mode);
close(fd);
}
/*
- * When downgrading privileges, set the gid before the uid; when upgrading,
- * set uid before gid.
+ * Irrevocably set credentials to specific uid and gid.
*/
-void
-set_creds(uid_t uid, gid_t gid)
+static void
+set_creds(const char *test, uid_t uid, gid_t gid)
{
+ gid_t gids[1] = { gid };
- if (setegid(gid) < 0)
- err(-1, "setegid(%d)", gid);
- if (seteuid(uid) < 0)
- err(-1, "seteuid(%d)", uid);
+ if (setgid(gid) < 0)
+ err(-1, "test %s: setegid(%d)", test, gid);
+ if (setgroups(sizeof(gids)/sizeof(gid_t), gids) < 0)
+ err(-1, "test %s: setgroups(%d)", test, gid);
+ if (setuid(uid) < 0)
+ err(-1, "test %s: seteuid(%d)", test, uid);
}
-void
-set_euid(uid_t uid)
+static void
+enter_jail(const char *test)
{
+ struct jail j;
- if (seteuid(uid) < 0)
- err(-1, "seteuid(%d)", uid);
+ bzero(&j, sizeof(j));
+ j.version = 0;
+ j.path = "/";
+ j.hostname = "test";
+ j.ip_number = htonl(INADDR_LOOPBACK);
+ if (jail(&j) < 0)
+ err(-1, "test %s: jail", test);
}
-void
-restore_creds(void)
+static void
+run_child(struct test *test, int asroot, int injail)
{
- if (seteuid(UID_ROOT) < 0)
- err(-1, "seteuid(%d)", UID_ROOT);
- if (setegid(GID_WHEEL) < 0)
- err(-1, "setegid(%d)", GID_WHEEL);
+ setprogname(test->t_name);
+ if (injail)
+ enter_jail(test->t_name);
+ if (!asroot)
+ set_creds(test->t_name, UID_OWNER, GID_OWNER);
+ test->t_test_func(asroot, injail, test);
}
/*
- * Execute tests in a child process so they don't contaminate each other,
- * especially with regard to file descriptors, credentials, working
- * directories, and chroot status.
+ * Run a test in a particular credential context -- always call the setup and
+ * cleanup routines; if setup succeeds, also run the test. Test cleanup must
+ * handle cases where the setup has failed, so may need to maintain their own
+ * state in order to know what needs cleaning up (such as whether temporary
+ * files were created).
*/
static void
-run(const char *funcname, void (*func)(void))
+run(struct test *test, int asroot, int injail)
{
pid_t childpid, pid;
- printf("running %s\n", funcname);
+ if (test->t_setup_func != NULL) {
+ if ((test->t_setup_func)(asroot, injail, test) != 0) {
+ warnx("run(%s, %d, %d) setup failed", test->t_name,
+ asroot, injail);
+ goto cleanup;
+ }
+ }
fflush(stdout);
fflush(stderr);
childpid = fork();
- if (childpid == -1)
- err(-1, "test %s unable to fork", funcname);
+ if (childpid == -1) {
+ warn("run(%s, %d, %d) fork failed", test->t_name, asroot,
+ injail);
+ goto cleanup;
+ }
if (childpid == 0) {
- setprogname(funcname);
- func();
+ run_child(test, asroot, injail);
fflush(stdout);
fflush(stderr);
exit(0);
@@ -135,50 +456,42 @@ run(const char *funcname, void (*func)(void))
while (1) {
pid = waitpid(childpid, NULL, 0);
if (pid == -1)
- warn("waitpid %s", funcname);
+ warn("test: waitpid %s", test->t_name);
if (pid == childpid)
break;
}
}
fflush(stdout);
fflush(stderr);
+cleanup:
+ if (test->t_cleanup_func != NULL)
+ test->t_cleanup_func(asroot, injail, test);
}
int
main(int argc, char *argv[])
{
+ int i;
- run("priv_acct", priv_acct);
- run("priv_adjtime", priv_adjtime);
- run("priv_clock_settime", priv_clock_settime);
- run("priv_io", priv_io);
- run("priv_kenv_set", priv_kenv_set);
- run("priv_kenv_unset", priv_kenv_unset);
- run("priv_proc_setlogin", priv_proc_setlogin);
- run("priv_proc_setrlimit", priv_proc_setrlimit);
- run("priv_sched_rtprio", priv_sched_rtprio);
- run("priv_sched_setpriority", priv_sched_setpriority);
- run("priv_settimeofday", priv_settimeofday);
- run("priv_sysctl_write", priv_sysctl_write);
- run("priv_vfs_admin", priv_vfs_admin);
- run("priv_vfs_chown", priv_vfs_chown);
- run("priv_vfs_chroot", priv_vfs_chroot);
- run("priv_vfs_clearsugid", priv_vfs_clearsugid);
- run("priv_vfs_extattr_system", priv_vfs_extattr_system);
- run("priv_vfs_fhopen", priv_vfs_fhopen);
- run("priv_vfs_fhstat", priv_vfs_fhstat);
- run("priv_vfs_fhstatfs", priv_vfs_fhstatfs);
- run("priv_vfs_generation", priv_vfs_generation);
- run("priv_vfs_getfh", priv_vfs_getfh);
- run("priv_vfs_read", priv_vfs_read);
- run("priv_vfs_setgid", priv_vfs_setgid);
- run("priv_vfs_stickyfile", priv_vfs_stickyfile);
- run("priv_vfs_write", priv_vfs_write);
- run("priv_vm_madv_protect", priv_vm_madv_protect);
- run("priv_vm_mlock", priv_vm_mlock);
- run("priv_vm_munlock", priv_vm_munlock);
-
- run("test_utimes", test_utimes);
+ /*
+ * This test suite will need to become quite a bit more enlightened
+ * if the notion of privilege is truly separated from root, as tests
+ * make assumptions about when privilege will be present. In
+ * particular, VFS-related tests need to manage uids in order to
+ * force the use of privilege, and will likely need checking.
+ */
+ if (getuid() != 0 && geteuid() != 0)
+ errx(-1, "priv: must be run as root");
+ /*
+ * Run each test four times, varying whether the process is running
+ * as root and in jail in order to test all possible combinations.
+ */
+ for (i = 0; i < tests_count; i++) {
+ run(&tests[i], 0, 0);
+ run(&tests[i], 0, 1);
+ run(&tests[i], 1, 0);
+ run(&tests[i], 1, 1);
+ }
return (0);
}
diff --git a/tools/regression/priv/main.h b/tools/regression/priv/main.h
index 6c5616b..d863feb 100644
--- a/tools/regression/priv/main.h
+++ b/tools/regression/priv/main.h
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -40,51 +41,273 @@
#define KENV_VAR_NAME "test"
#define KENV_VAR_VALUE "test"
+#define KENV_VAR_LEN sizeof(KENV_VAR_VALUE)
/*
* Library routines used by many tests.
*/
-void assert_root(void);
-void setup_file(char *fpathp, uid_t uid, gid_t gid, mode_t mode);
-void set_creds(uid_t uid, gid_t gid);
-void set_euid(uid_t uid);
-void restore_creds(void);
+void setup_dir(const char *test, char *dpathp, uid_t uid, gid_t gid,
+ mode_t mode);
+void setup_file(const char *test, char *fpathp, uid_t uid, gid_t gid,
+ mode_t mode);
+void expect(const char *test, int error, int expected_error,
+ int expected_errno);
/*
- * Tests for specific privileges.
+ * Definition for a particular test, both used to manage the test list in
+ * main.c, and passed to tests so they can be aware of which specific test is
+ * running if particular method implementations are shared across tests.
*/
-void priv_acct(void);
-void priv_adjtime(void);
-void priv_clock_settime(void);
-void priv_io(void);
-void priv_kenv_set(void);
-void priv_kenv_unset(void);
-void priv_proc_setlogin(void);
-void priv_proc_setrlimit(void);
-void priv_sched_rtprio(void);
-void priv_sched_setpriority(void);
-void priv_settimeofday(void);
-void priv_sysctl_write(void);
-void priv_vfs_admin(void);
-void priv_vfs_chown(void);
-void priv_vfs_chroot(void);
-void priv_vfs_clearsugid(void);
-void priv_vfs_extattr_system(void);
-void priv_vfs_fhopen(void);
-void priv_vfs_fhstat(void);
-void priv_vfs_fhstatfs(void);
-void priv_vfs_generation(void);
-void priv_vfs_getfh(void);
-void priv_vfs_read(void);
-void priv_vfs_setgid(void);
-void priv_vfs_stickyfile(void);
-void priv_vfs_write(void);
-void priv_vm_madv_protect(void);
-void priv_vm_mlock(void);
-void priv_vm_munlock(void);
+struct test {
+ const char *t_name;
+ int (*t_setup_func)(int asroot, int injail,
+ struct test *test);
+ void (*t_test_func)(int asroot, int injail,
+ struct test *test);
+ void (*t_cleanup_func)(int asroot, int injail,
+ struct test *test);
+};
/*
- * Tests for more complex access control logic involving more than one
- * privilege, or privilege combined with DAC.
+ * Prototypes for test functions that will be hooked up to the test vector in
+ * main.c. It's possible to imagine more dynamic (convenient?) ways to do
+ * this.
*/
-void test_utimes(void);
+int priv_acct_setup(int, int, struct test *);
+void priv_acct_enable(int, int, struct test *);
+void priv_acct_disable(int, int, struct test *);
+void priv_acct_rotate(int, int, struct test *);
+void priv_acct_noopdisable(int, int, struct test *);
+void priv_acct_cleanup(int, int, struct test *);
+
+int priv_adjtime_setup(int, int, struct test *);
+void priv_adjtime_set(int, int, struct test *);
+void priv_adjtime_cleanup(int, int, struct test *);
+
+int priv_audit_submit_setup(int, int, struct test *);
+void priv_audit_submit(int, int, struct test *);
+void priv_audit_submit_cleanup(int, int, struct test *);
+
+int priv_audit_control_setup(int, int, struct test *);
+void priv_audit_control(int, int, struct test *);
+void priv_audit_control_cleanup(int, int, struct test *);
+
+int priv_audit_getaudit_setup(int, int, struct test *);
+void priv_audit_getaudit(int, int, struct test *);
+void priv_audit_getaudit_addr(int, int, struct test *);
+void priv_audit_getaudit_cleanup(int, int, struct test *);
+
+int priv_audit_setaudit_setup(int, int, struct test *);
+void priv_audit_setaudit(int, int, struct test *);
+void priv_audit_setaudit_addr(int, int, struct test *);
+void priv_audit_setaudit_cleanup(int, int, struct test *);
+
+int priv_clock_settime_setup(int, int, struct test *);
+void priv_clock_settime(int, int, struct test *);
+void priv_clock_settime_cleanup(int, int, struct test *);
+
+int priv_cred_setup(int, int, struct test *);
+void priv_cred_setuid(int, int, struct test *);
+void priv_cred_seteuid(int, int, struct test *);
+void priv_cred_setgid(int, int, struct test *);
+void priv_cred_setegid(int, int, struct test *);
+void priv_cred_setgroups(int, int, struct test *);
+void priv_cred_setreuid(int, int, struct test *);
+void priv_cred_setregid(int, int, struct test *);
+void priv_cred_setresuid(int, int, struct test *);
+void priv_cred_setresgid(int, int, struct test *);
+void priv_cred_cleanup(int, int, struct test *);
+
+int priv_io_setup(int, int, struct test *);
+void priv_io(int, int, struct test *);
+void priv_io_cleanup(int, int, struct test *);
+
+int priv_kenv_set_setup(int, int, struct test *);
+void priv_kenv_set(int, int, struct test *);
+void priv_kenv_set_cleanup(int, int, struct test *);
+
+int priv_kenv_unset_setup(int, int, struct test *);
+void priv_kenv_unset(int, int, struct test *);
+void priv_kenv_unset_cleanup(int, int, struct test *);
+
+int priv_msgbuf_privonly_setup(int, int, struct test *);
+void priv_msgbuf_privonly(int, int, struct test *);
+
+int priv_msgbuf_unprivok_setup(int, int, struct test *);
+void priv_msgbuf_unprivok(int, int, struct test *);
+
+void priv_msgbuf_cleanup(int, int, struct test *);
+
+int priv_netinet_raw_setup(int, int, struct test *);
+void priv_netinet_raw(int, int, struct test *);
+void priv_netinet_raw_cleanup(int, int, struct test *);
+
+int priv_proc_setlogin_setup(int, int, struct test *);
+void priv_proc_setlogin(int, int, struct test *);
+void priv_proc_setlogin_cleanup(int, int, struct test *);
+
+int priv_proc_setrlimit_setup(int, int, struct test *);
+void priv_proc_setrlimit_raisemax(int, int, struct test *);
+void priv_proc_setrlimit_raisecur(int, int, struct test *);
+void priv_proc_setrlimit_raisecur_nopriv(int, int, struct test *);
+void priv_proc_setrlimit_cleanup(int, int, struct test *);
+
+int priv_sched_rtprio_setup(int, int, struct test *);
+void priv_sched_rtprio_curproc_normal(int, int, struct test *);
+void priv_sched_rtprio_curproc_idle(int, int, struct test *);
+void priv_sched_rtprio_curproc_realtime(int, int, struct test *);
+
+void priv_sched_rtprio_myproc_normal(int, int, struct test *);
+void priv_sched_rtprio_myproc_idle(int, int, struct test *);
+void priv_sched_rtprio_myproc_realtime(int, int, struct test *);
+
+void priv_sched_rtprio_aproc_normal(int, int, struct test *);
+void priv_sched_rtprio_aproc_idle(int, int, struct test *);
+void priv_sched_rtprio_aproc_realtime(int, int, struct test *);
+void priv_sched_rtprio_cleanup(int, int, struct test *);
+
+int priv_sched_setpriority_setup(int, int, struct test *);
+void priv_sched_setpriority_curproc(int, int, struct test *);
+void priv_sched_setpriority_myproc(int, int, struct test *);
+void priv_sched_setpriority_aproc(int, int, struct test *);
+void priv_sched_setpriority_cleanup(int, int, struct test *);
+
+int priv_settimeofday_setup(int, int, struct test *);
+void priv_settimeofday(int, int, struct test *);
+void priv_settimeofday_cleanup(int, int, struct test *);
+
+int priv_sysctl_write_setup(int, int, struct test *);
+void priv_sysctl_write(int, int, struct test *);
+void priv_sysctl_writejail(int, int, struct test *);
+void priv_sysctl_write_cleanup(int, int, struct test *);
+
+int priv_vfs_chflags_froot_setup(int, int, struct test *);
+void priv_vfs_chflags_froot_uflags(int, int, struct test *);
+void priv_vfs_chflags_froot_sflags(int, int, struct test *);
+
+int priv_vfs_chflags_fowner_setup(int, int, struct test *);
+void priv_vfs_chflags_fowner_uflags(int, int, struct test *);
+void priv_vfs_chflags_fowner_sflags(int, int, struct test *);
+
+int priv_vfs_chflags_fother_setup(int, int, struct test *);
+void priv_vfs_chflags_fother_uflags(int, int, struct test *);
+void priv_vfs_chflags_fother_sflags(int, int, struct test *);
+
+void priv_vfs_chflags_cleanup(int, int, struct test *);
+
+int priv_vfs_chmod_froot_setup(int, int, struct test *);
+void priv_vfs_chmod_froot(int, int, struct test *);
+
+int priv_vfs_chmod_fowner_setup(int, int, struct test *);
+void priv_vfs_chmod_fowner(int, int, struct test *);
+
+int priv_vfs_chmod_fother_setup(int, int, struct test *);
+void priv_vfs_chmod_fother(int, int, struct test *);
+
+void priv_vfs_chmod_cleanup(int, int, struct test *);
+
+int priv_vfs_chown_uid_setup(int, int, struct test *);
+void priv_vfs_chown_uid(int, int, struct test *);
+
+int priv_vfs_chown_mygid_setup(int, int, struct test *);
+void priv_vfs_chown_mygid(int, int, struct test *);
+
+int priv_vfs_chown_othergid_setup(int, int, struct test *);
+void priv_vfs_chown_othergid(int, int, struct test *);
+
+void priv_vfs_chown_cleanup(int, int, struct test *);
+
+int priv_vfs_chroot_setup(int, int, struct test *);
+void priv_vfs_chroot(int, int, struct test *);
+void priv_vfs_chroot_cleanup(int, int, struct test *);
+
+int priv_vfs_clearsugid_setup(int, int, struct test *);
+void priv_vfs_clearsugid_chgrp(int, int, struct test *);
+void priv_vfs_clearsugid_extattr(int, int, struct test *);
+void priv_vfs_clearsugid_write(int, int, struct test *);
+void priv_vfs_clearsugid_cleanup(int, int, struct test *);
+
+int priv_vfs_extattr_system_setup(int, int, struct test *);
+void priv_vfs_extattr_system(int, int, struct test *);
+void priv_vfs_extattr_system_cleanup(int, int, struct test *);
+
+int priv_vfs_fhopen_setup(int, int, struct test *);
+void priv_vfs_fhopen(int, int, struct test *);
+void priv_vfs_fhopen_cleanup(int, int, struct test *);
+
+int priv_vfs_fhstat_setup(int, int, struct test *);
+void priv_vfs_fhstat(int, int, struct test *);
+void priv_vfs_fhstat_cleanup(int, int, struct test *);
+
+int priv_vfs_fhstatfs_setup(int, int, struct test *);
+void priv_vfs_fhstatfs(int, int, struct test *);
+void priv_vfs_fhstatfs_cleanup(int, int, struct test *);
+
+int priv_vfs_generation_setup(int, int, struct test *);
+void priv_vfs_generation(int, int, struct test *);
+void priv_vfs_generation_cleanup(int, int, struct test *);
+
+int priv_vfs_getfh_setup(int, int, struct test *);
+void priv_vfs_getfh(int, int, struct test *);
+void priv_vfs_getfh_cleanup(int, int, struct test *);
+
+int priv_vfs_readwrite_fowner_setup(int, int, struct test *);
+void priv_vfs_readwrite_fowner(int, int, struct test *);
+
+int priv_vfs_readwrite_fgroup_setup(int, int, struct test *);
+void priv_vfs_readwrite_fgroup(int, int, struct test *);
+
+int priv_vfs_readwrite_fother_setup(int, int, struct test *);
+void priv_vfs_readwrite_fother(int, int, struct test *);
+
+void priv_vfs_readwrite_cleanup(int, int, struct test *);
+
+int priv_vfs_setgid_fowner_setup(int, int, struct test *);
+void priv_vfs_setgid_fowner(int, int, struct test *);
+
+int priv_vfs_setgid_fother_setup(int, int, struct test *);
+void priv_vfs_setgid_fother(int, int, struct test *);
+
+void priv_vfs_setgid_cleanup(int, int, struct test *);
+
+int priv_vfs_stickyfile_dir_fowner_setup(int, int, struct test *);
+
+void priv_vfs_stickyfile_dir_fowner(int, int, struct test *);
+int priv_vfs_stickyfile_dir_fother_setup(int, int, struct test *);
+void priv_vfs_stickyfile_dir_fother(int, int, struct test *);
+
+void priv_vfs_stickyfile_dir_cleanup(int, int, struct test *);
+
+int priv_vfs_stickyfile_file_fowner_setup(int, int, struct test *);
+void priv_vfs_stickyfile_file_fowner(int, int, struct test *);
+
+int priv_vfs_stickyfile_file_fother_setup(int, int, struct test *);
+void priv_vfs_stickyfile_file_fother(int, int, struct test *);
+
+void priv_vfs_stickyfile_file_cleanup(int, int, struct test *);
+
+int priv_vfs_utimes_froot_setup(int, int, struct test *);
+void priv_vfs_utimes_froot(int, int, struct test *);
+void priv_vfs_utimes_froot_null(int, int, struct test *);
+
+int priv_vfs_utimes_fowner_setup(int, int, struct test *);
+void priv_vfs_utimes_fowner(int, int, struct test *);
+void priv_vfs_utimes_fowner_null(int, int, struct test *);
+
+int priv_vfs_utimes_fother_setup(int, int, struct test *);
+void priv_vfs_utimes_fother(int, int, struct test *);
+void priv_vfs_utimes_fother_null(int, int, struct test *);
+
+void priv_vfs_utimes_cleanup(int, int, struct test *);
+
+int priv_vm_madv_protect_setup(int, int, struct test *);
+void priv_vm_madv_protect(int, int, struct test *);
+void priv_vm_madv_protect_cleanup(int, int, struct test *);
+
+int priv_vm_mlock_setup(int, int, struct test *);
+void priv_vm_mlock(int, int, struct test *);
+void priv_vm_mlock_cleanup(int, int, struct test *);
+
+int priv_vm_munlock_setup(int, int, struct test *);
+void priv_vm_munlock(int, int, struct test *);
+void priv_vm_munlock_cleanup(int, int, struct test *);
diff --git a/tools/regression/priv/priv_acct.c b/tools/regression/priv/priv_acct.c
index bc4a41e7..d1324bb 100644
--- a/tools/regression/priv/priv_acct.c
+++ b/tools/regression/priv/priv_acct.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,11 +31,13 @@
*/
/*
- * Test that configuring accounting requires privilege. First check that
- * accounting is not in use on the system to prevent disrupting the
- * accounting service. Confirm three different state transitions, both as
- * privileged and non-privileged: disabled to enabled, rotate, and enabled to
- * disabled.
+ * Test that configuring accounting requires privilege. We test four cases
+ * across {!jail, jail}:
+ *
+ * priv_acct_enable - enable accounting from a disabled state
+ * priv_acct_disable - disable accounting from an enabled state
+ * priv_acct_rotate - rotate the accounting file
+ * priv_acct_noopdisable - disable accounting when already disabled
*/
#include <sys/types.h>
@@ -49,130 +52,127 @@
#include "main.h"
#define SYSCTL_NAME "kern.acct_configured"
-#define PATH_TEMPLATE "/tmp/acct.XXXXXXXXXXX"
-void
-priv_acct(void)
+/*
+ * Actual filenames used across all of the tests.
+ */
+static int fpath1_initialized;
+static char fpath1[1024];
+static int fpath2_initialized;
+static char fpath2[1024];
+
+int
+priv_acct_setup(int asroot, int injail, struct test *test)
{
- char fpath1[1024] = PATH_TEMPLATE;
- char fpath2[1024] = PATH_TEMPLATE;
- int error, fd, i;
size_t len;
+ int i;
- assert_root();
-
- /*
- * Check that accounting isn't already configured in the kernel.
- */
len = sizeof(i);
- if (sysctlbyname(SYSCTL_NAME, &i, &len, NULL, 0) < 0)
- err(-1, "sysctlbyname(%s)", SYSCTL_NAME);
- if (i != 0)
- errx(-1, "sysctlbyname(%s) indicates accounting configured",
+ if (sysctlbyname(SYSCTL_NAME, &i, &len, NULL, 0) < 0) {
+ warn("priv_acct_setup: sysctlbyname(%s)", SYSCTL_NAME);
+ return (-1);
+ }
+ if (i != 0) {
+ warnx("sysctlbyname(%s) indicates accounting configured",
SYSCTL_NAME);
-
- /*
- * Create two temporary files to use as accounting targets.
- */
- fd = mkstemp(fpath1);
- if (fd < 0)
- err(-1, "mkstemp");
- close(fd);
- fd = mkstemp(fpath2);
- if (fd < 0) {
- warn("mkstemp");
- (void)unlink(fpath1);
- exit(-1);
+ return (-1);
}
-
- /*
- * Change the permissions on the file so that access control on the
- * file doesn't come into play.
- */
- if (chmod(fpath1, 0666) < 0) {
- warn("chmod(%s, 0666)", fpath1);
- goto out;
+ setup_file("priv_acct_setup: fpath1", fpath1, 0, 0, 0666);
+ fpath1_initialized = 1;
+ setup_file("priv_acct_setup: fpath2", fpath2, 0, 0, 0666);
+ fpath2_initialized = 1;
+
+ if (test->t_test_func == priv_acct_enable ||
+ test->t_test_func == priv_acct_noopdisable) {
+ if (acct(NULL) != 0) {
+ warn("priv_acct_setup: acct(NULL)");
+ return (-1);
+ }
+ } else if (test->t_test_func == priv_acct_disable ||
+ test->t_test_func == priv_acct_rotate) {
+ if (acct(fpath1) != 0) {
+ warn("priv_acct_setup: acct(\"%s\")", fpath1);
+ return (-1);
+ }
}
+ return (0);
+}
- if (chmod(fpath2, 0666) < 0) {
- warn("chmod(%s, 0600)", fpath2);
- goto out;
- }
+void
+priv_acct_cleanup(int asroot, int injail, struct test *test)
+{
- /*
- * Test that privileged can move through entire life cycle.
- */
- if (acct(fpath1) < 0) {
- warn("acct(NULL -> %s) as root", fpath1);
- goto out;
+ (void)acct(NULL);
+ if (fpath1_initialized) {
+ (void)unlink(fpath1);
+ fpath1_initialized = 0;
}
-
- if (acct(fpath2) < 0) {
- warn("acct(%s -> %s) as root", fpath1, fpath2);
- goto out;
+ if (fpath2_initialized) {
+ (void)unlink(fpath2);
+ fpath2_initialized = 0;
}
+}
- if (acct(NULL) < 0) {
- warn("acct(%s -> NULL) as root", fpath1);
- goto out;
- }
+void
+priv_acct_enable(int asroot, int injail, struct test *test)
+{
+ int error;
- /*
- * Testing for unprivileged is a bit more tricky, as expect each step
- * to fail, so must replay various bits of the setup process as root
- * so that each step can be tested as !root.
- */
- set_euid(UID_OTHER);
error = acct(fpath1);
- if (error == 0) {
- warnx("acct(NULL -> %s) succeeded as !root", fpath1);
- goto out;
- }
- if (errno != EPERM) {
- warn("acct(NULL -> %s) wrong errno %d as !root", fpath1,
- errno);
- goto out;
- }
+ if (asroot && injail)
+ expect("priv_acct_enable(root, jail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_acct_enable(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_acct_enable(!root, jail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_acct_enable(!root, !jail)", error, -1, EPERM);
+}
- set_euid(UID_ROOT);
- if (acct(fpath1) < 0) {
- err(-1, "acct(NULL -> %s) setup for !root", fpath1);
- goto out;
- }
+void
+priv_acct_disable(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = acct(NULL);
+ if (asroot && injail)
+ expect("priv_acct_disable(root, jail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_acct_disable(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_acct_disable(!root, jail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_acct_disable(!root, !jail)", error, -1, EPERM);
+}
+
+void
+priv_acct_rotate(int asroot, int injail, struct test *test)
+{
+ int error;
- set_euid(UID_OTHER);
error = acct(fpath2);
- if (error == 0) {
- warnx("acct(%s -> %s) succeeded as !root", fpath1, fpath2);
- goto out;
- }
- if (errno != EPERM) {
- warn("acct(%s -> %s) wrong errno %d as !root", fpath1,
- fpath2, errno);
- goto out;
- }
+ if (asroot && injail)
+ expect("priv_acct_rotate(root, jail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_acct_rotate(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_acct_rotate(!root, jail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_acct_rotate(!root, !jail)", error, -1, EPERM);
+}
- set_euid(UID_ROOT);
- if (acct(fpath2) < 0) {
- err(-1, "acct(%s -> %s) setup for !root", fpath1, fpath2);
- goto out;
- }
+void
+priv_acct_noopdisable(int asroot, int injail, struct test *test)
+{
+ int error;
- set_euid(UID_OTHER);
error = acct(NULL);
- if (error == 0) {
- warnx("acct(%s -> NULL) succeeded as !root", fpath2);
- goto out;
- }
- if (errno != EPERM) {
- warn("acct(%s -> NULL) wrong errno %d as !root", fpath2,
- errno);
- goto out;
- }
-
-out:
- (void)seteuid(UID_ROOT);
- (void)acct(NULL);
- (void)unlink(fpath1);
- (void)unlink(fpath2);
+ if (asroot && injail)
+ expect("priv_acct_noopdisable(root, jail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_acct_noopdisable(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_acct_noopdisable(!root, jail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_acct_noopdisable(!root, !jail)", error, -1, EPERM);
}
diff --git a/tools/regression/priv/priv_adjtime.c b/tools/regression/priv/priv_adjtime.c
index 791de97..65fbfac 100644
--- a/tools/regression/priv/priv_adjtime.c
+++ b/tools/regression/priv/priv_adjtime.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -31,7 +32,8 @@
/*
* Confirm that privilege is required to invoke adjtime(); first query, then
- * try setting first with, and then without privilege.
+ * try setting with and without privilege. Hopefully this will not disturb
+ * system time too much.
*/
#include <sys/time.h>
@@ -42,34 +44,41 @@
#include "main.h"
-void
-priv_adjtime(void)
+static int initialized;
+static struct timeval query_tv;
+
+int
+priv_adjtime_setup(int asroot, int injail, struct test *test)
{
- struct timeval tv;
- int error;
- assert_root();
+ if (initialized)
+ return (0);
+ if (adjtime(NULL, &query_tv) < 0) {
+ warn("priv_adjtime_setup: adjtime(NULL)");
+ return (-1);
+ }
+ initialized = 1;
+ return (0);
+}
- /*
- * Query time adjustment.
- */
- if (adjtime(NULL, &tv) < 0)
- err(-1, "adjtime");
+void
+priv_adjtime_set(int asroot, int injail, struct test *test)
+{
+ int error;
- /*
- * Set with privilege.
- */
- if (adjtime(&tv, NULL) < 0)
- err(-1, "adjtime as root");
+ error = adjtime(&query_tv, NULL);
+ if (asroot && injail)
+ expect("priv_adjtime(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_adjtime(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_adjtime(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_adjtime(!asroot, !injail)", error, -1, EPERM);
+}
- /*
- * Set without privilege.
- */
- set_euid(UID_OTHER);
+void
+priv_adjtime_cleanup(int asroot, int injail, struct test *test)
+{
- error = adjtime(&tv, NULL);
- if (error == 0)
- errx(-1, "adjtime succeeded as !root");
- if (errno != EPERM)
- errx(-1, "adjtime wrong errno %d as !root", errno);
}
diff --git a/tools/regression/priv/priv_audit_control.c b/tools/regression/priv/priv_audit_control.c
new file mode 100644
index 0000000..a661819
--- /dev/null
+++ b/tools/regression/priv/priv_audit_control.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 2007 Robert M. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Confirm that privilege is required to issue an audit control command via
+ * auditon(). We do a simple policy retrieve.
+ *
+ * XXXRW: It would be a good idea to also test auditctl(), which also tests
+ * PRIV_AUDIT_CONTROL.
+ */
+
+#include <sys/types.h>
+
+#include <bsm/audit.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "main.h"
+
+int
+priv_audit_control_setup(int asroot, int injail, struct test *test)
+{
+
+ /*
+ * XXXRW: It would be nice if we checked for audit being configured
+ * here.
+ */
+ return (0);
+}
+
+void
+priv_audit_control(int asroot, int injail, struct test *test)
+{
+ long policy;
+ int error;
+
+ error = auditon(A_GETPOLICY, &policy, sizeof(policy));
+ if (asroot && injail)
+ expect("priv_audit_control(asroot, injail)", error, -1,
+ ENOSYS);
+ if (asroot && !injail)
+ expect("priv_audit_control(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_audit_control(!asroot, injail)", error, -1,
+ ENOSYS);
+ if (!asroot && !injail)
+ expect("priv_audit_control(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_audit_control_cleanup(int asroot, int injail, struct test *test)
+{
+
+}
diff --git a/tools/regression/priv/priv_audit_getaudit.c b/tools/regression/priv/priv_audit_getaudit.c
new file mode 100644
index 0000000..cccabed
--- /dev/null
+++ b/tools/regression/priv/priv_audit_getaudit.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2007 Robert M. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Confirm that privilege is required to query process audit state.
+ */
+
+#include <sys/types.h>
+
+#include <bsm/audit.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "main.h"
+
+int
+priv_audit_getaudit_setup(int asroot, int injail, struct test *test)
+{
+
+ /*
+ * XXXRW: It would be nice if we checked for audit being configured
+ * here.
+ */
+ return (0);
+}
+
+void
+priv_audit_getaudit(int asroot, int injail, struct test *test)
+{
+ auditinfo_t ai;
+ int error;
+
+ error = getaudit(&ai);
+ if (asroot && injail)
+ expect("priv_audit_getaudit(asroot, injail)", error, -1,
+ ENOSYS);
+ if (asroot && !injail)
+ expect("priv_audit_getaudit(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_audit_getaudit(!asroot, injail)", error, -1,
+ ENOSYS);
+ if (!asroot && !injail)
+ expect("priv_audit_getaudit(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_audit_getaudit_addr(int asroot, int injail, struct test *test)
+{
+ auditinfo_addr_t aia;
+ int error;
+
+ error = getaudit_addr(&aia, sizeof(aia));
+ if (asroot && injail)
+ expect("priv_audit_getaudit_addr(asroot, injail)", error, -1,
+ ENOSYS);
+ if (asroot && !injail)
+ expect("priv_audit_getaudit_addr(asroot, !injail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_audit_getaudit_addr(!asroot, injail)", error,
+ -1, ENOSYS);
+ if (!asroot && !injail)
+ expect("priv_audit_getaudit_addr(!asroot, !injail)", error,
+ -1, EPERM);
+}
+
+void
+priv_audit_getaudit_cleanup(int asroot, int injail, struct test *test)
+{
+
+}
diff --git a/tools/regression/priv/priv_audit_setaudit.c b/tools/regression/priv/priv_audit_setaudit.c
new file mode 100644
index 0000000..0b6d8db
--- /dev/null
+++ b/tools/regression/priv/priv_audit_setaudit.c
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2007 Robert M. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Confirm privilege is required to set process audit properties; we first
+ * query current properties so that the attempted operation is a no-op.
+ */
+
+#include <sys/types.h>
+
+#include <bsm/audit.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "main.h"
+
+static auditinfo_t ai;
+static auditinfo_addr_t aia;
+
+int
+priv_audit_setaudit_setup(int asroot, int injail, struct test *test)
+{
+
+ if (getaudit(&ai) < 0) {
+ warn("priv_audit_setaudit_setup: getaudit");
+ return (-1);
+ }
+ if (getaudit_addr(&aia, sizeof(aia)) < 0) {
+ warn("priv_audit_setaudit_setup: getaudit_addr");
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+priv_audit_setaudit(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setaudit(&ai);
+ if (asroot && injail)
+ expect("priv_audit_setaudit(asroot, injail)", error, -1,
+ ENOSYS);
+ if (asroot && !injail)
+ expect("priv_audit_setaudit(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_audit_setaudit(!asroot, injail)", error, -1,
+ ENOSYS);
+ if (!asroot && !injail)
+ expect("priv_audit_setaudit(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_audit_setaudit_addr(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setaudit_addr(&aia, sizeof(aia));
+ if (asroot && injail)
+ expect("priv_audit_setaudit_addr(asroot, injail)", error, -1,
+ ENOSYS);
+ if (asroot && !injail)
+ expect("priv_audit_setaudit_addr(asroot, !injail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_audit_setaudit_addr(!asroot, injail)", error,
+ -1, ENOSYS);
+ if (!asroot && !injail)
+ expect("priv_audit_setaudit_addr(!asroot, !injail)", error,
+ -1, EPERM);
+}
+
+void
+priv_audit_setaudit_cleanup(int asroot, int injail, struct test *test)
+{
+
+}
diff --git a/tools/regression/priv/priv_audit_submit.c b/tools/regression/priv/priv_audit_submit.c
new file mode 100644
index 0000000..915f6e6
--- /dev/null
+++ b/tools/regression/priv/priv_audit_submit.c
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2007 Robert M. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Confirm that privilege is required to submit an audit record; we don't
+ * actually submit a record, but instead rely on the fact that length
+ * validation of the record will occur after the kernel privilege check.
+ *
+ * XXX: It might be better to submit a nul record of some sort.
+ */
+
+#include <sys/types.h>
+
+#include <bsm/audit.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "main.h"
+
+int
+priv_audit_submit_setup(int asroot, int injail, struct test *test)
+{
+
+ /*
+ * XXXRW: It would be nice if we checked for audit being configured
+ * here.
+ */
+ return (0);
+}
+
+void
+priv_audit_submit(int asroot, int injail, struct test *test)
+{
+ char record[MAX_AUDIT_RECORD_SIZE+10];
+ int error;
+
+ bzero(record, sizeof(record));
+ error = audit(record, sizeof(record));
+ if (asroot && injail)
+ expect("priv_audit_submit(asroot, injail)", error, -1,
+ ENOSYS);
+ if (asroot && !injail)
+ expect("priv_audit_submit(asroot, !injail)", error, -1,
+ EINVAL);
+ if (!asroot && injail)
+ expect("priv_audit_submit(!asroot, injail)", error, -1,
+ ENOSYS);
+ if (!asroot && !injail)
+ expect("priv_audit_submit(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_audit_submit_cleanup(int asroot, int injail, struct test *test)
+{
+
+}
diff --git a/tools/regression/priv/priv_clock_settime.c b/tools/regression/priv/priv_clock_settime.c
index e3d1089..84b8beb 100644
--- a/tools/regression/priv/priv_clock_settime.c
+++ b/tools/regression/priv/priv_clock_settime.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -43,34 +44,41 @@
#include "main.h"
-void
-priv_clock_settime(void)
+static struct timespec the_time;
+
+int
+priv_clock_settime_setup(int asroot, int injail, struct test *test)
{
- struct timespec ts;
- int error;
- assert_root();
+ if (clock_gettime(CLOCK_REALTIME, &the_time) < 0) {
+ warn("priv_clock_settime_setup: "
+ "clock_gettime(CLOCK_REALTIME)");
+ return (-1);
+ }
+ return (0);
+}
- /*
- * Query time.
- */
- if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
- err(-1, "clock_gettime");
+void
+priv_clock_settime(int asroot, int injail, struct test *test)
+{
+ int error;
- /*
- * Set with privilege.
- */
- if (clock_settime(CLOCK_REALTIME, &ts) < 0)
- err(-1, "clock_settime as root");
+ error = clock_settime(CLOCK_REALTIME, &the_time);
+ if (asroot && injail)
+ expect("priv_clock_settime(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_clock_settime(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_clock_settime(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_clock_settime(!asroot, !injail", error, -1,
+ EPERM);
+}
- /*
- * Set without privilege.
- */
- set_euid(UID_OTHER);
+void
+priv_clock_settime_cleanup(int asroot, int injail, struct test *test)
+{
- error = clock_settime(CLOCK_REALTIME, &ts);
- if (error == 0)
- errx(-1, "clock_settime succeeded as !root");
- if (errno != EPERM)
- errx(-1, "clock_settime wrong errno %d as !root", errno);
}
diff --git a/tools/regression/priv/priv_cred.c b/tools/regression/priv/priv_cred.c
new file mode 100644
index 0000000..6e060cf
--- /dev/null
+++ b/tools/regression/priv/priv_cred.c
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 2007 Robert M. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Confirm that various UID/GID/etc-related system calls require root
+ * privilege in the absense of any saved/real/etc variations in the
+ * credential. It would be nice to also check cases where those bits of the
+ * credential are more interesting.
+ *
+ * XXXRW: Add support for testing more diverse real/saved scenarios.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "main.h"
+
+int
+priv_cred_setup(int asroot, int injail, struct test *test)
+{
+
+ return (0);
+}
+
+void
+priv_cred_setuid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setuid(UID_OTHER);
+ if (asroot && injail)
+ expect("priv_setuid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setuid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setuid(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setuid(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_seteuid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = seteuid(UID_OTHER);
+ if (asroot && injail)
+ expect("priv_seteuid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_seteuid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_seteuid(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_seteuid(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_setgid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setgid(GID_OTHER);
+ if (asroot && injail)
+ expect("priv_setgid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setgid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setgid(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setgid(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_setegid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setegid(GID_OTHER);
+ if (asroot && injail)
+ expect("priv_setegid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setegid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setegd(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setegid(!asroot, !injail)", error, -1, EPERM);
+}
+
+static const gid_t gidset[] = {GID_WHEEL, GID_OTHER};
+static const int gidset_len = sizeof(gidset) / sizeof(gid_t);
+
+void
+priv_cred_setgroups(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setgroups(gidset_len, gidset);
+ if (asroot && injail)
+ expect("priv_setgroups(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setgroups(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setgroups(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setgroups(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_setreuid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setreuid(UID_OTHER, UID_OTHER);
+ if (asroot && injail)
+ expect("priv_setreuid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setreuid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setreuid(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setreuid(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_setregid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setregid(GID_OTHER, GID_OTHER);
+ if (asroot && injail)
+ expect("priv_setregid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setregid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setregid(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setregid(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_setresuid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setresuid(UID_OTHER, UID_OTHER, UID_OTHER);
+ if (asroot && injail)
+ expect("priv_setresuid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setresuid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setresuid(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setresuid(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_setresgid(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = setresgid(GID_OTHER, GID_OTHER, GID_OTHER);
+ if (asroot && injail)
+ expect("priv_setresgid(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_setresgid(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_setresgid(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_setresgid(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_cred_cleanup(int asroot, int injail, struct test *test)
+{
+
+}
diff --git a/tools/regression/priv/priv_io.c b/tools/regression/priv/priv_io.c
index 1af1847..31e60a0 100644
--- a/tools/regression/priv/priv_io.c
+++ b/tools/regression/priv/priv_io.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -32,9 +33,8 @@
/*
* Test privilege check on /dev/io. By default, the permissions also protect
* against non-superuser access, so this program will modify permissions on
- * /dev/io to allow group access for the wheel group, and revert the change
- * on exit. This is not good for run-time security, but is necessary to test
- * the checks properly.
+ * /dev/io to allow world access, and revert the change on exit. This is not
+ * good for run-time security, but is necessary to test the checks properly.
*/
#include <sys/types.h>
@@ -47,89 +47,66 @@
#include "main.h"
-#define NEW_PERMS 0660
+#define NEW_PERMS 0666
#define DEV_IO "/dev/io"
#define EXPECTED_PERMS 0600
-static mode_t saved_perms;
+static int initialized;
+static mode_t saved_perms;
-static void
-save_perms(void)
+int
+priv_io_setup(int asroot, int asjail, struct test *test)
{
struct stat sb;
- if (stat(DEV_IO, &sb) < 0)
- err(-1, "save_perms: stat(%s)", DEV_IO);
-
+ if (stat(DEV_IO, &sb) < 0) {
+ warn("priv_io_setup: stat(%s)", DEV_IO);
+ return (-1);
+ }
saved_perms = sb.st_mode & ALLPERMS;
-
- if (saved_perms != EXPECTED_PERMS)
- err(-1, "save_perms: perms = 0%o; expected 0%o", saved_perms,
- EXPECTED_PERMS);
-
-}
-
-static void
-set_perms(void)
-{
-
- if (chmod(DEV_IO, NEW_PERMS) < 0)
- err(-1, "set_perms: chmod(%s, 0%o)", DEV_IO, NEW_PERMS);
-}
-
-static void
-restore_perms(void)
-{
-
- if (chmod(DEV_IO, saved_perms) < 0)
- err(-1, "restore_perms: chmod(%s, 0%o)", DEV_IO, saved_perms);
+ if (saved_perms != EXPECTED_PERMS) {
+ warnx("priv_io_setup: perms = 0%o; expected 0%o",
+ saved_perms, EXPECTED_PERMS);
+ return (-1);
+ }
+ if (chmod(DEV_IO, NEW_PERMS) < 0) {
+ warn("priv_io_setup: chmod(%s, 0%o)", DEV_IO, NEW_PERMS);
+ return (-1);
+ }
+ initialized = 1;
+ return (0);
}
-static void
-try_open(const char *test_case, uid_t uid, int expected)
+void
+priv_io(int asroot, int injail, struct test *test)
{
- int fd;
+ int error, fd;
- set_euid(uid);
fd = open(DEV_IO, O_RDONLY);
- if (expected == 0) {
- if (fd == -1) {
- warn("try_open: %s open(%s) errno %d", DEV_IO,
- test_case, errno);
- goto out;
- }
+ if (fd < 0)
+ error = -1;
+ else
+ error = 0;
+ if (asroot && injail)
+ expect("priv_io(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_io(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_io(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_io(!asroot, !injail)", error, -1, EPERM);
+ if (fd != -1)
close(fd);
- goto out;
- }
- if (fd >= 0) {
- warn("try_open: %s open(%s) unexpected success", test_case,
- DEV_IO);
- close(fd);
- goto out;
- }
- if (errno == expected)
- goto out;
- warn("try_open: %s open(%s) wrong errno %d, expected %d", DEV_IO,
- test_case, errno, expected);
-out:
- set_euid(UID_ROOT);
}
void
-priv_io(void)
+priv_io_cleanup(int asroot, int asjail, struct test *test)
{
- assert_root();
-
- save_perms();
-
- try_open("root:0600", UID_ROOT, 0);
- try_open("other", UID_OTHER, EACCES);
-
- set_perms();
-
- try_open("root:0660", UID_ROOT, 0);
- try_open("other", UID_OTHER, EPERM);
-
- restore_perms();
+ if (!initialized)
+ return;
+ if (chmod(DEV_IO, saved_perms) < 0)
+ err(-1, "priv_io_cleanup: chmod(%s, 0%o)", DEV_IO,
+ saved_perms);
+ initialized = 0;
}
diff --git a/tools/regression/priv/priv_kenv_set.c b/tools/regression/priv/priv_kenv_set.c
index 96e785d..1e750e0 100644
--- a/tools/regression/priv/priv_kenv_set.c
+++ b/tools/regression/priv/priv_kenv_set.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,7 @@
*/
/*
- * Test that setting a kernel environment variable requires privilege, by
- * first trying it with privilege, then without.
+ * Test that setting a kernel environment variable requires privilege.
*/
#include <sys/types.h>
@@ -44,25 +44,33 @@
#include "main.h"
+int
+priv_kenv_set_setup(int asroot, int injail, struct test *test)
+{
+
+ (void)kenv(KENV_UNSET, KENV_VAR_NAME, NULL, 0);
+ return (0);
+}
+
void
-priv_kenv_set(void)
+priv_kenv_set(int asroot, int injail, struct test *test)
{
int error;
- assert_root();
-
- error = kenv(KENV_SET, KENV_VAR_NAME, KENV_VAR_VALUE,
- strlen(KENV_VAR_VALUE)+1);
- if (error)
- err(-1, "kenv(KENV_SET, ...) as root");
+ error = kenv(KENV_SET, KENV_VAR_NAME, KENV_VAR_VALUE, KENV_VAR_LEN);
+ if (asroot && injail)
+ expect("priv_kenv_set(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_kenv_set(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_kenv_set(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_kenv_set(!asroot, !injail)", error, -1, EPERM);
+}
- set_euid(UID_OTHER);
+void
+priv_kenv_set_cleanup(int asroot, int injail, struct test *test)
+{
- error = kenv(KENV_SET, KENV_VAR_NAME, KENV_VAR_VALUE,
- strlen(KENV_VAR_VALUE)+1);
- if (error == 0)
- errx(-1, "kenv(KENV_SET, ...) as !root succeeded");
- if (errno != EPERM)
- err(-1, "kenv(KENV_SET, ...) as !root wrong errno %d",
- errno);
+ (void)kenv(KENV_UNSET, KENV_VAR_NAME, NULL, 0);
}
diff --git a/tools/regression/priv/priv_kenv_unset.c b/tools/regression/priv/priv_kenv_unset.c
index 2bb800d..02004da 100644
--- a/tools/regression/priv/priv_kenv_unset.c
+++ b/tools/regression/priv/priv_kenv_unset.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,7 @@
*/
/*
- * Test that setting a kernel environment variable, then trying to unset it
- * without and with privilege.
+ * Test setting a kernel environment variable, then try to unset it.
*/
#include <sys/types.h>
@@ -44,34 +44,36 @@
#include "main.h"
-void
-priv_kenv_unset(void)
+int
+priv_kenv_unset_setup(int asroot, int injail, struct test *test)
{
- int error;
- assert_root();
+ if (kenv(KENV_SET, KENV_VAR_NAME, KENV_VAR_VALUE, KENV_VAR_LEN) < 0) {
+ warn("priv_kenv_unset: kenv");
+ return (-1);
+ }
+ return (0);
+}
- error = kenv(KENV_SET, KENV_VAR_NAME, KENV_VAR_VALUE,
- strlen(KENV_VAR_VALUE)+1);
- if (error)
- err(-1, "kenv(KENV_SET, ...) as root");
+void
+priv_kenv_unset(int asroot, int injail, struct test *test)
+{
+ int error;
error = kenv(KENV_UNSET, KENV_VAR_NAME, NULL, 0);
- if (error)
- err(-1, "kenv(KENV_UNSET, ...) as root");
-
- /* Set it again for !root. */
- error = kenv(KENV_SET, KENV_VAR_NAME, KENV_VAR_VALUE,
- strlen(KENV_VAR_VALUE)+1);
- if (error)
- err(-1, "kenv(KENV_SET, ...) as root");
+ if (asroot && injail)
+ expect("priv_kenv_unset(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_kenv_unset(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_kenv_unset(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_kenv_unset(!asroot, !injail)", error, -1, EPERM);
+}
- set_euid(UID_OTHER);
+void
+priv_kenv_unset_cleanup(int asroot, int injail, struct test *test)
+{
- error = kenv(KENV_UNSET, KENV_VAR_NAME, NULL, 0);
- if (error == 0)
- errx(-1, "kenv(KENV_UNSET, ...) as !root succeeded");
- if (errno != EPERM)
- err(-1, "kenv(KENV_UNSET, ...) as !root wrong errno %d",
- errno);
+ (void)kenv(KENV_UNSET, KENV_VAR_NAME, NULL, 0);
}
diff --git a/tools/regression/priv/priv_msgbuf.c b/tools/regression/priv/priv_msgbuf.c
new file mode 100644
index 0000000..c8db210
--- /dev/null
+++ b/tools/regression/priv/priv_msgbuf.c
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (c) 2007 Robert M. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Confirm that when security.bsd.unprivileged_read_msgbuf is set to 0,
+ * privilege is required to read the kernel message buffer.
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "main.h"
+
+#define MSGBUF_CONTROL_NAME "security.bsd.unprivileged_read_msgbuf"
+#define MSGBUF_NAME "kern.msgbuf"
+
+/*
+ * We must query and save the original value, then restore it when done.
+ */
+static int unprivileged_read_msgbuf;
+static int unprivileged_read_msgbuf_initialized;
+
+int
+priv_msgbuf_privonly_setup(int asroot, int injail, struct test *test)
+{
+ size_t len;
+ int newval;
+
+ /*
+ * Separately query and set to make debugging easier.
+ */
+ len = sizeof(unprivileged_read_msgbuf);
+ if (sysctlbyname(MSGBUF_CONTROL_NAME, &unprivileged_read_msgbuf,
+ &len, NULL, 0) < 0) {
+ warn("priv_msgbuf_privonly_setup: sysctlbyname query");
+ return (-1);
+ }
+ newval = 0;
+ if (sysctlbyname(MSGBUF_CONTROL_NAME, NULL, NULL, &newval,
+ sizeof(newval)) < 0) {
+ warn("priv_msgbuf_privonly_setup: sysctlbyname set");
+ return (-1);
+ }
+ unprivileged_read_msgbuf_initialized = 1;
+ return (0);
+}
+
+void
+priv_msgbuf_privonly(int asroot, int injail, struct test *test)
+{
+ size_t len;
+ int error;
+
+ error = sysctlbyname(MSGBUF_NAME, NULL, &len, NULL, 0);
+ if (asroot && injail)
+ expect("priv_msgbuf_privonly(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_msgbuf_privonly(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_msgbuf_privonly(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_msgbuf_privonly(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+int
+priv_msgbuf_unprivok_setup(int asroot, int injail, struct test *test)
+{
+ size_t len;
+ int newval;
+
+ /*
+ * Separately query and set to make debugging easier.
+ */
+ len = sizeof(unprivileged_read_msgbuf);
+ if (sysctlbyname(MSGBUF_CONTROL_NAME, &unprivileged_read_msgbuf, &len,
+ NULL, 0) < 0) {
+ warn("priv_msgbuf_unprivok_setup: sysctlbyname query");
+ return (-1);
+ }
+ newval = 1;
+ if (sysctlbyname(MSGBUF_CONTROL_NAME, NULL, NULL, &newval,
+ sizeof(newval)) < 0) {
+ warn("priv_msgbuf_unprivok_setup: sysctlbyname set");
+ return (-1);
+ }
+ unprivileged_read_msgbuf_initialized = 1;
+ return (0);
+}
+
+void
+priv_msgbuf_unprivok(int asroot, int injail, struct test *test)
+{
+ size_t len;
+ int error;
+
+ error = sysctlbyname(MSGBUF_NAME, NULL, &len, NULL, 0);
+ if (asroot && injail)
+ expect("priv_msgbuf_unprivok(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_msgbuf_unprivok(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_msgbuf_unprivok(!asroot, injail)", error, 0, 0);
+ if (!asroot && !injail)
+ expect("priv_msgbuf_unprivok(!asroot, !injail)", error, 0, 0);
+}
+
+void
+priv_msgbuf_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (unprivileged_read_msgbuf_initialized) {
+ (void)sysctlbyname(MSGBUF_NAME, NULL, NULL,
+ &unprivileged_read_msgbuf,
+ sizeof(unprivileged_read_msgbuf));
+ unprivileged_read_msgbuf_initialized = 0;
+ }
+}
diff --git a/tools/regression/priv/priv_netinet_raw.c b/tools/regression/priv/priv_netinet_raw.c
new file mode 100644
index 0000000..75f66c0
--- /dev/null
+++ b/tools/regression/priv/priv_netinet_raw.c
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2007 Robert M. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Confirm that privilege is required to open a raw IP socket, and that this
+ * is not allowed in jail.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "main.h"
+
+int
+priv_netinet_raw_setup(int asroot, int injail, struct test *test)
+{
+
+ return (0);
+}
+
+void
+priv_netinet_raw(int asroot, int injail, struct test *test)
+{
+ int error, fd;
+
+ fd = socket(PF_INET, SOCK_RAW, 0);
+ if (fd < 0)
+ error = -1;
+ else
+ error = 0;
+ if (asroot && injail)
+ expect("priv_netinet_raw(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_netinet_raw(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_netinet_raw(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_netinet_raw(!asroot, !injail)", error,
+ -1, EPERM);
+ if (fd >= 0)
+ (void)close(fd);
+}
+
+void
+priv_netinet_raw_cleanup(int asroot, int injail, struct test *test)
+{
+
+}
diff --git a/tools/regression/priv/priv_proc_setlogin.c b/tools/regression/priv/priv_proc_setlogin.c
index 6f5e756..f04b79f 100644
--- a/tools/regression/priv/priv_proc_setlogin.c
+++ b/tools/regression/priv/priv_proc_setlogin.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,44 +31,58 @@
*/
/*
- * Test that privilege is required to call setlogin(). Do so by first
- * querying with getlogin(), then setting the result back using setlogin(),
- * at first with privilege, then without.
+ * Test privileges for setlogin(); first query with getlogin() so that the
+ * result is a no-op, since it affects the entire login session.
*/
+#include <sys/param.h>
+
#include <err.h>
#include <errno.h>
#include <unistd.h>
#include "main.h"
-void
-priv_proc_setlogin(void)
-{
- char *loginname;
- int error;
+static int initialized;
+static char *loginname;
- assert_root();
+int
+priv_proc_setlogin_setup(int asroot, int injail, struct test *test)
+{
+ if (initialized)
+ return (0);
loginname = getlogin();
- if (loginname == NULL)
- err(-1, "getlogin");
+ if (loginname == NULL) {
+ warn("priv_proc_setlogin_setup: getlogin");
+ return (-1);
+ }
+ initialized = 1;
+ return (0);
+}
+
+void
+priv_proc_setlogin(int asroot, int injail, struct test *test)
+{
+ int error;
- /*
- * First, with privilege.
- */
error = setlogin(loginname);
- if (error)
- err(-1, "setlogin(%s) as root", loginname);
+ if (asroot && injail)
+ expect("priv_proc_setlogin(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_proc_setlogin(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_proc_setlogin(!sroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_proc_setlogin(!asroot, !injail)", error, -1,
+ EPERM);
+}
- /*
- * Then again, without privilege.
- */
- set_euid(UID_OTHER);
+void
+priv_proc_setlogin_cleanup(int asroot, int injail, struct test *test)
+{
- error = setlogin(loginname);
- if (error == 0)
- errx(-1, "setlogin(%s) succeeded as !root", loginname);
- if (errno != EPERM)
- err(-1, "setlogin(%s) wrong errno %d", loginname, errno);
+ if (initialized)
+ (void)setlogin(loginname);
}
diff --git a/tools/regression/priv/priv_proc_setrlimit.c b/tools/regression/priv/priv_proc_setrlimit.c
index adf471b..590f55f 100644
--- a/tools/regression/priv/priv_proc_setrlimit.c
+++ b/tools/regression/priv/priv_proc_setrlimit.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -29,13 +30,13 @@
* $FreeBSD$
*/
-/*
+/*-
* Test that raising current resource limits above hard resource limits
- * requires privilege. There is one privilege check, but two conditions:
- *
- * - To raise the current above the maximum.
+ * requires privilege. We test three cases:
*
- * - To raise the maximum.
+ * - Raise the current above the maximum (privileged).
+ * - Raise the current to the maximum (unprivileged).
+ * - Raise the maximum (privileged).
*/
#include <sys/types.h>
@@ -48,90 +49,122 @@
#include "main.h"
-void
-priv_proc_setrlimit(void)
-{
- struct rlimit rl, rl_lower, rl_raise_max, rl_raise_cur;
- int error;
+static int initialized;
+static struct rlimit rl_base;
+static struct rlimit rl_lowered;
- assert_root();
+int
+priv_proc_setrlimit_setup(int asroot, int injail, struct test *test)
+{
- /*
- * To make sure that there is room to raise the resource limit, we
- * must first lower it. Otherwise, if the resource limit is already
- * at the global maximum, that complicates matters. In principle, we
- * can bump into privilege failures during setup, but there's not
- * much we can do about that. Keep this prototypical setting around
- * as the target to restore to later.
- */
- if (getrlimit(RLIMIT_DATA, &rl) < 0)
- err(-1, "getrlimit(RLIMIT_DATA)");
+ if (getrlimit(RLIMIT_DATA, &rl_base) < 0) {
+ warn("priv_proc_setrlimit_setup: getrlimit");
+ return (-1);
+ }
/*
- * What to lower to before trying to raise.
+ * Must lower current and limit to make sure there's room to try to
+ * raise them during tests. Set current lower than max so we can
+ * raise it later also.
*/
- rl_lower = rl;
- rl_lower.rlim_cur -= 10;
- rl_lower.rlim_max = rl_lower.rlim_cur;
+ rl_lowered = rl_base;
+ rl_lowered.rlim_cur -= 20;
+ rl_lowered.rlim_max -= 10;
+ if (setrlimit(RLIMIT_DATA, &rl_lowered) < 0) {
+ warn("priv_proc_setrlimit_setup: setrlimit");
+ return (-1);
+ }
+ initialized = 1;
+ return (0);
+}
- /*
- * Raise the maximum.
- */
- rl_raise_max = rl;
- rl_raise_max.rlim_max += 10;
+/*
+ * Try increasing the maximum limits on the process, which requires
+ * privilege.
+ */
+void
+priv_proc_setrlimit_raisemax(int asroot, int injail, struct test *test)
+{
+ struct rlimit rl;
+ int error;
- /*
- * Raise the current above the maximum.
- */
- rl_raise_cur = rl;
- rl_raise_cur.rlim_cur += 10;
+ rl = rl_lowered;
+ rl.rlim_max = rl_base.rlim_max;
+ error = setrlimit(RLIMIT_DATA, &rl);
+ if (asroot && injail)
+ expect("priv_proc_setrlimit_raisemax(asroot, injail)", error,
+ 0, 0);
+ if (asroot && !injail)
+ expect("priv_proc_setrlimit_raisemax(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_proc_setrlimit_raisemax(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_proc_setrlimit_raisemax(!asroot, !injail)",
+ error, -1, EPERM);
+}
- /*
- * Test raising the maximum with privilege.
- */
- if (setrlimit(RLIMIT_DATA, &rl_lower) < 0)
- err(-1, "setrlimit(RLIMIT_DATA, lower) as root");
+/*
+ * Try setting the current limit to the current maximum, which is allowed
+ * without privilege.
+ */
+void
+priv_proc_setrlimit_raisecur_nopriv(int asroot, int injail,
+ struct test *test)
+{
+ struct rlimit rl;
+ int error;
- if (setrlimit(RLIMIT_DATA, &rl_raise_max) < 0)
- err(-1, "setrlimit(RLIMIT_DATA, raise_max) as root");
+ rl = rl_lowered;
+ rl.rlim_cur = rl.rlim_max;
+ error = setrlimit(RLIMIT_DATA, &rl);
+ if (asroot && injail)
+ expect("priv_proc_setrlimit_raiscur_nopriv(asroot, injail)",
+ error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_proc_setrlimit_raisecur_nopriv(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_proc_setrlimit_raisecur_nopriv(!asroot, injail)",
+ error, 0, 0);
+ if (!asroot && !injail)
+ expect("priv_proc_setrlimit_raisecur_nopriv(!asroot, !injail)",
+ error, 0, 0);
+}
- /*
- * Test raising the current above the maximum with privilege.
- */
- if (setrlimit(RLIMIT_DATA, &rl_lower) < 0)
- err(-1, "setrlimit(RLIMIT_DATA, lower) as root");
+/*
+ * Try raising the current limits above the maximum, which requires
+ * privilege.
+ */
+void
+priv_proc_setrlimit_raisecur(int asroot, int injail, struct test *test)
+{
+ struct rlimit rl;
+ int error;
- if (setrlimit(RLIMIT_DATA, &rl_raise_cur) < 0)
- err(-1, "setrlimit(RLIMIT_DATA, raise_cur) as root");
+ rl = rl_lowered;
+ rl.rlim_cur = rl.rlim_max + 10;
+ error = setrlimit(RLIMIT_DATA, &rl);
+ if (asroot && injail)
+ expect("priv_proc_setrlimit_raisecur(asroot, injail)", error,
+ 0, 0);
+ if (asroot && !injail)
+ expect("priv_proc_setrlimit_raisecur(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_proc_setrlimit_raisecur(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_proc_setrlimit_raisecur(!asroot, !injail)",
+ error, -1, EPERM);
+}
- /*
- * Test raising the maximum without privilege.
- */
- if (setrlimit(RLIMIT_DATA, &rl_lower) < 0)
- err(-1, "setrlimit(RLIMIT_DATA, lower) as root");
-
- set_euid(UID_OTHER);
- error = setrlimit(RLIMIT_DATA, &rl_raise_max);
- if (error == 0)
- errx(-1,
- "setrlimit(RLIMIT_DATA, raise_max) succeeded as !root");
- if (errno != EPERM)
- err(-1, "setrlimit(RLIMIT_DATA, raise_max) wrong errno %d "
- "as !root", errno);
+void
+priv_proc_setrlimit_cleanup(int asroot, int injail, struct test *test)
+{
- /*
- * Test raising the current above the maximum without privilege.
- */
- set_euid(UID_ROOT);
- if (setrlimit(RLIMIT_DATA, &rl_lower) < 0)
- err(-1, "setrlimit(RLIMIT_DATA, lower) as root");
- set_euid(UID_OTHER);
-
- error = setrlimit(RLIMIT_DATA, &rl_raise_cur);
- if (error == 0)
- errx(-1,
- "setrlimit(RLIMIT_DATA, raise_cur) succeeded as !root");
- if (errno != EPERM)
- err(-1, "setrlimit(RLIMIT_DATA, raise_cur) wrong errno %d "
- "as !root", errno);
+ if (initialized)
+ (void)setrlimit(RLIMIT_DATA, &rl_base);
+ initialized = 0;
}
diff --git a/tools/regression/priv/priv_sched_rtprio.c b/tools/regression/priv/priv_sched_rtprio.c
index 72d1756..2498f3f 100644
--- a/tools/regression/priv/priv_sched_rtprio.c
+++ b/tools/regression/priv/priv_sched_rtprio.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -54,181 +55,275 @@
#include "main.h"
-static void
-dummy(void)
-{
-
- while (1)
- sleep(1);
-}
+static int childproc_running;
+static pid_t childproc;
-static void
-collect(pid_t test_pid, pid_t dummy_pid)
+int
+priv_sched_rtprio_setup(int asroot, int injail, struct test *test)
{
- pid_t pid;
+ int another_uid, need_child;
/*
- * First, collect the main test process. When it has exited, then
- * kill off the dummy process.
+ * Some tests require a second process with specific credentials.
+ * Set that up here, and kill in cleanup.
*/
- if (test_pid > 0) {
- while (1) {
- pid = waitpid(test_pid, NULL, 0);
- if (pid == -1)
- warn("waitpid(%d (test), NULL, 0)", test_pid);
- if (pid == test_pid)
- break;
- }
+ need_child = 0;
+ if (test->t_test_func == priv_sched_rtprio_aproc_normal ||
+ test->t_test_func == priv_sched_rtprio_aproc_idle ||
+ test->t_test_func == priv_sched_rtprio_aproc_realtime) {
+ need_child = 1;
+ another_uid = 1;
+ }
+ if (test->t_test_func == priv_sched_rtprio_myproc_normal ||
+ test->t_test_func == priv_sched_rtprio_myproc_idle ||
+ test->t_test_func == priv_sched_rtprio_myproc_realtime) {
+ need_child = 1;
}
- if (kill(dummy_pid, SIGKILL) < 0)
- err(-1, "kill(%d, SIGKILL)", dummy_pid);
-
- while (1) {
- pid = waitpid(dummy_pid, NULL, 0);
- if (pid == -1)
- warn("waitpid(%d, NULL, 0)", dummy_pid);
- if (pid == dummy_pid)
- return;
+ if (need_child) {
+ childproc = fork();
+ if (childproc < 0) {
+ warn("priv_sched_setup: fork");
+ return (-1);
+ }
+ if (childproc == 0) {
+ if (another_uid) {
+ if (setresuid(UID_THIRD, UID_THIRD,
+ UID_THIRD) < 0)
+ err(-1, "setresuid(%d)", UID_THIRD);
+ }
+ while (1)
+ sleep(1);
+ }
+ childproc_running = 1;
+ sleep(1); /* Allow dummy thread to change uids. */
}
+ return (0);
}
-static void
-test(pid_t dummy_pid)
+void
+priv_sched_rtprio_curproc_normal(int asroot, int injail, struct test *test)
{
struct rtprio rtp;
int error;
- /*
- * Tests first as root. Test that we can set normal, realtime, and
- * idle priorities on the current thread and on the dummy thread.
- */
- rtp.type = RTP_PRIO_REALTIME;
+ rtp.type = RTP_PRIO_NORMAL;
rtp.prio = 0;
- if (rtprio(RTP_SET, 0, &rtp) < 0)
- err(-1, "rtprio(RTP_SET, 0, {REALTIME, 0}) as root");
+ error = rtprio(RTP_SET, 0, &rtp);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_curproc_normal(asroot, injail)",
+ error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_curproc_normal(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_curproc_normal(!asroot, injail)",
+ error, 0, 0);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_curproc_normal(!asroot, !injail)",
+ error, 0, 0);
+}
+
+void
+priv_sched_rtprio_curproc_idle(int asroot, int injail, struct test *test)
+{
+ struct rtprio rtp;
+ int error;
rtp.type = RTP_PRIO_IDLE;
rtp.prio = 0;
- if (rtprio(RTP_SET, 0, &rtp) < 0)
- err(-1, "rtprio(RTP_SET, 0, {IDLE, 0}) as root");
+ error = rtprio(RTP_SET, 0, &rtp);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_curproc_idle(asroot, injail)",
+ error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_curproc_idle(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_curproc_idle(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_curproc_idle(!asroot, !injail)",
+ error, -1, EPERM);
+}
- rtp.type = RTP_PRIO_NORMAL;
- rtp.prio = 0;
- if (rtprio(RTP_SET, 0, &rtp) < 0)
- err(-1, "rtprio(RTP_SET, 0, {NORMAL, 0) as root");
+void
+priv_sched_rtprio_curproc_realtime(int asroot, int injail, struct test *test)
+{
+ struct rtprio rtp;
+ int error;
rtp.type = RTP_PRIO_REALTIME;
rtp.prio = 0;
- if (rtprio(RTP_SET, dummy_pid, &rtp) < 0)
- err(-1, "rtprio(RTP_SET, %d, {REALTIME, 0}) as root",
- dummy_pid);
+ error = rtprio(RTP_SET, 0, &rtp);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_curproc_realtime(asroot, injail)",
+ error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_curproc_realtime(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_curproc_realtime(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_curproc_realtime(!asroot, !injail)",
+ error, -1, EPERM);
+}
- rtp.type = RTP_PRIO_IDLE;
- rtp.prio = 0;
- if (rtprio(RTP_SET, dummy_pid, &rtp) < 0)
- err(-1, "rtprio(RTP_SET, %d, {IDLE, 0}) as root", dummy_pid);
+void
+priv_sched_rtprio_myproc_normal(int asroot, int injail, struct test *test)
+{
+ struct rtprio rtp;
+ int error;
rtp.type = RTP_PRIO_NORMAL;
rtp.prio = 0;
- if (rtprio(RTP_SET, dummy_pid, &rtp) < 0)
- err(-1, "rtprio(RTP_SET, %d, {NORMAL, 0) as root",
- dummy_pid);
+ error = rtprio(RTP_SET, 0, &rtp);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_myproc_normal(asroot, injail)",
+ error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_myproc_normal(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_myproc_normal(!asroot, injail)",
+ error, 0, 0);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_myproc_normal(!asroot, !injail)",
+ error, 0, 0);
+}
- /*
- * Then test again as a different credential.
- */
- if (setresuid(UID_OTHER, UID_OTHER, UID_OTHER) < 0)
- err(-1, "setresuid(%d)", UID_OTHER);
+void
+priv_sched_rtprio_myproc_idle(int asroot, int injail, struct test *test)
+{
+ struct rtprio rtp;
+ int error;
- rtp.type = RTP_PRIO_REALTIME;
+ rtp.type = RTP_PRIO_IDLE;
rtp.prio = 0;
error = rtprio(RTP_SET, 0, &rtp);
- if (error == 0)
- errx(-1,
- "rtprio(RTP_SET, 0, {REALTIME, 0}) succeeded as !root");
- if (errno != EPERM)
- err(-1, "rtprio(RTP_SET, 0, {REALTIME, 0}) wrong errno %d as"
- " !root", errno);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_myproc_idle(asroot, injail)",
+ error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_myproc_idle(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_myproc_idle(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_myproc_idle(!asroot, !injail)",
+ error, -1, EPERM);
+}
- rtp.type = RTP_PRIO_IDLE;
+void
+priv_sched_rtprio_myproc_realtime(int asroot, int injail, struct test *test)
+{
+ struct rtprio rtp;
+ int error;
+
+ rtp.type = RTP_PRIO_REALTIME;
rtp.prio = 0;
error = rtprio(RTP_SET, 0, &rtp);
- if (error == 0)
- errx(-1, "rtprio(RTP_SET, 0, {IDLE, 0}) succeeded as !root");
- if (errno != EPERM)
- err(-1, "rtprio(RTP_SET, 0, {IDLE, 0}) wrong errno %d as "
- "!root", errno);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_myproc_realtime(asroot, injail)",
+ error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_myproc_realtime(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_myproc_realtime(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_myproc_realtime(!asroot, !injail)",
+ error, -1, EPERM);
+}
+
+void
+priv_sched_rtprio_aproc_normal(int asroot, int injail, struct test *test)
+{
+ struct rtprio rtp;
+ int error;
rtp.type = RTP_PRIO_NORMAL;
rtp.prio = 0;
- if (rtprio(RTP_SET, 0, &rtp) < 0)
- err(-1, "rtprio(RTP_SET, 0, {NORMAL, 0}) as !root");
+ error = rtprio(RTP_SET, childproc, &rtp);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_aproc_normal(asroot, injail)",
+ error, -1, ESRCH);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_aproc_normal(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_aproc_normal(!asroot, injail)",
+ error, -1, ESRCH);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_aproc_normal(!asroot, !injail)",
+ error, -1, EPERM);
+}
- rtp.type = RTP_PRIO_REALTIME;
- rtp.prio = 0;
- error = rtprio(RTP_SET, dummy_pid, &rtp);
- if (error == 0)
- errx(-1,
- "rtprio(RTP_SET, %d, {REALTIME, 0}) succeeded as !root",
- dummy_pid);
- if (errno != EPERM)
- err(-1, "rtprio(RTP_SET, %d, {REALTIME, 0}) wrong errno %d as"
- " !root", dummy_pid, errno);
+void
+priv_sched_rtprio_aproc_idle(int asroot, int injail, struct test *test)
+{
+ struct rtprio rtp;
+ int error;
rtp.type = RTP_PRIO_IDLE;
rtp.prio = 0;
- error = rtprio(RTP_SET, dummy_pid, &rtp);
- if (error == 0)
- errx(-1, "rtprio(RTP_SET, %d, {IDLE, 0}) succeeded as !root",
- dummy_pid);
- if (errno != EPERM)
- err(-1,
- "rtprio(RTP_SET, %d, {IDLE, 0}) wrong errno %d as !root",
- dummy_pid, errno);
-
- rtp.type = RTP_PRIO_NORMAL;
- rtp.prio = 0;
- error = rtprio(RTP_SET, dummy_pid, &rtp);
- if (error == 0)
- errx(-1,
- "rtprio(RTP_SET, %d, {NORMAL, 0) succeeded as !root",
- dummy_pid);
- if (errno != EPERM)
- err(-1, "rtprio(RTP_SET, %d, {NORMAL, 0}) wrong errno %d as "
- "!root", dummy_pid, errno);
-
- exit(0);
+ error = rtprio(RTP_SET, childproc, &rtp);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_aproc_idle(asroot, injail)",
+ error, -1, ESRCH);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_aproc_idle(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_aproc_idle(!asroot, injail)",
+ error, -1, ESRCH);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_aroc_idle(!asroot, !injail)",
+ error, -1, EPERM);
}
void
-priv_sched_rtprio(void)
+priv_sched_rtprio_aproc_realtime(int asroot, int injail, struct test *test)
{
- pid_t dummy_pid, test_pid;
+ struct rtprio rtp;
+ int error;
- assert_root();
+ rtp.type = RTP_PRIO_REALTIME;
+ rtp.prio = 0;
+ error = rtprio(RTP_SET, childproc, &rtp);
+ if (asroot && injail)
+ expect("priv_sched_rtprio_aproc_realtime(asroot, injail)",
+ error, -1, ESRCH);
+ if (asroot && !injail)
+ expect("priv_sched_rtprio_aproc_realtime(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_rtprio_aproc_realtime(!asroot, injail)",
+ error, -1, ESRCH);
+ if (!asroot && !injail)
+ expect("priv_sched_rtprio_aproc_realtime(!asroot, !injail)",
+ error, -1, EPERM);
+}
- /*
- * Set up dummy process, which we will kill before exiting.
- */
- dummy_pid = fork();
- if (dummy_pid < 0)
- err(-1, "fork - dummy");
- if (dummy_pid == 0) {
- if (setresuid(UID_THIRD, UID_THIRD, UID_THIRD) < 0)
- err(-1, "setresuid(%d)", UID_THIRD);
- dummy();
- }
- sleep(1); /* Allow dummy thread to change uids. */
+void
+priv_sched_rtprio_cleanup(int asroot, int injail, struct test *test)
+{
+ pid_t pid;
- test_pid = fork();
- if (test_pid < 0) {
- warn("fork - test");
- collect(-1, dummy_pid);
- return;
+ if (childproc_running) {
+ (void)kill(childproc, SIGKILL);
+ while (1) {
+ pid = waitpid(childproc, NULL, 0);
+ if (pid == -1)
+ warn("waitpid(%d (test), NULL, 0)",
+ childproc);
+ if (pid == childproc)
+ break;
+ }
+ childproc_running = 0;
+ childproc = -1;
}
- if (test_pid == 0)
- test(dummy_pid);
-
- collect(test_pid, dummy_pid);
}
diff --git a/tools/regression/priv/priv_sched_setpriority.c b/tools/regression/priv/priv_sched_setpriority.c
index 4d56813..219fd8c 100644
--- a/tools/regression/priv/priv_sched_setpriority.c
+++ b/tools/regression/priv/priv_sched_setpriority.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -50,114 +51,123 @@
#include "main.h"
-static void
-dummy(void)
-{
-
- while (1)
- sleep(1);
-}
+static int childproc_running;
+static pid_t childproc;
-static void
-collect(pid_t test_pid, pid_t dummy_pid)
+int
+priv_sched_setpriority_setup(int asroot, int injail, struct test *test)
{
- pid_t pid;
+ int another_uid, need_child;
/*
- * First, collect the main test process. When it has exited, then
- * kill off the dummy process.
+ * Some tests require a second process with specific credentials.
+ * Set that up here, and kill in cleanup.
*/
- if (test_pid > 0) {
- while (1) {
- pid = waitpid(test_pid, NULL, 0);
- if (pid == -1)
- warn("waitpid(%d (test), NULL, 0)", test_pid);
- if (pid == test_pid)
- break;
- }
+ need_child = 0;
+ if (test->t_test_func == priv_sched_setpriority_aproc) {
+ need_child = 1;
+ another_uid = 1;
}
-
- if (kill(dummy_pid, SIGKILL) < 0)
- err(-1, "kill(%d, SIGKILL)", dummy_pid);
-
- while (1) {
- pid = waitpid(dummy_pid, NULL, 0);
- if (pid == -1)
- warn("waitpid(%d, NULL, 0)", dummy_pid);
- if (pid == dummy_pid)
- return;
+ if (test->t_test_func == priv_sched_setpriority_myproc)
+ need_child = 1;
+
+ if (need_child) {
+ childproc = fork();
+ if (childproc < 0) {
+ warn("priv_sched_setup: fork");
+ return (-1);
+ }
+ if (childproc == 0) {
+ if (another_uid) {
+ if (setresuid(UID_THIRD, UID_THIRD,
+ UID_THIRD) < 0)
+ err(-1, "setresuid(%d)", UID_THIRD);
+ }
+ while (1)
+ sleep(1);
+ }
+ childproc_running = 1;
+ sleep(1); /* Allow dummy thread to change uids. */
}
+ return (0);
}
-static void
-test(pid_t dummy_pid)
+void
+priv_sched_setpriority_curproc(int asroot, int injail, struct test *test)
{
int error;
- /*
- * Tests first as root.
- */
- if (setpriority(PRIO_PROCESS, 0, -1) < 0)
- err(-1, "setpriority(PRIO_PROCESS, 0, -1) as root");
+ error = setpriority(PRIO_PROCESS, 0, -1);
+ if (asroot && injail)
+ expect("priv_sched_setpriority_curproc(asroot, injail)",
+ error, -1, EACCES);
+ if (asroot && !injail)
+ expect("priv_sched_setpriority_curproc(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_setpriority_curproc(!asroot, injail)",
+ error, -1, EACCES);
+ if (!asroot && !injail)
+ expect("priv_sched_setpriority_curproc(!asroot, !injail)",
+ error, -1, EACCES);
+}
- if (setpriority(PRIO_PROCESS, dummy_pid, -1) < 0)
- err(-1, "setpriority(PRIO_PROCESS, %d, -1) as root",
- dummy_pid);
+void
+priv_sched_setpriority_myproc(int asroot, int injail, struct test *test)
+{
+ int error;
- /*
- * Then test again as a different credential.
- */
- if (setresuid(UID_OTHER, UID_OTHER, UID_OTHER) < 0)
- err(-1, "setresuid(%d)", UID_OTHER);
-
- error = setpriority(PRIO_PROCESS, 0, -2);
- if (error == 0)
- errx(-1,
- "setpriority(PRIO_PROCESS, 0, -2) succeeded as !root");
- if (errno != EACCES)
- err(-1, "setpriority(PRIO_PROCESS, 0, 2) wrong errno %d as "
- "!root", errno);
-
- error = setpriority(PRIO_PROCESS, dummy_pid, -2);
- if (error == 0)
- errx(-1,
- "setpriority(PRIO_PROCESS, %d, -2) succeeded as !root",
- dummy_pid);
- if (errno != EPERM)
- err(-1, "setpriority(PRIO_PROCESS, %d, 2) wrong errno %d as "
- "!root", dummy_pid, errno);
-
- exit(0);
+ error = setpriority(PRIO_PROCESS, 0, -1);
+ if (asroot && injail)
+ expect("priv_sched_setpriority_myproc(asroot, injail)",
+ error, -1, EACCES);
+ if (asroot && !injail)
+ expect("priv_sched_setpriority_myproc(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_setpriority_myproc(!asroot, injail)",
+ error, -1, EACCES);
+ if (!asroot && !injail)
+ expect("priv_sched_setpriority_myproc(!asroot, !injail)",
+ error, -1, EACCES);
}
void
-priv_sched_setpriority(void)
+priv_sched_setpriority_aproc(int asroot, int injail, struct test *test)
{
- pid_t dummy_pid, test_pid;
+ int error;
- assert_root();
+ error = setpriority(PRIO_PROCESS, 0, -1);
+ if (asroot && injail)
+ expect("priv_sched_setpriority_aproc(asroot, injail)",
+ error, -1, EACCES);
+ if (asroot && !injail)
+ expect("priv_sched_setpriority_aproc(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sched_setpriority_aproc(!asroot, injail)",
+ error, -1, EACCES);
+ if (!asroot && !injail)
+ expect("priv_sched_setpriority_aproc(!asroot, !injail)",
+ error, -1, EACCES);
+}
- /*
- * Set up dummy process, which we will kill before exiting.
- */
- dummy_pid = fork();
- if (dummy_pid < 0)
- err(-1, "fork - dummy");
- if (dummy_pid == 0) {
- if (setresuid(UID_THIRD, UID_THIRD, UID_THIRD) < 0)
- err(-1, "setresuid(%d)", UID_THIRD);
- dummy();
- }
- sleep(1); /* Allow dummy thread to change uids. */
+void
+priv_sched_setpriority_cleanup(int asroot, int injail, struct test *test)
+{
+ pid_t pid;
- test_pid = fork();
- if (test_pid < 0) {
- warn("fork - test");
- collect(-1, dummy_pid);
- return;
+ if (childproc_running) {
+ (void)kill(childproc, SIGKILL);
+ while (1) {
+ pid = waitpid(childproc, NULL, 0);
+ if (pid == -1)
+ warn("waitpid(%d (test), NULL, 0)",
+ childproc);
+ if (pid == childproc)
+ break;
+ }
+ childproc_running = 0;
+ childproc = -1;
}
- if (test_pid == 0)
- test(dummy_pid);
-
- collect(test_pid, dummy_pid);
}
diff --git a/tools/regression/priv/priv_settimeofday.c b/tools/regression/priv/priv_settimeofday.c
index d18582f..df9300e 100644
--- a/tools/regression/priv/priv_settimeofday.c
+++ b/tools/regression/priv/priv_settimeofday.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -43,34 +44,40 @@
#include "main.h"
-void
-priv_settimeofday(void)
+static struct timeval now;
+
+int
+priv_settimeofday_setup(int asroot, int injail, struct test *test)
{
- struct timeval tv;
- int error;
- assert_root();
+ if (gettimeofday(&now, NULL) < 0) {
+ warn("priv_settimeofday_setup: gettimeofday");
+ return (-1);
+ }
+ return (0);
+}
- /*
- * Query time.
- */
- if (gettimeofday(&tv, NULL) < 0)
- err(-1, "gettimeofday");
+void
+priv_settimeofday(int asroot, int injail, struct test *test)
+{
+ int error;
- /*
- * Set with privilege.
- */
- if (settimeofday(&tv, NULL) < 0)
- err(-1, "settimeofday as root");
+ error = settimeofday(&now, NULL);
+ if (asroot && injail)
+ expect("priv_settimeofday(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_settimeofday(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_settimeofday(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_settimeofday(!asroot, !injail)", error, -1,
+ EPERM);
+}
- /*
- * Set without privilege.
- */
- set_euid(UID_OTHER);
+void
+priv_settimeofday_cleanup(int asroot, int injail, struct test *test)
+{
- error = settimeofday(&tv, NULL);
- if (error == 0)
- errx(-1, "settimeofday succeeded as !root");
- if (errno != EPERM)
- errx(-1, "settimeofday wrong errno %d as !root", errno);
}
diff --git a/tools/regression/priv/priv_sysctl_write.c b/tools/regression/priv/priv_sysctl_write.c
index becff06..25e02f9 100644
--- a/tools/regression/priv/priv_sysctl_write.c
+++ b/tools/regression/priv/priv_sysctl_write.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,9 +31,12 @@
*/
/*
- * Test that sysctls can only be written with privilege by trying first with,
- * then without privilege. Do this by first reading, then setting the
- * hostname as a no-op.
+ * Two privileges exist for writing sysctls -- one for sysctls writable only
+ * outside of jail (PRIV_SYSCTL_WRITE) and one for those also writable inside
+ * jail (PRIV_SYSCTL_WRITEJAIL).
+ *
+ * Test the prior by attempting to write to kern.domainname, and the latter
+ * by attempting to write to kern.hostname.
*/
#include <sys/types.h>
@@ -46,44 +50,79 @@
#include "main.h"
#define KERN_HOSTNAME_STRING "kern.hostname"
+#define KERN_DOMAINNAME_STRING "kern.domainname"
-void
-priv_sysctl_write(void)
+static char stored_hostname[1024];
+static char stored_domainname[1024];
+
+int
+priv_sysctl_write_setup(int asroot, int injail, struct test *test)
{
- char buffer[1024];
size_t len;
int error;
- assert_root();
-
- /*
- * First query the current value.
- */
- len = sizeof(buffer);
- error = sysctlbyname(KERN_HOSTNAME_STRING, buffer, &len, NULL, 0);
- if (error)
- err(-1, "sysctlbyname(\"%s\") query", KERN_HOSTNAME_STRING);
-
- /*
- * Now try to set with privilege.
- */
- error = sysctlbyname(KERN_HOSTNAME_STRING, NULL, NULL, buffer,
- strlen(buffer));
- if (error)
- err(-1, "sysctlbyname(\"%s\") set as root",
+ len = sizeof(stored_hostname);
+ error = sysctlbyname(KERN_HOSTNAME_STRING, stored_hostname, &len,
+ NULL, 0);
+ if (error) {
+ warn("priv_sysctl_write_setup: sysctlbyname(\"%s\")",
KERN_HOSTNAME_STRING);
+ return (-1);
+ }
- /*
- * Now without privilege.
- */
- set_euid(UID_OTHER);
+ len = sizeof(stored_hostname);
+ error = sysctlbyname(KERN_DOMAINNAME_STRING, stored_domainname, &len,
+ NULL, 0);
+ if (error) {
+ warn("priv_sysctl_write_setup: sysctlbyname(\"%s\")",
+ KERN_DOMAINNAME_STRING);
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+priv_sysctl_write(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = sysctlbyname(KERN_DOMAINNAME_STRING, NULL, NULL,
+ stored_domainname, strlen(stored_domainname));
+ if (asroot && injail)
+ expect("priv_sysctl_write(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_sysctl_write(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sysctl_write(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_sysctl_write(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_sysctl_writejail(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = sysctlbyname(KERN_HOSTNAME_STRING, NULL, NULL,
+ stored_hostname, strlen(stored_hostname));
+ if (asroot && injail)
+ expect("priv_sysctl_writejail(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_sysctl_writejail(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_sysctl_writejail(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_sysctl_writejail(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_sysctl_write_cleanup(int asroot, int injail, struct test *test)
+{
- error = sysctlbyname(KERN_HOSTNAME_STRING, NULL, NULL, buffer,
- strlen(buffer));
- if (error == 0)
- errx(-1, "sysctlbyname(\"%s\") succeeded as !root",
- KERN_HOSTNAME_STRING);
- if (errno != EPERM)
- err(-1, "sysctlbyname(\"%s\") wrong errno %d",
- KERN_HOSTNAME_STRING, errno);
}
diff --git a/tools/regression/priv/priv_vfs_admin.c b/tools/regression/priv/priv_vfs_admin.c
deleted file mode 100644
index f06e9b2..0000000
--- a/tools/regression/priv/priv_vfs_admin.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*-
- * Copyright (c) 2006 nCircle Network Security, Inc.
- * All rights reserved.
- *
- * This software was developed by Robert N. M. Watson for the TrustedBSD
- * Project under contract to nCircle Network Security, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
- * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * Check that privilege is required for a variety of administrative
- * activities on a file owned by another user. Admin privileges are required
- * for the following services:
- *
- * - Set file flags.
- * - Set utimes to non-NULL.
- * - Set file mode.
- * - Set file ownership.
- * - Remove a file from a sticky directory. (XXXRW: Not tested here.)
- * - Set the ACL on a file. (XXXRW: Not tested here.)
- * - Delete the ACL on a file. (XXXRW: Not tested here.)
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "main.h"
-
-static u_long
-getflags(char *fpathp)
-{
- struct stat sb;
-
- if (stat(fpathp, &sb) < 0)
- err(-1, "stat(%s)", fpathp);
-
- return (sb.st_flags);
-}
-
-static void
-priv_vfs_admin_chflags(void)
-{
- char fpath[1024];
- u_long flags;
- int error;
-
- /*
- * Test that setting file flags works as and not as the file owner
- * when running with privilege, but only as the file owner when
- * running without privilege.
- */
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0600);
- flags = getflags(fpath);
- flags |= UF_NODUMP;
- if (chflags(fpath, flags) < 0) {
- warn("chflags(%s, UF_NODUMP) owner as root", fpath);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- flags = getflags(fpath);
- flags |= UF_NODUMP;
- if (chflags(fpath, flags) < 0) {
- warn("chflags(%s, UF_NODUMP) !owner as root", fpath);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- flags = getflags(fpath);
- flags |= UF_NODUMP;
- set_euid(UID_OWNER);
- if (chflags(fpath, flags) < 0) {
- warn("chflags(%s, UF_NODUMP) owner as !root", fpath);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- flags = getflags(fpath);
- flags |= UF_NODUMP;
- set_euid(UID_OTHER);
- error = chflags(fpath, flags);
- if (error == 0) {
- warnx("chflags(%s, UF_NODUMP) succeeded !owner as !root",
- fpath);
- goto out;
- }
- if (errno != EPERM) {
- warn("chflags(%s, UF_NODUMP) wrong errno %d !owner a !root",
- fpath, errno);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
-out:
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
-}
-
-static void
-priv_vfs_admin_utimes(void)
-{
- struct timeval tv[2];
- char fpath[1024];
- int error;
-
- /*
- * Actual values don't matter here.
- */
- tv[0].tv_sec = 0;
- tv[0].tv_usec = 0;
- tv[1].tv_sec = 0;
- tv[1].tv_usec = 0;
-
- /*
- * When using a non-NULL argument to utimes(), must either hold
- * privilege or be the file owner. Check all four possible
- * combinations of privilege, ownership.
- */
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0600);
- if (utimes(fpath, tv) < 0) {
- warn("utimes(%s, !NULL) owner as root", fpath);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- if (utimes(fpath, tv) < 0) {
- warn("utimes(%s, !NULL) !owner as root", fpath);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OWNER);
- if (utimes(fpath, tv) < 0) {
- warn("utimes(%s, !NULL) owner as !root", fpath);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OTHER);
- error = utimes(fpath, tv);
- if (error == 0) {
- warnx("utimes(%s, !NULL) succeeded !owner as !root",
- fpath);
- goto out;
- }
- if (errno != EPERM) {
- warn("utimes(%s, !NULL) wrong errno %d !owner a !root",
- fpath, errno);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
-out:
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
-}
-
-static void
-priv_vfs_admin_chmod(void)
-{
- char fpath[1024];
- int error;
-
- /*
- * Test that setting file permissions works either as file owner or
- * not when running with privilege, but only as file owner when
- * running without privilege.
- */
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0600);
- if (chmod(fpath, 0640) < 0) {
- warn("chmod(%s, 0640) owner as root", fpath);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- if (chmod(fpath, 0640) < 0) {
- warn("chmod(%s, 0640) !owner as root", fpath);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OWNER);
- if (chmod(fpath, 0640) < 0) {
- warn("chmod(%s, 0640) owner as !root", fpath);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OTHER);
- error = chmod(fpath, 0640);
- if (error == 0) {
- warnx("chmod(%s, 0640) succeeded !owner as !root",
- fpath);
- goto out;
- }
- if (errno != EPERM) {
- warn("chmod(%s, 0640) wrong errno %d !owner a !root",
- fpath, errno);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
-out:
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
-}
-
-static const gid_t gidset[] = { GID_WHEEL, GID_OWNER, GID_OTHER};
-
-static void
-priv_vfs_admin_chown(void)
-{
- char fpath[1024];
- int error;
-
- /*
- * Test that the group of the file can only be changed with privilege
- * or as the owner. These test is run last as it frobs the group
- * context. We change the file group from one group we're in to
- * another we're in to avoid any other access control checks failing.
- */
- if (setgroups(3, gidset) < 0)
- err(-1, "priv_vfs_admin_chown:setgroups(3, {%d, %d, %d})",
- GID_WHEEL, GID_OWNER, GID_OTHER);
-
- /*
- * Test that setting file permissions works either as file owner or
- * not when running with privilege, but only as file owner when
- * running without privilege.
- */
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0600);
- if (chown(fpath, -1, GID_OWNER) < 0) {
- warn("chown(%s, %d) owner as root", fpath, GID_OWNER);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- if (chown(fpath, -1, GID_OWNER) < 0) {
- warn("chown(%s, %d) !owner as root", fpath, GID_OWNER);
- goto out;
- }
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OWNER);
- if (chown(fpath, -1, GID_OWNER) < 0) {
- warn("chown(%s, %d) owner as !root", fpath, GID_OWNER);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OTHER);
- error = chown(fpath, -1, GID_OWNER);
- if (error == 0) {
- warnx("chown(%s, %d) succeeded !owner as !root",
- fpath, GID_OWNER);
- goto out;
- }
- if (errno != EPERM) {
- warn("chown(%s, %d) wrong errno %d !owner a !root",
- fpath, GID_OWNER, errno);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
-out:
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
-}
-
-void
-priv_vfs_admin(void)
-{
-
- assert_root();
-
- priv_vfs_admin_chflags();
- priv_vfs_admin_utimes();
- priv_vfs_admin_chmod();
- priv_vfs_admin_chown(); /* Run this last. */
-}
diff --git a/tools/regression/priv/priv_vfs_chflags.c b/tools/regression/priv/priv_vfs_chflags.c
new file mode 100644
index 0000000..469b12b
--- /dev/null
+++ b/tools/regression/priv/priv_vfs_chflags.c
@@ -0,0 +1,254 @@
+/*-
+ * Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project under contract to nCircle Network Security, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Test privileges associated with setting file flags on files; whether or
+ * not it requires privilege depends on the flag, and some flags cannot be
+ * set in jail at all.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "main.h"
+
+static char fpath[1024];
+static int fpath_initialized;
+
+/*
+ * For chflags, we consider three dimmensions: process owner, file owner, and
+ * flag type. The calling framework handles variations in process owner; the
+ * rest are handled via multiple tests. One cleanup function is used.
+ */
+static u_long
+getflags(char *fpathp)
+{
+ struct stat sb;
+
+ if (stat(fpathp, &sb) < 0)
+ err(-1, "stat(%s)", fpathp);
+
+ return (sb.st_flags);
+}
+
+int
+priv_vfs_chflags_froot_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_chflags_froot_setup: fpath", fpath, UID_ROOT,
+ GID_WHEEL, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+int
+priv_vfs_chflags_fowner_setup(int asroot, int injail,
+ struct test *test)
+{
+
+ setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OWNER,
+ GID_OWNER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+int
+priv_vfs_chflags_fother_setup(int asroot, int injail,
+ struct test *test)
+{
+
+ setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OTHER,
+ GID_OTHER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+void
+priv_vfs_chflags_froot_uflags(int asroot, int injail,
+ struct test *test)
+{
+ u_long flags;
+ int error;
+
+ flags = getflags(fpath);
+ flags |= UF_NODUMP;
+ error = chflags(fpath, flags);
+ if (asroot && injail)
+ expect("priv_vfs_chflags_froot_uflags(asroot, injail)",
+ error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chflags_froot_uflags(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chflags_froot_uflags(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chflags_froot_uflags(!asroot, !injail)",
+ error, -1, EPERM);
+}
+
+void
+priv_vfs_chflags_fowner_uflags(int asroot, int injail,
+ struct test *test)
+{
+ u_long flags;
+ int error;
+
+ flags = getflags(fpath);
+ flags |= UF_NODUMP;
+ error = chflags(fpath, flags);
+ if (asroot && injail)
+ expect("priv_vfs_chflags_fowner_uflags(asroot, injail)",
+ error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chflags_fowner_uflags(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chflags_fowner_uflags(!asroot, injail)",
+ error, 0, 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_chflags_fowner_uflags(!asroot, !injail)",
+ error, 0, 0);
+}
+
+void
+priv_vfs_chflags_fother_uflags(int asroot, int injail,
+ struct test *test)
+{
+ u_long flags;
+ int error;
+
+ flags = getflags(fpath);
+ flags |= UF_NODUMP;
+ error = chflags(fpath, flags);
+ if (asroot && injail)
+ expect("priv_vfs_chflags_fother_uflags(asroot, injail)",
+ error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chflags_fother_uflags(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chflags_fother_uflags(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chflags_fother_uflags(!asroot, !injail)",
+ error, -1, EPERM);
+}
+
+void
+priv_vfs_chflags_froot_sflags(int asroot, int injail,
+ struct test *test)
+{
+ u_long flags;
+ int error;
+
+ flags = getflags(fpath);
+ flags |= SF_ARCHIVED;
+ error = chflags(fpath, flags);
+ if (asroot && injail)
+ expect("priv_vfs_chflags_froot_sflags(asroot, injail)",
+ error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_chflags_froot_sflags(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chflags_froot_sflags(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chflags_froot_sflags(!asroot, !injail)",
+ error, -1, EPERM);
+}
+
+void
+priv_vfs_chflags_fowner_sflags(int asroot, int injail,
+ struct test *test)
+{
+ u_long flags;
+ int error;
+
+ flags = getflags(fpath);
+ flags |= SF_ARCHIVED;
+ error = chflags(fpath, flags);
+ if (asroot && injail)
+ expect("priv_vfs_chflags_fowner_sflags(asroot, injail)",
+ error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_chflags_fowner_sflags(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chflags_fowner_sflags(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chflags_fowner_sflags(!asroot, !injail)",
+ error, -1, EPERM);
+}
+
+void
+priv_vfs_chflags_fother_sflags(int asroot, int injail,
+ struct test *test)
+{
+ u_long flags;
+ int error;
+
+ flags = getflags(fpath);
+ flags |= SF_ARCHIVED;
+ error = chflags(fpath, flags);
+ if (asroot && injail)
+ expect("priv_vfs_chflags_fother_sflags(asroot, injail)",
+ error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_chflags_fother_sflags(asroot, !injail)",
+ error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chflags_fother_sflags(!asroot, injail)",
+ error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chflags_fother_sflags(!asroot, !injail)",
+ error, -1, EPERM);
+}
+
+void
+priv_vfs_chflags_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)chflags(fpath, 0);
+ (void)unlink(fpath);
+ fpath_initialized = 0;
+ }
+}
diff --git a/tools/regression/priv/priv_vfs_chmod.c b/tools/regression/priv/priv_vfs_chmod.c
new file mode 100644
index 0000000..6a64871
--- /dev/null
+++ b/tools/regression/priv/priv_vfs_chmod.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project under contract to nCircle Network Security, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Check that we must either be running as root or the owner of the file in
+ * order to modify permissions on the file.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "main.h"
+
+static char fpath[1024];
+static int fpath_initialized;
+
+int
+priv_vfs_chmod_froot_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_chmod_setup: fpath", fpath, UID_ROOT, GID_WHEEL,
+ 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+int
+priv_vfs_chmod_fowner_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_chmod_setup: fpath", fpath, UID_OWNER,
+ GID_OWNER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+int
+priv_vfs_chmod_fother_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_chmod_setup: fpath", fpath, UID_OTHER,
+ GID_OTHER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+void
+priv_vfs_chmod_froot(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(fpath, 0640);
+ if (asroot && injail)
+ expect("priv_vfs_chmod_froot(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chmod_froot(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chmod_froot(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chmod_froot(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_vfs_chmod_fowner(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(fpath, 0640);
+ if (asroot && injail)
+ expect("priv_vfs_chmod_fowner(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chmod_fowner(asroot, !injail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chmod_fowner(!asroot, injail)", error, 0,
+ 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_chmod_fowner(!asroot, !injail)", error, 0,
+ 0);
+}
+
+void
+priv_vfs_chmod_fother(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(fpath, 0640);
+ if (asroot && injail)
+ expect("priv_vfs_chmod_fother(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chmod_fother(asroot, !injail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chmod_fother(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chmod_fother(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_vfs_chmod_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
+ }
+}
diff --git a/tools/regression/priv/priv_vfs_chown.c b/tools/regression/priv/priv_vfs_chown.c
index 8d72ac2..c0c10e6 100644
--- a/tools/regression/priv/priv_vfs_chown.c
+++ b/tools/regression/priv/priv_vfs_chown.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert M. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -50,121 +51,114 @@
#include "main.h"
-const gid_t gidset[] = {GID_WHEEL, GID_OWNER};
+static char fpath[1024];
+static int fpath_initialized;
+
+/*
+ * Check that changing the uid of a file requires privilege.
+ */
+int
+priv_vfs_chown_uid_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_chown_uid: fpath", fpath, UID_ROOT, GID_WHEEL,
+ 0600);
+ fpath_initialized = 1;
+ return (0);
+}
void
-priv_vfs_chown(void)
+priv_vfs_chown_uid(int asroot, int injail, struct test *test)
{
- char fpath[1024];
int error;
- assert_root();
+ error = chown(fpath, UID_OWNER, -1);
+ if (asroot && injail)
+ expect("priv_vfs_chown_uid(root, jail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chown_uid(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chown_uid(!root, jail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chown_uid(!root, !jail)", error, -1, EPERM);
+}
- /*
- * Before beginning, set up group set for process. Place in wheel
- * and owner groups; don't put in other group so that when we chown
- * to the other group, it's as a non-member.
- */
- if (setgroups(2, gidset) < 0)
- err(-1, "setgroups(2, {%d, %d})", GID_WHEEL, GID_OWNER);
+/*
+ * Check that changing the gid of a file owned by the user is allowed without
+ * privilege as long as the gid matches the process.
+ */
+int
+priv_vfs_chown_mygid_setup(int asroot, int injail, struct test *test)
+{
/*
- * In the first pass, confirm that all works as desired with
- * privilege.
- *
- * Check that chown when non-owner works fine. Do a no-op change to
- * avoid other permission checks. Note that we can't request
- * (-1, -1) and get an access control check, we have to request
- * specific uid/gid that are not the same.
+ * Create a file with a matching uid to the test process, but not a
+ * matching gid.
*/
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- if (chown(fpath, -1, GID_OWNER) < 0) {
- warn("chown(%s, -1, %d) as root", fpath, GID_OWNER);
- goto out;
- }
- (void)unlink(fpath);
+ setup_file("priv_vfs_chown_mygid: fpath", fpath, asroot ? UID_ROOT :
+ UID_OWNER, GID_OTHER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
- /*
- * Check that chown changing uid works with privilege.
- */
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- if (chown(fpath, UID_OTHER, -1) < 0) {
- warn("chown(%s, %d, -1) as root", fpath, UID_OTHER);
- goto out;
- }
- (void)unlink(fpath);
+void
+priv_vfs_chown_mygid(int asroot, int injail, struct test *test)
+{
+ int error;
- /*
- * Check that can change the file group to one we are not a member of
- * when running with privilege.
- */
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- if (chown(fpath, -1, GID_OTHER) < 0) {
- warn("chown(%s, -1, %d) as root", fpath, GID_OTHER);
- goto out;
- }
- (void)unlink(fpath);
+ error = chown(fpath, -1, asroot ? GID_WHEEL : GID_OWNER);
+ if (asroot && injail)
+ expect("priv_vfs_chown_mygid(root, jail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chown_mygid(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chown_mygid(!root, !jail)", error, 0, 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_chown_mygid(!root, !jail)", error, 0, 0);
+}
- /*
- * Now, the same again, but without privilege.
- *
- * Confirm that we can't chown a file we don't own, even as a no-op.
- */
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OTHER);
- error = chown(fpath, -1, GID_OWNER);
- if (error == 0) {
- warnx("chown(%s, -1, %d) succeeded as !root, non-owner",
- fpath, GID_OWNER);
- goto out;
- }
- if (errno != EPERM) {
- warn("chown(%s, -1, %d) wrong errno %d as !root, non-owner",
- fpath, GID_OWNER, errno);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
+/*
+ * Check that changing the gid of a file owned by the user is not allowed
+ * without privilege if the gid doesn't match the process.
+ */
+int
+priv_vfs_chown_othergid_setup(int asroot, int injail, struct test *test)
+{
/*
- * Check that we can't change the uid of the file without privilege,
- * even though we own the file.
- */
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OWNER);
- error = chown(fpath, UID_OTHER, -1);
- if (error == 0) {
- warnx("chown(%s, %d, -1) succeeded as !root", fpath,
- UID_OTHER);
- goto out;
- }
- if (errno != EPERM) {
- warn("chown(%s, %d, -1) wrong errno %d as !root", fpath,
- UID_OTHER, errno);
- goto out;
- }
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-
- /*
- * Check that can't change the file group to one we are not a member
- * of when running without privilege.
+ * Create a file with a matching uid to the test process with a
+ * matching gid.
*/
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
- set_euid(UID_OWNER);
+ setup_file("priv_vfs_chown_othergid: fpath", fpath, asroot ? UID_ROOT
+ : UID_OWNER, asroot ? GID_WHEEL : GID_OWNER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+void
+priv_vfs_chown_othergid(int asroot, int injail, struct test *test)
+{
+ int error;
+
error = chown(fpath, -1, GID_OTHER);
- if (error == 0) {
- warn("chown(%s, -1, %d) succeeded as !root", fpath, GID_OTHER);
- goto out;
- }
- if (errno != EPERM) {
- warn("chown(%s, -1, %d) wrong errno %d as !root", fpath,
- errno, GID_OTHER);
- goto out;
+ if (asroot && injail)
+ expect("priv_vfs_chown_othergid(root, jail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chown_othergid(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chown_othergid(!root, !jail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chown_othergid(!root, !jail)", error, -1,
+ EPERM);
+}
+
+void
+priv_vfs_chown_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
}
- set_euid(UID_ROOT);
- (void)unlink(fpath);
-out:
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
}
diff --git a/tools/regression/priv/priv_vfs_chroot.c b/tools/regression/priv/priv_vfs_chroot.c
index 06c36d4..4ba15e5 100644
--- a/tools/regression/priv/priv_vfs_chroot.c
+++ b/tools/regression/priv/priv_vfs_chroot.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,7 @@
*/
/*
- * Test that chroot() requires privilege; try with, and without. Do a no-op
- * chroot() to "/".
+ * Test that chroot() requires privilege--do a no-op chroot() to "/".
*
* XXXRW: Would also be good to check fchroot() permission, but that is not
* exposed via the BSD API.
@@ -43,21 +43,31 @@
#include "main.h"
+int
+priv_vfs_chroot_setup(int asroot, int injail, struct test *test)
+{
+
+ return (0);
+}
+
void
-priv_vfs_chroot(void)
+priv_vfs_chroot(int asroot, int injail, struct test *test)
{
int error;
- assert_root();
-
- if (chroot("/") < 0)
- err(-1, "chroot(\"/\") as root");
+ error = chroot("/");
+ if (asroot && injail)
+ expect("priv_vfs_chroot(asroot, injail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_chroot(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_chroot(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_chroot(!asroot, !injail)", error, -1, EPERM);
+}
- set_euid(UID_OTHER);
+void
+priv_vfs_chroot_cleanup(int asroot, int injail, struct test *test)
+{
- error = chroot("/");
- if (error == 0)
- errx(-1, "chroot(\"/\") succeeded as !root");
- if (errno != EPERM)
- err(-1, "chroot(\"/\") wrong errno %d as !root", errno);
}
diff --git a/tools/regression/priv/priv_vfs_clearsugid.c b/tools/regression/priv/priv_vfs_clearsugid.c
index a8ddcd5..b62a928 100644
--- a/tools/regression/priv/priv_vfs_clearsugid.c
+++ b/tools/regression/priv/priv_vfs_clearsugid.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -31,16 +32,21 @@
/*
* There are three cases in which the file system will clear the setuid or
- * setgid bits on a file when running as !root:
+ * setgid bits on a file when running unprivileged:
*
* - When the file is chown()'d and either of the uid or the gid is changed.
+ * (currently, only changing the file gid applies, as privilege is required
+ * to change the uid).
*
- * - The file is written to succeesfully.
+ * - The file is written to successfully.
*
* - An extended attribute of the file is written to successfully.
*
- * Test each case first as root (that flags aren't cleared), and then as
- * !root, to check they are cleared.
+ * In each case, check that the flags are cleared if unprivileged, and that
+ * they aren't cleared if privileged.
+ *
+ * We can't use expect() as we're looking for side-effects rather than
+ * success/failure of the system call.
*/
#include <sys/types.h>
@@ -55,161 +61,92 @@
#include "main.h"
-static const gid_t gidset[] = {GID_WHEEL, GID_OWNER, GID_OTHER};
+static char fpath[1024];
+static int fpath_initialized;
/*
- * Confirm that the setuid bit is set on a file. Don't return on failure.
+ * If running as root, check that SUID is still set; otherwise, check that it
+ * is not.
*/
static void
-confirm_setuid(char *fpathp, char *test_case)
+confirm_sugid(char *test_case, int asroot, int injail)
{
struct stat sb;
- if (stat(fpathp, &sb) < 0) {
- warn("%s stat(%s)", test_case, fpathp);
- (void)seteuid(UID_ROOT);
- (void)unlink(fpathp);
- exit(-1);
+ if (stat(fpath, &sb) < 0) {
+ warn("%s stat(%s)", test_case, fpath);
+ return;
}
- if (!(sb.st_mode & S_ISUID)) {
- warnx("case %s stat(%s) not setuid", test_case, fpathp);
- (void)seteuid(UID_ROOT);
- (void)unlink(fpathp);
- exit(-1);
+ if (asroot) {
+ if (!(sb.st_mode & S_ISUID))
+ warnx("%s(root, %s): !SUID", test_case, injail ?
+ "jail" : "!jail");
+ } else {
+ if (sb.st_mode & S_ISUID)
+ warnx("%s(!root, %s): SUID", test_case, injail ?
+ "jail" : "!jail");
}
}
-/*
- * Confirm that the setuid bit is not set on a file. Don't return on failure.
- */
-static void
-confirm_notsetuid(char *fpathp, char *test_case)
+int
+priv_vfs_clearsugid_setup(int asroot, int injail, struct test *test)
{
- struct stat sb;
- if (stat(fpathp, &sb) < 0) {
- warn("%s stat(%s)", test_case, fpathp);
- (void)seteuid(UID_ROOT);
- (void)unlink(fpathp);
- exit(-1);
- }
- if (sb.st_mode & S_ISUID) {
- warnx("case %s stat(%s) is setuid", test_case, fpathp);
- (void)seteuid(UID_ROOT);
- (void)unlink(fpathp);
- exit(-1);
- }
+ setup_file("priv_vfs_clearsugid_setup: fpath", fpath, UID_OWNER,
+ GID_OTHER, 0600 | S_ISUID);
+ fpath_initialized = 1;
+ return (0);
+}
+
+void
+priv_vfs_clearsugid_chgrp(int asroot, int injail, struct test *test)
+{
+
+ if (chown(fpath, -1, asroot ? GID_WHEEL : GID_OWNER) < 0)
+ err(-1, "priv_vfs_clearsugid_chgrp(%s, %s): chrgrp",
+ asroot ? "root" : "!root", injail ? "jail" : "!jail");
+ confirm_sugid("priv_vfs_clearsugid_chgrp", asroot, injail);
}
#define EA_NAMESPACE EXTATTR_NAMESPACE_USER
#define EA_NAME "clearsugid"
#define EA_DATA "test"
#define EA_SIZE (strlen(EA_DATA))
+
void
-priv_vfs_clearsugid(void)
+priv_vfs_clearsugid_extattr(int asroot, int injail, struct test *test)
{
- char ch, fpath[1024];
- int fd;
- assert_root();
-
- /*
- * Before starting on work, set up group IDs so that the process can
- * change the group ID of the file without privilege, in order to see
- * the effects. That way privilege is only required to maintain the
- * setuid bit. For the chown() test, we change only the group id, as
- * that can be done with or without privilege.
- */
- if (setgroups(3, gidset) < 0)
- err(-1, "setgroups(2, {%d, %d})", GID_WHEEL, GID_OWNER);
-
- /*
- * chown() with privilege.
- */
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0600 | S_ISUID);
- if (chown(fpath, -1, GID_OTHER) < 0)
- warn("chown(%s, -1, %d) as root", fpath, GID_OTHER);
- confirm_setuid(fpath, "chown as root");
- (void)unlink(fpath);
-
- /*
- * write() with privilege.
- */
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0600 | S_ISUID);
- fd = open(fpath, O_RDWR);
- if (fd < 0) {
- warn("open(%s) as root", fpath);
- goto out;
- }
- ch = 0;
- if (write(fd, &ch, sizeof(ch)) < 0) {
- warn("write(%s) as root", fpath);
- goto out;
- }
- close(fd);
- confirm_setuid(fpath, "write as root");
- (void)unlink(fpath);
-
- /*
- * extwrite() with privilege.
- */
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0600 | S_ISUID);
if (extattr_set_file(fpath, EA_NAMESPACE, EA_NAME, EA_DATA, EA_SIZE)
- < 0) {
- warn("extattr_set_file(%s, user, %s, %s, %d) as root",
- fpath, EA_NAME, EA_DATA, EA_SIZE);
- goto out;
- }
- confirm_setuid(fpath, "extwrite as root");
- (void)unlink(fpath);
-
- /*
- * chown() without privilege.
- */
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600 | S_ISUID);
- set_euid(UID_OWNER);
- if (chown(fpath, -1, GID_OTHER) < 0)
- warn("chown(%s, -1, %d) as !root", fpath, GID_OTHER);
- set_euid(UID_ROOT);
- confirm_notsetuid(fpath, "chown as !root");
- (void)unlink(fpath);
-
- /*
- * write() without privilege.
- */
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600 | S_ISUID);
- set_euid(UID_OWNER);
+ < 0)
+ err(-1,
+ "priv_vfs_clearsugid_extattr(%s, %s): extattr_set_file",
+ asroot ? "root" : "!root", injail ? "jail" : "!jail");
+ confirm_sugid("priv_vfs_clearsugid_extattr", asroot, injail);
+}
+
+void
+priv_vfs_clearsugid_write(int asroot, int injail, struct test *test)
+{
+ int fd;
+
fd = open(fpath, O_RDWR);
- if (fd < 0) {
- warn("open(%s) as !root", fpath);
- goto out;
- }
- ch = 0;
- if (write(fd, &ch, sizeof(ch)) < 0) {
- warn("write(%s) as !root", fpath);
- goto out;
- }
- close(fd);
- set_euid(UID_ROOT);
- confirm_notsetuid(fpath, "write as !root");
- (void)unlink(fpath);
-
- /*
- * extwrite() without privilege.
- */
- setup_file(fpath, UID_OWNER, GID_OWNER, 0600 | S_ISUID);
- set_euid(UID_OWNER);
- if (extattr_set_file(fpath, EA_NAMESPACE, EA_NAME, EA_DATA, EA_SIZE)
- < 0) {
- warn("extattr_set_file(%s, user, %s, %s, %d) as !root",
- fpath, EA_NAME, EA_DATA, EA_SIZE);
- goto out;
- }
- set_euid(UID_ROOT);
- confirm_notsetuid(fpath, "extwrite as !root");
- (void)unlink(fpath);
+ if (fd < 0)
+ err(-1, "priv_vfs_clearsugid_write(%s, %s): open",
+ asroot ? "root" : "!root", injail ? "jail" : "!jail");
+ if (write(fd, EA_DATA, EA_SIZE) < 0)
+ err(-1, "priv_vfs_clearsugid_write(%s, %s): write",
+ asroot ? "root" : "!root", injail ? "jail" : "!jail");
+ (void)close(fd);
+ confirm_sugid("priv_vfs_clearsugid_write", asroot, injail);
+}
-out:
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
+void
+priv_vfs_clearsugid_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
+ }
}
diff --git a/tools/regression/priv/priv_vfs_extattr_system.c b/tools/regression/priv/priv_vfs_extattr_system.c
index d67c550..9f8f887 100644
--- a/tools/regression/priv/priv_vfs_extattr_system.c
+++ b/tools/regression/priv/priv_vfs_extattr_system.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -49,48 +50,57 @@
#define EA_DATA "test"
#define EA_SIZE strlen(EA_DATA)
-void
-priv_vfs_extattr_system(void)
-{
- char fpath[1024];
- int error;
+static char fpath[1024];
+static int fpath_initialized;
- assert_root();
+int
+priv_vfs_extattr_system_setup(int asroot, int injail, struct test *test)
+{
/*
* Set file perms so that discretionary access control would grant
* write rights on non-system EAs on the file.
*/
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0666);
+ setup_file("priv_vfs_extattr_system_setup: fpath", fpath, UID_ROOT,
+ GID_WHEEL, 0666);
+ fpath_initialized = 1;
+ return (0);
+}
- /*
- * Try with privilege.
- */
- if (extattr_set_file(fpath, EA_NAMESPACE, EA_NAME, EA_DATA, EA_SIZE)
- < 0) {
- warn("extattr_set_file(SYSTEM, %s, %s, %d) as root",
- EA_NAME, EA_DATA, EA_SIZE);
- goto out;
- }
+void
+priv_vfs_extattr_system(int asroot, int injail, struct test *test)
+{
+ ssize_t ret;
+ int error;
- set_euid(UID_OTHER);
+ ret = extattr_set_file(fpath, EA_NAMESPACE, EA_NAME, EA_DATA,
+ EA_SIZE);
+ if (ret < 0)
+ error = -1;
+ else if (ret == EA_SIZE)
+ error = 0;
+ else
+ err(-1, "priv_vfs_extattr_system: set returned %d", ret);
+ if (asroot && injail)
+ expect("priv_vfs_extattr_system(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_extattr_system(asroot, !injail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_extattr_system(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_extattr_system(!asroot, !injail)", error,
+ -1, EPERM);
+}
- /*
- * Try without privilege.
- */
- error = extattr_set_file(fpath, EA_NAMESPACE, EA_NAME, EA_DATA,
- EA_SIZE);
- if (error == 0) {
- warn("extattr_set_file(SYSTEM, %s, %s, %d) succeeded as !root",
- EA_NAME, EA_DATA, EA_SIZE);
- goto out;
- }
- if (errno != EPERM) {
- warn("extattr_set_file(SYSTEM, %s, %s, %d) wrong errno %d "
- "as !root", EA_NAME, EA_DATA, EA_SIZE, errno);
- goto out;
+void
+priv_vfs_extattr_system_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
}
-out:
- seteuid(UID_ROOT);
- (void)unlink(fpath);
}
diff --git a/tools/regression/priv/priv_vfs_fhopen.c b/tools/regression/priv/priv_vfs_fhopen.c
index cb4006d..32b32f9 100644
--- a/tools/regression/priv/priv_vfs_fhopen.c
+++ b/tools/regression/priv/priv_vfs_fhopen.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,9 +31,8 @@
*/
/*
- * Confirm that calls to fhopen() require privilege, trying with, and
- * without. We create a temporary file and grab the file handle using
- * getfh() before starting.
+ * Confirm that calls to fhopen() require non-jailed priilege. We create a
+ * temporary file and grab the file handle using getfh() before starting.
*/
#include <sys/param.h>
@@ -45,48 +45,53 @@
#include "main.h"
-void
-priv_vfs_fhopen(void)
-{
- char fpath[1024];
- fhandle_t fh;
- int fd;
+static char fpath[1024];
+static int fpath_initialized;
+static fhandle_t fh;
- assert_root();
-
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0644);
+int
+priv_vfs_fhopen_setup(int asroot, int injail, struct test *test)
+{
+ setup_file("private_vfs_fhopen_setup: fpath", fpath, UID_ROOT,
+ GID_WHEEL, 0644);
+ fpath_initialized = 1;
if (getfh(fpath, &fh) < 0) {
- warn("getfh(%s)", fpath);
- goto out;
+ warn("priv_vfs_fhopen_setup: getfh(%s)", fpath);
+ return (-1);
}
+ return (0);
+}
- /*
- * First, try with privilege.
- */
- fd = fhopen(&fh, O_RDONLY);
- if (fd < 0) {
- warn("fhopen(%s) as root", fpath);
- goto out;
- }
- close(fd);
-
- /*
- * Now, without privilege.
- */
- set_euid(UID_OTHER);
+void
+priv_vfs_fhopen(int asroot, int injail, struct test *test)
+{
+ int errno_saved, error, fd;
fd = fhopen(&fh, O_RDONLY);
if (fd >= 0) {
- warnx("fhopen(%s) succeeded as !root", fpath);
+ error = 0;
+ errno_saved = errno;
close(fd);
- goto out;
- }
- if (errno != EPERM) {
- warn("fhopen(%s) wrong errno %d as !root", fpath, errno);
- goto out;
+ errno = errno_saved;
+ } else
+ error = -1;
+ if (asroot && injail)
+ expect("priv_vfs_fhopen(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_fhopen(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_fhopen(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_fhopen(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_vfs_fhopen_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
}
-out:
- seteuid(UID_ROOT);
- (void)unlink(fpath);
}
diff --git a/tools/regression/priv/priv_vfs_fhstat.c b/tools/regression/priv/priv_vfs_fhstat.c
index c8e58e8..18506fa 100644
--- a/tools/regression/priv/priv_vfs_fhstat.c
+++ b/tools/regression/priv/priv_vfs_fhstat.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,9 +31,8 @@
*/
/*
- * Confirm that calls to fhstat() require privilege, trying with, and
- * without. We create a temporary file and grab the file handle using
- * getfh() before starting.
+ * Confirm that calls to fhstat() require non-jailed privilege. We create a
+ * temporary file and grab the file handle using getfh() before starting.
*/
#include <sys/param.h>
@@ -45,45 +45,47 @@
#include "main.h"
-void
-priv_vfs_fhstat(void)
-{
- char fpath[1024];
- struct stat sb;
- fhandle_t fh;
- int error;
-
- assert_root();
+static char fpath[1024];
+static int fpath_initialized;
+static fhandle_t fh;
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0644);
+int
+priv_vfs_fhstat_setup(int asroot, int injail, struct test *test)
+{
+ setup_file("priv_vfs_fhstat_setup: fpath", fpath, UID_ROOT,
+ GID_WHEEL, 0644);
+ fpath_initialized = 1;
if (getfh(fpath, &fh) < 0) {
- warn("getfh(%s)", fpath);
- goto out;
+ warn("priv_vfs_fhstat_setup: getfh(%s)", fpath);
+ return (-1);
}
+ return (0);
+}
- /*
- * First, try with privilege.
- */
- if (fhstat(&fh, &sb) < 0) {
- warn("fhstat(%s) as root", fpath);
- goto out;
- }
+void
+priv_vfs_fhstat(int asroot, int injail, struct test *test)
+{
+ struct stat sb;
+ int error;
- /*
- * Now, without privilege.
- */
- set_euid(UID_OTHER);
error = fhstat(&fh, &sb);
- if (error == 0) {
- warn("fhstat(%s) succeeded as !root", fpath);
- goto out;
- }
- if (errno != EPERM) {
- warn("fhstat(%s) wrong errno %d as !root", fpath, errno);
- goto out;
+ if (asroot && injail)
+ expect("priv_vfs_fhstat(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_fhstat(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_fhstat(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_fhstat(!asroot, !injail)", error, -1, EPERM);
+}
+
+void
+priv_vfs_fhstat_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
}
-out:
- seteuid(UID_ROOT);
- (void)unlink(fpath);
}
diff --git a/tools/regression/priv/priv_vfs_fhstatfs.c b/tools/regression/priv/priv_vfs_fhstatfs.c
index 4709fe2..f814989 100644
--- a/tools/regression/priv/priv_vfs_fhstatfs.c
+++ b/tools/regression/priv/priv_vfs_fhstatfs.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,9 +31,8 @@
*/
/*
- * Confirm that calls to fhstatfs() require privilege, trying with, and
- * without. We create a temporary file and grab the file handle using
- * getfh() before starting.
+ * Confirm that calls to fhstatfs() require non-jailed privilege. We create
+ * a temporary file and grab the file handle using getfh() before starting.
*/
#include <sys/param.h>
@@ -44,46 +44,50 @@
#include "main.h"
-void
-priv_vfs_fhstatfs(void)
-{
- char fpath[1024];
- struct statfs sf;
- fhandle_t fh;
- int error;
-
- assert_root();
+static char fpath[1024];
+static int fpath_initialized;
+static fhandle_t fh;
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0644);
+int
+priv_vfs_fhstatfs_setup(int asroot, int injail, struct test *test)
+{
+ setup_file("priv_vfs_fhstatfs_setup: fpath", fpath, UID_ROOT,
+ GID_WHEEL, 0644);
+ fpath_initialized = 1;
if (getfh(fpath, &fh) < 0) {
- warn("getfh(%s)", fpath);
- goto out;
- }
-
- /*
- * First, try with privilege.
- */
- if (fhstatfs(&fh, &sf) < 0) {
- warn("fhstatfs(%s) as root", fpath);
- goto out;
+ warn("priv_vfs_fhstatfs_setup: getfh(%s)", fpath);
+ return (-1);
}
+ return (0);
+}
- /*
- * Now, without privilege.
- */
- set_euid(UID_OTHER);
+void
+priv_vfs_fhstatfs(int asroot, int injail, struct test *test)
+{
+ struct statfs sf;
+ int error;
error = fhstatfs(&fh, &sf);
- if (error == 0) {
- warnx("fhstatfs(%s) succeeded as !root", fpath);
- goto out;
- }
- if (errno != EPERM) {
- warn("fhstatfs(%s) wrong errno %d as !root", fpath, errno);
- goto out;
+ if (asroot && injail)
+ expect("priv_vfs_fhstatfs(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_fhstatfs(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_fhstatfs(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_fhstatfs(!asroot, !injail)", error, -1,
+ EPERM);
+}
+
+void
+priv_vfs_fhstatfs_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
}
-out:
- seteuid(UID_ROOT);
- (void)unlink(fpath);
}
diff --git a/tools/regression/priv/priv_vfs_generation.c b/tools/regression/priv/priv_vfs_generation.c
index 2ccca79..0ac58c5 100644
--- a/tools/regression/priv/priv_vfs_generation.c
+++ b/tools/regression/priv/priv_vfs_generation.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -33,8 +34,8 @@
* Confirm that a generation number isn't returned by stat() when not running
* with privilege. In order to differentiate between a generation of 0 and
* a generation not being returned, we have to create a temporary file known
- * to have a non-0 generation. We try up to 10 times, and then give up,
- * which is non-ideal, but better than not testing for a problem.
+ * to have a non-0 generation. We try up to MAX_TRIES times, and then give
+ * up, which is non-ideal, but better than not testing for a problem.
*/
#include <sys/stat.h>
@@ -46,68 +47,74 @@
#include "main.h"
-/*
- * Can't use setup_file() since the resulting file needs to have specific
- * properties.
- */
-void
-priv_vfs_generation(void)
+static char fpath[1024];
+static int fpath_initialized;
+
+#define MAX_TRIES 100
+
+int
+priv_vfs_generation_setup(int asroot, int injail, struct test *test)
{
- char fpath[1024] = "/tmp/priv.XXXXXXXXXX";
struct stat sb;
- int fd, i;
-
- assert_root();
+ int i;
/*
- * Create a file with a non-0 generation number. Try ten times,
- * which gives a high chance of succeeds, fail otherwise. Not ideal,
- * since we can't distinguish the file having a generation of 0 from
- * not being able to query it for access control reasons. The perils
- * of an API that changes behavior based on lack of privilege rather
- * than failing...
+ * The kernel zeros the generation number field when an unprivileged
+ * user stats a file. In order to distinguish the two cases, we
+ * therefore require a file that we know has a non-zero generation
+ * number. We try up to MAX_TRIES times and otherwise fail.
*/
- for (i = 0; i < 10; i++) {
- fd = mkstemp(fpath);
- if (fd < 0)
- err(-1, "mkstemp");
- if (fstat(fd, &sb) < 0) {
- warn("fstat(%s)", fpath);
- close(fd);
- goto out;
+ for (i = 0; i < MAX_TRIES; i++) {
+ setup_file("priv_vfs_generation_setup: fpath", fpath,
+ UID_ROOT, GID_WHEEL, 0644);
+ if (stat(fpath, &sb) < 0) {
+ warn("priv_vfs_generation_setup: fstat(%s)", fpath);
+ (void)unlink(fpath);
+ return (-1);
+ }
+ if (sb.st_gen != 0) {
+ fpath_initialized = 1;
+ return (0);
}
- if (sb.st_gen != 0)
- break;
- close(fd);
- (void)unlink(fpath);
- strcpy(fpath, "/tmp/generation.XXXXXXXXXX");
- fd = -1;
}
- if (fd == -1)
- errx(-1,
- "could not create file with non-0 generation as root");
- close(fd);
+ warnx("priv_vfs_generation_setup: unable to create gen file");
+ return (-1);
+}
- /*
- * We've already tested that fstat() works, but try stat() to be
- * consistent between privileged and unprivileged tests.
- */
- if (stat(fpath, &sb) < 0) {
- warn("stat(%s) as root", fpath);
- goto out;
- }
+void
+priv_vfs_generation(int asroot, int injail, struct test *test)
+{
+ struct stat sb;
+ int error;
- set_euid(UID_OTHER);
+ error = stat(fpath, &sb);
+ if (error < 0)
+ warn("priv_vfs_generation(asroot, injail) stat");
- if (stat(fpath, &sb) < 0) {
- warn("stat(%s) as !root", fpath);
- goto out;
- }
+ if (sb.st_gen == 0) {
+ error = -1;
+ errno = EPERM;
+ } else
+ error = 0;
+ if (asroot && injail)
+ expect("priv_vfs_generation(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_generation(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_generation(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_generation(!asroot, !injail)", error, -1,
+ EPERM);
+}
- if (sb.st_gen != 0)
- warn("stat(%s) returned generation as !root", fpath);
+void
+priv_vfs_generation_cleanup(int asroot, int injail, struct test *test)
+{
-out:
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
+ }
}
diff --git a/tools/regression/priv/priv_vfs_getfh.c b/tools/regression/priv/priv_vfs_getfh.c
index ff5d6fe..d2904df 100644
--- a/tools/regression/priv/priv_vfs_getfh.c
+++ b/tools/regression/priv/priv_vfs_getfh.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,7 @@
*/
/*
- * Check that getfh() requires privilege; run it with, and without,
- * privilege.
+ * Check that getfh() requires non-jailed privilege.
*/
#include <sys/param.h>
@@ -43,36 +43,37 @@
#include "main.h"
+static char fpath[1024];
+
+int
+priv_vfs_getfh_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_getfh_setup: fpath", fpath, UID_ROOT, GID_WHEEL,
+ 0644);
+ return (0);
+}
+
void
-priv_vfs_getfh(void)
+priv_vfs_getfh(int asroot, int injail, struct test *test)
{
- char fpath[1024];
fhandle_t fh;
int error;
- assert_root();
-
- setup_file(fpath, UID_ROOT, GID_WHEEL, 0644);
-
- if (getfh(fpath, &fh) < 0) {
- warn("getfh(%s) as root", fpath);
- goto out;
- }
-
- set_euid(UID_OTHER);
-
error = getfh(fpath, &fh);
- if (error == 0) {
- warnx("getfh(%s) succeeded as !root", fpath);
- goto out;
- }
+ if (asroot && injail)
+ expect("priv_vfs_getfh(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vfs_getfh(asroot, !injail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_getfh(!asroot, injail)", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_getfh(!asroot, !injail)", error, -1, EPERM);
+}
- if (errno != EPERM) {
- warn("getfh(%s) wrong errno %d as !root", fpath, errno);
- goto out;
- }
+void
+priv_vfs_getfh_cleanup(int asroot, int injail, struct test *test)
+{
-out:
- (void)seteuid(UID_ROOT);
(void)unlink(fpath);
}
diff --git a/tools/regression/priv/priv_vfs_read_write.c b/tools/regression/priv/priv_vfs_read_write.c
index c7f479d..5bf5a03 100644
--- a/tools/regression/priv/priv_vfs_read_write.c
+++ b/tools/regression/priv/priv_vfs_read_write.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -47,324 +48,212 @@
#include "main.h"
-struct test_arguments {
- int open_flags;
- uid_t proc_uid;
- gid_t proc_gid;
- uid_t file_uid;
- gid_t file_gid;
-};
+static char fpath_none[1024];
+static char fpath_read[1024];
+static char fpath_write[1024];
+static char fpath_readwrite[1024];
-/*
- * Rather special-purpose, don't reuse. Will need updating if anything other
- * than O_RDONLY and O_WRONLY are to be used in tests.
- */
-static const char *
-flags_to_string(int flags)
-{
-
- switch (flags) {
- case O_RDONLY:
- return ("O_RDONLY");
-
- case O_WRONLY:
- return ("O_WRONLY");
-
- default:
- return ("unknown");
- }
-}
+static int fpath_none_initialized;
+static int fpath_read_initialized;
+static int fpath_write_initialized;
+static int fpath_readwrite_initialized;
static void
-test_perm(struct test_arguments ta, mode_t file_mode, int expected)
+try_io(const char *label, const char *fpathp, int asroot, int injail,
+ int flags, int expected_error, int expected_errno)
{
- uid_t proc_uid, file_uid;
- gid_t proc_gid, file_gid;
- int fd, open_flags;
- char fpath[1024];
-
- proc_uid = ta.proc_uid;
- proc_gid = ta.proc_gid;
- file_uid = ta.file_uid;
- file_gid = ta.file_gid;
- open_flags = ta.open_flags;
-
- setup_file(fpath, file_uid, file_gid, file_mode);
- set_creds(proc_uid, proc_gid);
-
- fd = open(fpath, open_flags);
-
- if (expected == 0) {
- if (fd <= 0) {
- warn("test_perm(%s, %d, %d, %d, %d, %04o, %d) "
- "returned %d instead of %d",
- flags_to_string(open_flags), proc_uid, proc_gid,
- file_uid, file_gid, file_mode, expected,
- errno, expected);
- restore_creds();
- (void)unlink(fpath);
- exit(-1);
- }
- close(fd);
+ int fd;
+
+ fd = open(fpathp, flags);
+ if (fd < 0) {
+ if (expected_error != -1)
+ warnx("%s(%s, %s): expected (%d, %d) got (-1, %d)",
+ label, asroot ? "root" : "!root", injail ? "jail"
+ : "!jail", expected_error, expected_errno, errno);
} else {
- if (fd >= 0) {
- warnx("test_perm(%s, %d, %d, %d, %d, %04o, %d)"
- " returned 0 instead of %d",
- flags_to_string(open_flags), proc_uid, proc_gid,
- file_uid, file_gid, file_mode, expected,
- expected);
- close(fd);
- restore_creds();
- (void)unlink(fpath);
- exit(-1);
- } else if (errno != expected) {
- warn("test_perm(%s, %d, %d, %d, %d, %04o, %d)"
- " returned %d instead of %d",
- flags_to_string(open_flags), proc_uid, proc_gid,
- file_uid, file_gid, file_mode, expected,
- errno, expected);
- restore_creds();
- (void)unlink(fpath);
- exit(-1);
- }
+ if (expected_error == -1)
+ warnx("%s(%s, %s): expected (%d, %d) got 0", label,
+ asroot ? "root" : "!root", injail ? "jail" :
+ "!jail", expected_error, expected_errno);
+ (void)close(fd);
}
-
- restore_creds();
- (void)unlink(fpath);
}
-static const gid_t gidset[] = { GID_WHEEL };
-
-static void
-preamble(void)
+int
+priv_vfs_readwrite_fowner_setup(int asroot, int injail, struct test *test)
{
- if (getuid() != UID_ROOT)
- errx(-1, "must be run as root");
- if (setgroups(1, gidset) < 0)
- err(-1, "setgroups(1, {%d})", GID_WHEEL);
+ setup_file("priv_vfs_readwrite_fowner_setup: fpath_none", fpath_none,
+ asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0000);
+ fpath_none_initialized = 1;
+ setup_file("priv_vfs_readwrite_fowner_setup: fpath_read", fpath_read,
+ asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0400);
+ fpath_read_initialized = 1;
+ setup_file("priv_vfs_readwrite_fowner_setup: fpath_write",
+ fpath_write, asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0200);
+ fpath_write_initialized = 1;
+ setup_file("priv_vfs_readwrite_fowner_setup: fpath_readwrite",
+ fpath_readwrite, asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0600);
+ fpath_readwrite_initialized = 1;
+ return (0);
}
-void
-priv_vfs_read(void)
+int
+priv_vfs_readwrite_fgroup_setup(int asroot, int injail, struct test *test)
{
- struct test_arguments ta;
-
- preamble();
-
- ta.open_flags = O_RDONLY;
-
- /*
- * Privileged user and file owner. All tests should pass.
- */
- ta.proc_uid = UID_ROOT;
- ta.proc_gid = GID_WHEEL;
- ta.file_uid = UID_ROOT;
- ta.file_gid = GID_WHEEL;
-
- test_perm(ta, 0000, 0);
- test_perm(ta, 0100, 0);
- test_perm(ta, 0200, 0);
- test_perm(ta, 0300, 0);
- test_perm(ta, 0400, 0);
- test_perm(ta, 0500, 0);
- test_perm(ta, 0600, 0);
- test_perm(ta, 0700, 0);
-
- /*
- * Privileged user and file group. All tests should pass.
- */
- ta.proc_uid = UID_ROOT;
- ta.proc_gid = GID_WHEEL;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_WHEEL;
-
- test_perm(ta, 0000, 0);
- test_perm(ta, 0010, 0);
- test_perm(ta, 0020, 0);
- test_perm(ta, 0030, 0);
- test_perm(ta, 0040, 0);
- test_perm(ta, 0050, 0);
- test_perm(ta, 0060, 0);
- test_perm(ta, 0070, 0);
-
- /*
- * Privileged user and file other. All tests should pass.
- */
- ta.proc_uid = UID_ROOT;
- ta.proc_gid = GID_WHEEL;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
-
- test_perm(ta, 0000, 0);
- test_perm(ta, 0001, 0);
- test_perm(ta, 0002, 0);
- test_perm(ta, 0003, 0);
- test_perm(ta, 0004, 0);
- test_perm(ta, 0005, 0);
- test_perm(ta, 0006, 0);
- test_perm(ta, 0007, 0);
-
- /*
- * Unprivileged user and file owner. Various DAC failures.
- */
- ta.proc_uid = UID_OWNER;
- ta.proc_gid = GID_OWNER;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
- test_perm(ta, 0000, EACCES);
- test_perm(ta, 0100, EACCES);
- test_perm(ta, 0200, EACCES);
- test_perm(ta, 0300, EACCES);
- test_perm(ta, 0400, 0);
- test_perm(ta, 0500, 0);
- test_perm(ta, 0600, 0);
- test_perm(ta, 0700, 0);
-
- /*
- * Unprivileged user and file group. Various DAC failures.
- */
- ta.proc_uid = UID_OTHER;
- ta.proc_gid = GID_OWNER;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
-
- test_perm(ta, 0000, EACCES);
- test_perm(ta, 0010, EACCES);
- test_perm(ta, 0020, EACCES);
- test_perm(ta, 0030, EACCES);
- test_perm(ta, 0040, 0);
- test_perm(ta, 0050, 0);
- test_perm(ta, 0060, 0);
- test_perm(ta, 0070, 0);
+ setup_file("priv_vfs_readwrite_fgroup_setup: fpath_none", fpath_none,
+ UID_OTHER, asroot ? GID_WHEEL : GID_OWNER, 0000);
+ fpath_none_initialized = 1;
+ setup_file("priv_vfs_readwrite_fgroup_setup: fpath_read", fpath_read,
+ UID_OTHER, asroot ? GID_WHEEL : GID_OWNER, 0040);
+ fpath_read_initialized = 1;
+ setup_file("priv_vfs_readwrite_fgroup_setup: fpath_write",
+ fpath_write, UID_OTHER, asroot ? GID_WHEEL : GID_OWNER, 0020);
+ fpath_write_initialized = 1;
+ setup_file("priv_vfs_readwrite_fgroup_setup: fpath_readwrite",
+ fpath_readwrite, UID_OTHER, asroot ? GID_WHEEL : GID_OWNER,
+ 0060);
+ fpath_readwrite_initialized = 1;
+ return (0);
+}
- /*
- * Unprivileged user and file other. Various DAC failures.
- */
- ta.proc_uid = UID_OTHER;
- ta.proc_gid = GID_OTHER;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
+int
+priv_vfs_readwrite_fother_setup(int asroot, int injail, struct test *test)
+{
- test_perm(ta, 0000, EACCES);
- test_perm(ta, 0001, EACCES);
- test_perm(ta, 0002, EACCES);
- test_perm(ta, 0003, EACCES);
- test_perm(ta, 0004, 0);
- test_perm(ta, 0005, 0);
- test_perm(ta, 0006, 0);
- test_perm(ta, 0007, 0);
+ setup_file("priv_vfs_readwrite_fother_setup: fpath_none", fpath_none,
+ UID_OTHER, GID_OTHER, 0000);
+ fpath_none_initialized = 1;
+ setup_file("priv_vfs_readwrite_fother_setup: fpath_read", fpath_read,
+ UID_OTHER, GID_OTHER, 0004);
+ fpath_read_initialized = 1;
+ setup_file("priv_vfs_readwrite_fother_setup: fpath_write",
+ fpath_write, UID_OTHER, GID_OTHER, 0002);
+ fpath_write_initialized = 1;
+ setup_file("priv_vfs_readwrite_fother_setup: fpath_readwrite",
+ fpath_readwrite, UID_OTHER, GID_OTHER, 0006);
+ fpath_readwrite_initialized = 1;
+ return (0);
}
void
-priv_vfs_write(void)
+priv_vfs_readwrite_fowner(int asroot, int injail, struct test *test)
{
- struct test_arguments ta;
-
- preamble();
-
- ta.open_flags = O_WRONLY;
- /*
- * Privileged user and file owner. All tests should pass.
- */
- ta.proc_uid = UID_ROOT;
- ta.proc_gid = GID_WHEEL;
- ta.file_uid = UID_ROOT;
- ta.file_gid = GID_WHEEL;
-
- test_perm(ta, 0000, 0);
- test_perm(ta, 0100, 0);
- test_perm(ta, 0200, 0);
- test_perm(ta, 0300, 0);
- test_perm(ta, 0400, 0);
- test_perm(ta, 0500, 0);
- test_perm(ta, 0600, 0);
- test_perm(ta, 0700, 0);
-
- /*
- * Privileged user and file group. All tests should pass.
- */
- ta.proc_uid = UID_ROOT;
- ta.proc_gid = GID_WHEEL;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_WHEEL;
-
- test_perm(ta, 0000, 0);
- test_perm(ta, 0010, 0);
- test_perm(ta, 0020, 0);
- test_perm(ta, 0030, 0);
- test_perm(ta, 0040, 0);
- test_perm(ta, 0050, 0);
- test_perm(ta, 0060, 0);
- test_perm(ta, 0070, 0);
-
- /*
- * Privileged user and file other. All tests should pass.
- */
- ta.proc_uid = UID_ROOT;
- ta.proc_gid = GID_WHEEL;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
-
- test_perm(ta, 0000, 0);
- test_perm(ta, 0001, 0);
- test_perm(ta, 0002, 0);
- test_perm(ta, 0003, 0);
- test_perm(ta, 0004, 0);
- test_perm(ta, 0005, 0);
- test_perm(ta, 0006, 0);
- test_perm(ta, 0007, 0);
+ try_io("priv_vfs_readwrite_fowner(none, O_RDONLY)", fpath_none,
+ asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fowner(none, O_WRONLY)", fpath_none,
+ asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fowner(none, O_RDWR)", fpath_none,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fowner(read, O_RDONLY)", fpath_read,
+ asroot, injail, O_RDONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fowner(read, O_WRONLY)", fpath_read,
+ asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fowner(read, O_RDWR)", fpath_read,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fowner(write, O_RDONLY)", fpath_write,
+ asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fowner(write, O_WRONLY)", fpath_write,
+ asroot, injail, O_WRONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fowner(write, O_RDWR)", fpath_write,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fowner(write, O_RDONLY)", fpath_readwrite,
+ asroot, injail, O_RDONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fowner(write, O_WRONLY)", fpath_readwrite,
+ asroot, injail, O_WRONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fowner(write, O_RDWR)", fpath_readwrite,
+ asroot, injail, O_RDWR, 0, 0);
+}
- /*
- * Unprivileged user and file owner. Various DAC failures.
- */
- ta.proc_uid = UID_OWNER;
- ta.proc_gid = GID_OWNER;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
+void
+priv_vfs_readwrite_fgroup(int asroot, int injail, struct test *test)
+{
- test_perm(ta, 0000, EACCES);
- test_perm(ta, 0100, EACCES);
- test_perm(ta, 0200, 0);
- test_perm(ta, 0300, 0);
- test_perm(ta, 0400, EACCES);
- test_perm(ta, 0500, EACCES);
- test_perm(ta, 0600, 0);
- test_perm(ta, 0700, 0);
+ try_io("priv_vfs_readwrite_fgroup(none, O_RDONLY)", fpath_none,
+ asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fgroup(none, O_WRONLY)", fpath_none,
+ asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fgroup(none, O_RDWR)", fpath_none,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fgroup(read, O_RDONLY)", fpath_read,
+ asroot, injail, O_RDONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fgroup(read, O_WRONLY)", fpath_read,
+ asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fgroup(read, O_RDWR)", fpath_read,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fgroup(write, O_RDONLY)", fpath_write,
+ asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fgroup(write, O_WRONLY)", fpath_write,
+ asroot, injail, O_WRONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fgroup(write, O_RDWR)", fpath_write,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fgroup(write, O_RDONLY)", fpath_readwrite,
+ asroot, injail, O_RDONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fgroup(write, O_WRONLY)", fpath_readwrite,
+ asroot, injail, O_WRONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fgroup(write, O_RDWR)", fpath_readwrite,
+ asroot, injail, O_RDWR, 0, 0);
+}
- /*
- * Unprivileged user and file group. Various DAC failures.
- */
- ta.proc_uid = UID_OTHER;
- ta.proc_gid = GID_OWNER;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
+void
+priv_vfs_readwrite_fother(int asroot, int injail, struct test *test)
+{
- test_perm(ta, 0000, EACCES);
- test_perm(ta, 0010, EACCES);
- test_perm(ta, 0020, 0);
- test_perm(ta, 0030, 0);
- test_perm(ta, 0040, EACCES);
- test_perm(ta, 0050, EACCES);
- test_perm(ta, 0060, 0);
- test_perm(ta, 0070, 0);
+ try_io("priv_vfs_readwrite_fother(none, O_RDONLY)", fpath_none,
+ asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fother(none, O_WRONLY)", fpath_none,
+ asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fother(none, O_RDWR)", fpath_none,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fother(read, O_RDONLY)", fpath_read,
+ asroot, injail, O_RDONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fother(read, O_WRONLY)", fpath_read,
+ asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fother(read, O_RDWR)", fpath_read,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fother(write, O_RDONLY)", fpath_write,
+ asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
+ try_io("priv_vfs_readwrite_fother(write, O_WRONLY)", fpath_write,
+ asroot, injail, O_WRONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fother(write, O_RDWR)", fpath_write,
+ asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
+
+ try_io("priv_vfs_readwrite_fother(write, O_RDONLY)", fpath_readwrite,
+ asroot, injail, O_RDONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fother(write, O_WRONLY)", fpath_readwrite,
+ asroot, injail, O_WRONLY, 0, 0);
+ try_io("priv_vfs_readwrite_fother(write, O_RDWR)", fpath_readwrite,
+ asroot, injail, O_RDWR, 0, 0);
+}
- /*
- * Unprivileged user and file other. Various DAC failures.
- */
- ta.proc_uid = UID_OTHER;
- ta.proc_gid = GID_OTHER;
- ta.file_uid = UID_OWNER;
- ta.file_gid = GID_OWNER;
+void
+priv_vfs_readwrite_cleanup(int asroot, int injail, struct test *test)
+{
- test_perm(ta, 0000, EACCES);
- test_perm(ta, 0001, EACCES);
- test_perm(ta, 0002, 0);
- test_perm(ta, 0003, 0);
- test_perm(ta, 0004, EACCES);
- test_perm(ta, 0005, EACCES);
- test_perm(ta, 0006, 0);
- test_perm(ta, 0007, 0);
+ if (fpath_none_initialized) {
+ (void)unlink(fpath_none);
+ fpath_none_initialized = 0;
+ }
+ if (fpath_read_initialized) {
+ (void)unlink(fpath_read);
+ fpath_read_initialized = 0;
+ }
+ if (fpath_write_initialized) {
+ (void)unlink(fpath_write);
+ fpath_write_initialized = 0;
+ }
+ if (fpath_readwrite_initialized) {
+ (void)unlink(fpath_readwrite);
+ fpath_readwrite_initialized = 0;
+ }
}
diff --git a/tools/regression/priv/priv_vfs_setgid.c b/tools/regression/priv/priv_vfs_setgid.c
index b763ef6..62ebf8c 100644
--- a/tools/regression/priv/priv_vfs_setgid.c
+++ b/tools/regression/priv/priv_vfs_setgid.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -45,99 +46,76 @@
#include "main.h"
-static const gid_t gidset_without[] = {GID_WHEEL};
-static const gid_t gidset_with[] = {GID_WHEEL, GID_OWNER};
+static char fpath[1024];
+static int fpath_initialized;
-void
-priv_vfs_setgid(void)
+int
+priv_vfs_setgid_fowner_setup(int asroot, int injail, struct test *test)
{
- char fpath[1024];
- int error, fd;
-
- assert_root();
-
- setup_file(fpath, UID_ROOT, GID_OWNER, 0644);
-
- if (setgroups(1, gidset_without) < 0) {
- warn("setgroups(1, {%d})", gidset_without[0]);
- goto out;
- }
-
- fd = open(fpath, O_RDWR);
- if (fd < 0) {
- warn("open(%s, O_RDWR)", fpath);
- goto out;
- }
- /*
- * With privilege, set mode on file.
- */
- if (fchmod(fd, 0600 | S_ISGID) < 0) {
- warn("fchmod(%s, 0600 | S_ISGID) as root", fpath);
- goto out;
- }
-
- /*
- * Reset mode and chown file before dropping privilege.
- */
- if (fchmod(fd, 0600) < 0) {
- warn("fchmod(%s, 0600) as root", fpath);
- goto out;
- }
-
- if (fchown(fd, UID_OWNER, GID_OWNER) < 0) {
- warn("fchown(%s, %d, %d) as root", fpath, UID_OWNER,
- GID_OTHER);
- goto out;
- }
+ setup_file("priv_vfs_setgid_fowner: fpath", fpath, UID_OWNER,
+ GID_OWNER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
- /*
- * Drop privilege.
- */
- set_euid(UID_OWNER);
+int
+priv_vfs_setgid_fother_setup(int asroot, int injail, struct test *test)
+{
- /*
- * Without privilege, set mode on file.
- */
- error = fchmod(fd, 0600 | S_ISGID);
- if (error == 0) {
- warnx("fchmod(%s, 0600 | S_ISGID) succeeded as !root",
- fpath);
- goto out;
- }
- if (errno != EPERM) {
- warn("fchmod(%s, 0600 | S_ISGID) wrong errno %d as !root",
- fpath, errno);
- goto out;
- }
+ /* NOTE: owner uid, *other* gid. */
+ setup_file("priv_vfs_setgid_forther: fpath", fpath, UID_OWNER,
+ GID_OTHER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
- /*
- * Turn privilege back on so that we confirm privilege isn't required
- * if we are a group member of the file's group.
- */
- set_euid(UID_ROOT);
+void
+priv_vfs_setgid_fowner(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(fpath, 0600 | S_ISGID);
+ if (asroot && injail)
+ expect("priv_vfs_setgid_fowner(asroot, injail)", error, 0,
+ 0);
+ if (asroot && !injail)
+ expect("priv_vfs_setgid_fowner(asroot, !injail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_setgid_fowner(!asroot, injail)", error, 0,
+ 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_setgid_fowner(!asroot, !injail)", error, 0,
+ 0);
+}
- if (setgroups(2, gidset_with) < 0) {
- warn("setgroups(2, {%d, %d})", gidset_with[0],
- gidset_with[1]);
- goto out;
- }
+void
+priv_vfs_setgid_fother(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(fpath, 0600 | S_ISGID);
+ if (asroot && injail)
+ expect("priv_vfs_setgid_fother(asroot, injail)", error, 0,
+ 0);
+ if (asroot && !injail)
+ expect("priv_vfs_setgid_fother(asroot, !injail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_setgid_fother(!asroot, injail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_setgid_fother(!asroot, !injail)", error, -1,
+ EPERM);
+}
- if (seteuid(UID_OWNER) < 0) {
- warn("seteuid(%d) pass 2", UID_OWNER);
- goto out;
- }
+void
+priv_vfs_setgid_cleanup(int asroot, int injail, struct test *test)
+{
- /*
- * Without privilege, set mode on file (this time with right gid).
- */
- if (fchmod(fd, 0600 | S_ISGID) < 0) {
- warnx("fchmod(%s, 0600 | S_ISGID) pass 2 as !root", fpath);
- sleep(10);
- goto out;
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
}
-
-out:
- seteuid(UID_ROOT);
- (void)unlink(fpath);
}
diff --git a/tools/regression/priv/priv_vfs_stickyfile.c b/tools/regression/priv/priv_vfs_stickyfile.c
index 11c5d5a..5dcf350 100644
--- a/tools/regression/priv/priv_vfs_stickyfile.c
+++ b/tools/regression/priv/priv_vfs_stickyfile.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,8 @@
*/
/*
- * Check that privilege is required to set the sticky bit on a file, but not
- * a directory. Try with and without privilege.
+ * Check that privilege is required to set the sticky bit on a file but not a
+ * directory.
*/
#include <sys/stat.h>
@@ -42,99 +43,152 @@
#include "main.h"
-static void
-cleanup(const char *fpath, const char *dpath)
+char fpath[1024];
+int fpath_initialized;
+
+char dpath[1024];
+int dpath_initialized;
+
+int
+priv_vfs_stickyfile_dir_fowner_setup(int asroot, int injail,
+ struct test *test)
{
- (void)seteuid(UID_ROOT);
- (void)unlink(fpath);
- if (dpath != NULL)
- (void)rmdir(dpath);
+ setup_dir("priv_vfs_stickyfile_fowner_setup: dpath", dpath,
+ UID_OWNER, GID_OWNER, 0700);
+ dpath_initialized = 1;
+ return (0);
}
-void
-priv_vfs_stickyfile(void)
+int
+priv_vfs_stickyfile_dir_fother_setup(int asroot, int injail,
+ struct test *test)
{
- char fpath[1024] = "/tmp/stickyfile.XXXXXXXXXXX";
- char dpath[1024] = "/tmp/stickyfile.XXXXXXXXXXX", *dpathp;
- int error, fd;
- assert_root();
+ setup_dir("priv_vfs_stickyfile_fother_setup: dpath", dpath,
+ UID_OTHER, GID_OTHER, 0700);
+ dpath_initialized = 1;
+ return (0);
+}
- fd = mkstemp(fpath);
- if (fd < 0)
- err(-1, "mkstemp");
+int
+priv_vfs_stickyfile_file_fowner_setup(int asroot, int injail,
+ struct test *test)
+{
- dpathp = mkdtemp(dpath);
- if (dpathp == NULL) {
- warn("mkdtemp");
- goto out;
- }
+ setup_file("priv_vfs_stickyfile_fowner_setup: fpath", fpath,
+ UID_OWNER, GID_OWNER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
- /*
- * First, with privilege, set and clear the sticky bit on the file
- * and directory.
- */
- if (fchmod(fd, 0600 | S_ISTXT) < 0) {
- warn("fchmod(%s, 0600 | S_ISTXT) on file as root", fpath);
- goto out;
- }
+int
+priv_vfs_stickyfile_file_fother_setup(int asroot, int injail,
+ struct test *test)
+{
- if (chmod(dpathp, 0700 | S_ISTXT) < 0) {
- warn("chmod(%s, 0600 | S_ISTXT) on dir as root", dpath);
- goto out;
- }
+ setup_file("priv_vfs_stickyfile_fother_setup: fpath", fpath,
+ UID_OTHER, GID_OTHER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
- /*
- * Reset to remove sticky bit before changing credential.
- */
- if (fchmod(fd, 0600) < 0) {
- warn("fchmod(%s, 0600) on file as root", fpath);
- goto out;
- }
+void
+priv_vfs_stickyfile_dir_fowner(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(dpath, 0700 | S_ISTXT);
+ if (asroot && injail)
+ expect("priv_vfs_stickyfile_dir_fowner(root, jail)", error,
+ 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_stickyfile_dir_fowner(root, !jail)", error,
+ 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_stickyfile_dir_fowner(!root, jail)", error,
+ 0, 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_stickyfile_dir_fowner(!root, !jail)", error,
+ 0, 0);
+}
- if (chmod(dpath, 0700) < 0) {
- warn("chmod(%s, 0600) on dir as root", dpath);
- goto out;
- }
+void
+priv_vfs_stickyfile_dir_fother(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(dpath, 0700 | S_ISTXT);
+ if (asroot && injail)
+ expect("priv_vfs_stickyfile_dir_fother(root, jail)", error,
+ 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_stickyfile_dir_fother(root, !jail)", error,
+ 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_stickyfile_dir_fother(!root, jail)", error,
+ -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_stickyfile_dir_fother(!root, !jail)", error,
+ -1, EPERM);
+}
- /*
- * Chown the file and directory to target user -- we're checking for
- * the specific right to set the sticky bit, not the general right to
- * chmod().
- */
- if (fchown(fd, UID_OTHER, -1) < 0) {
- warn("fchown(%s, %d, -1)", fpath, UID_OTHER);
- goto out;
- }
+void
+priv_vfs_stickyfile_file_fowner(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(fpath, 0600 | S_ISTXT);
+ if (asroot && injail)
+ expect("priv_vfs_stickyfile_file_fowner(root, jail)", error,
+ 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_stickyfile_file_fowner(root, !jail)", error,
+ 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_stickyfile_file_fowner(!root, jail)", error,
+ -1, EFTYPE);
+ if (!asroot && !injail)
+ expect("priv_vfs_stickyfile_file_fowner(!root, !jail)", error,
+ -1, EFTYPE);
+}
- if (chown(dpath, UID_OTHER, -1) < 0) {
- warn("chown(%s, %d, -1)", fpath, UID_OTHER);
- goto out;
- }
+void
+priv_vfs_stickyfile_file_fother(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = chmod(fpath, 0600 | S_ISTXT);
+ if (asroot && injail)
+ expect("priv_vfs_stickyfile_file_fother(root, jail)", error,
+ 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_stickyfile_file_fother(root, !jail)", error,
+ 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_stickyfile_file_fother(!root, jail)", error,
+ -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_stickyfile_file_fother(!root, !jail)", error,
+ -1, EPERM);
+}
- /*
- * Change credential and try again.
- */
- set_euid(UID_OTHER);
+void
+priv_vfs_stickyfile_dir_cleanup(int asroot, int injail, struct test *test)
+{
- error = fchmod(fd, 0600 | S_ISTXT);
- if (error == 0) {
- warnx("fchmod(%s, 0600 | S_ISTXT) succeeded on file as "
- "!root", fpath);
- goto out;
- }
- if (errno != EFTYPE) {
- warn("fchmod(%s, 0600 | S_ISTXT) wrong errno %d as !root",
- fpath, errno);
- goto out;
+ if (dpath_initialized) {
+ (void)rmdir(dpath);
+ dpath_initialized = 0;
}
+}
+
+void
+priv_vfs_stickyfile_file_cleanup(int asroot, int injail, struct test *test)
+{
- if (chmod(dpathp, 0700 | S_ISTXT) < 0) {
- warn("chmod(%s, 0600 | S_ISTXT) on dir as !root", dpath);
- goto out;
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
}
-out:
- setuid(UID_ROOT);
- cleanup(fpath, dpathp);
}
diff --git a/tools/regression/priv/priv_vfs_utimes.c b/tools/regression/priv/priv_vfs_utimes.c
new file mode 100644
index 0000000..78fe691
--- /dev/null
+++ b/tools/regression/priv/priv_vfs_utimes.c
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson for the TrustedBSD
+ * Project under contract to nCircle Network Security, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
+ * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Test NULL and non-NULL tv arguments to utimes() -- if NULL, then it is
+ * allowed without privilege if the owner or if write access is held. If
+ * non-NULL, privilege is required even if writable.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "main.h"
+
+static char fpath[1024];
+static int fpath_initialized;
+
+int
+priv_vfs_utimes_froot_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_utimes_froot_setup: fpath", fpath,
+ UID_ROOT, GID_WHEEL, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+int
+priv_vfs_utimes_fowner_setup(int asroot, int injail, struct test *test)
+{
+
+ setup_file("priv_vfs_utimes_fowner_setup: fpath", fpath,
+ UID_OWNER, GID_OWNER, 0600);
+ fpath_initialized = 1;
+ return (0);
+}
+
+int
+priv_vfs_utimes_fother_setup(int asroot, int injail, struct test *test)
+{
+
+ /*
+ * In the 'other' case, we make the file writable by the test user so
+ * we can evaluate the difference between setting the time to NULL,
+ * which is possible as a writer, and non-NULL, which requires
+ * ownership.
+ */
+ setup_file("priv_vfs_utimes_fother_setup: fpath", fpath,
+ UID_OTHER, GID_OTHER, 0666);
+ fpath_initialized = 1;
+ return (0);
+}
+
+void
+priv_vfs_utimes_froot(int asroot, int injail, struct test *test)
+{
+ struct timeval tv[2];
+ int error;
+
+ tv[0].tv_sec = 0;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = 0;
+ tv[1].tv_usec = 0;
+ error = utimes(fpath, tv);
+ if (asroot && injail)
+ expect("priv_vfs_utimes_froot(root, jail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_utimes_froot(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_utimes_froot(!root, jail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_utimes_froot(!root, !jail)", error, -1,
+ EPERM);
+}
+
+void
+priv_vfs_utimes_froot_null(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = utimes(fpath, NULL);
+ if (asroot && injail)
+ expect("priv_vfs_utimes_froot_null(root, jail)", error, 0,
+ 0);
+ if (asroot && !injail)
+ expect("priv_vfs_utimes_froot_null(root, !jail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_utimes_froot_null(!root, jail)", error, -1,
+ EACCES);
+ if (!asroot && !injail)
+ expect("priv_vfs_utimes_froot_null(!root, !jail)", error, -1,
+ EACCES);
+}
+
+void
+priv_vfs_utimes_fowner(int asroot, int injail, struct test *test)
+{
+ struct timeval tv[2];
+ int error;
+
+ tv[0].tv_sec = 0;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = 0;
+ tv[1].tv_usec = 0;
+ error = utimes(fpath, tv);
+ if (asroot && injail)
+ expect("priv_vfs_utimes_fowner(root, jail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_utimes_fowner(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_utimes_fowner(!root, jail)", error, 0, 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_utimes_fowner(!root, !jail)", error, 0, 0);
+}
+
+void
+priv_vfs_utimes_fowner_null(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = utimes(fpath, NULL);
+ if (asroot && injail)
+ expect("priv_vfs_utimes_fowner_null(root, jail)", error, 0,
+ 0);
+ if (asroot && !injail)
+ expect("priv_vfs_utimes_fowner_null(root, !jail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_utimes_fowner_null(!root, jail)", error, 0,
+ 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_utimes_fowner_null(!root, !jail)", error, 0,
+ 0);
+}
+
+void
+priv_vfs_utimes_fother(int asroot, int injail, struct test *test)
+{
+ struct timeval tv[2];
+ int error;
+
+ tv[0].tv_sec = 0;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = 0;
+ tv[1].tv_usec = 0;
+ error = utimes(fpath, tv);
+ if (asroot && injail)
+ expect("priv_vfs_utimes_fother(root, jail)", error, 0, 0);
+ if (asroot && !injail)
+ expect("priv_vfs_utimes_fother(root, !jail)", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vfs_utimes_fother(!root, jail)", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vfs_utimes_fother(!root, !jail)", error, -1,
+ EPERM);
+}
+
+void
+priv_vfs_utimes_fother_null(int asroot, int injail, struct test *test)
+{
+ int error;
+
+ error = utimes(fpath, NULL);
+ if (asroot && injail)
+ expect("priv_vfs_utimes_fother_null(root, jail)", error, 0,
+ 0);
+ if (asroot && !injail)
+ expect("priv_vfs_utimes_fother_null(root, !jail)", error, 0,
+ 0);
+ if (!asroot && injail)
+ expect("priv_vfs_utimes_fother_null(!root, jail)", error, 0,
+ 0);
+ if (!asroot && !injail)
+ expect("priv_vfs_utimes_fother_null(!root, !jail)", error, 0,
+ 0);
+}
+
+void
+priv_vfs_utimes_cleanup(int asroot, int injail, struct test *test)
+{
+
+ if (fpath_initialized) {
+ (void)unlink(fpath);
+ fpath_initialized = 0;
+ }
+}
diff --git a/tools/regression/priv/priv_vm_madv_protect.c b/tools/regression/priv/priv_vm_madv_protect.c
index 737adbf..008e531 100644
--- a/tools/regression/priv/priv_vm_madv_protect.c
+++ b/tools/regression/priv/priv_vm_madv_protect.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,7 @@
*/
/*
- * Test that madvise(..., MADV_PROTECT) requires privilege by running it first
- * with privilege, then again without.
+ * Test that madvise(..., MADV_PROTECT) requires privilege.
*/
#include <sys/types.h>
@@ -43,22 +43,34 @@
#include "main.h"
+int
+priv_vm_madv_protect_setup(int asroot, int injail, struct test *test)
+{
+
+ return (0);
+}
+
void
-priv_vm_madv_protect(void)
+priv_vm_madv_protect(int asroot, int injail, struct test *test)
{
int error;
- assert_root();
-
error = madvise(NULL, 0, MADV_PROTECT);
- if (error)
- err(-1, "madvise(..., MADV_PROTECT) as root");
+ if (asroot && injail)
+ expect("priv_vm_madv_protect(asroot, injail)", error, -1,
+ EPERM);
+ if (asroot && !injail)
+ expect("priv_vm_madv_protect(asroot, !injail", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vm_madv_protect(!asroot, injail", error, -1,
+ EPERM);
+ if (!asroot && !injail)
+ expect("priv_vm_madv_protect(!asroot, !injail", error, -1,
+ EPERM);
+}
- set_euid(UID_OTHER);
+void
+priv_vm_madv_protect_cleanup(int asroot, int injail, struct test *test)
+{
- error = madvise(NULL, 0, MADV_PROTECT);
- if (error == 0)
- errx(-1, "mlock as !root succeeded");
- if (errno != EPERM)
- err(-1, "mlock as !root wrong errno %d", errno);
}
diff --git a/tools/regression/priv/priv_vm_mlock.c b/tools/regression/priv/priv_vm_mlock.c
index 3da06d3..5cdbc70 100644
--- a/tools/regression/priv/priv_vm_mlock.c
+++ b/tools/regression/priv/priv_vm_mlock.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,7 @@
*/
/*
- * Test that mlock() requires privilege by running it first with privilege,
- * then again without.
+ * Test that mlock() requires privilege.
*/
#include <sys/types.h>
@@ -43,22 +43,31 @@
#include "main.h"
+int
+priv_vm_mlock_setup(int asroot, int injail, struct test *test)
+{
+
+ return (0);
+}
+
void
-priv_vm_mlock(void)
+priv_vm_mlock(int asroot, int injail, struct test *test)
{
int error;
- assert_root();
-
error = mlock(&error, getpagesize());
- if (error)
- err(-1, "mlock as root");
+ if (asroot && injail)
+ expect("priv_vm_mlock(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vm_mlock(asroot, !injail", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vm_mlock(!asroot, injail", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vm_mlock(!asroot, !injail", error, -1, EPERM);
+}
- set_euid(UID_OTHER);
+void
+priv_vm_mlock_cleanup(int asroot, int injail, struct test *test)
+{
- error = mlock(&error, getpagesize());
- if (error == 0)
- errx(-1, "mlock as !root succeeded");
- if (errno != EPERM)
- err(-1, "mlock as !root wrong errno %d", errno);
}
diff --git a/tools/regression/priv/priv_vm_munlock.c b/tools/regression/priv/priv_vm_munlock.c
index 9e8713a..d5a474a 100644
--- a/tools/regression/priv/priv_vm_munlock.c
+++ b/tools/regression/priv/priv_vm_munlock.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006 nCircle Network Security, Inc.
+ * Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert N. M. Watson for the TrustedBSD
@@ -30,8 +31,7 @@
*/
/*
- * Test that munlock() requires privilege by running it first with privilege,
- * then again without.
+ * Test that munlock() requires privilege.
*/
#include <sys/types.h>
@@ -43,22 +43,32 @@
#include "main.h"
+int
+priv_vm_munlock_setup(int asroot, int injail, struct test *test)
+{
+
+ return (0);
+}
+
void
-priv_vm_munlock(void)
+priv_vm_munlock(int asroot, int injail, struct test *test)
{
int error;
- assert_root();
-
error = munlock(&error, getpagesize());
- if (error)
- err(-1, "munlock as root");
+ if (asroot && injail)
+ expect("priv_vm_munlock(asroot, injail)", error, -1, EPERM);
+ if (asroot && !injail)
+ expect("priv_vm_munlock(asroot, !injail", error, 0, 0);
+ if (!asroot && injail)
+ expect("priv_vm_munlock(!asroot, injail", error, -1, EPERM);
+ if (!asroot && !injail)
+ expect("priv_vm_munlock(!asroot, !injail", error, -1, EPERM);
+}
- set_euid(UID_OTHER);
- error = munlock(&error, getpagesize());
- if (error == 0)
- errx(-1, "munlock as !root succeeded");
- if (errno != EPERM)
- err(-1, "munlock as !root wrong errno %d", errno);
+void
+priv_vm_munlock_cleanup(int asroot, int injail, struct test *test)
+{
+
}
diff --git a/tools/regression/priv/test_utimes.c b/tools/regression/priv/test_utimes.c
deleted file mode 100644
index 51cef52..0000000
--- a/tools/regression/priv/test_utimes.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*-
- * Copyright (c) 2006 nCircle Network Security, Inc.
- * All rights reserved.
- *
- * This software was developed by Robert N. M. Watson for the TrustedBSD
- * Project under contract to nCircle Network Security, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
- * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * If times is NULL, ... The caller must be the owner of the file, have
- * permission to write the file, or be the super-user.
- *
- * If times is non-NULL, ... The caller must be the owner of the file or be
- * the super-user.
- *
- * To test these, create a temporary file owned by uid_owner; then run a
- * series of tests as root, owner, and other, along with various modes, to
- * see what is permitted, and if not, what error is returned.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "main.h"
-
-static int
-try_utimes(const char *path, mode_t mode, uid_t uid,
- struct timeval *timestamp, int expected)
-{
- int error;
-
- if (chmod(path, mode) < 0) {
- warn("try_utimes(%s, %d, %d, 0x%08x): chmod", path, mode, uid,
- (u_int)timestamp);
- (void)unlink(path);
- exit(-1);
- }
-
- if (seteuid(uid) < 0) {
- warn("try_utimes(%s, %d, %d, 0x%08x): seteuid(%d)", path,
- mode, uid, (u_int)timestamp, uid);
- (void)unlink(path);
- exit(-1);
- }
-
- error = utimes(path, timestamp);
-
- if (seteuid(UID_ROOT) < 0) {
- warn("try_utimes(%s, %d, %d, 0x%08x): seteuid(UID_ROOT)",
- path, mode, uid, (u_int)timestamp);
- (void)unlink(path);
- exit(-1);
- }
-
- if (expected == 0) {
- if (error != 0) {
- (void)unlink(path);
- errx(-1, "try_utimes(%s, 0%o, %d, 0x%08x) failed %d",
- path, mode, uid, (u_int)timestamp, errno);
- }
- return (0);
- }
-
- if (expected == errno)
- return (0);
-
- (void)unlink(path);
- errx(-1, "try_utimes(%s, 0%o, %d, 0x%08x) wrong err %d", path, mode,
- uid, (u_int)timestamp, errno);
-}
-
-void
-test_utimes(void)
-{
- char path[128] = "/tmp/utimes.XXXXXXXXX";
- struct timeval timestamp[2];
- int fd;
-
- if (getuid() != 0)
- errx(-1, "must be run as root");
-
- fd = mkstemp(path);
- if (fd == -1)
- err(-1, "mkstemp");
-
- if (chown(path, UID_OWNER, -1) < 0) {
- warn("chown(%s, %d)", path, UID_OWNER);
- (void)unlink(path);
- return;
- }
-
- bzero(timestamp, sizeof(timestamp));
-
- try_utimes(path, 0444, UID_ROOT, NULL, 0);
- try_utimes(path, 0444, UID_OWNER, NULL, 0);
- /* Denied by permissions. */
- try_utimes(path, 0444, UID_OTHER, NULL, EACCES);
-
- try_utimes(path, 0444, UID_ROOT, timestamp, 0);
- try_utimes(path, 0444, UID_OWNER, timestamp, 0);
- try_utimes(path, 0444, UID_OTHER, timestamp, EPERM);
-
- try_utimes(path, 0644, UID_ROOT, NULL, 0);
- try_utimes(path, 0644, UID_OWNER, NULL, 0);
- /* Denied by permissions. */
- try_utimes(path, 0644, UID_OTHER, NULL, EACCES);
-
- try_utimes(path, 0644, UID_ROOT, timestamp, 0);
- try_utimes(path, 0644, UID_OWNER, timestamp, 0);
- /* Denied as not owner. */
- try_utimes(path, 0644, UID_OTHER, timestamp, EPERM);
-
- try_utimes(path, 0666, UID_ROOT, NULL, 0);
- try_utimes(path, 0666, UID_OWNER, NULL, 0);
- try_utimes(path, 0666, UID_OTHER, NULL, 0);
-
- try_utimes(path, 0666, UID_ROOT, timestamp, 0);
- try_utimes(path, 0666, UID_OWNER, timestamp, 0);
- /* Denied as not owner. */
- try_utimes(path, 0666, UID_OTHER, timestamp, EPERM);
-
- (void)unlink(path);
-}
OpenPOWER on IntegriCloud