summaryrefslogtreecommitdiffstats
path: root/sys/security
diff options
context:
space:
mode:
authorcsjp <csjp@FreeBSD.org>2008-11-11 21:57:03 +0000
committercsjp <csjp@FreeBSD.org>2008-11-11 21:57:03 +0000
commit91a570b2e4cb1a2f386618178e26b64c72045054 (patch)
tree2ceb633e1416058aa83b2e9857eeac5b851912fd /sys/security
parent83407db259b48d45da4d45d23fe20f2565f89a8b (diff)
downloadFreeBSD-src-91a570b2e4cb1a2f386618178e26b64c72045054.zip
FreeBSD-src-91a570b2e4cb1a2f386618178e26b64c72045054.tar.gz
Add support for extended header BSM tokens. Currently we use the
regular header tokens. The extended header tokens contain an IP or IPv6 address which makes it possible to identify which host an audit record came from when audit records are centralized. If the host information has not been specified, the system will default to the old style headers. Otherwise, audit records that are created as a result of system calls will contain host information. This implemented has been designed to be consistent with the Solaris implementation. Host information is set/retrieved using the A_GETKAUDIT and A_SETKAUDIT auditon(2) commands. These commands require that a pointer to a auditinfo_addr_t object is passed. Currently only IP and IPv6 address families are supported. The users pace bits associated with this change will follow in an openbsm import. Reviewed by: rwatson, (sson, wsalamon (older version)) MFC after: 1 month
Diffstat (limited to 'sys/security')
-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
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:
OpenPOWER on IntegriCloud