1 /*- 2 * Copyright (c) 1999-2009 Apple 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 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 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/mount.h> 35 #include <sys/namei.h> 36 #include <sys/priv.h> 37 #include <sys/proc.h> 38 #include <sys/sysproto.h> 39 #include <sys/systm.h> 40 #include <sys/vnode.h> 41 #include <sys/jail.h> 42 43 #include <bsm/audit.h> 44 #include <bsm/audit_kevents.h> 45 46 #include <security/audit/audit.h> 47 #include <security/audit/audit_private.h> 48 #include <security/mac/mac_framework.h> 49 50 #ifdef AUDIT 51 52 /* 53 * System call to allow a user space application to submit a BSM audit record 54 * to the kernel for inclusion in the audit log. This function does little 55 * verification on the audit record that is submitted. 56 * 57 * XXXAUDIT: Audit preselection for user records does not currently work, 58 * since we pre-select only based on the AUE_audit event type, not the event 59 * type submitted as part of the user audit data. 60 */ 61 /* ARGSUSED */ 62 int 63 sys_audit(struct thread *td, struct audit_args *uap) 64 { 65 int error; 66 void * rec; 67 struct kaudit_record *ar; 68 69 if (jailed(td->td_ucred)) 70 return (ENOSYS); 71 error = priv_check(td, PRIV_AUDIT_SUBMIT); 72 if (error) 73 return (error); 74 75 if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) 76 return (EINVAL); 77 78 ar = currecord(); 79 80 /* 81 * If there's no current audit record (audit() itself not audited) 82 * commit the user audit record. 83 */ 84 if (ar == NULL) { 85 86 /* 87 * This is not very efficient; we're required to allocate a 88 * complete kernel audit record just so the user record can 89 * tag along. 90 * 91 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and 92 * special pre-select handling? 93 */ 94 td->td_ar = audit_new(AUE_NULL, td); 95 if (td->td_ar == NULL) 96 return (ENOTSUP); 97 td->td_pflags |= TDP_AUDITREC; 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_system_check_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 143 free_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 */ 156 int 157 sys_auditon(struct thread *td, struct auditon_args *uap) 158 { 159 struct ucred *cred, *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_system_check_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_OLDSETPOLICY: 189 case A_SETKMASK: 190 case A_SETQCTRL: 191 case A_OLDSETQCTRL: 192 case A_SETSTAT: 193 case A_SETUMASK: 194 case A_SETSMASK: 195 case A_SETCOND: 196 case A_OLDSETCOND: 197 case A_SETCLASS: 198 case A_SETPMASK: 199 case A_SETFSIZE: 200 case A_SETKAUDIT: 201 case A_GETCLASS: 202 case A_GETPINFO: 203 case A_GETPINFO_ADDR: 204 case A_SENDTRIGGER: 205 error = copyin(uap->data, (void *)&udata, uap->length); 206 if (error) 207 return (error); 208 AUDIT_ARG_AUDITON(&udata); 209 break; 210 } 211 212 /* 213 * XXXAUDIT: Locking? 214 */ 215 switch (uap->cmd) { 216 case A_OLDGETPOLICY: 217 case A_GETPOLICY: 218 if (uap->length == sizeof(udata.au_policy64)) { 219 if (!audit_fail_stop) 220 udata.au_policy64 |= AUDIT_CNT; 221 if (audit_panic_on_write_fail) 222 udata.au_policy64 |= AUDIT_AHLT; 223 if (audit_argv) 224 udata.au_policy64 |= AUDIT_ARGV; 225 if (audit_arge) 226 udata.au_policy64 |= AUDIT_ARGE; 227 break; 228 } 229 if (uap->length != sizeof(udata.au_policy)) 230 return (EINVAL); 231 if (!audit_fail_stop) 232 udata.au_policy |= AUDIT_CNT; 233 if (audit_panic_on_write_fail) 234 udata.au_policy |= AUDIT_AHLT; 235 if (audit_argv) 236 udata.au_policy |= AUDIT_ARGV; 237 if (audit_arge) 238 udata.au_policy |= AUDIT_ARGE; 239 break; 240 241 case A_OLDSETPOLICY: 242 case A_SETPOLICY: 243 if (uap->length == sizeof(udata.au_policy64)) { 244 if (udata.au_policy & (~AUDIT_CNT|AUDIT_AHLT| 245 AUDIT_ARGV|AUDIT_ARGE)) 246 return (EINVAL); 247 audit_fail_stop = ((udata.au_policy64 & AUDIT_CNT) == 248 0); 249 audit_panic_on_write_fail = (udata.au_policy64 & 250 AUDIT_AHLT); 251 audit_argv = (udata.au_policy64 & AUDIT_ARGV); 252 audit_arge = (udata.au_policy64 & AUDIT_ARGE); 253 break; 254 } 255 if (uap->length != sizeof(udata.au_policy)) 256 return (EINVAL); 257 if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV| 258 AUDIT_ARGE)) 259 return (EINVAL); 260 /* 261 * XXX - Need to wake up waiters if the policy relaxes? 262 */ 263 audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0); 264 audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT); 265 audit_argv = (udata.au_policy & AUDIT_ARGV); 266 audit_arge = (udata.au_policy & AUDIT_ARGE); 267 break; 268 269 case A_GETKMASK: 270 if (uap->length != sizeof(udata.au_mask)) 271 return (EINVAL); 272 udata.au_mask = audit_nae_mask; 273 break; 274 275 case A_SETKMASK: 276 if (uap->length != sizeof(udata.au_mask)) 277 return (EINVAL); 278 audit_nae_mask = udata.au_mask; 279 break; 280 281 case A_OLDGETQCTRL: 282 case A_GETQCTRL: 283 if (uap->length == sizeof(udata.au_qctrl64)) { 284 udata.au_qctrl64.aq64_hiwater = 285 (u_int64_t)audit_qctrl.aq_hiwater; 286 udata.au_qctrl64.aq64_lowater = 287 (u_int64_t)audit_qctrl.aq_lowater; 288 udata.au_qctrl64.aq64_bufsz = 289 (u_int64_t)audit_qctrl.aq_bufsz; 290 udata.au_qctrl64.aq64_minfree = 291 (u_int64_t)audit_qctrl.aq_minfree; 292 break; 293 } 294 if (uap->length != sizeof(udata.au_qctrl)) 295 return (EINVAL); 296 udata.au_qctrl = audit_qctrl; 297 break; 298 299 case A_OLDSETQCTRL: 300 case A_SETQCTRL: 301 if (uap->length == sizeof(udata.au_qctrl64)) { 302 if ((udata.au_qctrl64.aq64_hiwater > AQ_MAXHIGH) || 303 (udata.au_qctrl64.aq64_lowater >= 304 udata.au_qctrl.aq_hiwater) || 305 (udata.au_qctrl64.aq64_bufsz > AQ_MAXBUFSZ) || 306 (udata.au_qctrl64.aq64_minfree < 0) || 307 (udata.au_qctrl64.aq64_minfree > 100)) 308 return (EINVAL); 309 audit_qctrl.aq_hiwater = 310 (int)udata.au_qctrl64.aq64_hiwater; 311 audit_qctrl.aq_lowater = 312 (int)udata.au_qctrl64.aq64_lowater; 313 audit_qctrl.aq_bufsz = 314 (int)udata.au_qctrl64.aq64_bufsz; 315 audit_qctrl.aq_minfree = 316 (int)udata.au_qctrl64.aq64_minfree; 317 audit_qctrl.aq_delay = -1; /* Not used. */ 318 break; 319 } 320 if (uap->length != sizeof(udata.au_qctrl)) 321 return (EINVAL); 322 if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) || 323 (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) || 324 (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) || 325 (udata.au_qctrl.aq_minfree < 0) || 326 (udata.au_qctrl.aq_minfree > 100)) 327 return (EINVAL); 328 329 audit_qctrl = udata.au_qctrl; 330 /* XXX The queue delay value isn't used with the kernel. */ 331 audit_qctrl.aq_delay = -1; 332 break; 333 334 case A_GETCWD: 335 return (ENOSYS); 336 break; 337 338 case A_GETCAR: 339 return (ENOSYS); 340 break; 341 342 case A_GETSTAT: 343 return (ENOSYS); 344 break; 345 346 case A_SETSTAT: 347 return (ENOSYS); 348 break; 349 350 case A_SETUMASK: 351 return (ENOSYS); 352 break; 353 354 case A_SETSMASK: 355 return (ENOSYS); 356 break; 357 358 case A_OLDGETCOND: 359 case A_GETCOND: 360 if (uap->length == sizeof(udata.au_cond64)) { 361 if (audit_enabled && !audit_suspended) 362 udata.au_cond64 = AUC_AUDITING; 363 else 364 udata.au_cond64 = AUC_NOAUDIT; 365 break; 366 } 367 if (uap->length != sizeof(udata.au_cond)) 368 return (EINVAL); 369 if (audit_enabled && !audit_suspended) 370 udata.au_cond = AUC_AUDITING; 371 else 372 udata.au_cond = AUC_NOAUDIT; 373 break; 374 375 case A_OLDSETCOND: 376 case A_SETCOND: 377 if (uap->length == sizeof(udata.au_cond64)) { 378 if (udata.au_cond64 == AUC_NOAUDIT) 379 audit_suspended = 1; 380 if (udata.au_cond64 == AUC_AUDITING) 381 audit_suspended = 0; 382 if (udata.au_cond64 == AUC_DISABLED) { 383 audit_suspended = 1; 384 audit_shutdown(NULL, 0); 385 } 386 break; 387 } 388 if (uap->length != sizeof(udata.au_cond)) 389 return (EINVAL); 390 if (udata.au_cond == AUC_NOAUDIT) 391 audit_suspended = 1; 392 if (udata.au_cond == AUC_AUDITING) 393 audit_suspended = 0; 394 if (udata.au_cond == AUC_DISABLED) { 395 audit_suspended = 1; 396 audit_shutdown(NULL, 0); 397 } 398 break; 399 400 case A_GETCLASS: 401 if (uap->length != sizeof(udata.au_evclass)) 402 return (EINVAL); 403 udata.au_evclass.ec_class = au_event_class( 404 udata.au_evclass.ec_number); 405 break; 406 407 case A_SETCLASS: 408 if (uap->length != sizeof(udata.au_evclass)) 409 return (EINVAL); 410 au_evclassmap_insert(udata.au_evclass.ec_number, 411 udata.au_evclass.ec_class); 412 break; 413 414 case A_GETPINFO: 415 if (uap->length != sizeof(udata.au_aupinfo)) 416 return (EINVAL); 417 if (udata.au_aupinfo.ap_pid < 1) 418 return (ESRCH); 419 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 420 return (ESRCH); 421 if ((error = p_cansee(td, tp)) != 0) { 422 PROC_UNLOCK(tp); 423 return (error); 424 } 425 cred = tp->p_ucred; 426 if (cred->cr_audit.ai_termid.at_type == AU_IPv6) { 427 PROC_UNLOCK(tp); 428 return (EINVAL); 429 } 430 udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid; 431 udata.au_aupinfo.ap_mask.am_success = 432 cred->cr_audit.ai_mask.am_success; 433 udata.au_aupinfo.ap_mask.am_failure = 434 cred->cr_audit.ai_mask.am_failure; 435 udata.au_aupinfo.ap_termid.machine = 436 cred->cr_audit.ai_termid.at_addr[0]; 437 udata.au_aupinfo.ap_termid.port = 438 (dev_t)cred->cr_audit.ai_termid.at_port; 439 udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid; 440 PROC_UNLOCK(tp); 441 break; 442 443 case A_SETPMASK: 444 if (uap->length != sizeof(udata.au_aupinfo)) 445 return (EINVAL); 446 if (udata.au_aupinfo.ap_pid < 1) 447 return (ESRCH); 448 newcred = crget(); 449 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) { 450 crfree(newcred); 451 return (ESRCH); 452 } 453 if ((error = p_cansee(td, tp)) != 0) { 454 PROC_UNLOCK(tp); 455 crfree(newcred); 456 return (error); 457 } 458 oldcred = tp->p_ucred; 459 crcopy(newcred, oldcred); 460 newcred->cr_audit.ai_mask.am_success = 461 udata.au_aupinfo.ap_mask.am_success; 462 newcred->cr_audit.ai_mask.am_failure = 463 udata.au_aupinfo.ap_mask.am_failure; 464 proc_set_cred(tp, newcred); 465 PROC_UNLOCK(tp); 466 crfree(oldcred); 467 break; 468 469 case A_SETFSIZE: 470 if (uap->length != sizeof(udata.au_fstat)) 471 return (EINVAL); 472 if ((udata.au_fstat.af_filesz != 0) && 473 (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) 474 return (EINVAL); 475 audit_fstat.af_filesz = udata.au_fstat.af_filesz; 476 break; 477 478 case A_GETFSIZE: 479 if (uap->length != sizeof(udata.au_fstat)) 480 return (EINVAL); 481 udata.au_fstat.af_filesz = audit_fstat.af_filesz; 482 udata.au_fstat.af_currsz = audit_fstat.af_currsz; 483 break; 484 485 case A_GETPINFO_ADDR: 486 if (uap->length != sizeof(udata.au_aupinfo_addr)) 487 return (EINVAL); 488 if (udata.au_aupinfo_addr.ap_pid < 1) 489 return (ESRCH); 490 if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL) 491 return (ESRCH); 492 cred = tp->p_ucred; 493 udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid; 494 udata.au_aupinfo_addr.ap_mask.am_success = 495 cred->cr_audit.ai_mask.am_success; 496 udata.au_aupinfo_addr.ap_mask.am_failure = 497 cred->cr_audit.ai_mask.am_failure; 498 udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid; 499 udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid; 500 PROC_UNLOCK(tp); 501 break; 502 503 case A_GETKAUDIT: 504 if (uap->length != sizeof(udata.au_kau_info)) 505 return (EINVAL); 506 audit_get_kinfo(&udata.au_kau_info); 507 break; 508 509 case A_SETKAUDIT: 510 if (uap->length != sizeof(udata.au_kau_info)) 511 return (EINVAL); 512 if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 && 513 udata.au_kau_info.ai_termid.at_type != AU_IPv6) 514 return (EINVAL); 515 audit_set_kinfo(&udata.au_kau_info); 516 break; 517 518 case A_SENDTRIGGER: 519 if (uap->length != sizeof(udata.au_trigger)) 520 return (EINVAL); 521 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || 522 (udata.au_trigger > AUDIT_TRIGGER_MAX)) 523 return (EINVAL); 524 return (audit_send_trigger(udata.au_trigger)); 525 526 default: 527 return (EINVAL); 528 } 529 530 /* 531 * Copy data back to userspace for the GET comands. 532 */ 533 switch (uap->cmd) { 534 case A_GETPOLICY: 535 case A_OLDGETPOLICY: 536 case A_GETKMASK: 537 case A_GETQCTRL: 538 case A_OLDGETQCTRL: 539 case A_GETCWD: 540 case A_GETCAR: 541 case A_GETSTAT: 542 case A_GETCOND: 543 case A_OLDGETCOND: 544 case A_GETCLASS: 545 case A_GETPINFO: 546 case A_GETFSIZE: 547 case A_GETPINFO_ADDR: 548 case A_GETKAUDIT: 549 error = copyout((void *)&udata, uap->data, uap->length); 550 if (error) 551 return (error); 552 break; 553 } 554 555 return (0); 556 } 557 558 /* 559 * System calls to manage the user audit information. 560 */ 561 /* ARGSUSED */ 562 int 563 sys_getauid(struct thread *td, struct getauid_args *uap) 564 { 565 int error; 566 567 if (jailed(td->td_ucred)) 568 return (ENOSYS); 569 error = priv_check(td, PRIV_AUDIT_GETAUDIT); 570 if (error) 571 return (error); 572 return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid, 573 sizeof(td->td_ucred->cr_audit.ai_auid))); 574 } 575 576 /* ARGSUSED */ 577 int 578 sys_setauid(struct thread *td, struct setauid_args *uap) 579 { 580 struct ucred *newcred, *oldcred; 581 au_id_t id; 582 int error; 583 584 if (jailed(td->td_ucred)) 585 return (ENOSYS); 586 error = copyin(uap->auid, &id, sizeof(id)); 587 if (error) 588 return (error); 589 audit_arg_auid(id); 590 newcred = crget(); 591 PROC_LOCK(td->td_proc); 592 oldcred = td->td_proc->p_ucred; 593 crcopy(newcred, oldcred); 594 #ifdef MAC 595 error = mac_cred_check_setauid(oldcred, id); 596 if (error) 597 goto fail; 598 #endif 599 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 600 if (error) 601 goto fail; 602 newcred->cr_audit.ai_auid = id; 603 proc_set_cred(td->td_proc, newcred); 604 PROC_UNLOCK(td->td_proc); 605 crfree(oldcred); 606 return (0); 607 fail: 608 PROC_UNLOCK(td->td_proc); 609 crfree(newcred); 610 return (error); 611 } 612 613 /* 614 * System calls to get and set process audit information. 615 */ 616 /* ARGSUSED */ 617 int 618 sys_getaudit(struct thread *td, struct getaudit_args *uap) 619 { 620 struct auditinfo ai; 621 struct ucred *cred; 622 int error; 623 624 cred = td->td_ucred; 625 if (jailed(cred)) 626 return (ENOSYS); 627 error = priv_check(td, PRIV_AUDIT_GETAUDIT); 628 if (error) 629 return (error); 630 if (cred->cr_audit.ai_termid.at_type == AU_IPv6) 631 return (E2BIG); 632 bzero(&ai, sizeof(ai)); 633 ai.ai_auid = cred->cr_audit.ai_auid; 634 ai.ai_mask = cred->cr_audit.ai_mask; 635 ai.ai_asid = cred->cr_audit.ai_asid; 636 ai.ai_termid.machine = cred->cr_audit.ai_termid.at_addr[0]; 637 ai.ai_termid.port = cred->cr_audit.ai_termid.at_port; 638 return (copyout(&ai, uap->auditinfo, sizeof(ai))); 639 } 640 641 /* ARGSUSED */ 642 int 643 sys_setaudit(struct thread *td, struct setaudit_args *uap) 644 { 645 struct ucred *newcred, *oldcred; 646 struct auditinfo ai; 647 int error; 648 649 if (jailed(td->td_ucred)) 650 return (ENOSYS); 651 error = copyin(uap->auditinfo, &ai, sizeof(ai)); 652 if (error) 653 return (error); 654 audit_arg_auditinfo(&ai); 655 newcred = crget(); 656 PROC_LOCK(td->td_proc); 657 oldcred = td->td_proc->p_ucred; 658 crcopy(newcred, oldcred); 659 #ifdef MAC 660 error = mac_cred_check_setaudit(oldcred, &ai); 661 if (error) 662 goto fail; 663 #endif 664 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 665 if (error) 666 goto fail; 667 bzero(&newcred->cr_audit, sizeof(newcred->cr_audit)); 668 newcred->cr_audit.ai_auid = ai.ai_auid; 669 newcred->cr_audit.ai_mask = ai.ai_mask; 670 newcred->cr_audit.ai_asid = ai.ai_asid; 671 newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine; 672 newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port; 673 newcred->cr_audit.ai_termid.at_type = AU_IPv4; 674 proc_set_cred(td->td_proc, newcred); 675 PROC_UNLOCK(td->td_proc); 676 crfree(oldcred); 677 return (0); 678 fail: 679 PROC_UNLOCK(td->td_proc); 680 crfree(newcred); 681 return (error); 682 } 683 684 /* ARGSUSED */ 685 int 686 sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 687 { 688 int error; 689 690 if (jailed(td->td_ucred)) 691 return (ENOSYS); 692 if (uap->length < sizeof(*uap->auditinfo_addr)) 693 return (EOVERFLOW); 694 error = priv_check(td, PRIV_AUDIT_GETAUDIT); 695 if (error) 696 return (error); 697 return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr, 698 sizeof(*uap->auditinfo_addr))); 699 } 700 701 /* ARGSUSED */ 702 int 703 sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 704 { 705 struct ucred *newcred, *oldcred; 706 struct auditinfo_addr aia; 707 int error; 708 709 if (jailed(td->td_ucred)) 710 return (ENOSYS); 711 error = copyin(uap->auditinfo_addr, &aia, sizeof(aia)); 712 if (error) 713 return (error); 714 audit_arg_auditinfo_addr(&aia); 715 if (aia.ai_termid.at_type != AU_IPv6 && 716 aia.ai_termid.at_type != AU_IPv4) 717 return (EINVAL); 718 newcred = crget(); 719 PROC_LOCK(td->td_proc); 720 oldcred = td->td_proc->p_ucred; 721 crcopy(newcred, oldcred); 722 #ifdef MAC 723 error = mac_cred_check_setaudit_addr(oldcred, &aia); 724 if (error) 725 goto fail; 726 #endif 727 error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0); 728 if (error) 729 goto fail; 730 newcred->cr_audit = aia; 731 proc_set_cred(td->td_proc, newcred); 732 PROC_UNLOCK(td->td_proc); 733 crfree(oldcred); 734 return (0); 735 fail: 736 PROC_UNLOCK(td->td_proc); 737 crfree(newcred); 738 return (error); 739 } 740 741 /* 742 * Syscall to manage audit files. 743 */ 744 /* ARGSUSED */ 745 int 746 sys_auditctl(struct thread *td, struct auditctl_args *uap) 747 { 748 struct nameidata nd; 749 struct ucred *cred; 750 struct vnode *vp; 751 int error = 0; 752 int flags; 753 754 if (jailed(td->td_ucred)) 755 return (ENOSYS); 756 error = priv_check(td, PRIV_AUDIT_CONTROL); 757 if (error) 758 return (error); 759 760 vp = NULL; 761 cred = NULL; 762 763 /* 764 * If a path is specified, open the replacement vnode, perform 765 * validity checks, and grab another reference to the current 766 * credential. 767 * 768 * On Darwin, a NULL path argument is also used to disable audit. 769 */ 770 if (uap->path == NULL) 771 return (EINVAL); 772 773 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, 774 UIO_USERSPACE, uap->path, td); 775 flags = AUDIT_OPEN_FLAGS; 776 error = vn_open(&nd, &flags, 0, NULL); 777 if (error) 778 return (error); 779 vp = nd.ni_vp; 780 #ifdef MAC 781 error = mac_system_check_auditctl(td->td_ucred, vp); 782 VOP_UNLOCK(vp, 0); 783 if (error) { 784 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 785 return (error); 786 } 787 #else 788 VOP_UNLOCK(vp, 0); 789 #endif 790 NDFREE(&nd, NDF_ONLY_PNBUF); 791 if (vp->v_type != VREG) { 792 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 793 return (EINVAL); 794 } 795 cred = td->td_ucred; 796 crhold(cred); 797 798 /* 799 * XXXAUDIT: Should audit_suspended actually be cleared by 800 * audit_worker? 801 */ 802 audit_suspended = 0; 803 804 audit_rotate_vnode(cred, vp); 805 806 return (error); 807 } 808 809 #else /* !AUDIT */ 810 811 int 812 sys_audit(struct thread *td, struct audit_args *uap) 813 { 814 815 return (ENOSYS); 816 } 817 818 int 819 sys_auditon(struct thread *td, struct auditon_args *uap) 820 { 821 822 return (ENOSYS); 823 } 824 825 int 826 sys_getauid(struct thread *td, struct getauid_args *uap) 827 { 828 829 return (ENOSYS); 830 } 831 832 int 833 sys_setauid(struct thread *td, struct setauid_args *uap) 834 { 835 836 return (ENOSYS); 837 } 838 839 int 840 sys_getaudit(struct thread *td, struct getaudit_args *uap) 841 { 842 843 return (ENOSYS); 844 } 845 846 int 847 sys_setaudit(struct thread *td, struct setaudit_args *uap) 848 { 849 850 return (ENOSYS); 851 } 852 853 int 854 sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 855 { 856 857 return (ENOSYS); 858 } 859 860 int 861 sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 862 { 863 864 return (ENOSYS); 865 } 866 867 int 868 sys_auditctl(struct thread *td, struct auditctl_args *uap) 869 { 870 871 return (ENOSYS); 872 } 873 #endif /* AUDIT */ 874