Index: head/stand/defaults/loader.conf =================================================================== --- head/stand/defaults/loader.conf (revision 338442) +++ head/stand/defaults/loader.conf (revision 338443) @@ -1,164 +1,169 @@ # This is loader.conf - a file full of useful variables that you can # set to change the default load behavior of your system. You should # not edit this file! Put any overrides into one of the # loader_conf_files instead and you will be able to update these # defaults later without spamming your local configuration information. # # All arguments must be in double quotes. # # $FreeBSD$ ### Basic configuration options ############################ exec="echo Loading /boot/defaults/loader.conf" kernel="kernel" # /boot sub-directory containing kernel and modules bootfile="kernel" # Kernel name (possibly absolute path) kernel_options="" # Flags to be passed to the kernel loader_conf_files="/boot/device.hints /boot/loader.conf /boot/loader.conf.local" nextboot_conf="/boot/nextboot.conf" nextboot_enable="NO" verbose_loading="NO" # Set to YES for verbose loader output ### Splash screen configuration ############################ splash_bmp_load="NO" # Set this to YES for bmp splash screen! splash_pcx_load="NO" # Set this to YES for pcx splash screen! splash_txt_load="NO" # Set this to YES for TheDraw splash screen! vesa_load="NO" # Set this to YES to load the vesa module bitmap_load="NO" # Set this to YES if you want splash screen! bitmap_name="splash.bmp" # Set this to the name of the file bitmap_type="splash_image_data" # and place it on the module_path ### Screen saver modules ################################### # This is best done in rc.conf screensave_load="NO" # Set to YES to load a screensaver module screensave_name="green_saver" # Set to the name of the screensaver module ### Random number generator configuration ################## # See rc.conf(5). The entropy_boot_file config variable must agree with the # settings below. entropy_cache_load="YES" # Set this to NO to disable loading # entropy at boot time entropy_cache_name="/boot/entropy" # Set this to the name of the file entropy_cache_type="boot_entropy_cache" # Required for the kernel to find # the boot-time entropy cache. This # must not change value even if the # _name above does change! ### RAM Blacklist configuration ############################ ram_blacklist_load="NO" # Set this to YES to load a file # containing a list of addresses to # exclude from the running system. ram_blacklist_name="/boot/blacklist.txt" # Set this to the name of the file ram_blacklist_type="ram_blacklist" # Required for the kernel to find # the blacklist module ### Microcode loading configuration ######################## cpu_microcode_load="NO" # Set this to YES to load and apply a # microcode update file during boot. cpu_microcode_name="/boot/firmware/ucode.bin" # Set this to the microcode # update file path. cpu_microcode_type="cpu_microcode" # Required for the kernel to find # the microcode update file. ### ACPI settings ########################################## acpi_dsdt_load="NO" # DSDT Overriding acpi_dsdt_type="acpi_dsdt" # Don't change this acpi_dsdt_name="/boot/acpi_dsdt.aml" # Override DSDT in BIOS by this file acpi_video_load="NO" # Load the ACPI video extension driver +### Audit settings ######################################### +audit_event_load="NO" # Preload audit_event config +audit_event_name="/etc/security/audit_event" +audit_event_type="etc_security_audit_event" + ### Initial memory disk settings ########################### #mdroot_load="YES" # The "mdroot" prefix is arbitrary. #mdroot_type="md_image" # Create md(4) disk at boot. #mdroot_name="/boot/root.img" # Path to a file containing the image. #rootdev="ufs:/dev/md0" # Set the root filesystem to md(4) device. ### Loader settings ######################################## #loader_delay="3" # Delay in seconds before loading anything. # Default is unset and disabled (no delay). #autoboot_delay="10" # Delay in seconds before autobooting, # -1 for no user interrupts, NO to disable #password="" # Prevent changes to boot options #bootlock_password="" # Prevent booting (see check-password.4th(8)) #geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root bootenv_autolist="YES" # Auto populate the list of ZFS Boot Environments #beastie_disable="NO" # Turn the beastie boot menu on and off efi_max_resolution="1x1" # Set the max resolution for EFI loader to use: # 480p, 720p, 1080p, 2160p/4k, 5k, or specify # WidthxHeight (e.g. 1920x1080) #kernels="kernel kernel.old" # Kernels to display in the boot menu #loader_logo="orbbw" # Desired logo: orbbw, orb, fbsdbw, beastiebw, beastie, none #comconsole_speed="9600" # Set the current serial console speed #console="vidconsole" # A comma separated list of console(s) #currdev="disk1s1a" # Set the current device module_path="/boot/modules;/boot/dtb;/boot/dtb/overlays" # Set the module search path #prompt="\\${interpret}" # Set the command prompt #root_disk_unit="0" # Force the root disk unit number #rootdev="disk1s1a" # Set the root filesystem #dumpdev="disk1s1b" # Set a dump device early in the boot process #tftp.blksize="1428" # Set the RFC 2348 TFTP block size. # If the TFTP server does not support RFC 2348, # the block size is set to 512. Valid: (8,9007) #twiddle_divisor="1" # >1 means slow down the progress indicator. ### Kernel settings ######################################## # The following boot_ variables are enabled by setting them to any value. # Their presence in the kernel environment (see kenv(1)) has the same # effect as setting the given boot flag (see boot(8)). #boot_askname="" # -a: Prompt the user for the name of the root device #boot_cdrom="" # -C: Attempt to mount root file system from CD-ROM #boot_ddb="" # -d: Instructs the kernel to start in the DDB debugger #boot_dfltroot="" # -r: Use the statically configured root file system #boot_gdb="" # -g: Selects gdb-remote mode for the kernel debugger #boot_multicons="" # -D: Use multiple consoles #boot_mute="" # -m: Mute the console #boot_pause="" # -p: Pause after each line during device probing #boot_serial="" # -h: Use serial console #boot_single="" # -s: Start system in single-user mode #boot_verbose="" # -v: Causes extra debugging information to be printed #init_path="/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init" # Sets the list of init candidates #init_shell="/bin/sh" # The shell binary used by init(8). #init_script="" # Initial script to run by init(8) before chrooting. #init_chroot="" # Directory for init(8) to chroot into. ### Kernel tunables ######################################## #hw.physmem="1G" # Limit physical memory. See loader(8) #kern.dfldsiz="" # Set the initial data size limit #kern.dflssiz="" # Set the initial stack size limit #kern.hz="100" # Set the kernel interval timer rate #kern.maxbcache="" # Set the max buffer cache KVA storage #kern.maxdsiz="" # Set the max data size #kern.maxfiles="" # Set the sys. wide open files limit #kern.maxproc="" # Set the maximum # of processes #kern.maxssiz="" # Set the max stack size #kern.maxswzone="" # Set the max swmeta KVA storage #kern.maxtsiz="" # Set the max text size #kern.maxusers="32" # Set size of various static tables #kern.msgbufsize="65536" # Set size of kernel message buffer #kern.nbuf="" # Set the number of buffer headers #kern.ncallout="" # Set the maximum # of timer events #kern.ngroups="1023" # Set the maximum # of supplemental groups #kern.sgrowsiz="" # Set the amount to grow stack #kern.cam.boot_delay="10000" # Delay (in ms) of root mount for CAM bus # registration, useful for USB sticks as root #kern.cam.scsi_delay="2000" # Delay (in ms) before probing SCSI #kern.ipc.maxsockets="" # Set the maximum number of sockets available #kern.ipc.nmbclusters="" # Set the number of mbuf clusters #kern.ipc.nsfbufs="" # Set the number of sendfile(2) bufs #net.inet.tcp.tcbhashsize="" # Set the value of TCBHASHSIZE #vfs.root.mountfrom="" # Specify root partition #vm.kmem_size="" # Sets the size of kernel memory (bytes) #debug.kdb.break_to_debugger="0" # Allow console to break into debugger. #debug.ktr.cpumask="0xf" # Bitmask of CPUs to enable KTR on #debug.ktr.mask="0x1200" # Bitmask of KTR events to enable #debug.ktr.verbose="1" # Enable console dump of KTR events ### Module loading syntax example ########################## #module_load="YES" # loads module "module" #module_name="realname" # uses "realname" instead of "module" #module_type="type" # passes "-t type" to load #module_flags="flags" # passes "flags" to the module #module_before="cmd" # executes "cmd" before loading the module #module_after="cmd" # executes "cmd" after loading the module #module_error="cmd" # executes "cmd" if load fails Index: head/sys/security/audit/audit_bsm_db.c =================================================================== --- head/sys/security/audit/audit_bsm_db.c (revision 338442) +++ head/sys/security/audit/audit_bsm_db.c (revision 338443) @@ -1,330 +1,405 @@ /* * Copyright (c) 1999-2009 Apple Inc. - * Copyright (c) 2005, 2016-2017 Robert N. M. Watson + * Copyright (c) 2005, 2016-2018 Robert N. M. Watson * All rights reserved. * * Portions of this software were developed by BAE Systems, the University of * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent * Computing (TC) research program. * * 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. * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Hash table functions for the audit event number to event class mask * mapping. */ #define EVCLASSMAP_HASH_TABLE_SIZE 251 struct evclass_elem { au_event_t event; au_class_t class; LIST_ENTRY(evclass_elem) entry; }; struct evclass_list { LIST_HEAD(, evclass_elem) head; }; static MALLOC_DEFINE(M_AUDITEVCLASS, "audit_evclass", "Audit event class"); static struct rwlock evclass_lock; static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE]; #define EVCLASS_LOCK_INIT() rw_init(&evclass_lock, "evclass_lock") #define EVCLASS_RLOCK() rw_rlock(&evclass_lock) #define EVCLASS_RUNLOCK() rw_runlock(&evclass_lock) #define EVCLASS_WLOCK() rw_wlock(&evclass_lock) #define EVCLASS_WUNLOCK() rw_wunlock(&evclass_lock) /* * Hash table maintaining a mapping from audit event numbers to audit event * names. For now, used only by DTrace, but present always so that userspace * tools can register and inspect fields consistently even if DTrace is not * present. * * struct evname_elem is defined in audit_private.h so that audit_dtrace.c can * use the definition. */ +#define EVNAMEMAP_HASH_TABLE_MODULE "etc_security_audit_event" #define EVNAMEMAP_HASH_TABLE_SIZE 251 struct evname_list { LIST_HEAD(, evname_elem) enl_head; }; static MALLOC_DEFINE(M_AUDITEVNAME, "audit_evname", "Audit event name"); static struct sx evnamemap_lock; static struct evname_list evnamemap_hash[EVNAMEMAP_HASH_TABLE_SIZE]; #define EVNAMEMAP_LOCK_INIT() sx_init(&evnamemap_lock, "evnamemap_lock"); #define EVNAMEMAP_RLOCK() sx_slock(&evnamemap_lock) #define EVNAMEMAP_RUNLOCK() sx_sunlock(&evnamemap_lock) #define EVNAMEMAP_WLOCK() sx_xlock(&evnamemap_lock) #define EVNAMEMAP_WUNLOCK() sx_xunlock(&evnamemap_lock) /* * Look up the class for an audit event in the class mapping table. */ au_class_t au_event_class(au_event_t event) { struct evclass_list *evcl; struct evclass_elem *evc; au_class_t class; EVCLASS_RLOCK(); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; class = 0; LIST_FOREACH(evc, &evcl->head, entry) { if (evc->event == event) { class = evc->class; goto out; } } out: EVCLASS_RUNLOCK(); return (class); } /* * Insert a event to class mapping. If the event already exists in the * mapping, then replace the mapping with the new one. * * XXX There is currently no constraints placed on the number of mappings. * May want to either limit to a number, or in terms of memory usage. */ void au_evclassmap_insert(au_event_t event, au_class_t class) { struct evclass_list *evcl; struct evclass_elem *evc, *evc_new; /* * Pessimistically, always allocate storage before acquiring mutex. * Free if there is already a mapping for this event. */ evc_new = malloc(sizeof(*evc), M_AUDITEVCLASS, M_WAITOK); EVCLASS_WLOCK(); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; LIST_FOREACH(evc, &evcl->head, entry) { if (evc->event == event) { evc->class = class; EVCLASS_WUNLOCK(); free(evc_new, M_AUDITEVCLASS); return; } } evc = evc_new; evc->event = event; evc->class = class; LIST_INSERT_HEAD(&evcl->head, evc, entry); EVCLASS_WUNLOCK(); } void au_evclassmap_init(void) { int i; EVCLASS_LOCK_INIT(); for (i = 0; i < EVCLASSMAP_HASH_TABLE_SIZE; i++) LIST_INIT(&evclass_hash[i].head); /* * Set up the initial event to class mapping for system calls. * * XXXRW: Really, this should walk all possible audit events, not all * native ABI system calls, as there may be audit events reachable * only through non-native system calls. It also seems a shame to * frob the mutex this early. */ for (i = 0; i < SYS_MAXSYSCALL; i++) { if (sysent[i].sy_auevent != AUE_NULL) au_evclassmap_insert(sysent[i].sy_auevent, 0); } } /* * Look up the name for an audit event in the event-to-name mapping table. */ int au_event_name(au_event_t event, char *name) { struct evname_list *enl; struct evname_elem *ene; int error; error = ENOENT; EVNAMEMAP_RLOCK(); enl = &evnamemap_hash[event % EVNAMEMAP_HASH_TABLE_SIZE]; LIST_FOREACH(ene, &enl->enl_head, ene_entry) { if (ene->ene_event == event) { strlcpy(name, ene->ene_name, EVNAMEMAP_NAME_SIZE); error = 0; goto out; } } out: EVNAMEMAP_RUNLOCK(); return (error); } /* * Insert a event-to-name mapping. If the event already exists in the * mapping, then replace the mapping with the new one. * * XXX There is currently no constraints placed on the number of mappings. * May want to either limit to a number, or in terms of memory usage. * * XXXRW: Accepts truncated name -- but perhaps should return failure instead? * * XXXRW: It could be we need a way to remove existing names...? * * XXXRW: We handle collisions between numbers, but I wonder if we also need a * way to handle name collisions, for DTrace, where probe names must be * unique? */ void au_evnamemap_insert(au_event_t event, const char *name) { struct evname_list *enl; struct evname_elem *ene, *ene_new; /* * Pessimistically, always allocate storage before acquiring lock. * Free if there is already a mapping for this event. */ ene_new = malloc(sizeof(*ene_new), M_AUDITEVNAME, M_WAITOK | M_ZERO); EVNAMEMAP_WLOCK(); enl = &evnamemap_hash[event % EVNAMEMAP_HASH_TABLE_SIZE]; LIST_FOREACH(ene, &enl->enl_head, ene_entry) { if (ene->ene_event == event) { EVNAME_LOCK(ene); (void)strlcpy(ene->ene_name, name, sizeof(ene->ene_name)); EVNAME_UNLOCK(ene); EVNAMEMAP_WUNLOCK(); free(ene_new, M_AUDITEVNAME); return; } } ene = ene_new; mtx_init(&ene->ene_lock, "au_evnamemap", NULL, MTX_DEF); ene->ene_event = event; (void)strlcpy(ene->ene_name, name, sizeof(ene->ene_name)); LIST_INSERT_HEAD(&enl->enl_head, ene, ene_entry); EVNAMEMAP_WUNLOCK(); } +/* + * If /etc/security/audit_event has been preloaded by the boot loader, parse + * it to build an initial set of event number<->name mappings. + */ +static void +au_evnamemap_init_preload(void) +{ + caddr_t kmdp; + char *endptr, *line, *nextline, *ptr; + const char *evnum_str, *evname; + size_t size; + long evnum; + u_int lineno; + + kmdp = preload_search_by_type(EVNAMEMAP_HASH_TABLE_MODULE); + if (kmdp == NULL) + return; + ptr = preload_fetch_addr(kmdp); + size = preload_fetch_size(kmdp); + + /* + * Parse preloaded configuration file "in place". Assume that the + * last character is a new line, meaning that we can replace it with a + * nul byte safely. We can then use strsep(3) to process the full + * buffer. + */ + ptr[size - 1] = '\0'; + + /* + * Process line by line. + */ + nextline = ptr; + lineno = 0; + while ((line = strsep(&nextline, "\n")) != NULL) { + /* + * Skip any leading white space. + */ + while (line[0] == ' ' || line[0] == '\t') + line++; + + /* + * Skip blank lines and comment lines. + */ + if (line[0] == '\0' || line[0] == '#') { + lineno++; + continue; + } + + /* + * Parse each line -- ":"-separated tuple of event number, + * event name, and other material we are less interested in. + */ + evnum_str = strsep(&line, ":"); + if (evnum_str == NULL || *evnum_str == '\0') { + printf("%s: Invalid line %u - evnum strsep\n", + __func__, lineno); + lineno++; + continue; + } + evnum = strtol(evnum_str, &endptr, 10); + if (*evnum_str == '\0' || *endptr != '\0' || + evnum <= 0 || evnum > UINT16_MAX) { + printf("%s: Invalid line %u - evnum strtol\n", + __func__, lineno); + lineno++; + continue; + } + evname = strsep(&line, ":"); + if (evname == NULL || *evname == '\0') { + printf("%s: Invalid line %u - evname strsp\n", + __func__, lineno); + lineno++; + continue; + } + au_evnamemap_insert(evnum, evname); + lineno++; + } +} + void au_evnamemap_init(void) { int i; EVNAMEMAP_LOCK_INIT(); for (i = 0; i < EVNAMEMAP_HASH_TABLE_SIZE; i++) LIST_INIT(&evnamemap_hash[i].enl_head); - - /* - * XXXRW: Unlike the event-to-class mapping, we don't attempt to - * pre-populate the list. Perhaps we should...? But not sure we - * really want to duplicate /etc/security/audit_event in the kernel - * -- and we'd need a way to remove names? - */ + au_evnamemap_init_preload(); } /* * The DTrace audit provider occasionally needs to walk the entries in the * event-to-name mapping table, and uses this public interface to do so. A * write lock is acquired so that the provider can safely update its fields in * table entries. */ void au_evnamemap_foreach(au_evnamemap_callback_t callback) { struct evname_list *enl; struct evname_elem *ene; int i; EVNAMEMAP_WLOCK(); for (i = 0; i < EVNAMEMAP_HASH_TABLE_SIZE; i++) { enl = &evnamemap_hash[i]; LIST_FOREACH(ene, &enl->enl_head, ene_entry) callback(ene); } EVNAMEMAP_WUNLOCK(); } #ifdef KDTRACE_HOOKS /* * Look up an event-to-name mapping table entry by event number. As evname * elements are stable in memory, we can return the pointer without the table * lock held -- but the caller will need to lock the element mutex before * accessing element fields. * * NB: the event identifier in elements is stable and can be read without * holding the evname_elem lock. */ struct evname_elem * au_evnamemap_lookup(au_event_t event) { struct evname_list *enl; struct evname_elem *ene; EVNAMEMAP_RLOCK(); enl = &evnamemap_hash[event % EVNAMEMAP_HASH_TABLE_SIZE]; LIST_FOREACH(ene, &enl->enl_head, ene_entry) { if (ene->ene_event == event) goto out; } ene = NULL; out: EVNAMEMAP_RUNLOCK(); return (ene); } #endif /* !KDTRACE_HOOKS */