diff options
Diffstat (limited to 'sys/security')
-rw-r--r-- | sys/security/audit/audit.c | 43 | ||||
-rw-r--r-- | sys/security/audit/audit.h | 2 | ||||
-rw-r--r-- | sys/security/audit/audit_bsm.c | 25 | ||||
-rw-r--r-- | sys/security/audit/audit_bsm_token.c | 45 | ||||
-rw-r--r-- | sys/security/audit/audit_private.h | 1 | ||||
-rw-r--r-- | sys/security/audit/audit_syscalls.c | 7 |
6 files changed, 119 insertions, 4 deletions
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: |