diff options
| author | Robert Watson <rwatson@FreeBSD.org> | 2017-03-27 10:38:53 +0000 |
|---|---|---|
| committer | Robert Watson <rwatson@FreeBSD.org> | 2017-03-27 10:38:53 +0000 |
| commit | 759c8caa5a6889ee891b1072f9dd4ada7cccf913 (patch) | |
| tree | b88313a0893a47d5a3c7ce4e522a1afded8305d8 /sys | |
| parent | d9da46bf1c036565b34651b2ff624404959323a5 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/security/audit/audit_bsm.c | 7 | ||||
| -rw-r--r-- | sys/security/audit/audit_bsm_klib.c | 143 | ||||
| -rw-r--r-- | sys/security/audit/audit_private.h | 39 | ||||
| -rw-r--r-- | sys/security/audit/audit_syscalls.c | 28 |
4 files changed, 216 insertions, 1 deletions
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c index 62f4d8527b61..5920d1b19779 100644 --- a/sys/security/audit/audit_bsm.c +++ b/sys/security/audit/audit_bsm.c @@ -1,7 +1,13 @@ /* * Copyright (c) 1999-2009 Apple Inc. + * Copyright (c) 2016-2017 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: @@ -67,6 +73,7 @@ kau_init(void) { au_evclassmap_init(); + au_evnamemap_init(); } /* diff --git a/sys/security/audit/audit_bsm_klib.c b/sys/security/audit/audit_bsm_klib.c index f44fac9d26a1..915b60356750 100644 --- a/sys/security/audit/audit_bsm_klib.c +++ b/sys/security/audit/audit_bsm_klib.c @@ -1,8 +1,13 @@ /* * Copyright (c) 1999-2009 Apple Inc. - * Copyright (c) 2005 Robert N. M. Watson + * Copyright (c) 2005, 2016 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: @@ -42,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rwlock.h> #include <sys/sem.h> #include <sys/sbuf.h> +#include <sys/sx.h> #include <sys/syscall.h> #include <sys/sysctl.h> #include <sys/sysent.h> @@ -76,6 +82,30 @@ static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE]; #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_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) + struct aue_open_event { int aoe_flags; au_event_t aoe_event; @@ -222,6 +252,117 @@ au_preselect(au_event_t event, au_class_t class, au_mask_t *mask_p, int sorf) } /* + * 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(); +} + +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? + */ +} + +/* + * 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(); +} + +/* * Convert sysctl names and present arguments to events. */ au_event_t diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h index b5c373ae53ec..d4de263a625b 100644 --- a/sys/security/audit/audit_private.h +++ b/sys/security/audit/audit_private.h @@ -1,7 +1,13 @@ /*- * Copyright (c) 1999-2009 Apple Inc. + * Copyright (c) 2016-2017 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: @@ -151,6 +157,7 @@ union auditon_udata { au_stat_t au_stat; au_fstat_t au_fstat; auditinfo_addr_t au_kau_info; + au_evname_map_t au_evname; }; struct posix_ipc_perm { @@ -368,6 +375,34 @@ extern int audit_in_failure; #define AUDIT_OPEN_FLAGS (FWRITE | O_APPEND) #define AUDIT_CLOSE_FLAGS (FWRITE | O_APPEND) +/* + * Audit event-to-name mapping structure, maintained in audit_bsm_klib.c. It + * appears in this header so that the DTrace audit provider can dereference + * instances passed back in the au_evname_foreach() callbacks. Safe access to + * its fields rquires holding ene_lock (after it is visible in the global + * table). + * + * Locking: + * (c) - Constant after inserted in the global table + * (l) - Protected by ene_lock + * (m) - Protected by evnamemap_lock (audit_bsm_klib.c) + * (M) - Writes protected by evnamemap_lock; reads unprotected. + */ +struct evname_elem { + au_event_t ene_event; /* (c) */ + char ene_name[EVNAMEMAP_NAME_SIZE]; /* (l) */ + LIST_ENTRY(evname_elem) ene_entry; /* (m) */ + struct mtx ene_lock; +}; + +#define EVNAME_LOCK(ene) mtx_lock(&(ene)->ene_lock) +#define EVNAME_UNLOCK(ene) mtx_unlock(&(ene)->ene_lock) + +/* + * Callback function typedef for the same. + */ +typedef void (*au_evnamemap_callback_t)(struct evname_elem *ene); + #include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/malloc.h> @@ -387,6 +422,10 @@ int au_preselect(au_event_t event, au_class_t class, void au_evclassmap_init(void); void au_evclassmap_insert(au_event_t event, au_class_t class); au_class_t au_event_class(au_event_t event); +void au_evnamemap_init(void); +void au_evnamemap_insert(au_event_t event, const char *name); +void au_evnamemap_foreach(au_evnamemap_callback_t callback); +int au_event_name(au_event_t event, char *name); au_event_t audit_ctlname_to_sysctlevent(int name[], uint64_t valid_arg); au_event_t audit_flags_and_error_to_openevent(int oflags, int error); au_event_t audit_flags_and_error_to_openatevent(int oflags, int error); diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c index b134b0a355f3..4c656c14a068 100644 --- a/sys/security/audit/audit_syscalls.c +++ b/sys/security/audit/audit_syscalls.c @@ -1,7 +1,13 @@ /*- * Copyright (c) 1999-2009 Apple Inc. + * Copyright (c) 2016 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: @@ -195,10 +201,12 @@ sys_auditon(struct thread *td, struct auditon_args *uap) case A_SETCOND: case A_OLDSETCOND: case A_SETCLASS: + case A_SETEVENT: case A_SETPMASK: case A_SETFSIZE: case A_SETKAUDIT: case A_GETCLASS: + case A_GETEVENT: case A_GETPINFO: case A_GETPINFO_ADDR: case A_SENDTRIGGER: @@ -404,6 +412,15 @@ sys_auditon(struct thread *td, struct auditon_args *uap) udata.au_evclass.ec_number); break; + case A_GETEVENT: + if (uap->length != sizeof(udata.au_evname)) + return (EINVAL); + error = au_event_name(udata.au_evname.en_number, + udata.au_evname.en_name); + if (error != 0) + return (error); + break; + case A_SETCLASS: if (uap->length != sizeof(udata.au_evclass)) return (EINVAL); @@ -411,6 +428,17 @@ sys_auditon(struct thread *td, struct auditon_args *uap) udata.au_evclass.ec_class); break; + case A_SETEVENT: + if (uap->length != sizeof(udata.au_evname)) + return (EINVAL); + + /* Ensure nul termination from userspace. */ + udata.au_evname.en_name[sizeof(udata.au_evname.en_name) - 1] + = 0; + au_evnamemap_insert(udata.au_evname.en_number, + udata.au_evname.en_name); + break; + case A_GETPINFO: if (uap->length != sizeof(udata.au_aupinfo)) return (EINVAL); |
