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