/*-
- * Copyright (c) 1999-2008 Apple Inc.
+ * Copyright (c) 1999-2016 Apple Inc.
* Copyright (c) 2006-2008 Robert N. M. Watson
* All rights reserved.
*
#include <kern/host.h>
#include <kern/zalloc.h>
-#include <kern/lock.h>
#include <kern/sched_prim.h>
#include <kern/task.h>
-#include <kern/wait_queue.h>
#include <net/route.h>
#define AUDIT_WORKER_SX_DESTROY() slck_destroy(&audit_worker_sl)
/*
- * The audit_draining flag is set when audit is disabled and the audit
+ * The audit_q_draining flag is set when audit is disabled and the audit
* worker queue is being drained.
*/
-static int audit_draining;
+static int audit_q_draining;
/*
* The special kernel audit record, audit_drain_kar, is used to mark the end of
*/
if (audit_qctrl.aq_minfree != 0) {
temp = mnt_stat->f_blocks / (100 / audit_qctrl.aq_minfree);
- if (mnt_stat->f_bfree < temp) {
- if (ppsratecheck(&last_lowspace_trigger,
- &cur_lowspace_trigger, 1)) {
+ if (mnt_stat->f_bfree < temp &&
+ ppsratecheck(&last_lowspace_trigger,
+ &cur_lowspace_trigger, 1))
(void)audit_send_trigger(
AUDIT_TRIGGER_LOW_SPACE);
- printf("Warning: audit space low (< %d%% free)"
- "on audit log file-system\n",
- audit_qctrl.aq_minfree);
- }
- }
}
/*
if (!(ar->k_ar_commit & AR_COMMIT_KERNEL) ||
((ar->k_ar_commit & AR_PRESELECT_PIPE) == 0 &&
- (ar->k_ar_commit & AR_PRESELECT_TRAIL) == 0))
+ (ar->k_ar_commit & AR_PRESELECT_TRAIL) == 0 &&
+ (ar->k_ar_commit & AR_PRESELECT_FILTER) == 0))
goto out;
auid = ar->k_ar.ar_subj_auid;
ar->k_ar_commit & AR_PRESELECT_TRAIL, bsm->data,
bsm->len);
+ if (ar->k_ar_commit & AR_PRESELECT_FILTER) {
+
+ /*
+ * XXXss - This needs to be generalized so new filters can
+ * be easily plugged in.
+ */
+ audit_sdev_submit(auid, ar->k_ar.ar_subj_asid, bsm->data,
+ bsm->len);
+ }
+
kau_free(bsm);
out:
if (trail_locked)
* Note: this means that the effect bound on the size of the pending record
* queue is 2x the length of the global queue.
*/
+__attribute__((noreturn))
static void
audit_worker(void)
{
struct kaudit_record *ar;
int lowater_signal;
- audit_ctx.vc_thread = current_thread();
+ if (audit_ctx.vc_thread == NULL)
+ audit_ctx.vc_thread = current_thread();
+
TAILQ_INIT(&ar_worklist);
mtx_lock(&audit_mtx);
while (1) {
* Wait for a record.
*/
while (TAILQ_EMPTY(&audit_q))
- cv_wait(&audit_worker_cv, &audit_mtx);
+ cv_wait_continuation(&audit_worker_cv, &audit_mtx,
+ (thread_continue_t)audit_worker);
/*
* If there are records in the global audit record queue,
while ((ar = TAILQ_FIRST(&ar_worklist))) {
TAILQ_REMOVE(&ar_worklist, ar, k_q);
if (ar->k_ar_commit & AR_DRAIN_QUEUE) {
- audit_draining = 0;
+ audit_q_draining = 0;
cv_broadcast(&audit_drain_cv);
} else {
audit_worker_process_record(ar);
{
kauth_cred_t old_audit_cred;
struct vnode *old_audit_vp;
- int audit_was_enabled;
KASSERT((cred != NULL && vp != NULL) || (cred == NULL && vp == NULL),
("audit_rotate_vnode: cred %p vp %p", cred, vp));
- /*
- * Rotate the vnode/cred, and clear the rotate flag so that we will
- * send a rotate trigger if the new file fills.
- */
- AUDIT_WORKER_SX_XLOCK();
- old_audit_cred = audit_ctx.vc_ucred;
- old_audit_vp = audit_vp;
- audit_ctx.vc_ucred = cred;
- audit_file_rotate_wait = 0;
- audit_was_enabled = audit_enabled;
- if ((audit_enabled = (NULL != vp)))
- audit_vp = vp;
- audit_draining = (audit_was_enabled && !audit_enabled);
- AUDIT_WORKER_SX_XUNLOCK();
- /*
- * If audit (was enabled and) is now disabled then drain the audit
- * record queue and wait until it is done.
- */
mtx_lock(&audit_mtx);
- if (audit_draining) {
+ if (audit_enabled && (NULL == vp)) {
+ /* Auditing is currently enabled but will be disabled. */
+
+ /*
+ * Disable auditing now so nothing more is added while the
+ * audit worker thread is draining the audit record queue.
+ */
+ audit_enabled = 0;
+
/*
- * Insert the special drain record in the queue.
+ * Drain the auditing queue by inserting a drain record at the
+ * end of the queue and waiting for the audit worker thread
+ * to find this record and signal that it is done before
+ * we close the audit trail.
*/
+ audit_q_draining = 1;
while (audit_q_len >= audit_qctrl.aq_hiwater)
cv_wait(&audit_watermark_cv, &audit_mtx);
TAILQ_INSERT_TAIL(&audit_q, &audit_drain_kar, k_q);
audit_q_len++;
cv_signal(&audit_worker_cv);
-
- /*
- * Wait for the audit worker thread to signal it is done.
- */
- while (audit_draining)
- cv_wait(&audit_drain_cv, &audit_mtx);
-
- audit_vp = NULL;
}
+
+ /* If the audit queue is draining then wait here until it's done. */
+ while (audit_q_draining)
+ cv_wait(&audit_drain_cv, &audit_mtx);
mtx_unlock(&audit_mtx);
+
+ /*
+ * Rotate the vnode/cred, and clear the rotate flag so that we will
+ * send a rotate trigger if the new file fills.
+ */
+ AUDIT_WORKER_SX_XLOCK();
+ old_audit_cred = audit_ctx.vc_ucred;
+ old_audit_vp = audit_vp;
+ audit_ctx.vc_ucred = cred;
+ audit_vp = vp;
+ audit_file_rotate_wait = 0;
+ audit_enabled = (audit_vp != NULL);
+ AUDIT_WORKER_SX_XUNLOCK();
+
/*
* If there was an old vnode/credential, close and free.
*/