aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorRobert Watson <rwatson@FreeBSD.org>2017-03-27 10:38:53 +0000
committerRobert Watson <rwatson@FreeBSD.org>2017-03-27 10:38:53 +0000
commit759c8caa5a6889ee891b1072f9dd4ada7cccf913 (patch)
treeb88313a0893a47d5a3c7ce4e522a1afded8305d8 /sys
parentd9da46bf1c036565b34651b2ff624404959323a5 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/security/audit/audit_bsm.c7
-rw-r--r--sys/security/audit/audit_bsm_klib.c143
-rw-r--r--sys/security/audit/audit_private.h39
-rw-r--r--sys/security/audit/audit_syscalls.c28
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);