From owner-svn-src-head@freebsd.org Mon Mar 27 10:38:54 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B583BCA1165; Mon, 27 Mar 2017 10:38:54 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8D658F6C; Mon, 27 Mar 2017 10:38:54 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v2RAcrVg021355; Mon, 27 Mar 2017 10:38:53 GMT (envelope-from rwatson@FreeBSD.org) Received: (from rwatson@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v2RAcr6Q021351; Mon, 27 Mar 2017 10:38:53 GMT (envelope-from rwatson@FreeBSD.org) Message-Id: <201703271038.v2RAcr6Q021351@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rwatson set sender to rwatson@FreeBSD.org using -f From: Robert Watson Date: Mon, 27 Mar 2017 10:38:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r316018 - head/sys/security/audit X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 27 Mar 2017 10:38:54 -0000 Author: rwatson Date: Mon Mar 27 10:38:53 2017 New Revision: 316018 URL: https://svnweb.freebsd.org/changeset/base/316018 Log: Introduce an audit event identifier -> audit event name mapping database in the kernel audit implementation, similar the exist class mapping database. This will be used by the DTrace audit provider to map audit event identifiers originating in the system-call table back into strings for the purposes of setting probe names. The database is initialised and maintained by auditd(8), which reads values in from the audit_events configuration file, and then manages them using the A_GETEVENT and A_SETEVENT auditon(2) operations. Obtained from: TrustedBSD Project Sponsored by: DARPA, AFRL MFC after: 3 weeks Modified: head/sys/security/audit/audit_bsm.c head/sys/security/audit/audit_bsm_klib.c head/sys/security/audit/audit_private.h head/sys/security/audit/audit_syscalls.c Modified: head/sys/security/audit/audit_bsm.c ============================================================================== --- head/sys/security/audit/audit_bsm.c Mon Mar 27 09:45:27 2017 (r316017) +++ head/sys/security/audit/audit_bsm.c Mon Mar 27 10:38:53 2017 (r316018) @@ -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(); } /* Modified: head/sys/security/audit/audit_bsm_klib.c ============================================================================== --- head/sys/security/audit/audit_bsm_klib.c Mon Mar 27 09:45:27 2017 (r316017) +++ head/sys/security/audit/audit_bsm_klib.c Mon Mar 27 10:38:53 2017 (r316018) @@ -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 #include #include +#include #include #include #include @@ -76,6 +82,30 @@ static struct evclass_list evclass_hash[ #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_ } /* + * 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 Modified: head/sys/security/audit/audit_private.h ============================================================================== --- head/sys/security/audit/audit_private.h Mon Mar 27 09:45:27 2017 (r316017) +++ head/sys/security/audit/audit_private.h Mon Mar 27 10:38:53 2017 (r316018) @@ -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 #include #include @@ -387,6 +422,10 @@ int au_preselect(au_event_t event, au_ 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); Modified: head/sys/security/audit/audit_syscalls.c ============================================================================== --- head/sys/security/audit/audit_syscalls.c Mon Mar 27 09:45:27 2017 (r316017) +++ head/sys/security/audit/audit_syscalls.c Mon Mar 27 10:38:53 2017 (r316018) @@ -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 au 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 au 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 au 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);