audit_syscalls.c revision 170777
1/* 2 * Copyright (c) 1999-2005 Apple Computer, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $FreeBSD: head/sys/security/audit/audit_syscalls.c 170777 2007-06-15 15:20:56Z rwatson $ 30 */ 31 32#include "opt_mac.h" 33 34#include <sys/param.h> 35#include <sys/mount.h> 36#include <sys/namei.h> 37#include <sys/priv.h> 38#include <sys/proc.h> 39#include <sys/sysproto.h> 40#include <sys/systm.h> 41#include <sys/vnode.h> 42#include <sys/jail.h> 43 44#include <bsm/audit.h> 45#include <bsm/audit_kevents.h> 46 47#include <security/audit/audit.h> 48#include <security/audit/audit_private.h> 49#include <security/mac/mac_framework.h> 50 51#ifdef AUDIT 52 53/* 54 * System call to allow a user space application to submit a BSM audit record 55 * to the kernel for inclusion in the audit log. This function does little 56 * verification on the audit record that is submitted. 57 * 58 * XXXAUDIT: Audit preselection for user records does not currently work, 59 * since we pre-select only based on the AUE_audit event type, not the event 60 * type submitted as part of the user audit data. 61 */ 62/* ARGSUSED */ 63int 64audit(struct thread *td, struct audit_args *uap) 65{ 66 int error; 67 void * rec; 68 struct kaudit_record *ar; 69 70 if (jailed(td->td_ucred)) 71 return (ENOSYS); 72 error = priv_check(td, PRIV_AUDIT_SUBMIT); 73 if (error) 74 return (error); 75 76 if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) 77 return (EINVAL); 78 79 ar = currecord(); 80 81 /* 82 * If there's no current audit record (audit() itself not audited) 83 * commit the user audit record. 84 */ 85 if (ar == NULL) { 86 87 /* 88 * This is not very efficient; we're required to allocate a 89 * complete kernel audit record just so the user record can 90 * tag along. 91 * 92 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and 93 * special pre-select handling? 94 */ 95 td->td_ar = audit_new(AUE_NULL, td); 96 if (td->td_ar == NULL) 97 return (ENOTSUP); 98 ar = td->td_ar; 99 } 100 101 if (uap->length > MAX_AUDIT_RECORD_SIZE) 102 return (EINVAL); 103 104 rec = malloc(uap->length, M_AUDITDATA, M_WAITOK); 105 106 error = copyin(uap->record, rec, uap->length); 107 if (error) 108 goto free_out; 109 110 /* Verify the record. */ 111 if (bsm_rec_verify(rec) == 0) { 112 error = EINVAL; 113 goto free_out; 114 } 115 116#ifdef MAC 117 error = mac_check_system_audit(td->td_ucred, rec, uap->length); 118 if (error) 119 goto free_out; 120#endif 121 122 /* 123 * Attach the user audit record to the kernel audit record. Because 124 * this system call is an auditable event, we will write the user 125 * record along with the record for this audit event. 126 * 127 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen, 128 * k_ar_commit & AR_COMMIT_USER? 129 */ 130 ar->k_udata = rec; 131 ar->k_ulen = uap->length; 132 ar->k_ar_commit |= AR_COMMIT_USER; 133 134 /* 135 * Currently we assume that all preselection has been performed in 136 * userspace. We unconditionally set these masks so that the records 137 * get committed both to the trail and pipe. In the future we will 138 * want to setup kernel based preselection. 139 */ 140 ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE); 141 return (0); 142 143free_out: 144 /* 145 * audit_syscall_exit() will free the audit record on the thread even 146 * if we allocated it above. 147 */ 148 free(rec, M_AUDITDATA); 149 return (error); 150} 151 152/* 153 * System call to manipulate auditing. 154 */ 155/* ARGSUSED */ 156int 157auditon(struct thread *td, struct auditon_args *uap) 158{ 159 struct ucred *newcred, *oldcred; 160 int error; 161 union auditon_udata udata; 162 struct proc *tp; 163 164 if (jailed(td->td_ucred)) 165 return (ENOSYS); 166 AUDIT_ARG(cmd, uap->cmd); 167 168#ifdef MAC 169 error = mac_check_system_auditon(td->td_ucred, uap->cmd); 170 if (error) 171 return (error); 172#endif 173 174 error = priv_check(td, PRIV_AUDIT_CONTROL); 175 if (error) 176 return (error); 177 178 if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata))) 179 return (EINVAL); 180 181 memset((void *)&udata, 0, sizeof(udata)); 182 183 /* 184 * Some of the GET commands use the arguments too. 185 */ 186 switch (uap->cmd) { 187 case A_SETPOLICY: 188 case A_SETKMASK: 189 case A_SETQCTRL: 190 case A_SETSTAT: 191 case A_SETUMASK: 192 case A_SETSMASK: 193 case A_SETCOND: 194 case A_SETCLASS: 195 case A_SETPMASK: 196 case A_SETFSIZE: 197 case A_SETKAUDIT: 198 case A_GETCLASS: 199 case A_GETPINFO: 200 case A_GETPINFO_ADDR: 201 case A_SENDTRIGGER: 202 error = copyin(uap->data, (void *)&udata, uap->length); 203 if (error) 204 return (error); 205 AUDIT_ARG(auditon, &udata); 206 break; 207 } 208 209 /* 210 * XXXAUDIT: Locking? 211 */ 212 switch (uap->cmd) { 213 case A_GETPOLICY: 214 if (!audit_fail_stop) 215 udata.au_policy |= AUDIT_CNT; 216 if (audit_panic_on_write_fail) 217 udata.au_policy |= AUDIT_AHLT; 218 if (audit_argv) 219 udata.au_policy |= AUDIT_ARGV; 220 if (audit_arge) 221 udata.au_policy |= AUDIT_ARGE; 222 break; 223 224 case A_SETPOLICY: 225 if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV| 226 AUDIT_ARGE)) 227 return (EINVAL); 228 /* 229 * XXX - Need to wake up waiters if the policy relaxes? 230 */ 231 audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0); 232 audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT); 233 audit_argv = (udata.au_policy & AUDIT_ARGV); 234 audit_arge = (udata.au_policy & AUDIT_ARGE); 235 break; 236 237 case A_GETKMASK: 238 udata.au_mask = audit_nae_mask; 239 break; 240 241 case A_SETKMASK: 242 audit_nae_mask = udata.au_mask; 243 break; 244 245 case A_GETQCTRL: 246 udata.au_qctrl = audit_qctrl; 247 break; 248 249 case A_SETQCTRL: 250 if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) || 251 (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) || 252 (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) || 253 (udata.au_qctrl.aq_minfree < 0) || 254 (udata.au_qctrl.aq_minfree > 100)) 255 return (EINVAL); 256 257 audit_qctrl = udata.au_qctrl; 258 /* XXX The queue delay value isn't used with the kernel. */ 259 audit_qctrl.aq_delay = -1; 260 break; 261 262 case A_GETCWD: 263 return (ENOSYS); 264 break; 265 266 case A_GETCAR: 267 return (ENOSYS); 268 break; 269 270 case A_GETSTAT: 271 return (ENOSYS); 272 break; 273 274 case A_SETSTAT: 275 return (ENOSYS); 276 break; 277 278 case A_SETUMASK: 279 return (ENOSYS); 280 break; 281 282 case A_SETSMASK: 283 return (ENOSYS); 284 break; 285 286 case A_GETCOND: 287 if (audit_enabled && !audit_suspended) 288 udata.au_cond = AUC_AUDITING; 289 else 290 udata.au_cond = AUC_NOAUDIT; 291 break; 292 293 case A_SETCOND: 294 if (udata.au_cond == AUC_NOAUDIT) 295 audit_suspended = 1; 296 if (udata.au_cond == AUC_AUDITING) 297 audit_suspended = 0; 298 if (udata.au_cond == AUC_DISABLED) { 299 audit_suspended = 1; 300 audit_shutdown(NULL, 0); 301 } 302 break; 303 304 case A_GETCLASS: 305 udata.au_evclass.ec_class = au_event_class( 306 udata.au_evclass.ec_number); 307 break; 308 309 case A_SETCLASS: 310 au_evclassmap_insert(udata.au_evclass.ec_number, 311 udata.au_evclass.ec_class); 312 break; 313 314 case A_GETPINFO: 315 if (udata.au_aupinfo.ap_pid < 1) 316 return (EINVAL); 317 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 318 return (EINVAL); 319 if (p_cansee(td, tp) != 0) { 320 PROC_UNLOCK(tp); 321 return (EINVAL); 322 } 323 if (tp->p_ucred->cr_audit.ai_termid.at_type == AU_IPv6) { 324 PROC_UNLOCK(tp); 325 return (EINVAL); 326 } 327 udata.au_aupinfo.ap_auid = 328 tp->p_ucred->cr_audit.ai_auid; 329 udata.au_aupinfo.ap_mask.am_success = 330 tp->p_ucred->cr_audit.ai_mask.am_success; 331 udata.au_aupinfo.ap_mask.am_failure = 332 tp->p_ucred->cr_audit.ai_mask.am_failure; 333 udata.au_aupinfo.ap_termid.machine = 334 tp->p_ucred->cr_audit.ai_termid.at_addr[0]; 335 udata.au_aupinfo.ap_termid.port = 336 (dev_t)tp->p_ucred->cr_audit.ai_termid.at_port; 337 udata.au_aupinfo.ap_asid = 338 tp->p_ucred->cr_audit.ai_asid; 339 PROC_UNLOCK(tp); 340 break; 341 342 case A_SETPMASK: 343 if (udata.au_aupinfo.ap_pid < 1) 344 return (EINVAL); 345 newcred = crget(); 346 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) { 347 crfree(newcred); 348 return (EINVAL); 349 } 350 if (p_cansee(td, tp) != 0) { 351 PROC_UNLOCK(tp); 352 crfree(newcred); 353 return (EINVAL); 354 } 355 oldcred = tp->p_ucred; 356 crcopy(newcred, oldcred); 357 newcred->cr_audit.ai_mask.am_success = 358 udata.au_aupinfo.ap_mask.am_success; 359 newcred->cr_audit.ai_mask.am_failure = 360 udata.au_aupinfo.ap_mask.am_failure; 361 td->td_proc->p_ucred = newcred; 362 PROC_UNLOCK(tp); 363 crfree(oldcred); 364 break; 365 366 case A_SETFSIZE: 367 if ((udata.au_fstat.af_filesz != 0) && 368 (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) 369 return (EINVAL); 370 audit_fstat.af_filesz = udata.au_fstat.af_filesz; 371 break; 372 373 case A_GETFSIZE: 374 udata.au_fstat.af_filesz = audit_fstat.af_filesz; 375 udata.au_fstat.af_currsz = audit_fstat.af_currsz; 376 break; 377 378 case A_GETPINFO_ADDR: 379 if (udata.au_aupinfo_addr.ap_pid < 1) 380 return (EINVAL); 381 if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL) 382 return (EINVAL); 383 udata.au_aupinfo_addr.ap_auid = 384 tp->p_ucred->cr_audit.ai_auid; 385 udata.au_aupinfo_addr.ap_mask.am_success = 386 tp->p_ucred->cr_audit.ai_mask.am_success; 387 udata.au_aupinfo_addr.ap_mask.am_failure = 388 tp->p_ucred->cr_audit.ai_mask.am_failure; 389 udata.au_aupinfo_addr.ap_termid = 390 tp->p_ucred->cr_audit.ai_termid; 391 udata.au_aupinfo_addr.ap_asid = 392 tp->p_ucred->cr_audit.ai_asid; 393 PROC_UNLOCK(tp); 394 break; 395 396 case A_GETKAUDIT: 397 return (ENOSYS); 398 break; 399 400 case A_SETKAUDIT: 401 return (ENOSYS); 402 break; 403 404 case A_SENDTRIGGER: 405 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || 406 (udata.au_trigger > AUDIT_TRIGGER_MAX)) 407 return (EINVAL); 408 return (send_trigger(udata.au_trigger)); 409 } 410 411 /* 412 * Copy data back to userspace for the GET comands. 413 */ 414 switch (uap->cmd) { 415 case A_GETPOLICY: 416 case A_GETKMASK: 417 case A_GETQCTRL: 418 case A_GETCWD: 419 case A_GETCAR: 420 case A_GETSTAT: 421 case A_GETCOND: 422 case A_GETCLASS: 423 case A_GETPINFO: 424 case A_GETFSIZE: 425 case A_GETPINFO_ADDR: 426 case A_GETKAUDIT: 427 error = copyout((void *)&udata, uap->data, uap->length); 428 if (error) 429 return (error); 430 break; 431 } 432 433 return (0); 434} 435 436/* 437 * System calls to manage the user audit information. 438 */ 439/* ARGSUSED */ 440int 441getauid(struct thread *td, struct getauid_args *uap) 442{ 443 int error; 444 445 if (jailed(td->td_ucred)) 446 return (ENOSYS); 447 error = priv_check(td, PRIV_AUDIT_GETAUDIT); 448 if (error) 449 return (error); 450 return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid, 451 sizeof(td->td_ucred->cr_audit.ai_auid))); 452} 453 454/* ARGSUSED */ 455int 456setauid(struct thread *td, struct setauid_args *uap) 457{ 458 struct ucred *newcred, *oldcred; 459 au_id_t id; 460 int error; 461 462 if (jailed(td->td_ucred)) 463 return (ENOSYS); 464 error = copyin(uap->auid, &id, sizeof(id)); 465 if (error) 466 return (error); 467 audit_arg_auid(id); 468 newcred = crget(); 469 PROC_LOCK(td->td_proc); 470 oldcred = td->td_proc->p_ucred; 471 crcopy(newcred, oldcred); 472#ifdef MAC 473 error = mac_check_proc_setauid(oldcred, id); 474 if (error) 475 goto fail; 476#endif 477 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 478 if (error) 479 goto fail; 480 newcred->cr_audit.ai_auid = id; 481 td->td_proc->p_ucred = newcred; 482 PROC_UNLOCK(td->td_proc); 483 crfree(oldcred); 484 return (0); 485fail: 486 PROC_UNLOCK(td->td_proc); 487 crfree(newcred); 488 return (error); 489} 490 491/* 492 * System calls to get and set process audit information. 493 */ 494/* ARGSUSED */ 495int 496getaudit(struct thread *td, struct getaudit_args *uap) 497{ 498 struct auditinfo ai; 499 int error; 500 501 if (jailed(td->td_ucred)) 502 return (ENOSYS); 503 error = priv_check(td, PRIV_AUDIT_GETAUDIT); 504 if (error) 505 return (error); 506 bzero(&ai, sizeof(ai)); 507 ai.ai_auid = td->td_ucred->cr_audit.ai_auid; 508 ai.ai_mask = td->td_ucred->cr_audit.ai_mask; 509 ai.ai_asid = td->td_ucred->cr_audit.ai_asid; 510 ai.ai_termid.machine = td->td_ucred->cr_audit.ai_termid.at_addr[0]; 511 ai.ai_termid.port = td->td_ucred->cr_audit.ai_termid.at_port; 512 return (copyout(&ai, uap->auditinfo, sizeof(&ai))); 513} 514 515/* ARGSUSED */ 516int 517setaudit(struct thread *td, struct setaudit_args *uap) 518{ 519 struct ucred *newcred, *oldcred; 520 struct auditinfo ai; 521 int error; 522 523 if (jailed(td->td_ucred)) 524 return (ENOSYS); 525 error = copyin(uap->auditinfo, &ai, sizeof(ai)); 526 if (error) 527 return (error); 528 audit_arg_auditinfo(&ai); 529 newcred = crget(); 530 PROC_LOCK(td->td_proc); 531 oldcred = td->td_proc->p_ucred; 532 crcopy(newcred, oldcred); 533#ifdef MAC 534 error = mac_check_proc_setaudit(oldcred, &ai); 535 if (error) 536 goto fail; 537#endif 538 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 539 if (error) 540 goto fail; 541 bzero(&newcred->cr_audit, sizeof(newcred->cr_audit)); 542 newcred->cr_audit.ai_auid = ai.ai_auid; 543 newcred->cr_audit.ai_mask = ai.ai_mask; 544 newcred->cr_audit.ai_asid = ai.ai_asid; 545 newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine; 546 newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port; 547 newcred->cr_audit.ai_termid.at_type = AU_IPv4; 548 td->td_proc->p_ucred = newcred; 549 PROC_UNLOCK(td->td_proc); 550 crfree(oldcred); 551 return (0); 552fail: 553 PROC_UNLOCK(td->td_proc); 554 crfree(newcred); 555 return (error); 556} 557 558/* ARGSUSED */ 559int 560getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 561{ 562 int error; 563 564 if (jailed(td->td_ucred)) 565 return (ENOSYS); 566 if (uap->length < sizeof(*uap->auditinfo_addr)) 567 return (EOVERFLOW); 568 error = priv_check(td, PRIV_AUDIT_GETAUDIT); 569 if (error) 570 return (error); 571 return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr, 572 sizeof(*uap->auditinfo_addr))); 573} 574 575/* ARGSUSED */ 576int 577setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 578{ 579 struct ucred *newcred, *oldcred; 580 struct auditinfo_addr aia; 581 int error; 582 583 if (jailed(td->td_ucred)) 584 return (ENOSYS); 585 error = copyin(uap->auditinfo_addr, &aia, sizeof(aia)); 586 if (error) 587 return (error); 588 /* XXXRW: Audit argument. */ 589 newcred = crget(); 590 PROC_LOCK(td->td_proc); 591 oldcred = td->td_proc->p_ucred; 592 crcopy(newcred, oldcred); 593#ifdef MAC 594 error = mac_check_proc_setaudit(oldcred, NULL); 595 if (error) 596 goto fail; 597#endif 598 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 599 if (error) 600 goto fail; 601 newcred->cr_audit = aia; 602 td->td_proc->p_ucred = newcred; 603 PROC_UNLOCK(td->td_proc); 604 crfree(oldcred); 605 return (0); 606fail: 607 PROC_UNLOCK(td->td_proc); 608 crfree(newcred); 609 return (error); 610} 611 612/* 613 * Syscall to manage audit files. 614 */ 615/* ARGSUSED */ 616int 617auditctl(struct thread *td, struct auditctl_args *uap) 618{ 619 struct nameidata nd; 620 struct ucred *cred; 621 struct vnode *vp; 622 int error = 0; 623 int flags, vfslocked; 624 625 if (jailed(td->td_ucred)) 626 return (ENOSYS); 627 error = priv_check(td, PRIV_AUDIT_CONTROL); 628 if (error) 629 return (error); 630 631 vp = NULL; 632 cred = NULL; 633 634 /* 635 * If a path is specified, open the replacement vnode, perform 636 * validity checks, and grab another reference to the current 637 * credential. 638 * 639 * On Darwin, a NULL path argument is also used to disable audit. 640 */ 641 if (uap->path == NULL) 642 return (EINVAL); 643 644 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 645 UIO_USERSPACE, uap->path, td); 646 flags = AUDIT_OPEN_FLAGS; 647 error = vn_open(&nd, &flags, 0, NULL); 648 if (error) 649 return (error); 650 vfslocked = NDHASGIANT(&nd); 651 vp = nd.ni_vp; 652#ifdef MAC 653 error = mac_check_system_auditctl(td->td_ucred, vp); 654 VOP_UNLOCK(vp, 0, td); 655 if (error) { 656 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 657 VFS_UNLOCK_GIANT(vfslocked); 658 return (error); 659 } 660#else 661 VOP_UNLOCK(vp, 0, td); 662#endif 663 NDFREE(&nd, NDF_ONLY_PNBUF); 664 if (vp->v_type != VREG) { 665 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 666 VFS_UNLOCK_GIANT(vfslocked); 667 return (EINVAL); 668 } 669 VFS_UNLOCK_GIANT(vfslocked); 670 cred = td->td_ucred; 671 crhold(cred); 672 673 /* 674 * XXXAUDIT: Should audit_suspended actually be cleared by 675 * audit_worker? 676 */ 677 audit_suspended = 0; 678 679 audit_rotate_vnode(cred, vp); 680 681 return (error); 682} 683 684#else /* !AUDIT */ 685 686int 687audit(struct thread *td, struct audit_args *uap) 688{ 689 690 return (ENOSYS); 691} 692 693int 694auditon(struct thread *td, struct auditon_args *uap) 695{ 696 697 return (ENOSYS); 698} 699 700int 701getauid(struct thread *td, struct getauid_args *uap) 702{ 703 704 return (ENOSYS); 705} 706 707int 708setauid(struct thread *td, struct setauid_args *uap) 709{ 710 711 return (ENOSYS); 712} 713 714int 715getaudit(struct thread *td, struct getaudit_args *uap) 716{ 717 718 return (ENOSYS); 719} 720 721int 722setaudit(struct thread *td, struct setaudit_args *uap) 723{ 724 725 return (ENOSYS); 726} 727 728int 729getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 730{ 731 732 return (ENOSYS); 733} 734 735int 736setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 737{ 738 739 return (ENOSYS); 740} 741 742int 743auditctl(struct thread *td, struct auditctl_args *uap) 744{ 745 746 return (ENOSYS); 747} 748#endif /* AUDIT */ 749