audit_syscalls.c revision 159318
1155192Srwatson/* 2155192Srwatson * Copyright (c) 1999-2005 Apple Computer, Inc. 3155192Srwatson * All rights reserved. 4155192Srwatson * 5155192Srwatson * Redistribution and use in source and binary forms, with or without 6155192Srwatson * modification, are permitted provided that the following conditions 7155192Srwatson * are met: 8155192Srwatson * 1. Redistributions of source code must retain the above copyright 9155192Srwatson * notice, this list of conditions and the following disclaimer. 10155192Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11155192Srwatson * notice, this list of conditions and the following disclaimer in the 12155192Srwatson * documentation and/or other materials provided with the distribution. 13155192Srwatson * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14155192Srwatson * its contributors may be used to endorse or promote products derived 15155192Srwatson * from this software without specific prior written permission. 16155192Srwatson * 17155192Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 18155192Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19155192Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20155192Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 21155192Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22155192Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23155192Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24155192Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25155192Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26155192Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27155192Srwatson * POSSIBILITY OF SUCH DAMAGE. 28155192Srwatson * 29155192Srwatson * $FreeBSD: head/sys/security/audit/audit_syscalls.c 159318 2006-06-05 22:36:12Z rwatson $ 30155192Srwatson */ 31155192Srwatson 32155192Srwatson#include <sys/param.h> 33159318Srwatson#include <sys/mount.h> 34155192Srwatson#include <sys/namei.h> 35155192Srwatson#include <sys/proc.h> 36155192Srwatson#include <sys/sysproto.h> 37155192Srwatson#include <sys/systm.h> 38155192Srwatson#include <sys/vnode.h> 39155192Srwatson 40155192Srwatson#include <bsm/audit.h> 41155192Srwatson#include <bsm/audit_kevents.h> 42155192Srwatson#include <security/audit/audit.h> 43155192Srwatson#include <security/audit/audit_private.h> 44155192Srwatson 45155192Srwatson#ifdef AUDIT 46155192Srwatson 47155192Srwatson/* 48155192Srwatson * MPSAFE 49155192Srwatson * 50156889Srwatson * System call to allow a user space application to submit a BSM audit record 51156889Srwatson * to the kernel for inclusion in the audit log. This function does little 52156889Srwatson * verification on the audit record that is submitted. 53155192Srwatson * 54156889Srwatson * XXXAUDIT: Audit preselection for user records does not currently work, 55156889Srwatson * since we pre-select only based on the AUE_audit event type, not the event 56156889Srwatson * type submitted as part of the user audit data. 57155192Srwatson */ 58155192Srwatson/* ARGSUSED */ 59155192Srwatsonint 60155192Srwatsonaudit(struct thread *td, struct audit_args *uap) 61155192Srwatson{ 62155192Srwatson int error; 63155192Srwatson void * rec; 64155192Srwatson struct kaudit_record *ar; 65155192Srwatson 66155192Srwatson error = suser(td); 67155192Srwatson if (error) 68155192Srwatson return (error); 69155192Srwatson 70155192Srwatson if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) 71155192Srwatson return (EINVAL); 72155192Srwatson 73155192Srwatson ar = currecord(); 74155192Srwatson 75156889Srwatson /* 76156889Srwatson * If there's no current audit record (audit() itself not audited) 77155192Srwatson * commit the user audit record. 78155192Srwatson */ 79155192Srwatson if (ar == NULL) { 80155192Srwatson 81156889Srwatson /* 82156889Srwatson * This is not very efficient; we're required to allocate a 83156889Srwatson * complete kernel audit record just so the user record can 84156889Srwatson * tag along. 85155192Srwatson * 86155192Srwatson * XXXAUDIT: Maybe AUE_AUDIT in the system call context and 87155192Srwatson * special pre-select handling? 88155192Srwatson */ 89155192Srwatson td->td_ar = audit_new(AUE_NULL, td); 90155192Srwatson if (td->td_ar == NULL) 91155192Srwatson return (ENOTSUP); 92155192Srwatson ar = td->td_ar; 93155192Srwatson } 94155192Srwatson 95156889Srwatson if (uap->length > MAX_AUDIT_RECORD_SIZE) 96155192Srwatson return (EINVAL); 97155192Srwatson 98155192Srwatson rec = malloc(uap->length, M_AUDITDATA, M_WAITOK); 99155192Srwatson 100155192Srwatson error = copyin(uap->record, rec, uap->length); 101155192Srwatson if (error) 102155192Srwatson goto free_out; 103155192Srwatson 104156889Srwatson /* Verify the record. */ 105155192Srwatson if (bsm_rec_verify(rec) == 0) { 106155192Srwatson error = EINVAL; 107155192Srwatson goto free_out; 108155192Srwatson } 109155192Srwatson 110156889Srwatson /* 111156889Srwatson * Attach the user audit record to the kernel audit record. Because 112155192Srwatson * this system call is an auditable event, we will write the user 113155192Srwatson * record along with the record for this audit event. 114155192Srwatson * 115155192Srwatson * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen, 116155192Srwatson * k_ar_commit & AR_COMMIT_USER? 117155192Srwatson */ 118155192Srwatson ar->k_udata = rec; 119155192Srwatson ar->k_ulen = uap->length; 120155192Srwatson ar->k_ar_commit |= AR_COMMIT_USER; 121155192Srwatson return (0); 122155192Srwatson 123155192Srwatsonfree_out: 124156889Srwatson /* 125156889Srwatson * audit_syscall_exit() will free the audit record on the thread even 126156889Srwatson * if we allocated it above. 127155192Srwatson */ 128155192Srwatson free(rec, M_AUDITDATA); 129155192Srwatson return (error); 130155192Srwatson} 131155192Srwatson 132155192Srwatson/* 133155192Srwatson * MPSAFE 134155192Srwatson * 135155192Srwatson * System call to manipulate auditing. 136155192Srwatson */ 137155192Srwatson/* ARGSUSED */ 138155192Srwatsonint 139155192Srwatsonauditon(struct thread *td, struct auditon_args *uap) 140155192Srwatson{ 141155192Srwatson int error; 142155192Srwatson union auditon_udata udata; 143155192Srwatson struct proc *tp; 144155192Srwatson 145155192Srwatson AUDIT_ARG(cmd, uap->cmd); 146155192Srwatson error = suser(td); 147155192Srwatson if (error) 148155192Srwatson return (error); 149155192Srwatson 150155192Srwatson if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata))) 151155192Srwatson return (EINVAL); 152155192Srwatson 153155192Srwatson memset((void *)&udata, 0, sizeof(udata)); 154155192Srwatson 155156889Srwatson /* 156156889Srwatson * Some of the GET commands use the arguments too. 157156889Srwatson */ 158155192Srwatson switch (uap->cmd) { 159155192Srwatson case A_SETPOLICY: 160155192Srwatson case A_SETKMASK: 161155192Srwatson case A_SETQCTRL: 162155192Srwatson case A_SETSTAT: 163155192Srwatson case A_SETUMASK: 164155192Srwatson case A_SETSMASK: 165155192Srwatson case A_SETCOND: 166155192Srwatson case A_SETCLASS: 167155192Srwatson case A_SETPMASK: 168155192Srwatson case A_SETFSIZE: 169155192Srwatson case A_SETKAUDIT: 170155192Srwatson case A_GETCLASS: 171155192Srwatson case A_GETPINFO: 172155192Srwatson case A_GETPINFO_ADDR: 173155192Srwatson case A_SENDTRIGGER: 174155192Srwatson error = copyin(uap->data, (void *)&udata, uap->length); 175155192Srwatson if (error) 176155192Srwatson return (error); 177155192Srwatson AUDIT_ARG(auditon, &udata); 178155192Srwatson break; 179155192Srwatson } 180155192Srwatson 181156889Srwatson /* 182156889Srwatson * XXX Need to implement these commands by accessing the global 183155192Srwatson * values associated with the commands. 184155192Srwatson * 185155192Srwatson * XXXAUDIT: Locking? 186155192Srwatson */ 187155192Srwatson switch (uap->cmd) { 188155192Srwatson case A_GETPOLICY: 189155192Srwatson if (!audit_fail_stop) 190155192Srwatson udata.au_policy |= AUDIT_CNT; 191155192Srwatson if (audit_panic_on_write_fail) 192155192Srwatson udata.au_policy |= AUDIT_AHLT; 193155192Srwatson break; 194155192Srwatson 195155192Srwatson case A_SETPOLICY: 196155192Srwatson if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT)) 197155192Srwatson return (EINVAL); 198155192Srwatson /* 199155192Srwatson * XXX - Need to wake up waiters if the policy relaxes? 200155192Srwatson */ 201155192Srwatson audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0); 202155192Srwatson audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT); 203155192Srwatson break; 204155192Srwatson 205155192Srwatson case A_GETKMASK: 206155192Srwatson udata.au_mask = audit_nae_mask; 207155192Srwatson break; 208155192Srwatson 209155192Srwatson case A_SETKMASK: 210155192Srwatson audit_nae_mask = udata.au_mask; 211155192Srwatson break; 212155192Srwatson 213155192Srwatson case A_GETQCTRL: 214155192Srwatson udata.au_qctrl = audit_qctrl; 215155192Srwatson break; 216155192Srwatson 217155192Srwatson case A_SETQCTRL: 218155192Srwatson if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) || 219155192Srwatson (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) || 220155192Srwatson (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) || 221155192Srwatson (udata.au_qctrl.aq_minfree < 0) || 222155192Srwatson (udata.au_qctrl.aq_minfree > 100)) 223155192Srwatson return (EINVAL); 224155192Srwatson 225155192Srwatson audit_qctrl = udata.au_qctrl; 226155192Srwatson /* XXX The queue delay value isn't used with the kernel. */ 227155192Srwatson audit_qctrl.aq_delay = -1; 228155192Srwatson break; 229155192Srwatson 230155192Srwatson case A_GETCWD: 231155192Srwatson return (ENOSYS); 232155192Srwatson break; 233155192Srwatson 234155192Srwatson case A_GETCAR: 235155192Srwatson return (ENOSYS); 236155192Srwatson break; 237155192Srwatson 238155192Srwatson case A_GETSTAT: 239155192Srwatson return (ENOSYS); 240155192Srwatson break; 241155192Srwatson 242155192Srwatson case A_SETSTAT: 243155192Srwatson return (ENOSYS); 244155192Srwatson break; 245155192Srwatson 246155192Srwatson case A_SETUMASK: 247155192Srwatson return (ENOSYS); 248155192Srwatson break; 249155192Srwatson 250155192Srwatson case A_SETSMASK: 251155192Srwatson return (ENOSYS); 252155192Srwatson break; 253155192Srwatson 254155192Srwatson case A_GETCOND: 255155192Srwatson if (audit_enabled && !audit_suspended) 256155192Srwatson udata.au_cond = AUC_AUDITING; 257155192Srwatson else 258155192Srwatson udata.au_cond = AUC_NOAUDIT; 259155192Srwatson break; 260155192Srwatson 261155192Srwatson case A_SETCOND: 262156889Srwatson if (udata.au_cond == AUC_NOAUDIT) 263155192Srwatson audit_suspended = 1; 264156889Srwatson if (udata.au_cond == AUC_AUDITING) 265155192Srwatson audit_suspended = 0; 266155192Srwatson if (udata.au_cond == AUC_DISABLED) { 267155192Srwatson audit_suspended = 1; 268155192Srwatson audit_shutdown(NULL, 0); 269155192Srwatson } 270155192Srwatson break; 271155192Srwatson 272155192Srwatson case A_GETCLASS: 273156889Srwatson udata.au_evclass.ec_class = au_event_class( 274156889Srwatson udata.au_evclass.ec_number); 275155192Srwatson break; 276155192Srwatson 277155192Srwatson case A_SETCLASS: 278155192Srwatson au_evclassmap_insert(udata.au_evclass.ec_number, 279156889Srwatson udata.au_evclass.ec_class); 280155192Srwatson break; 281155192Srwatson 282155192Srwatson case A_GETPINFO: 283156889Srwatson if (udata.au_aupinfo.ap_pid < 1) 284155192Srwatson return (EINVAL); 285155192Srwatson 286155192Srwatson /* XXXAUDIT: p_cansee()? */ 287155192Srwatson if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 288155192Srwatson return (EINVAL); 289155192Srwatson 290155192Srwatson udata.au_aupinfo.ap_auid = tp->p_au->ai_auid; 291156889Srwatson udata.au_aupinfo.ap_mask.am_success = 292156889Srwatson tp->p_au->ai_mask.am_success; 293156889Srwatson udata.au_aupinfo.ap_mask.am_failure = 294156889Srwatson tp->p_au->ai_mask.am_failure; 295156889Srwatson udata.au_aupinfo.ap_termid.machine = 296156889Srwatson tp->p_au->ai_termid.machine; 297156889Srwatson udata.au_aupinfo.ap_termid.port = tp->p_au->ai_termid.port; 298155192Srwatson udata.au_aupinfo.ap_asid = tp->p_au->ai_asid; 299155192Srwatson PROC_UNLOCK(tp); 300155192Srwatson break; 301155192Srwatson 302155192Srwatson case A_SETPMASK: 303156889Srwatson if (udata.au_aupinfo.ap_pid < 1) 304155192Srwatson return (EINVAL); 305155192Srwatson 306155192Srwatson /* XXXAUDIT: p_cansee()? */ 307155192Srwatson if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 308155192Srwatson return (EINVAL); 309155192Srwatson 310156889Srwatson tp->p_au->ai_mask.am_success = 311156889Srwatson udata.au_aupinfo.ap_mask.am_success; 312156889Srwatson tp->p_au->ai_mask.am_failure = 313156889Srwatson udata.au_aupinfo.ap_mask.am_failure; 314155192Srwatson PROC_UNLOCK(tp); 315155192Srwatson break; 316155192Srwatson 317155192Srwatson case A_SETFSIZE: 318155192Srwatson if ((udata.au_fstat.af_filesz != 0) && 319155192Srwatson (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) 320155192Srwatson return (EINVAL); 321155192Srwatson audit_fstat.af_filesz = udata.au_fstat.af_filesz; 322155192Srwatson break; 323155192Srwatson 324155192Srwatson case A_GETFSIZE: 325155192Srwatson udata.au_fstat.af_filesz = audit_fstat.af_filesz; 326155192Srwatson udata.au_fstat.af_currsz = audit_fstat.af_currsz; 327155192Srwatson break; 328155192Srwatson 329155192Srwatson case A_GETPINFO_ADDR: 330155192Srwatson return (ENOSYS); 331155192Srwatson break; 332155192Srwatson 333155192Srwatson case A_GETKAUDIT: 334155192Srwatson return (ENOSYS); 335155192Srwatson break; 336155192Srwatson 337155192Srwatson case A_SETKAUDIT: 338155192Srwatson return (ENOSYS); 339155192Srwatson break; 340155192Srwatson 341155192Srwatson case A_SENDTRIGGER: 342155192Srwatson if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || 343155192Srwatson (udata.au_trigger > AUDIT_TRIGGER_MAX)) 344155192Srwatson return (EINVAL); 345156845Srwatson return (send_trigger(udata.au_trigger)); 346155192Srwatson } 347156889Srwatson 348156889Srwatson /* 349156889Srwatson * Copy data back to userspace for the GET comands. 350156889Srwatson */ 351155192Srwatson switch (uap->cmd) { 352155192Srwatson case A_GETPOLICY: 353155192Srwatson case A_GETKMASK: 354155192Srwatson case A_GETQCTRL: 355155192Srwatson case A_GETCWD: 356155192Srwatson case A_GETCAR: 357155192Srwatson case A_GETSTAT: 358155192Srwatson case A_GETCOND: 359155192Srwatson case A_GETCLASS: 360155192Srwatson case A_GETPINFO: 361155192Srwatson case A_GETFSIZE: 362155192Srwatson case A_GETPINFO_ADDR: 363155192Srwatson case A_GETKAUDIT: 364155192Srwatson error = copyout((void *)&udata, uap->data, uap->length); 365155192Srwatson if (error) 366155192Srwatson return (error); 367155192Srwatson break; 368155192Srwatson } 369155192Srwatson 370155192Srwatson return (0); 371155192Srwatson} 372155192Srwatson 373156889Srwatson/* 374155192Srwatson * MPSAFE 375155192Srwatson * 376155192Srwatson * System calls to manage the user audit information. 377155192Srwatson */ 378155192Srwatson/* ARGSUSED */ 379155192Srwatsonint 380155192Srwatsongetauid(struct thread *td, struct getauid_args *uap) 381155192Srwatson{ 382155192Srwatson int error; 383155192Srwatson au_id_t id; 384155192Srwatson 385155192Srwatson error = suser(td); 386155192Srwatson if (error) 387155192Srwatson return (error); 388155192Srwatson 389155192Srwatson /* 390156889Srwatson * XXX: Integer read on static pointer dereference: doesn't need 391156889Srwatson * locking? 392155192Srwatson */ 393155192Srwatson PROC_LOCK(td->td_proc); 394155192Srwatson id = td->td_proc->p_au->ai_auid; 395155192Srwatson PROC_UNLOCK(td->td_proc); 396155192Srwatson return copyout(&id, uap->auid, sizeof(id)); 397155192Srwatson} 398155192Srwatson 399155192Srwatson/* MPSAFE */ 400155192Srwatson/* ARGSUSED */ 401155192Srwatsonint 402155192Srwatsonsetauid(struct thread *td, struct setauid_args *uap) 403155192Srwatson{ 404155192Srwatson int error; 405155192Srwatson au_id_t id; 406155192Srwatson 407155192Srwatson error = suser(td); 408155192Srwatson if (error) 409155192Srwatson return (error); 410155192Srwatson 411155192Srwatson error = copyin(uap->auid, &id, sizeof(id)); 412155192Srwatson if (error) 413155192Srwatson return (error); 414155192Srwatson 415155192Srwatson audit_arg_auid(id); 416155192Srwatson 417155192Srwatson /* 418156889Srwatson * XXX: Integer write on static pointer dereference: doesn't need 419156889Srwatson * locking? 420155192Srwatson * 421155192Srwatson * XXXAUDIT: Might need locking to serialize audit events in the same 422155192Srwatson * order as change events? Or maybe that's an under-solveable 423155192Srwatson * problem. 424155192Srwatson * 425155192Srwatson * XXXRW: Test privilege while holding the proc lock? 426156889Srwatson */ 427155192Srwatson PROC_LOCK(td->td_proc); 428155192Srwatson td->td_proc->p_au->ai_auid = id; 429155192Srwatson PROC_UNLOCK(td->td_proc); 430155192Srwatson 431155192Srwatson return (0); 432155192Srwatson} 433155192Srwatson 434155192Srwatson/* 435155192Srwatson * MPSAFE 436156889Srwatson * System calls to get and set process audit information. 437155192Srwatson */ 438155192Srwatson/* ARGSUSED */ 439155192Srwatsonint 440155192Srwatsongetaudit(struct thread *td, struct getaudit_args *uap) 441155192Srwatson{ 442155192Srwatson struct auditinfo ai; 443155192Srwatson int error; 444155192Srwatson 445155192Srwatson error = suser(td); 446155192Srwatson if (error) 447155192Srwatson return (error); 448155192Srwatson 449155192Srwatson PROC_LOCK(td->td_proc); 450155192Srwatson ai = *td->td_proc->p_au; 451155192Srwatson PROC_UNLOCK(td->td_proc); 452155192Srwatson 453155192Srwatson return (copyout(&ai, uap->auditinfo, sizeof(ai))); 454155192Srwatson} 455155192Srwatson 456155192Srwatson/* MPSAFE */ 457155192Srwatson/* ARGSUSED */ 458155192Srwatsonint 459155192Srwatsonsetaudit(struct thread *td, struct setaudit_args *uap) 460155192Srwatson{ 461155192Srwatson struct auditinfo ai; 462155192Srwatson int error; 463155192Srwatson 464155192Srwatson error = suser(td); 465155192Srwatson if (error) 466155192Srwatson return (error); 467155192Srwatson 468155192Srwatson error = copyin(uap->auditinfo, &ai, sizeof(ai)); 469155192Srwatson if (error) 470155192Srwatson return (error); 471155192Srwatson 472155192Srwatson audit_arg_auditinfo(&ai); 473155192Srwatson 474155192Srwatson /* 475155192Srwatson * XXXRW: Test privilege while holding the proc lock? 476155192Srwatson */ 477155192Srwatson PROC_LOCK(td->td_proc); 478155192Srwatson *td->td_proc->p_au = ai; 479155192Srwatson PROC_UNLOCK(td->td_proc); 480155192Srwatson 481155192Srwatson return (0); 482155192Srwatson} 483155192Srwatson 484155192Srwatson/* MPSAFE */ 485155192Srwatson/* ARGSUSED */ 486155192Srwatsonint 487155192Srwatsongetaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 488155192Srwatson{ 489155192Srwatson int error; 490155192Srwatson 491155192Srwatson error = suser(td); 492155192Srwatson if (error) 493155192Srwatson return (error); 494155192Srwatson return (ENOSYS); 495155192Srwatson} 496155192Srwatson 497155192Srwatson/* MPSAFE */ 498155192Srwatson/* ARGSUSED */ 499155192Srwatsonint 500155192Srwatsonsetaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 501155192Srwatson{ 502155192Srwatson int error; 503155192Srwatson 504155192Srwatson error = suser(td); 505155192Srwatson if (error) 506155192Srwatson return (error); 507155192Srwatson return (ENOSYS); 508155192Srwatson} 509155192Srwatson 510155192Srwatson/* 511155192Srwatson * MPSAFE 512155192Srwatson * Syscall to manage audit files. 513155192Srwatson * 514155192Srwatson * XXX: Should generate an audit event. 515155192Srwatson */ 516155192Srwatson/* ARGSUSED */ 517155192Srwatsonint 518155192Srwatsonauditctl(struct thread *td, struct auditctl_args *uap) 519155192Srwatson{ 520155192Srwatson struct nameidata nd; 521155192Srwatson struct ucred *cred; 522155192Srwatson struct vnode *vp; 523155192Srwatson int error = 0; 524159318Srwatson int flags, vfslocked; 525155192Srwatson 526155192Srwatson error = suser(td); 527155192Srwatson if (error) 528155192Srwatson return (error); 529155192Srwatson 530155192Srwatson vp = NULL; 531155192Srwatson cred = NULL; 532155192Srwatson 533155192Srwatson /* 534155192Srwatson * If a path is specified, open the replacement vnode, perform 535155192Srwatson * validity checks, and grab another reference to the current 536155192Srwatson * credential. 537155192Srwatson * 538155192Srwatson * XXXAUDIT: On Darwin, a NULL path is used to disable audit. 539155192Srwatson */ 540155192Srwatson if (uap->path == NULL) 541155192Srwatson return (EINVAL); 542155192Srwatson 543159318Srwatson NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE, 544159318Srwatson uap->path, td); 545155192Srwatson flags = AUDIT_OPEN_FLAGS; 546155192Srwatson error = vn_open(&nd, &flags, 0, -1); 547159318Srwatson if (error) 548159318Srwatson return (error); 549159318Srwatson vfslocked = NDHASGIANT(&nd); 550155192Srwatson VOP_UNLOCK(nd.ni_vp, 0, td); 551155192Srwatson vp = nd.ni_vp; 552155192Srwatson if (vp->v_type != VREG) { 553155192Srwatson vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 554159318Srwatson VFS_UNLOCK_GIANT(vfslocked); 555159318Srwatson return (EINVAL); 556155192Srwatson } 557159318Srwatson VFS_UNLOCK_GIANT(vfslocked); 558155192Srwatson cred = td->td_ucred; 559155192Srwatson crhold(cred); 560155192Srwatson 561155192Srwatson /* 562155192Srwatson * XXXAUDIT: Should audit_suspended actually be cleared by 563155192Srwatson * audit_worker? 564155192Srwatson */ 565155192Srwatson audit_suspended = 0; 566155192Srwatson 567155192Srwatson audit_rotate_vnode(cred, vp); 568155192Srwatson 569155192Srwatson return (error); 570155192Srwatson} 571155192Srwatson 572155192Srwatson#else /* !AUDIT */ 573155192Srwatson 574155192Srwatsonint 575155192Srwatsonaudit(struct thread *td, struct audit_args *uap) 576155192Srwatson{ 577155192Srwatson 578155192Srwatson return (ENOSYS); 579155192Srwatson} 580155192Srwatson 581155192Srwatsonint 582155192Srwatsonauditon(struct thread *td, struct auditon_args *uap) 583155192Srwatson{ 584155192Srwatson 585155192Srwatson return (ENOSYS); 586155192Srwatson} 587155192Srwatson 588155192Srwatsonint 589155192Srwatsongetauid(struct thread *td, struct getauid_args *uap) 590155192Srwatson{ 591155192Srwatson 592155192Srwatson return (ENOSYS); 593155192Srwatson} 594155192Srwatson 595155192Srwatsonint 596155192Srwatsonsetauid(struct thread *td, struct setauid_args *uap) 597155192Srwatson{ 598155192Srwatson 599155192Srwatson return (ENOSYS); 600155192Srwatson} 601155192Srwatson 602155192Srwatsonint 603155192Srwatsongetaudit(struct thread *td, struct getaudit_args *uap) 604155192Srwatson{ 605155192Srwatson 606155192Srwatson return (ENOSYS); 607155192Srwatson} 608155192Srwatson 609155192Srwatsonint 610155192Srwatsonsetaudit(struct thread *td, struct setaudit_args *uap) 611155192Srwatson{ 612155192Srwatson 613155192Srwatson return (ENOSYS); 614155192Srwatson} 615155192Srwatson 616155192Srwatsonint 617155192Srwatsongetaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 618155192Srwatson{ 619155192Srwatson 620155192Srwatson return (ENOSYS); 621155192Srwatson} 622155192Srwatson 623155192Srwatsonint 624155192Srwatsonsetaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 625155192Srwatson{ 626155192Srwatson 627155192Srwatson return (ENOSYS); 628155192Srwatson} 629155192Srwatson 630155192Srwatsonint 631155192Srwatsonauditctl(struct thread *td, struct auditctl_args *uap) 632155192Srwatson{ 633155192Srwatson 634155192Srwatson return (ENOSYS); 635155192Srwatson} 636155192Srwatson 637155192Srwatsonvoid 638155192Srwatsonaudit_proc_init(struct proc *p) 639155192Srwatson{ 640155192Srwatson 641155192Srwatson} 642155192Srwatson 643155192Srwatsonvoid 644155192Srwatsonaudit_proc_fork(struct proc *parent, struct proc *child) 645155192Srwatson{ 646155192Srwatson 647155192Srwatson} 648155192Srwatson 649155192Srwatsonvoid 650155192Srwatsonaudit_proc_free(struct proc *p) 651155192Srwatson{ 652155192Srwatson 653155192Srwatson} 654155192Srwatson 655155192Srwatson#endif /* AUDIT */ 656