X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..008676633c2ad2c325837c2b64915f7ded690a8f:/bsd/security/audit/audit_worker.c diff --git a/bsd/security/audit/audit_worker.c b/bsd/security/audit/audit_worker.c index d9ef366a2..85b5c8241 100644 --- a/bsd/security/audit/audit_worker.c +++ b/bsd/security/audit/audit_worker.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999-2010 Apple Inc. + * Copyright (c) 1999-2016 Apple Inc. * Copyright (c) 2006-2008 Robert N. M. Watson * All rights reserved. * @@ -68,10 +68,8 @@ #include #include -#include #include #include -#include #include @@ -105,10 +103,10 @@ static struct vnode *audit_vp; #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 @@ -416,6 +414,7 @@ out: * 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) { @@ -460,7 +459,7 @@ audit_worker(void) 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); @@ -485,51 +484,54 @@ audit_rotate_vnode(kauth_cred_t cred, struct vnode *vp) { 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. */ + /* - * Insert the special drain record in the queue. + * Disable auditing now so nothing more is added while the + * audit worker thread is draining the audit record queue. */ + audit_enabled = 0; + + /* + * 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. */