/* ARGSUSED */ int auditctl(struct thread *td, struct auditctl_args *uap) { struct nameidata nd; struct ucred *cred; struct vnode *vp; int error = 0; int flags, vfslocked; if (jailed(td->td_ucred)) return (ENOSYS); error = priv_check(td, PRIV_AUDIT_CONTROL); if (error) return (error); vp = NULL; cred = NULL; /* * If a path is specified, open the replacement vnode, perform * validity checks, and grab another reference to the current * credential. * * On Darwin, a NULL path argument is also used to disable audit. */ if (uap->path == NULL) return (EINVAL); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, UIO_USERSPACE, uap->path, td); flags = AUDIT_OPEN_FLAGS; error = vn_open(&nd, &flags, 0, NULL); if (error) return (error); vfslocked = NDHASGIANT(&nd); vp = nd.ni_vp; #ifdef MAC error = mac_system_check_auditctl(td->td_ucred, vp); VOP_UNLOCK(vp, 0); if (error) { vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); VFS_UNLOCK_GIANT(vfslocked); return (error); } #else VOP_UNLOCK(vp, 0); #endif NDFREE(&nd, NDF_ONLY_PNBUF); if (vp->v_type != VREG) { vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); VFS_UNLOCK_GIANT(vfslocked); return (EINVAL); } VFS_UNLOCK_GIANT(vfslocked); cred = td->td_ucred; crhold(cred); /* * XXXAUDIT: Should audit_suspended actually be cleared by * audit_worker? */ audit_suspended = 0; audit_rotate_vnode(cred, vp); return (error); }
/* ARGSUSED */ int auditctl(proc_t p, struct auditctl_args *uap, __unused int32_t *retval) { struct nameidata nd; kauth_cred_t cred; struct vnode *vp; int error = 0; error = suser(kauth_cred_get(), &p->p_acflag); if (error) return (error); vp = NULL; cred = NULL; /* * If a path is specified, open the replacement vnode, perform * validity checks, and grab another reference to the current * credential. * * XXX Changes API slightly. NULL path no longer disables audit but * returns EINVAL. */ if (uap->path == USER_ADDR_NULL) return (EINVAL); NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW | LOCKLEAF | AUDITVNPATH1, (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), uap->path, vfs_context_current()); error = vn_open(&nd, AUDIT_OPEN_FLAGS, 0); if (error) return (error); vp = nd.ni_vp; #if CONFIG_MACF /* * Accessibility of the vnode was determined in vn_open; the * mac_system_check_auditctl should only determine whether that vnode * is appropriate for storing audit data, or that the caller was * permitted to control the auditing system at all. For example, a * confidentiality policy may want to ensure that audit files are * always high sensitivity. */ error = mac_system_check_auditctl(kauth_cred_get(), vp); if (error) { vn_close(vp, AUDIT_CLOSE_FLAGS, vfs_context_current()); vnode_put(vp); return (error); } #endif if (vp->v_type != VREG) { vn_close(vp, AUDIT_CLOSE_FLAGS, vfs_context_current()); vnode_put(vp); return (EINVAL); } mtx_lock(&audit_mtx); /* * XXXAUDIT: Should audit_suspended actually be cleared by * audit_worker? */ audit_suspended = 0; mtx_unlock(&audit_mtx); /* * The following gets unreferenced in audit_rotate_vnode() * after the rotation and it is no longer needed. */ cred = kauth_cred_get_with_ref(); audit_rotate_vnode(cred, vp); vnode_put(vp); return (error); }