Date: Sun, 31 May 2009 18:28:50 GMT From: Ilias Marinos <marinosi@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 163188 for review Message-ID: <200905311828.n4VISorE019427@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=163188 Change 163188 by marinosi@marinosi_redrum on 2009/05/31 18:27:53 -Towards a slice based audit system. The standard audit system is the base slice. -Slice's device skeleton moved in //sys/security/audit as rwatson suggested. NOT tested. Affected files ... .. //depot/projects/soc2009/marinosi_appaudit/src/sys/bsm/audit.h#2 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/appaudit/audit_slice_dev.c#2 delete .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/appaudit/audit_slice_private.h#2 delete .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit.c#2 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit.h#2 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_arg.c#2 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_private.h#2 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_slice.c#1 add .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_slice.h#1 add .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_syscalls.c#2 edit .. //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_worker.c#2 edit Differences ... ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/bsm/audit.h#2 (text) ==== @@ -126,6 +126,9 @@ #define A_SETQCTRL 36 #define A_GETCOND 37 #define A_SETCOND 38 +#define A_CREATESLICE 39 +#define A_UPDATESLICE 40 +#define A_REMOVESLICE 41 /* * Audit policy controls. ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit.c#2 (text) ==== @@ -70,6 +70,8 @@ #include <security/audit/audit.h> #include <security/audit/audit_private.h> +#include <security/audit/audit_slice.h> + #include <vm/uma.h> static uma_zone_t audit_record_zone; @@ -81,83 +83,10 @@ SYSCTL_NODE(_security, OID_AUTO, audit, CTLFLAG_RW, 0, "TrustedBSD audit controls"); -/* - * Audit control settings that are set/read by system calls and are hence - * non-static. - * - * Define the audit control flags. - */ -int audit_enabled; -int audit_suspended; -/* - * Flags controlling behavior in low storage situations. Should we panic if - * a write fails? Should we fail stop if we're out of disk space? - */ -int audit_panic_on_write_fail; -int audit_fail_stop; -int audit_argv; -int audit_arge; - -/* - * Are we currently "failing stop" due to out of disk space? - */ -int audit_in_failure; - -/* - * Global audit statistics. - */ -struct audit_fstat audit_fstat; - -/* - * Preselection mask for non-attributable events. - */ -struct au_mask audit_nae_mask; - +struct audit_slice base_slice; +struct audit_slice *audit_base_slice = &base_slice; /* - * Mutex to protect global variables shared between various threads and - * processes. - */ -struct mtx audit_mtx; - -/* - * Queue of audit records ready for delivery to disk. We insert new records - * at the tail, and remove records from the head. Also, a count of the - * number of records used for checking queue depth. In addition, a counter - * of records that we have allocated but are not yet in the queue, which is - * needed to estimate the total size of the combined set of records - * outstanding in the system. - */ -struct kaudit_queue audit_q; -int audit_q_len; -int audit_pre_q_len; - -/* - * Audit queue control settings (minimum free, low/high water marks, etc.) - */ -struct au_qctrl audit_qctrl; - -/* - * Condition variable to signal to the worker that it has work to do: either - * new records are in the queue, or a log replacement is taking place. - */ -struct cv audit_worker_cv; - -/* - * Condition variable to flag when crossing the low watermark, meaning that - * threads blocked due to hitting the high watermark can wake up and continue - * to commit records. - */ -struct cv audit_watermark_cv; - -/* - * Condition variable for auditing threads wait on when in fail-stop mode. - * Threads wait on this CV forever (and ever), never seeing the light of day - * again. - */ -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) @@ -261,38 +190,42 @@ * call into the BSM assembly code to initialize it. */ static void -audit_init(void) +audit_init(void *arg) { - audit_enabled = 0; - audit_suspended = 0; - audit_panic_on_write_fail = 0; - audit_fail_stop = 0; - audit_in_failure = 0; - audit_argv = 0; - audit_arge = 0; + struct audit_slice *as = (struct audit_slice *) arg; + + as->audit_enabled = 0; + as->audit_suspended = 0; + as->audit_panic_on_write_fail = 0; + as->audit_fail_stop = 0; + as->audit_in_failure = 0; + as->audit_argv = 0; + as->audit_arge = 0; + + - audit_fstat.af_filesz = 0; /* '0' means unset, unbounded. */ - audit_fstat.af_currsz = 0; - audit_nae_mask.am_success = 0; - audit_nae_mask.am_failure = 0; + as->audit_fstat.af_filesz = 0; /* '0' means unset, unbounded. */ + as->audit_fstat.af_currsz = 0; + as->audit_nae_mask.am_success = 0; + as->audit_nae_mask.am_failure = 0; - TAILQ_INIT(&audit_q); - audit_q_len = 0; - audit_pre_q_len = 0; - audit_qctrl.aq_hiwater = AQ_HIWATER; - audit_qctrl.aq_lowater = AQ_LOWATER; - audit_qctrl.aq_bufsz = AQ_BUFSZ; - audit_qctrl.aq_minfree = AU_FS_MINFREE; + TAILQ_INIT(&(as->audit_q)); + as->audit_q_len = 0; + as->audit_pre_q_len = 0; + as->audit_qctrl.aq_hiwater = AQ_HIWATER; + as->audit_qctrl.aq_lowater = AQ_LOWATER; + as->audit_qctrl.aq_bufsz = AQ_BUFSZ; + as->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); + mtx_init(&(as->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"); + cv_init(&(as->audit_worker_cv), "audit_worker_cv"); + cv_init(&(as->audit_watermark_cv), "audit_watermark_cv"); + cv_init(&(as->audit_fail_cv), "audit_fail_cv"); audit_record_zone = uma_zcreate("audit_record", sizeof(struct kaudit_record), audit_record_ctor, @@ -308,10 +241,11 @@ SHUTDOWN_PRI_FIRST); /* Start audit worker thread. */ - audit_worker_init(); + audit_worker_init(as); } -SYSINIT(audit_init, SI_SUB_AUDIT, SI_ORDER_FIRST, audit_init, NULL); +/* Init the base slice */ +SYSINIT(audit_init, SI_SUB_AUDIT, SI_ORDER_FIRST, audit_init, &audit_base_slice); /* * Drain the audit queue and close the log at shutdown. Note that this can @@ -352,9 +286,10 @@ struct kaudit_record *ar; int no_record; - mtx_lock(&audit_mtx); - no_record = (audit_suspended || !audit_enabled); - mtx_unlock(&audit_mtx); + mtx_lock(&(audit_base_slice->audit_mtx)); + no_record = (&(audit_base_slice->audit_suspended) || + !(audit_base_slice->audit_enabled)); + mtx_unlock(&(audit_base_slice->audit_mtx)); if (no_record) return (NULL); @@ -366,9 +301,9 @@ ar = uma_zalloc_arg(audit_record_zone, td, M_WAITOK); ar->k_ar.ar_event = event; - mtx_lock(&audit_mtx); - audit_pre_q_len++; - mtx_unlock(&audit_mtx); + mtx_lock(&(audit_base_slice->audit_mtx)); + audit_base_slice->audit_pre_q_len++; + mtx_unlock(&(audit_base_slice->audit_mtx)); return (ar); } @@ -397,7 +332,7 @@ * value from the system call and using the appropriate audit mask. */ if (ar->k_ar.ar_subj_auid == AU_DEFAUDITID) - aumask = &audit_nae_mask; + aumask = &(audit_base_slice->audit_nae_mask); else aumask = &ar->k_ar.ar_subj_amask; @@ -440,9 +375,9 @@ ar->k_ar_commit |= AR_PRESELECT_PIPE; if ((ar->k_ar_commit & (AR_PRESELECT_TRAIL | AR_PRESELECT_PIPE | AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE)) == 0) { - mtx_lock(&audit_mtx); - audit_pre_q_len--; - mtx_unlock(&audit_mtx); + mtx_lock(&(audit_base_slice->audit_mtx)); + audit_base_slice->audit_pre_q_len--; + mtx_unlock(&(audit_base_slice->audit_mtx)); audit_free(ar); return; } @@ -455,10 +390,11 @@ * Note: it could be that some records initiated while audit was * enabled should still be committed? */ - mtx_lock(&audit_mtx); - if (audit_suspended || !audit_enabled) { - audit_pre_q_len--; - mtx_unlock(&audit_mtx); + mtx_lock(&(audit_base_slice->audit_mtx)); + if (audit_base_slice->audit_suspended + || !audit_base_slice->audit_enabled) { + audit_base_slice->audit_pre_q_len--; + mtx_unlock(&(audit_base_slice->audit_mtx)); audit_free(ar); return; } @@ -467,14 +403,16 @@ * Constrain the number of committed audit records based on the * configurable parameter. */ - while (audit_q_len >= audit_qctrl.aq_hiwater) - cv_wait(&audit_watermark_cv, &audit_mtx); + while (audit_base_slice->audit_q_len >= + audit_base_slice->audit_qctrl.aq_hiwater) + cv_wait(&(audit_base_slice->audit_watermark_cv), + &(audit_base_slice->audit_mtx)); - TAILQ_INSERT_TAIL(&audit_q, ar, k_q); - audit_q_len++; - audit_pre_q_len--; - cv_signal(&audit_worker_cv); - mtx_unlock(&audit_mtx); + TAILQ_INSERT_TAIL(&(audit_base_slice->audit_q), ar, k_q); + audit_base_slice->audit_q_len++; + audit_base_slice->audit_pre_q_len--; + cv_signal(&(audit_base_slice->audit_worker_cv)); + mtx_unlock(&(audit_base_slice->audit_mtx)); } /* @@ -516,7 +454,7 @@ */ auid = td->td_ucred->cr_audit.ai_auid; if (auid == AU_DEFAUDITID) - aumask = &audit_nae_mask; + aumask = &(audit_base_slice->audit_nae_mask); else aumask = &td->td_ucred->cr_audit.ai_mask; @@ -538,9 +476,10 @@ * audit record is still required for this event by * re-calling au_preselect(). */ - if (audit_in_failure && + if (audit_base_slice->audit_in_failure && priv_check(td, PRIV_AUDIT_FAILSTOP) != 0) { - cv_wait(&audit_fail_cv, &audit_mtx); + cv_wait(&(audit_base_slice->audit_fail_cv), + &(audit_base_slice->audit_mtx)); panic("audit_failing_stop: thread continued"); } td->td_ar = audit_new(event, td); @@ -656,7 +595,7 @@ cred = td->td_ucred; auid = cred->cr_audit.ai_auid; if (auid == AU_DEFAUDITID) - aumask = &audit_nae_mask; + aumask = &(audit_base_slice->audit_nae_mask); else aumask = &cred->cr_audit.ai_mask; /* ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit.h#2 (text) ==== @@ -191,7 +191,7 @@ } while (0) #define AUDIT_SYSCALL_ENTER(code, td) do { \ - if (audit_enabled) { \ + if (audit_base_slice->audit_enabled) { \ audit_syscall_enter(code, td); \ } \ } while (0) ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_arg.c#2 (text) ==== @@ -50,6 +50,8 @@ #include <security/audit/audit.h> #include <security/audit/audit_private.h> +#include <security/audit/audit_slice.h> + /* * Calls to manipulate elements of the audit record structure from system * call code. Macro wrappers will prevent this functions from being entered @@ -791,7 +793,7 @@ { struct kaudit_record *ar; - if (audit_argv == 0) + if (audit_base_slice->audit_argv == 0) return; ar = currecord(); @@ -812,7 +814,7 @@ { struct kaudit_record *ar; - if (audit_arge == 0) + if (audit_base_slice->audit_arge == 0) return; ar = currecord(); ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_private.h#2 (text) ==== @@ -346,9 +346,6 @@ struct kaudit_record *currecord(void); void audit_free(struct kaudit_record *ar); void audit_shutdown(void *arg, int howto); -void audit_rotate_vnode(struct ucred *cred, - struct vnode *vp); -void audit_worker_init(void); /* * Audit pipe functions. ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_syscalls.c#2 (text) ==== @@ -49,6 +49,8 @@ #include <security/audit/audit_private.h> #include <security/mac/mac_framework.h> +#include <security/audit/audit_slice.h> + #ifdef AUDIT /* @@ -74,7 +76,8 @@ if (error) return (error); - if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) + if ((uap->length <= 0) || (uap->length > + audit_base_slice->audit_qctrl.aq_bufsz)) return (EINVAL); ar = currecord(); @@ -218,25 +221,25 @@ case A_OLDGETPOLICY: case A_GETPOLICY: if (uap->length == sizeof(udata.au_policy64)) { - if (!audit_fail_stop) + if (!audit_base_slice->audit_fail_stop) udata.au_policy64 |= AUDIT_CNT; - if (audit_panic_on_write_fail) + if (audit_base_slice->audit_panic_on_write_fail) udata.au_policy64 |= AUDIT_AHLT; - if (audit_argv) + if (audit_base_slice->audit_argv) udata.au_policy64 |= AUDIT_ARGV; - if (audit_arge) + if (audit_base_slice->audit_arge) udata.au_policy64 |= AUDIT_ARGE; break; } if (uap->length != sizeof(udata.au_policy)) return (EINVAL); - if (!audit_fail_stop) + if (!audit_base_slice->audit_fail_stop) udata.au_policy |= AUDIT_CNT; - if (audit_panic_on_write_fail) + if (audit_base_slice->audit_panic_on_write_fail) udata.au_policy |= AUDIT_AHLT; - if (audit_argv) + if (audit_base_slice->audit_argv) udata.au_policy |= AUDIT_ARGV; - if (audit_arge) + if (audit_base_slice->audit_arge) udata.au_policy |= AUDIT_ARGE; break; @@ -246,12 +249,14 @@ if (udata.au_policy & (~AUDIT_CNT|AUDIT_AHLT| AUDIT_ARGV|AUDIT_ARGE)) return (EINVAL); - audit_fail_stop = ((udata.au_policy64 & AUDIT_CNT) == - 0); - audit_panic_on_write_fail = (udata.au_policy64 & - AUDIT_AHLT); - audit_argv = (udata.au_policy64 & AUDIT_ARGV); - audit_arge = (udata.au_policy64 & AUDIT_ARGE); + audit_base_slice->audit_fail_stop = ((udata.au_policy64 + & AUDIT_CNT) == 0); + audit_base_slice->audit_panic_on_write_fail = + (udata.au_policy64 & AUDIT_AHLT); + audit_base_slice->audit_argv = (udata.au_policy64 + & AUDIT_ARGV); + audit_base_slice->audit_arge = (udata.au_policy64 + & AUDIT_ARGE); break; } if (uap->length != sizeof(udata.au_policy)) @@ -262,40 +267,44 @@ /* * XXX - Need to wake up waiters if the policy relaxes? */ - audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0); - audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT); - audit_argv = (udata.au_policy & AUDIT_ARGV); - audit_arge = (udata.au_policy & AUDIT_ARGE); + audit_base_slice->audit_fail_stop = + ((udata.au_policy & AUDIT_CNT) == 0); + audit_base_slice->audit_panic_on_write_fail = + (udata.au_policy & AUDIT_AHLT); + audit_base_slice->audit_argv = + (udata.au_policy & AUDIT_ARGV); + audit_base_slice->audit_arge = + (udata.au_policy & AUDIT_ARGE); break; case A_GETKMASK: if (uap->length != sizeof(udata.au_mask)) return (EINVAL); - udata.au_mask = audit_nae_mask; + udata.au_mask = audit_base_slice->audit_nae_mask; break; case A_SETKMASK: if (uap->length != sizeof(udata.au_mask)) return (EINVAL); - audit_nae_mask = udata.au_mask; + audit_base_slice->audit_nae_mask = udata.au_mask; break; case A_OLDGETQCTRL: case A_GETQCTRL: if (uap->length == sizeof(udata.au_qctrl64)) { udata.au_qctrl64.aq64_hiwater = - (u_int64_t)audit_qctrl.aq_hiwater; + (u_int64_t)audit_base_slice->audit_qctrl.aq_hiwater; udata.au_qctrl64.aq64_lowater = - (u_int64_t)audit_qctrl.aq_lowater; + (u_int64_t)audit_base_slice->audit_qctrl.aq_lowater; udata.au_qctrl64.aq64_bufsz = - (u_int64_t)audit_qctrl.aq_bufsz; + (u_int64_t)audit_base_slice->audit_qctrl.aq_bufsz; udata.au_qctrl64.aq64_minfree = - (u_int64_t)audit_qctrl.aq_minfree; + (u_int64_t)audit_base_slice->audit_qctrl.aq_minfree; break; } if (uap->length != sizeof(udata.au_qctrl)) return (EINVAL); - udata.au_qctrl = audit_qctrl; + udata.au_qctrl = audit_base_slice->audit_qctrl; break; case A_OLDSETQCTRL: @@ -308,15 +317,16 @@ (udata.au_qctrl64.aq64_minfree < 0) || (udata.au_qctrl64.aq64_minfree > 100)) return (EINVAL); - audit_qctrl.aq_hiwater = + audit_base_slice->audit_qctrl.aq_hiwater = (int)udata.au_qctrl64.aq64_hiwater; - audit_qctrl.aq_lowater = + audit_base_slice->audit_qctrl.aq_lowater = (int)udata.au_qctrl64.aq64_lowater; - audit_qctrl.aq_bufsz = + audit_base_slice->audit_qctrl.aq_bufsz = (int)udata.au_qctrl64.aq64_bufsz; - audit_qctrl.aq_minfree = + audit_base_slice->audit_qctrl.aq_minfree = (int)udata.au_qctrl64.aq64_minfree; - audit_qctrl.aq_delay = -1; /* Not used. */ + /* Not used. */ + audit_base_slice->audit_qctrl.aq_delay = -1; break; } if (uap->length != sizeof(udata.au_qctrl)) @@ -328,9 +338,9 @@ (udata.au_qctrl.aq_minfree > 100)) return (EINVAL); - audit_qctrl = udata.au_qctrl; + audit_base_slice->audit_qctrl = udata.au_qctrl; /* XXX The queue delay value isn't used with the kernel. */ - audit_qctrl.aq_delay = -1; + audit_base_slice->audit_qctrl.aq_delay = -1; break; case A_GETCWD: @@ -360,7 +370,8 @@ case A_OLDGETCOND: case A_GETCOND: if (uap->length == sizeof(udata.au_cond64)) { - if (audit_enabled && !audit_suspended) + if (audit_base_slice->audit_enabled + && !audit_base_slice->audit_suspended) udata.au_cond64 = AUC_AUDITING; else udata.au_cond64 = AUC_NOAUDIT; @@ -368,7 +379,8 @@ } if (uap->length != sizeof(udata.au_cond)) return (EINVAL); - if (audit_enabled && !audit_suspended) + if (audit_base_slice->audit_enabled + && !audit_base_slice->audit_suspended) udata.au_cond = AUC_AUDITING; else udata.au_cond = AUC_NOAUDIT; @@ -378,11 +390,11 @@ case A_SETCOND: if (uap->length == sizeof(udata.au_cond64)) { if (udata.au_cond64 == AUC_NOAUDIT) - audit_suspended = 1; + audit_base_slice->audit_suspended = 1; if (udata.au_cond64 == AUC_AUDITING) - audit_suspended = 0; + audit_base_slice->audit_suspended = 0; if (udata.au_cond64 == AUC_DISABLED) { - audit_suspended = 1; + audit_base_slice->audit_suspended = 1; audit_shutdown(NULL, 0); } break; @@ -390,11 +402,11 @@ if (uap->length != sizeof(udata.au_cond)) return (EINVAL); if (udata.au_cond == AUC_NOAUDIT) - audit_suspended = 1; + audit_base_slice->audit_suspended = 1; if (udata.au_cond == AUC_AUDITING) - audit_suspended = 0; + audit_base_slice->audit_suspended = 0; if (udata.au_cond == AUC_DISABLED) { - audit_suspended = 1; + audit_base_slice->audit_suspended = 1; audit_shutdown(NULL, 0); } break; @@ -474,14 +486,17 @@ if ((udata.au_fstat.af_filesz != 0) && (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) return (EINVAL); - audit_fstat.af_filesz = udata.au_fstat.af_filesz; + audit_base_slice->audit_fstat.af_filesz + = udata.au_fstat.af_filesz; break; case A_GETFSIZE: if (uap->length != sizeof(udata.au_fstat)) return (EINVAL); - udata.au_fstat.af_filesz = audit_fstat.af_filesz; - udata.au_fstat.af_currsz = audit_fstat.af_currsz; + udata.au_fstat.af_filesz + = audit_base_slice->audit_fstat.af_filesz; + udata.au_fstat.af_currsz + = audit_base_slice->audit_fstat.af_currsz; break; case A_GETPINFO_ADDR: @@ -525,6 +540,21 @@ return (EINVAL); return (audit_send_trigger(udata.au_trigger)); + case A_CREATESLICE: + //if (uap->length != sizeof(udata.au_slice)) + // return (EINVAL); + return (0); + + case A_UPDATESLICE: + //if (uap->length != sizeof(udata.au_slice)) + // return (EINVAL); + return (0); + + case A_REMOVESLICE: + //if (uap->length != sizeof(udata.au_slice)) + // return (EINVAL); + return (0); + default: return (EINVAL); } @@ -805,7 +835,7 @@ * XXXAUDIT: Should audit_suspended actually be cleared by * audit_worker? */ - audit_suspended = 0; + audit_base_slice->audit_suspended = 0; audit_rotate_vnode(cred, vp); ==== //depot/projects/soc2009/marinosi_appaudit/src/sys/security/audit/audit_worker.c#2 (text) ==== @@ -69,33 +69,20 @@ #include <security/audit/audit.h> #include <security/audit/audit_private.h> +#include <security/audit/audit_slice.h> + #include <vm/uma.h> -/* - * Worker thread that will schedule disk I/O, etc. - */ -static struct proc *audit_thread; /* - * audit_cred and audit_vp are the stored credential and vnode to use for - * active audit trail. They are protected by the audit worker lock, which - * will be held across all I/O and all rotation to prevent them from being - * replaced (rotated) while in use. The audit_file_rotate_wait flag is set - * when the kernel has delivered a trigger to auditd to rotate the trail, and - * is cleared when the next rotation takes place. It is also protected by - * the audit worker lock. + * Slice-worker private mtx handling macros */ -static int audit_file_rotate_wait; -static struct ucred *audit_cred; -static struct vnode *audit_vp; -static struct sx audit_worker_lock; - -#define AUDIT_WORKER_LOCK_INIT() sx_init(&audit_worker_lock, \ +#define AUDIT_WORKER_LOCK_INIT() sx_init(&(as->audit_worker_lock), \ "audit_worker_lock"); -#define AUDIT_WORKER_LOCK_ASSERT() sx_assert(&audit_worker_lock, \ +#define AUDIT_WORKER_LOCK_ASSERT() sx_assert(&(as->audit_worker_lock), \ SA_XLOCKED) -#define AUDIT_WORKER_LOCK() sx_xlock(&audit_worker_lock) -#define AUDIT_WORKER_UNLOCK() sx_xunlock(&audit_worker_lock) +#define AUDIT_WORKER_LOCK() sx_xlock(&(as->audit_worker_lock)) +#define AUDIT_WORKER_UNLOCK() sx_xunlock(&(as->audit_worker_lock)) /* * Write an audit record to a file, performed as the last stage after both @@ -106,7 +93,7 @@ * the audit daemon, since the message is asynchronous anyway. */ static void -audit_record_write(struct vnode *vp, struct ucred *cred, void *data, +audit_record_write(struct audit_slice *as, void *data, size_t len) { static struct timeval last_lowspace_trigger; @@ -120,26 +107,26 @@ AUDIT_WORKER_LOCK_ASSERT(); - if (vp == NULL) + if (as->audit_vp == NULL) return; - mnt_stat = &vp->v_mount->mnt_stat; - vfslocked = VFS_LOCK_GIANT(vp->v_mount); + mnt_stat = &as->audit_vp->v_mount->mnt_stat; + vfslocked = VFS_LOCK_GIANT(as->audit_vp->v_mount); /* * First, gather statistics on the audit log file and file system so * that we know how we're doing on space. Consider failure of these * operations to indicate a future inability to write to the file. */ - error = VFS_STATFS(vp->v_mount, mnt_stat, curthread); + error = VFS_STATFS(as->audit_vp->v_mount, mnt_stat, curthread); if (error) goto fail; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - error = VOP_GETATTR(vp, &vattr, cred); - VOP_UNLOCK(vp, 0); + vn_lock(as->audit_vp, LK_EXCLUSIVE | LK_RETRY); + error = VOP_GETATTR(as->audit_vp, &vattr, as->audit_cred); + VOP_UNLOCK(as->audit_vp, 0); if (error) goto fail; - audit_fstat.af_currsz = vattr.va_size; + as->audit_fstat.af_currsz = vattr.va_size; /* * We handle four different space-related limits: @@ -177,16 +164,16 @@ * the daemon a trigger and continue processing the record. Triggers * are limited to 1/sec. */ - if (audit_qctrl.aq_minfree != 0) { - temp = mnt_stat->f_blocks / (100 / audit_qctrl.aq_minfree); + if (as->audit_qctrl.aq_minfree != 0) { + temp = mnt_stat->f_blocks / (100 / as->audit_qctrl.aq_minfree); if (mnt_stat->f_bfree < temp) { if (ppsratecheck(&last_lowspace_trigger, &cur_lowspace_trigger, 1)) { (void)audit_send_trigger( AUDIT_TRIGGER_LOW_SPACE); printf("Warning: disk space low (< %d%% free) " - "on audit log file-system\n", - audit_qctrl.aq_minfree); + "on audit log file-system for %s slice.\n", + as->audit_qctrl.aq_minfree, as->as_name); } } } @@ -196,11 +183,11 @@ * to the daemon. This is only approximate, which is fine as more * records may be generated before the daemon rotates the file. */ - if ((audit_fstat.af_filesz != 0) && (audit_file_rotate_wait == 0) && - (vattr.va_size >= audit_fstat.af_filesz)) { + if ((as->audit_fstat.af_filesz != 0) && (as->audit_file_rotate_wait == 0) && + (vattr.va_size >= as->audit_fstat.af_filesz)) { AUDIT_WORKER_LOCK_ASSERT(); - audit_file_rotate_wait = 1; + as->audit_file_rotate_wait = 1; (void)audit_send_trigger(AUDIT_TRIGGER_ROTATE_KERNEL); } @@ -215,16 +202,16 @@ * allow operation to continue, but this behavior is sufficient to * meet fail stop requirements in CAPP. */ - if (audit_fail_stop) { - if ((unsigned long)((audit_q_len + audit_pre_q_len + 1) * + if (as->audit_fail_stop) { + if ((unsigned long)((as->audit_q_len + as->audit_pre_q_len + 1) * MAX_AUDIT_RECORD_SIZE) / mnt_stat->f_bsize >= (unsigned long)(mnt_stat->f_bfree)) { if (ppsratecheck(&last_fail, &cur_fail, 1)) printf("audit_record_write: free space " - "below size of audit queue, failing " - "stop\n"); - audit_in_failure = 1; - } else if (audit_in_failure) { + "below size of audit queue, %s slice failing " + "stop\n", as->as_name); + as->audit_in_failure = 1; + } else if (as->audit_in_failure) { /* * Note: if we want to handle recovery, this is the * spot to do it: unset audit_in_failure, and issue a @@ -233,8 +220,8 @@ } } - error = vn_rdwr(UIO_WRITE, vp, data, len, (off_t)0, UIO_SYSSPACE, - IO_APPEND|IO_UNIT, cred, NULL, NULL, curthread); + error = vn_rdwr(UIO_WRITE, as->audit_vp, data, len, (off_t)0, UIO_SYSSPACE, + IO_APPEND|IO_UNIT, as->audit_cred, NULL, NULL, curthread); if (error == ENOSPC) goto fail_enospc; else if (error) @@ -249,11 +236,11 @@ * Note: if we handle recovery from audit_in_failure, then we need to * make panic here conditional. */ - if (audit_in_failure) { - if (audit_q_len == 0 && audit_pre_q_len == 0) { - VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); - (void)VOP_FSYNC(vp, MNT_WAIT, curthread); - VOP_UNLOCK(vp, 0); + if (as->audit_in_failure) { + if (as->audit_q_len == 0 && as->audit_pre_q_len == 0) { + VOP_LOCK(as->audit_vp, LK_EXCLUSIVE | LK_RETRY); + (void)VOP_FSYNC(as->audit_vp, MNT_WAIT, curthread); + VOP_UNLOCK(as->audit_vp, 0); panic("Audit store overflow; record queue drained."); } } @@ -267,14 +254,14 @@ * this can reflect either our preemptive detection of insufficient * space, or ENOSPC returned by the vnode write call. */ - if (audit_fail_stop) { - VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); - (void)VOP_FSYNC(vp, MNT_WAIT, curthread); - VOP_UNLOCK(vp, 0); + if (as->audit_fail_stop) { + VOP_LOCK(as->audit_vp, LK_EXCLUSIVE | LK_RETRY); + (void)VOP_FSYNC(as->audit_vp, MNT_WAIT, curthread); + VOP_UNLOCK(as->audit_vp, 0); panic("Audit log space exhausted and fail-stop set."); } (void)audit_send_trigger(AUDIT_TRIGGER_NO_SPACE); - audit_suspended = 1; + as->audit_suspended = 1; /* FALLTHROUGH */ fail: @@ -282,10 +269,10 @@ * We have failed to write to the file, so the current record is * lost, which may require an immediate system halt. */ - if (audit_panic_on_write_fail) { - VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); - (void)VOP_FSYNC(vp, MNT_WAIT, curthread); - VOP_UNLOCK(vp, 0); + if (as->audit_panic_on_write_fail) { + VOP_LOCK(as->audit_vp, LK_EXCLUSIVE | LK_RETRY); + (void)VOP_FSYNC(as->audit_vp, MNT_WAIT, curthread); + VOP_UNLOCK(as->audit_vp, 0); panic("audit_worker: write error %d\n", error); } else if (ppsratecheck(&last_fail, &cur_fail, 1)) printf("audit_worker: write error %d\n", error); @@ -300,7 +287,7 @@ * written to disk, and audit pipes. */ static void -audit_worker_process_record(struct kaudit_record *ar) +audit_worker_process_record(struct kaudit_record *ar, struct audit_slice *as) { struct au_record *bsm; au_class_t class; @@ -329,7 +316,7 @@ if ((ar->k_ar_commit & AR_COMMIT_USER) && (ar->k_ar_commit & AR_PRESELECT_USER_TRAIL)) { AUDIT_WORKER_LOCK_ASSERT(); - audit_record_write(audit_vp, audit_cred, ar->k_udata, + audit_record_write(as, ar->k_udata, ar->k_ulen); } @@ -368,7 +355,7 @@ if (ar->k_ar_commit & AR_PRESELECT_TRAIL) { AUDIT_WORKER_LOCK_ASSERT(); - audit_record_write(audit_vp, audit_cred, bsm->data, bsm->len); + audit_record_write(as, bsm->data, bsm->len); } if (ar->k_ar_commit & AR_PRESELECT_PIPE) @@ -398,16 +385,18 @@ struct kaudit_record *ar; int lowater_signal; + struct audit_slice *as = (struct audit_slice * ) arg; + TAILQ_INIT(&ar_worklist); - mtx_lock(&audit_mtx); + mtx_lock(&(as->audit_mtx)); while (1) { - mtx_assert(&audit_mtx, MA_OWNED); + mtx_assert(&(as->audit_mtx), MA_OWNED); /* * Wait for a record. */ - while (TAILQ_EMPTY(&audit_q)) - cv_wait(&audit_worker_cv, &audit_mtx); + while (TAILQ_EMPTY(&(as->audit_q))) + cv_wait(&(as->audit_worker_cv), &(as->audit_mtx)); /* * If there are records in the global audit record queue, @@ -417,23 +406,23 @@ * continue generating records. */ lowater_signal = 0; - while ((ar = TAILQ_FIRST(&audit_q))) { - TAILQ_REMOVE(&audit_q, ar, k_q); - audit_q_len--; - if (audit_q_len == audit_qctrl.aq_lowater) + while ((ar = TAILQ_FIRST(&(as->audit_q)))) { + TAILQ_REMOVE(&(as->audit_q), ar, k_q); + as->audit_q_len--; + if (as->audit_q_len == as->audit_qctrl.aq_lowater) lowater_signal++; TAILQ_INSERT_TAIL(&ar_worklist, ar, k_q); } if (lowater_signal) - cv_broadcast(&audit_watermark_cv); + cv_broadcast(&(as->audit_watermark_cv)); - mtx_unlock(&audit_mtx); + mtx_unlock(&(as->audit_mtx)); while ((ar = TAILQ_FIRST(&ar_worklist))) { TAILQ_REMOVE(&ar_worklist, ar, k_q); - audit_worker_process_record(ar); + audit_worker_process_record(ar, as); audit_free(ar); } - mtx_lock(&audit_mtx); + mtx_lock(&(as->audit_mtx)); } } @@ -451,8 +440,11 @@ { struct ucred *old_audit_cred; struct vnode *old_audit_vp; + struct audit_slice *as; int vfslocked; + as = audit_base_slice; + KASSERT((cred != NULL && vp != NULL) || (cred == NULL && vp == NULL), ("audit_rotate_vnode: cred %p vp %p", cred, vp)); @@ -461,12 +453,12 @@ * send a rotate trigger if the new file fills. */ AUDIT_WORKER_LOCK(); - old_audit_cred = audit_cred; - old_audit_vp = audit_vp; - audit_cred = cred; - audit_vp = vp; - audit_file_rotate_wait = 0; - audit_enabled = (audit_vp != NULL); + old_audit_cred = as->audit_cred; + old_audit_vp = as->audit_vp; + as->audit_cred = cred; + as->audit_vp = vp; + as->audit_file_rotate_wait = 0; + as->audit_enabled = (as->audit_vp != NULL); AUDIT_WORKER_UNLOCK(); /* @@ -482,13 +474,14 @@ } void -audit_worker_init(void) +audit_worker_init(void *arg) { int error; + struct audit_slice *as = (struct audit_slice * ) arg; AUDIT_WORKER_LOCK_INIT(); - error = kproc_create(audit_worker, NULL, &audit_thread, RFHIGHPID, - 0, "audit"); + error = kproc_create(audit_worker,(void *) as, &(as->audit_thread), RFHIGHPID, + 0, as->as_name); if (error) panic("audit_worker_init: kproc_create returned %d", error); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905311828.n4VISorE019427>