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$ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/mount.h> 34 #include <sys/namei.h> 35 #include <sys/proc.h> 36 #include <sys/sysproto.h> 37 #include <sys/systm.h> 38 #include <sys/vnode.h> 39 40 #include <bsm/audit.h> 41 #include <bsm/audit_kevents.h> 42 #include <security/audit/audit.h> 43 #include <security/audit/audit_private.h> 44 45 #ifdef AUDIT 46 47 /* 48 * MPSAFE 49 * 50 * System call to allow a user space application to submit a BSM audit record 51 * to the kernel for inclusion in the audit log. This function does little 52 * verification on the audit record that is submitted. 53 * 54 * XXXAUDIT: Audit preselection for user records does not currently work, 55 * since we pre-select only based on the AUE_audit event type, not the event 56 * type submitted as part of the user audit data. 57 */ 58 /* ARGSUSED */ 59 int 60 audit(struct thread *td, struct audit_args *uap) 61 { 62 int error; 63 void * rec; 64 struct kaudit_record *ar; 65 66 error = suser(td); 67 if (error) 68 return (error); 69 70 if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz)) 71 return (EINVAL); 72 73 ar = currecord(); 74 75 /* 76 * If there's no current audit record (audit() itself not audited) 77 * commit the user audit record. 78 */ 79 if (ar == NULL) { 80 81 /* 82 * This is not very efficient; we're required to allocate a 83 * complete kernel audit record just so the user record can 84 * tag along. 85 * 86 * XXXAUDIT: Maybe AUE_AUDIT in the system call context and 87 * special pre-select handling? 88 */ 89 td->td_ar = audit_new(AUE_NULL, td); 90 if (td->td_ar == NULL) 91 return (ENOTSUP); 92 ar = td->td_ar; 93 } 94 95 if (uap->length > MAX_AUDIT_RECORD_SIZE) 96 return (EINVAL); 97 98 rec = malloc(uap->length, M_AUDITDATA, M_WAITOK); 99 100 error = copyin(uap->record, rec, uap->length); 101 if (error) 102 goto free_out; 103 104 /* Verify the record. */ 105 if (bsm_rec_verify(rec) == 0) { 106 error = EINVAL; 107 goto free_out; 108 } 109 110 /* 111 * Attach the user audit record to the kernel audit record. Because 112 * this system call is an auditable event, we will write the user 113 * record along with the record for this audit event. 114 * 115 * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen, 116 * k_ar_commit & AR_COMMIT_USER? 117 */ 118 ar->k_udata = rec; 119 ar->k_ulen = uap->length; 120 ar->k_ar_commit |= AR_COMMIT_USER; 121 return (0); 122 123 free_out: 124 /* 125 * audit_syscall_exit() will free the audit record on the thread even 126 * if we allocated it above. 127 */ 128 free(rec, M_AUDITDATA); 129 return (error); 130 } 131 132 /* 133 * MPSAFE 134 * 135 * System call to manipulate auditing. 136 */ 137 /* ARGSUSED */ 138 int 139 auditon(struct thread *td, struct auditon_args *uap) 140 { 141 int error; 142 union auditon_udata udata; 143 struct proc *tp; 144 145 AUDIT_ARG(cmd, uap->cmd); 146 error = suser(td); 147 if (error) 148 return (error); 149 150 if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata))) 151 return (EINVAL); 152 153 memset((void *)&udata, 0, sizeof(udata)); 154 155 /* 156 * Some of the GET commands use the arguments too. 157 */ 158 switch (uap->cmd) { 159 case A_SETPOLICY: 160 case A_SETKMASK: 161 case A_SETQCTRL: 162 case A_SETSTAT: 163 case A_SETUMASK: 164 case A_SETSMASK: 165 case A_SETCOND: 166 case A_SETCLASS: 167 case A_SETPMASK: 168 case A_SETFSIZE: 169 case A_SETKAUDIT: 170 case A_GETCLASS: 171 case A_GETPINFO: 172 case A_GETPINFO_ADDR: 173 case A_SENDTRIGGER: 174 error = copyin(uap->data, (void *)&udata, uap->length); 175 if (error) 176 return (error); 177 AUDIT_ARG(auditon, &udata); 178 break; 179 } 180 181 /* 182 * XXX Need to implement these commands by accessing the global 183 * values associated with the commands. 184 * 185 * XXXAUDIT: Locking? 186 */ 187 switch (uap->cmd) { 188 case A_GETPOLICY: 189 if (!audit_fail_stop) 190 udata.au_policy |= AUDIT_CNT; 191 if (audit_panic_on_write_fail) 192 udata.au_policy |= AUDIT_AHLT; 193 break; 194 195 case A_SETPOLICY: 196 if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT)) 197 return (EINVAL); 198 /* 199 * XXX - Need to wake up waiters if the policy relaxes? 200 */ 201 audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0); 202 audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT); 203 break; 204 205 case A_GETKMASK: 206 udata.au_mask = audit_nae_mask; 207 break; 208 209 case A_SETKMASK: 210 audit_nae_mask = udata.au_mask; 211 break; 212 213 case A_GETQCTRL: 214 udata.au_qctrl = audit_qctrl; 215 break; 216 217 case A_SETQCTRL: 218 if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) || 219 (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) || 220 (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) || 221 (udata.au_qctrl.aq_minfree < 0) || 222 (udata.au_qctrl.aq_minfree > 100)) 223 return (EINVAL); 224 225 audit_qctrl = udata.au_qctrl; 226 /* XXX The queue delay value isn't used with the kernel. */ 227 audit_qctrl.aq_delay = -1; 228 break; 229 230 case A_GETCWD: 231 return (ENOSYS); 232 break; 233 234 case A_GETCAR: 235 return (ENOSYS); 236 break; 237 238 case A_GETSTAT: 239 return (ENOSYS); 240 break; 241 242 case A_SETSTAT: 243 return (ENOSYS); 244 break; 245 246 case A_SETUMASK: 247 return (ENOSYS); 248 break; 249 250 case A_SETSMASK: 251 return (ENOSYS); 252 break; 253 254 case A_GETCOND: 255 if (audit_enabled && !audit_suspended) 256 udata.au_cond = AUC_AUDITING; 257 else 258 udata.au_cond = AUC_NOAUDIT; 259 break; 260 261 case A_SETCOND: 262 if (udata.au_cond == AUC_NOAUDIT) 263 audit_suspended = 1; 264 if (udata.au_cond == AUC_AUDITING) 265 audit_suspended = 0; 266 if (udata.au_cond == AUC_DISABLED) { 267 audit_suspended = 1; 268 audit_shutdown(NULL, 0); 269 } 270 break; 271 272 case A_GETCLASS: 273 udata.au_evclass.ec_class = au_event_class( 274 udata.au_evclass.ec_number); 275 break; 276 277 case A_SETCLASS: 278 au_evclassmap_insert(udata.au_evclass.ec_number, 279 udata.au_evclass.ec_class); 280 break; 281 282 case A_GETPINFO: 283 if (udata.au_aupinfo.ap_pid < 1) 284 return (EINVAL); 285 286 /* XXXAUDIT: p_cansee()? */ 287 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 288 return (EINVAL); 289 290 udata.au_aupinfo.ap_auid = tp->p_au->ai_auid; 291 udata.au_aupinfo.ap_mask.am_success = 292 tp->p_au->ai_mask.am_success; 293 udata.au_aupinfo.ap_mask.am_failure = 294 tp->p_au->ai_mask.am_failure; 295 udata.au_aupinfo.ap_termid.machine = 296 tp->p_au->ai_termid.machine; 297 udata.au_aupinfo.ap_termid.port = tp->p_au->ai_termid.port; 298 udata.au_aupinfo.ap_asid = tp->p_au->ai_asid; 299 PROC_UNLOCK(tp); 300 break; 301 302 case A_SETPMASK: 303 if (udata.au_aupinfo.ap_pid < 1) 304 return (EINVAL); 305 306 /* XXXAUDIT: p_cansee()? */ 307 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) 308 return (EINVAL); 309 310 tp->p_au->ai_mask.am_success = 311 udata.au_aupinfo.ap_mask.am_success; 312 tp->p_au->ai_mask.am_failure = 313 udata.au_aupinfo.ap_mask.am_failure; 314 PROC_UNLOCK(tp); 315 break; 316 317 case A_SETFSIZE: 318 if ((udata.au_fstat.af_filesz != 0) && 319 (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE)) 320 return (EINVAL); 321 audit_fstat.af_filesz = udata.au_fstat.af_filesz; 322 break; 323 324 case A_GETFSIZE: 325 udata.au_fstat.af_filesz = audit_fstat.af_filesz; 326 udata.au_fstat.af_currsz = audit_fstat.af_currsz; 327 break; 328 329 case A_GETPINFO_ADDR: 330 return (ENOSYS); 331 break; 332 333 case A_GETKAUDIT: 334 return (ENOSYS); 335 break; 336 337 case A_SETKAUDIT: 338 return (ENOSYS); 339 break; 340 341 case A_SENDTRIGGER: 342 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) || 343 (udata.au_trigger > AUDIT_TRIGGER_MAX)) 344 return (EINVAL); 345 return (send_trigger(udata.au_trigger)); 346 } 347 348 /* 349 * Copy data back to userspace for the GET comands. 350 */ 351 switch (uap->cmd) { 352 case A_GETPOLICY: 353 case A_GETKMASK: 354 case A_GETQCTRL: 355 case A_GETCWD: 356 case A_GETCAR: 357 case A_GETSTAT: 358 case A_GETCOND: 359 case A_GETCLASS: 360 case A_GETPINFO: 361 case A_GETFSIZE: 362 case A_GETPINFO_ADDR: 363 case A_GETKAUDIT: 364 error = copyout((void *)&udata, uap->data, uap->length); 365 if (error) 366 return (error); 367 break; 368 } 369 370 return (0); 371 } 372 373 /* 374 * MPSAFE 375 * 376 * System calls to manage the user audit information. 377 */ 378 /* ARGSUSED */ 379 int 380 getauid(struct thread *td, struct getauid_args *uap) 381 { 382 int error; 383 au_id_t id; 384 385 error = suser(td); 386 if (error) 387 return (error); 388 389 /* 390 * XXX: Integer read on static pointer dereference: doesn't need 391 * locking? 392 */ 393 PROC_LOCK(td->td_proc); 394 id = td->td_proc->p_au->ai_auid; 395 PROC_UNLOCK(td->td_proc); 396 return copyout(&id, uap->auid, sizeof(id)); 397 } 398 399 /* MPSAFE */ 400 /* ARGSUSED */ 401 int 402 setauid(struct thread *td, struct setauid_args *uap) 403 { 404 int error; 405 au_id_t id; 406 407 error = suser(td); 408 if (error) 409 return (error); 410 411 error = copyin(uap->auid, &id, sizeof(id)); 412 if (error) 413 return (error); 414 415 audit_arg_auid(id); 416 417 /* 418 * XXX: Integer write on static pointer dereference: doesn't need 419 * locking? 420 * 421 * XXXAUDIT: Might need locking to serialize audit events in the same 422 * order as change events? Or maybe that's an under-solveable 423 * problem. 424 * 425 * XXXRW: Test privilege while holding the proc lock? 426 */ 427 PROC_LOCK(td->td_proc); 428 td->td_proc->p_au->ai_auid = id; 429 PROC_UNLOCK(td->td_proc); 430 431 return (0); 432 } 433 434 /* 435 * MPSAFE 436 * System calls to get and set process audit information. 437 */ 438 /* ARGSUSED */ 439 int 440 getaudit(struct thread *td, struct getaudit_args *uap) 441 { 442 struct auditinfo ai; 443 int error; 444 445 error = suser(td); 446 if (error) 447 return (error); 448 449 PROC_LOCK(td->td_proc); 450 ai = *td->td_proc->p_au; 451 PROC_UNLOCK(td->td_proc); 452 453 return (copyout(&ai, uap->auditinfo, sizeof(ai))); 454 } 455 456 /* MPSAFE */ 457 /* ARGSUSED */ 458 int 459 setaudit(struct thread *td, struct setaudit_args *uap) 460 { 461 struct auditinfo ai; 462 int error; 463 464 error = suser(td); 465 if (error) 466 return (error); 467 468 error = copyin(uap->auditinfo, &ai, sizeof(ai)); 469 if (error) 470 return (error); 471 472 audit_arg_auditinfo(&ai); 473 474 /* 475 * XXXRW: Test privilege while holding the proc lock? 476 */ 477 PROC_LOCK(td->td_proc); 478 *td->td_proc->p_au = ai; 479 PROC_UNLOCK(td->td_proc); 480 481 return (0); 482 } 483 484 /* MPSAFE */ 485 /* ARGSUSED */ 486 int 487 getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 488 { 489 int error; 490 491 error = suser(td); 492 if (error) 493 return (error); 494 return (ENOSYS); 495 } 496 497 /* MPSAFE */ 498 /* ARGSUSED */ 499 int 500 setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 501 { 502 int error; 503 504 error = suser(td); 505 if (error) 506 return (error); 507 return (ENOSYS); 508 } 509 510 /* 511 * MPSAFE 512 * Syscall to manage audit files. 513 * 514 * XXX: Should generate an audit event. 515 */ 516 /* ARGSUSED */ 517 int 518 auditctl(struct thread *td, struct auditctl_args *uap) 519 { 520 struct nameidata nd; 521 struct ucred *cred; 522 struct vnode *vp; 523 int error = 0; 524 int flags, vfslocked; 525 526 error = suser(td); 527 if (error) 528 return (error); 529 530 vp = NULL; 531 cred = NULL; 532 533 /* 534 * If a path is specified, open the replacement vnode, perform 535 * validity checks, and grab another reference to the current 536 * credential. 537 * 538 * XXXAUDIT: On Darwin, a NULL path is used to disable audit. 539 */ 540 if (uap->path == NULL) 541 return (EINVAL); 542 543 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE, 544 uap->path, td); 545 flags = AUDIT_OPEN_FLAGS; 546 error = vn_open(&nd, &flags, 0, -1); 547 if (error) 548 return (error); 549 vfslocked = NDHASGIANT(&nd); 550 VOP_UNLOCK(nd.ni_vp, 0, td); 551 vp = nd.ni_vp; 552 if (vp->v_type != VREG) { 553 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td); 554 VFS_UNLOCK_GIANT(vfslocked); 555 return (EINVAL); 556 } 557 VFS_UNLOCK_GIANT(vfslocked); 558 cred = td->td_ucred; 559 crhold(cred); 560 561 /* 562 * XXXAUDIT: Should audit_suspended actually be cleared by 563 * audit_worker? 564 */ 565 audit_suspended = 0; 566 567 audit_rotate_vnode(cred, vp); 568 569 return (error); 570 } 571 572 #else /* !AUDIT */ 573 574 int 575 audit(struct thread *td, struct audit_args *uap) 576 { 577 578 return (ENOSYS); 579 } 580 581 int 582 auditon(struct thread *td, struct auditon_args *uap) 583 { 584 585 return (ENOSYS); 586 } 587 588 int 589 getauid(struct thread *td, struct getauid_args *uap) 590 { 591 592 return (ENOSYS); 593 } 594 595 int 596 setauid(struct thread *td, struct setauid_args *uap) 597 { 598 599 return (ENOSYS); 600 } 601 602 int 603 getaudit(struct thread *td, struct getaudit_args *uap) 604 { 605 606 return (ENOSYS); 607 } 608 609 int 610 setaudit(struct thread *td, struct setaudit_args *uap) 611 { 612 613 return (ENOSYS); 614 } 615 616 int 617 getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) 618 { 619 620 return (ENOSYS); 621 } 622 623 int 624 setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) 625 { 626 627 return (ENOSYS); 628 } 629 630 int 631 auditctl(struct thread *td, struct auditctl_args *uap) 632 { 633 634 return (ENOSYS); 635 } 636 637 void 638 audit_proc_init(struct proc *p) 639 { 640 641 } 642 643 void 644 audit_proc_fork(struct proc *parent, struct proc *child) 645 { 646 647 } 648 649 void 650 audit_proc_free(struct proc *p) 651 { 652 653 } 654 655 #endif /* AUDIT */ 656