summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/bsm/audit_internal.h2
-rw-r--r--sys/bsm/audit_record.h3
-rw-r--r--sys/security/audit/audit.c43
-rw-r--r--sys/security/audit/audit.h2
-rw-r--r--sys/security/audit/audit_bsm.c25
-rw-r--r--sys/security/audit/audit_bsm_token.c45
-rw-r--r--sys/security/audit/audit_private.h1
-rw-r--r--sys/security/audit/audit_syscalls.c7
8 files changed, 124 insertions, 4 deletions
diff --git a/sys/bsm/audit_internal.h b/sys/bsm/audit_internal.h
index 2c7a1ef..19bec45 100644
--- a/sys/bsm/audit_internal.h
+++ b/sys/bsm/audit_internal.h
@@ -72,7 +72,9 @@ typedef struct au_record au_record_t;
* token structures may contain pointers of whose contents we do not know the
* size (e.g text tokens).
*/
+#define AUDIT_HEADER_EX_SIZE(a) ((a)->ai_termid.at_type+18+sizeof(u_int32_t))
#define AUDIT_HEADER_SIZE 18
+#define MAX_AUDIT_HEADER_SIZE (5*sizeof(u_int32_t)+18)
#define AUDIT_TRAILER_SIZE 7
/*
diff --git a/sys/bsm/audit_record.h b/sys/bsm/audit_record.h
index dd3ea29..4e269ea 100644
--- a/sys/bsm/audit_record.h
+++ b/sys/bsm/audit_record.h
@@ -244,10 +244,13 @@ token_t *au_to_file(char *file, struct timeval tm);
token_t *au_to_header32_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
struct timeval tm);
+token_t *au_to_header32_ex_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
+ struct timeval tm, struct auditinfo_addr *aia);
token_t *au_to_header64_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
struct timeval tm);
#if !defined(KERNEL) && !defined(_KERNEL)
token_t *au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod);
+token_t *au_to_header_ex(int rec_size, au_event_t e_type, au_emod_t e_mod);
token_t *au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod);
token_t *au_to_header64(int rec_size, au_event_t e_type, au_emod_t e_mod);
#endif
diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c
index 737c693..8680ad3 100644
--- a/sys/security/audit/audit.c
+++ b/sys/security/audit/audit.c
@@ -158,6 +158,45 @@ struct cv audit_watermark_cv;
static struct cv audit_fail_cv;
/*
+ * Kernel audit information. This will store the current audit address
+ * or host information that the kernel will use when it's generating
+ * audit records. This data is modified by the A_GET{SET}KAUDIT auditon(2)
+ * command.
+ */
+static struct auditinfo_addr audit_kinfo;
+static struct rwlock audit_kinfo_lock;
+
+#define KINFO_LOCK_INIT() rw_init(&audit_kinfo_lock, "kernel audit info lock")
+#define KINFO_RLOCK() rw_rlock(&audit_kinfo_lock)
+#define KINFO_WLOCK() rw_wlock(&audit_kinfo_lock)
+#define KINFO_RUNLOCK() rw_runlock(&audit_kinfo_lock)
+#define KINFO_WUNLOCK() rw_wunlock(&audit_kinfo_lock)
+
+void
+audit_set_kinfo(struct auditinfo_addr *ak)
+{
+
+ KASSERT(ak->ai_termid.at_type == AU_IPv4 ||
+ ak->ai_termid.at_type == AU_IPv6,
+ ("audit_set_kinfo: invalid address type"));
+ KINFO_WLOCK();
+ audit_kinfo = *ak;
+ KINFO_WUNLOCK();
+}
+
+void
+audit_get_kinfo(struct auditinfo_addr *ak)
+{
+
+ KASSERT(audit_kinfo.ai_termid.at_type == AU_IPv4 ||
+ audit_kinfo.ai_termid.at_type == AU_IPv6,
+ ("audit_set_kinfo: invalid address type"));
+ KINFO_RLOCK();
+ *ak = audit_kinfo;
+ KINFO_RUNLOCK();
+}
+
+/*
* Construct an audit record for the passed thread.
*/
static int
@@ -241,7 +280,11 @@ audit_init(void)
audit_qctrl.aq_bufsz = AQ_BUFSZ;
audit_qctrl.aq_minfree = AU_FS_MINFREE;
+ audit_kinfo.ai_termid.at_type = AU_IPv4;
+ audit_kinfo.ai_termid.at_addr[0] = INADDR_ANY;
+
mtx_init(&audit_mtx, "audit_mtx", NULL, MTX_DEF);
+ KINFO_LOCK_INIT();
cv_init(&audit_worker_cv, "audit_worker_cv");
cv_init(&audit_watermark_cv, "audit_watermark_cv");
cv_init(&audit_fail_cv, "audit_fail_cv");
diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h
index 14dbcfd..9481c14 100644
--- a/sys/security/audit/audit.h
+++ b/sys/security/audit/audit.h
@@ -180,6 +180,8 @@ void audit_cred_proc1(struct ucred *cred);
void audit_proc_coredump(struct thread *td, char *path, int errcode);
void audit_thread_alloc(struct thread *td);
void audit_thread_free(struct thread *td);
+void audit_set_kinfo(struct auditinfo_addr *);
+void audit_get_kinfo(struct auditinfo_addr *);
/*
* Define a macro to wrap the audit_arg_* calls by checking the global
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index e060727..a62f35b 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -113,13 +113,34 @@ kau_close(struct au_record *rec, struct timespec *ctime, short event)
size_t tot_rec_size;
token_t *cur, *hdr, *trail;
struct timeval tm;
+ size_t hdrsize;
+ struct auditinfo_addr ak;
+ struct in6_addr *ap;
- tot_rec_size = rec->len + AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE;
+ audit_get_kinfo(&ak);
+ hdrsize = 0;
+ switch (ak.ai_termid.at_type) {
+ case AU_IPv4:
+ hdrsize = (ak.ai_termid.at_addr[0] == INADDR_ANY) ?
+ AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&ak);
+ break;
+ case AU_IPv6:
+ ap = (struct in6_addr *)&ak.ai_termid.at_addr[0];
+ hdrsize = (IN6_IS_ADDR_UNSPECIFIED(ap)) ? AUDIT_HEADER_SIZE :
+ AUDIT_HEADER_EX_SIZE(&ak);
+ break;
+ default:
+ panic("kau_close: invalid address family");
+ }
+ tot_rec_size = rec->len + hdrsize + AUDIT_TRAILER_SIZE;
rec->data = malloc(tot_rec_size, M_AUDITBSM, M_WAITOK | M_ZERO);
tm.tv_usec = ctime->tv_nsec / 1000;
tm.tv_sec = ctime->tv_sec;
- hdr = au_to_header32_tm(tot_rec_size, event, 0, tm);
+ if (hdrsize != AUDIT_HEADER_SIZE)
+ hdr = au_to_header32_ex_tm(tot_rec_size, event, 0, tm, &ak);
+ else
+ hdr = au_to_header32_tm(tot_rec_size, event, 0, tm);
TAILQ_INSERT_HEAD(&rec->token_q, hdr, tokens);
trail = au_to_trailer(tot_rec_size);
diff --git a/sys/security/audit/audit_bsm_token.c b/sys/security/audit/audit_bsm_token.c
index b60a688..ad9ffcc 100644
--- a/sys/security/audit/audit_bsm_token.c
+++ b/sys/security/audit/audit_bsm_token.c
@@ -1292,6 +1292,51 @@ au_to_exec_env(char **envp)
/*
* token ID 1 byte
* record byte count 4 bytes
+ * version # 1 byte
+ * event type 2 bytes
+ * event modifier 2 bytes
+ * address type/length 4 bytes
+ * machine address 4 bytes/16 bytes (IPv4/IPv6 address)
+ * seconds of time 4 bytes/8 bytes (32/64-bits)
+ * milliseconds of time 4 bytes/8 bytes (32/64-bits)
+ */
+token_t *
+au_to_header32_ex_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
+ struct timeval tm, struct auditinfo_addr *aia)
+{
+ token_t *t;
+ u_char *dptr = NULL;
+ u_int32_t timems;
+ struct au_tid_addr *tid;
+
+ tid = &aia->ai_termid;
+ KASSERT(tid->at_type == AU_IPv4 || tid->at_type == AU_IPv6,
+ ("au_to_header32_ex_tm: invalid address family"));
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
+ sizeof(u_char) + 2 * sizeof(u_int16_t) + 3 * sizeof(u_int32_t) +
+ tid->at_type);
+
+ ADD_U_CHAR(dptr, AUT_HEADER32_EX);
+ ADD_U_INT32(dptr, rec_size);
+ ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
+ ADD_U_INT16(dptr, e_type);
+ ADD_U_INT16(dptr, e_mod);
+ ADD_U_INT32(dptr, tid->at_type);
+ if (tid->at_type == AU_IPv6)
+ ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
+ else
+ ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
+ timems = tm.tv_usec / 1000;
+ /* Add the timestamp */
+ ADD_U_INT32(dptr, tm.tv_sec);
+ ADD_U_INT32(dptr, timems); /* We need time in ms. */
+ return (t);
+}
+
+/*
+ * token ID 1 byte
+ * record byte count 4 bytes
* version # 1 byte [2]
* event type 2 bytes
* event modifier 2 bytes
diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h
index d0cfe94..395d8c0 100644
--- a/sys/security/audit/audit_private.h
+++ b/sys/security/audit/audit_private.h
@@ -132,6 +132,7 @@ union auditon_udata {
au_qctrl_t au_qctrl;
au_stat_t au_stat;
au_fstat_t au_fstat;
+ auditinfo_addr_t au_kau_info;
};
struct posix_ipc_perm {
diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c
index 7b7cb0e..cf88c93 100644
--- a/sys/security/audit/audit_syscalls.c
+++ b/sys/security/audit/audit_syscalls.c
@@ -395,11 +395,14 @@ auditon(struct thread *td, struct auditon_args *uap)
break;
case A_GETKAUDIT:
- return (ENOSYS);
+ audit_get_kinfo(&udata.au_kau_info);
break;
case A_SETKAUDIT:
- return (ENOSYS);
+ if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 &&
+ udata.au_kau_info.ai_termid.at_type != AU_IPv6)
+ return (EINVAL);
+ audit_set_kinfo(&udata.au_kau_info);
break;
case A_SENDTRIGGER:
OpenPOWER on IntegriCloud