X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d9a64523371fa019c4575bb400cbbc3a50ac9903..c3c9b80d004dbbfdf763edeb97968c6997e3b45b:/bsd/security/audit/audit.c diff --git a/bsd/security/audit/audit.c b/bsd/security/audit/audit.c index e91adedf4..0a3217735 100644 --- a/bsd/security/audit/audit.c +++ b/bsd/security/audit/audit.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999-2009 Apple Inc. + * Copyright (c) 1999-2020 Apple Inc. * Copyright (c) 2006-2007 Robert N. M. Watson * All rights reserved. * @@ -74,7 +74,6 @@ #include #include -#include #include #include @@ -87,6 +86,7 @@ MALLOC_DEFINE(M_AUDITDATA, "audit_data", "Audit data storage"); MALLOC_DEFINE(M_AUDITPATH, "audit_path", "Audit path storage"); MALLOC_DEFINE(M_AUDITTEXT, "audit_text", "Audit text storage"); +KALLOC_HEAP_DEFINE(KHEAP_AUDIT, "Audit", KHEAP_ID_DEFAULT); /* * Audit control settings that are set/read by system calls and are hence @@ -94,11 +94,11 @@ MALLOC_DEFINE(M_AUDITTEXT, "audit_text", "Audit text storage"); * * Define the audit control flags. */ -int audit_enabled; -int audit_suspended; +int audit_enabled; +int audit_suspended; -int audit_syscalls; -au_class_t audit_kevent_mask; +int audit_syscalls; +au_class_t audit_kevent_mask; /* * The audit control mode is used to ensure configuration settings are only @@ -111,31 +111,31 @@ au_expire_after_t audit_expire_after; * 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; +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; +int audit_in_failure; /* * Global audit statistics. */ -struct audit_fstat audit_fstat; +struct audit_fstat audit_fstat; /* * Preselection mask for non-attributable events. */ -struct au_mask audit_nae_mask; +struct au_mask audit_nae_mask; /* * Mutex to protect global variables shared between various threads and * processes. */ -struct mtx audit_mtx; +struct mtx audit_mtx; /* * Queue of audit records ready for delivery to disk. We insert new records @@ -145,42 +145,43 @@ struct mtx audit_mtx; * 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; +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; +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; +struct cv audit_worker_cv; /* * Condition variable to signal when the worker is done draining the audit * queue. */ -struct cv audit_drain_cv; +struct cv audit_drain_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; +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; +static struct cv audit_fail_cv; -static zone_t audit_record_zone; +static ZONE_DECLARE(audit_record_zone, "audit_zone", + sizeof(struct kaudit_record), ZC_NONE); /* * Kernel audit information. This will store the current audit address @@ -188,20 +189,19 @@ static zone_t audit_record_zone; * 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; +static struct auditinfo_addr audit_kinfo; +static struct rwlock audit_kinfo_lock; -#define KINFO_LOCK_INIT() rw_init(&audit_kinfo_lock, \ - "audit_kinfo_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) +#define KINFO_LOCK_INIT() rw_init(&audit_kinfo_lock, \ + "audit_kinfo_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")); @@ -214,7 +214,6 @@ audit_set_kinfo(struct auditinfo_addr *ak) 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")); @@ -240,8 +239,8 @@ audit_record_ctor(proc_t p, struct kaudit_record *ar) cred = kauth_cred_proc_ref(p); /* - * Export the subject credential. - */ + * Export the subject credential. + */ cru2x(cred, &ar->k_ar.ar_subj_cred); ar->k_ar.ar_subj_ruid = kauth_cred_getruid(cred); ar->k_ar.ar_subj_rgid = kauth_cred_getrgid(cred); @@ -250,7 +249,7 @@ audit_record_ctor(proc_t p, struct kaudit_record *ar) ar->k_ar.ar_subj_auid = cred->cr_audit.as_aia_p->ai_auid; ar->k_ar.ar_subj_asid = cred->cr_audit.as_aia_p->ai_asid; bcopy(&cred->cr_audit.as_mask, &ar->k_ar.ar_subj_amask, - sizeof(struct au_mask)); + sizeof(struct au_mask)); bcopy(&cred->cr_audit.as_aia_p->ai_termid, &ar->k_ar.ar_subj_term_addr, sizeof(struct au_tid_addr)); kauth_cred_unref(&cred); @@ -260,27 +259,36 @@ audit_record_ctor(proc_t p, struct kaudit_record *ar) static void audit_record_dtor(struct kaudit_record *ar) { - - if (ar->k_ar.ar_arg_upath1 != NULL) + if (ar->k_ar.ar_arg_upath1 != NULL) { free(ar->k_ar.ar_arg_upath1, M_AUDITPATH); - if (ar->k_ar.ar_arg_upath2 != NULL) + } + if (ar->k_ar.ar_arg_upath2 != NULL) { free(ar->k_ar.ar_arg_upath2, M_AUDITPATH); - if (ar->k_ar.ar_arg_kpath1 != NULL) + } + if (ar->k_ar.ar_arg_kpath1 != NULL) { free(ar->k_ar.ar_arg_kpath1, M_AUDITPATH); - if (ar->k_ar.ar_arg_kpath2 != NULL) + } + if (ar->k_ar.ar_arg_kpath2 != NULL) { free(ar->k_ar.ar_arg_kpath2, M_AUDITPATH); - if (ar->k_ar.ar_arg_text != NULL) + } + if (ar->k_ar.ar_arg_text != NULL) { free(ar->k_ar.ar_arg_text, M_AUDITTEXT); - if (ar->k_ar.ar_arg_opaque != NULL) + } + if (ar->k_ar.ar_arg_opaque != NULL) { free(ar->k_ar.ar_arg_opaque, M_AUDITDATA); - if (ar->k_ar.ar_arg_data != NULL) + } + if (ar->k_ar.ar_arg_data != NULL) { free(ar->k_ar.ar_arg_data, M_AUDITDATA); - if (ar->k_udata != NULL) + } + if (ar->k_udata != NULL) { free(ar->k_udata, M_AUDITDATA); - if (ar->k_ar.ar_arg_argv != NULL) + } + if (ar->k_ar.ar_arg_argv != NULL) { free(ar->k_ar.ar_arg_argv, M_AUDITTEXT); - if (ar->k_ar.ar_arg_envv != NULL) + } + if (ar->k_ar.ar_arg_envv != NULL) { free(ar->k_ar.ar_arg_envv, M_AUDITTEXT); + } audit_identity_info_destruct(&ar->k_ar.ar_arg_identity); } @@ -292,7 +300,6 @@ audit_record_dtor(struct kaudit_record *ar) void audit_init(void) { - audit_enabled = 0; audit_syscalls = 0; audit_kevent_mask = 0; @@ -307,7 +314,7 @@ audit_init(void) audit_expire_after.size = 0; audit_expire_after.op_type = AUDIT_EXPIRE_OP_AND; - audit_fstat.af_filesz = 0; /* '0' means unset, unbounded. */ + 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; @@ -323,7 +330,6 @@ audit_init(void) audit_kinfo.ai_termid.at_type = AU_IPv4; audit_kinfo.ai_termid.at_addr[0] = INADDR_ANY; - _audit_lck_grp_init(); mtx_init(&audit_mtx, "audit_mtx", NULL, MTX_DEF); KINFO_LOCK_INIT(); cv_init(&audit_worker_cv, "audit_worker_cv"); @@ -331,11 +337,6 @@ audit_init(void) cv_init(&audit_watermark_cv, "audit_watermark_cv"); cv_init(&audit_fail_cv, "audit_fail_cv"); - audit_record_zone = zinit(sizeof(struct kaudit_record), - AQ_HIWATER*sizeof(struct kaudit_record), 8192, "audit_zone"); -#if CONFIG_MACF - audit_mac_init(); -#endif /* Init audit session subsystem. */ audit_session_init(); @@ -359,7 +360,6 @@ audit_init(void) void audit_shutdown(void) { - audit_rotate_vnode(NULL, NULL); } @@ -369,8 +369,7 @@ audit_shutdown(void) struct kaudit_record * currecord(void) { - - return (curthread()->uu_ar); + return curthread()->uu_ar; } /* @@ -399,12 +398,13 @@ audit_new(int event, proc_t p, __unused struct uthread *uthread) audit_override = (AUE_SESSION_START == event || AUE_SESSION_UPDATE == event || AUE_SESSION_END == event || AUE_SESSION_CLOSE == event); - + mtx_lock(&audit_mtx); no_record = (audit_suspended || !audit_enabled); mtx_unlock(&audit_mtx); - if (!audit_override && no_record) - return (NULL); + if (!audit_override && no_record) { + return NULL; + } /* * Initialize the audit record header. @@ -415,8 +415,9 @@ audit_new(int event, proc_t p, __unused struct uthread *uthread) * in the kernel. */ ar = zalloc(audit_record_zone); - if (ar == NULL) + if (ar == NULL) { return NULL; + } audit_record_ctor(p, ar); ar->k_ar.ar_event = event; @@ -424,27 +425,28 @@ audit_new(int event, proc_t p, __unused struct uthread *uthread) if (PROC_NULL != p) { if (audit_mac_new(p, ar) != 0) { zfree(audit_record_zone, ar); - return (NULL); + return NULL; } - } else + } else { ar->k_ar.ar_mac_records = NULL; + } #endif mtx_lock(&audit_mtx); audit_pre_q_len++; mtx_unlock(&audit_mtx); - return (ar); + return ar; } void audit_free(struct kaudit_record *ar) { - audit_record_dtor(ar); #if CONFIG_MACF - if (NULL != ar->k_ar.ar_mac_records) + if (NULL != ar->k_ar.ar_mac_records) { audit_mac_free(ar); + } #endif zfree(audit_record_zone, ar); } @@ -459,24 +461,27 @@ audit_commit(struct kaudit_record *ar, int error, int retval) struct au_mask *aumask; int audit_override; - if (ar == NULL) + if (ar == NULL) { return; + } /* * Decide whether to commit the audit record by checking the error * value from the system call and using the appropriate audit mask. */ - if (ar->k_ar.ar_subj_auid == AU_DEFAUDITID) + if (ar->k_ar.ar_subj_auid == AU_DEFAUDITID) { aumask = &audit_nae_mask; - else + } else { aumask = &ar->k_ar.ar_subj_amask; + } - if (error) + if (error) { sorf = AU_PRS_FAILURE; - else + } else { sorf = AU_PRS_SUCCESS; + } - switch(ar->k_ar.ar_event) { + switch (ar->k_ar.ar_event) { case AUE_OPEN_RWTC: /* * The open syscall always writes a AUE_OPEN_RWTC event; @@ -484,7 +489,7 @@ audit_commit(struct kaudit_record *ar, int error, int retval) * and the error value. */ ar->k_ar.ar_event = audit_flags_and_error_to_openevent( - ar->k_ar.ar_arg_fflags, error); + ar->k_ar.ar_arg_fflags, error); break; case AUE_OPEN_EXTENDED_RWTC: @@ -494,7 +499,7 @@ audit_commit(struct kaudit_record *ar, int error, int retval) * event based on the flags and the error value. */ ar->k_ar.ar_event = audit_flags_and_error_to_openextendedevent( - ar->k_ar.ar_arg_fflags, error); + ar->k_ar.ar_arg_fflags, error); break; case AUE_OPENAT_RWTC: @@ -504,7 +509,7 @@ audit_commit(struct kaudit_record *ar, int error, int retval) * event based on the flags and the error value. */ ar->k_ar.ar_event = audit_flags_and_error_to_openatevent( - ar->k_ar.ar_arg_fflags, error); + ar->k_ar.ar_arg_fflags, error); break; case AUE_OPENBYID_RWT: @@ -514,12 +519,12 @@ audit_commit(struct kaudit_record *ar, int error, int retval) * event based on the flags and the error value. */ ar->k_ar.ar_event = audit_flags_and_error_to_openbyidevent( - ar->k_ar.ar_arg_fflags, error); + ar->k_ar.ar_arg_fflags, error); break; case AUE_SYSCTL: ar->k_ar.ar_event = audit_ctlname_to_sysctlevent( - ar->k_ar.ar_arg_ctlname, ar->k_ar.ar_valid_arg); + ar->k_ar.ar_arg_ctlname, ar->k_ar.ar_valid_arg); break; case AUE_AUDITON: @@ -530,7 +535,7 @@ audit_commit(struct kaudit_record *ar, int error, int retval) case AUE_FCNTL: /* Convert some fcntl() commands to their own events. */ ar->k_ar.ar_event = audit_fcntl_command_event( - ar->k_ar.ar_arg_cmd, ar->k_ar.ar_arg_fflags, error); + ar->k_ar.ar_arg_cmd, ar->k_ar.ar_arg_fflags, error); break; } @@ -550,11 +555,13 @@ audit_commit(struct kaudit_record *ar, int error, int retval) AUE_SESSION_CLOSE == event); ar->k_ar_commit |= AR_COMMIT_KERNEL; - if (au_preselect(event, class, aumask, sorf) != 0) + if (au_preselect(event, class, aumask, sorf) != 0) { ar->k_ar_commit |= AR_PRESELECT_TRAIL; + } if (audit_pipe_preselect(auid, event, class, sorf, - ar->k_ar_commit & AR_PRESELECT_TRAIL) != 0) + ar->k_ar_commit & AR_PRESELECT_TRAIL) != 0) { 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 | AR_PRESELECT_FILTER)) == 0) { @@ -585,8 +592,9 @@ audit_commit(struct kaudit_record *ar, int error, int retval) * Constrain the number of committed audit records based on the * configurable parameter. */ - while (audit_q_len >= audit_qctrl.aq_hiwater) + while (audit_q_len >= audit_qctrl.aq_hiwater) { cv_wait(&audit_watermark_cv, &audit_mtx); + } TAILQ_INSERT_TAIL(&audit_q, ar, k_q); audit_q_len++; @@ -622,11 +630,13 @@ audit_syscall_enter(unsigned int code, proc_t proc, struct uthread *uthread) * the syscall table(s). This table is generated by makesyscalls.sh * from syscalls.master and stored in audit_kevents.c. */ - if (code >= nsysent) + if (code >= nsysent) { return; + } event = sys_au_event[code]; - if (event == AUE_NULL) + if (event == AUE_NULL) { return; + } KASSERT(uthread->uu_ar == NULL, ("audit_syscall_enter: uthread->uu_ar != NULL")); @@ -637,10 +647,11 @@ audit_syscall_enter(unsigned int code, proc_t proc, struct uthread *uthread) */ cred = kauth_cred_proc_ref(proc); auid = cred->cr_audit.as_aia_p->ai_auid; - if (auid == AU_DEFAUDITID) + if (auid == AU_DEFAUDITID) { aumask = &audit_nae_mask; - else + } else { aumask = &cred->cr_audit.as_mask; + } /* * Allocate an audit record, if preselection allows it, and store in @@ -652,8 +663,9 @@ audit_syscall_enter(unsigned int code, proc_t proc, struct uthread *uthread) * Note: audit_mac_syscall_enter() may call audit_new() and allocate * memory for the audit record (uu_ar). */ - if (audit_mac_syscall_enter(code, proc, uthread, cred, event) == 0) + if (audit_mac_syscall_enter(code, proc, uthread, cred, event) == 0) { goto out; + } #endif if (au_preselect(event, class, aumask, AU_PRS_BOTH)) { /* @@ -673,12 +685,14 @@ audit_syscall_enter(unsigned int code, proc_t proc, struct uthread *uthread) cv_wait(&audit_fail_cv, &audit_mtx); panic("audit_failing_stop: thread continued"); } - if (uthread->uu_ar == NULL) + if (uthread->uu_ar == NULL) { uthread->uu_ar = audit_new(event, proc, uthread); + } } else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) { - if (uthread->uu_ar == NULL) + if (uthread->uu_ar == NULL) { uthread->uu_ar = audit_new(event, proc, uthread); - } + } + } /* * All audited events will contain an identity @@ -718,14 +732,16 @@ audit_syscall_exit(int error, __unsed proc_t proc, struct uthread *uthread) * If there was an error, the return value is set to -1, imitating * the behavior of the cerror routine. */ - if (error) + if (error) { retval = -1; - else + } else { retval = uthread->uu_rval[0]; + } #if CONFIG_MACF - if (audit_mac_syscall_exit(code, uthread, error, retval) != 0) + if (audit_mac_syscall_exit(code, uthread, error, retval) != 0) { goto out; + } #endif audit_commit(uthread->uu_ar, error, retval); @@ -733,6 +749,77 @@ out: uthread->uu_ar = NULL; } +/* + * For system calls such as posix_spawn(2) the sub operations (i.e., file actions + * and port actions) need to be audited as their own events. Like with system + * calls we need to determine if the sub operation needs to be audited by + * examining preselection masks. + */ +void +audit_subcall_enter(au_event_t event, proc_t proc, struct uthread *uthread) +{ + struct au_mask *aumask; + au_class_t class; + au_id_t auid; + kauth_cred_t cred; + + /* + * Check which audit mask to use; either the kernel non-attributable + * event mask or the process audit mask. + */ + cred = kauth_cred_proc_ref(proc); + auid = cred->cr_audit.as_aia_p->ai_auid; + if (auid == AU_DEFAUDITID) { + aumask = &audit_nae_mask; + } else { + aumask = &cred->cr_audit.as_mask; + } + + /* + * Allocate an audit record, if preselection allows it, and store in + * the thread for later use. + */ + class = au_event_class(event); + + if (au_preselect(event, class, aumask, AU_PRS_BOTH)) { + /* + * If we're out of space and need to suspend unprivileged + * processes, do that here rather than trying to allocate + * another audit record. + * + * Note: we might wish to be able to continue here in the + * future, if the system recovers. That should be possible + * by means of checking the condition in a loop around + * cv_wait(). It might be desirable to reevaluate whether an + * audit record is still required for this event by + * re-calling au_preselect(). + */ + if (audit_in_failure && + suser(cred, &proc->p_acflag) != 0) { + cv_wait(&audit_fail_cv, &audit_mtx); + panic("audit_failing_stop: thread continued"); + } + if (uthread->uu_ar == NULL) { + uthread->uu_ar = audit_new(event, proc, uthread); + } + } else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) { + if (uthread->uu_ar == NULL) { + uthread->uu_ar = audit_new(event, proc, uthread); + } + } + + kauth_cred_unref(&cred); +} + +void +audit_subcall_exit(int error, struct uthread *uthread) +{ + /* A subcall doesn't have a return value so always zero. */ + audit_commit(uthread->uu_ar, error, 0 /* retval */); + + uthread->uu_ar = NULL; +} + /* * Calls to set up and tear down audit structures used during Mach system * calls. @@ -747,16 +834,19 @@ audit_mach_syscall_enter(unsigned short event) au_class_t class; au_id_t auid; - if (event == AUE_NULL) + if (event == AUE_NULL) { return; + } uthread = curthread(); - if (uthread == NULL) + if (uthread == NULL) { return; + } proc = current_proc(); - if (proc == NULL) + if (proc == NULL) { return; + } KASSERT(uthread->uu_ar == NULL, ("audit_mach_syscall_enter: uthread->uu_ar != NULL")); @@ -768,22 +858,24 @@ audit_mach_syscall_enter(unsigned short event) * Check which audit mask to use; either the kernel non-attributable * event mask or the process audit mask. */ - if (auid == AU_DEFAUDITID) + if (auid == AU_DEFAUDITID) { aumask = &audit_nae_mask; - else + } else { aumask = &cred->cr_audit.as_mask; + } /* * Allocate an audit record, if desired, and store in the BSD thread * for later use. */ class = au_event_class(event); - if (au_preselect(event, class, aumask, AU_PRS_BOTH)) + if (au_preselect(event, class, aumask, AU_PRS_BOTH)) { uthread->uu_ar = audit_new(event, proc, uthread); - else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) + } else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) { uthread->uu_ar = audit_new(event, proc, uthread); - else + } else { uthread->uu_ar = NULL; + } kauth_cred_unref(&cred); } @@ -808,8 +900,7 @@ audit_mach_syscall_exit(int retval, struct uthread *uthread) int kau_will_audit(void) { - - return (audit_enabled && currecord() != NULL); + return audit_enabled && currecord() != NULL; } #if CONFIG_COREDUMP @@ -832,23 +923,26 @@ audit_proc_coredump(proc_t proc, char *path, int errcode) */ my_cred = kauth_cred_proc_ref(proc); auid = my_cred->cr_audit.as_aia_p->ai_auid; - if (auid == AU_DEFAUDITID) + if (auid == AU_DEFAUDITID) { aumask = &audit_nae_mask; - else + } else { aumask = &my_cred->cr_audit.as_mask; + } kauth_cred_unref(&my_cred); /* * It's possible for coredump(9) generation to fail. Make sure that * we handle this case correctly for preselection. */ - if (errcode != 0) + if (errcode != 0) { sorf = AU_PRS_FAILURE; - else + } else { sorf = AU_PRS_SUCCESS; + } class = au_event_class(AUE_CORE); if (au_preselect(AUE_CORE, class, aumask, sorf) == 0 && - audit_pipe_preselect(auid, AUE_CORE, class, sorf, 0) == 0) + audit_pipe_preselect(auid, AUE_CORE, class, sorf, 0) == 0) { return; + } /* * If we are interested in seeing this audit record, allocate it. * Where possible coredump records should contain a pathname and arg32 @@ -856,19 +950,24 @@ audit_proc_coredump(proc_t proc, char *path, int errcode) */ uthread = curthread(); ar = audit_new(AUE_CORE, proc, uthread); + if (ar == NULL) { + return; + } if (path != NULL) { pathp = &ar->k_ar.ar_arg_upath1; *pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK); if (audit_canon_path(vfs_context_cwd(vfs_context_current()), path, - *pathp)) + *pathp)) { free(*pathp, M_AUDITPATH); - else + } else { ARG_SET_VALID(ar, ARG_UPATH1); + } } ar->k_ar.ar_arg_signum = proc->p_sigacts->ps_sig; ARG_SET_VALID(ar, ARG_SIGNUM); - if (errcode != 0) + if (errcode != 0) { ret = 1; + } audit_commit(ar, errcode, ret); } #endif /* CONFIG_COREDUMP */