1 /* 2 * Copyright (c) 2007-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 /*- 30 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 31 * Copyright (c) 2001 Ilmar S. Habibulin 32 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc. 33 * 34 * This software was developed by Robert Watson and Ilmar Habibulin for the 35 * TrustedBSD Project. 36 * 37 * This software was developed for the FreeBSD Project in part by Network 38 * Associates Laboratories, the Security Research Division of Network 39 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 40 * as part of the DARPA CHATS research program. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 */ 64 65 #include <string.h> 66 #include <sys/param.h> 67 #include <sys/ucred.h> 68 #include <sys/malloc.h> 69 #include <sys/sbuf.h> 70 #include <sys/vnode.h> 71 #include <sys/proc.h> 72 #include <sys/proc_internal.h> 73 #include <sys/kauth.h> 74 #include <sys/imgact.h> 75 #include <sys/reason.h> 76 #include <sys/vnode_internal.h> 77 #include <mach/mach_types.h> 78 #include <kern/task.h> 79 #include <kern/zalloc.h> 80 81 #include <os/hash.h> 82 83 #include <security/mac_internal.h> 84 #include <security/mac_mach_internal.h> 85 86 #include <bsd/security/audit/audit.h> 87 88 #include <os/log.h> 89 #include <kern/cs_blobs.h> 90 #include <sys/spawn.h> 91 #include <sys/spawn_internal.h> 92 93 struct label * 94 mac_cred_label_alloc(void) 95 { 96 struct label *label; 97 98 label = mac_labelzone_alloc(MAC_WAITOK); 99 if (label == NULL) { 100 return NULL; 101 } 102 MAC_PERFORM(cred_label_init, label); 103 return label; 104 } 105 106 void 107 mac_cred_label_init(struct ucred *cred) 108 { 109 cred->cr_label = mac_cred_label_alloc(); 110 } 111 112 void 113 mac_cred_label_seal(struct ucred *cred) 114 { 115 #if DEVELOPMENT || DEBUG 116 struct label **seal = (struct label **)-1; 117 118 zalloc_ro_update_field(ZONE_ID_MAC_LABEL, cred->cr_label, l_owner, &seal); 119 #else 120 (void)cred; 121 #endif 122 } 123 124 void 125 mac_cred_label_free(struct label *label) 126 { 127 #if DEVELOPMENT || DEBUG 128 struct label **seal = (struct label **)-1; 129 130 if (label->l_owner == seal) { 131 seal = NULL; 132 zalloc_ro_update_field(ZONE_ID_MAC_LABEL, label, l_owner, &seal); 133 } 134 #endif 135 136 MAC_PERFORM(cred_label_destroy, label); 137 mac_labelzone_free(label); 138 } 139 140 struct label * 141 mac_cred_label(struct ucred *cred) 142 { 143 return cred->cr_label; 144 } 145 146 bool 147 mac_cred_label_is_equal(const struct label *a, const struct label *b) 148 { 149 return memcmp(a->l_perpolicy, b->l_perpolicy, sizeof(a->l_perpolicy)) == 0; 150 } 151 152 uint32_t 153 mac_cred_label_hash_update(const struct label *a, uint32_t hash) 154 { 155 return os_hash_jenkins_update(a->l_perpolicy, sizeof(a->l_perpolicy), hash); 156 } 157 158 int 159 mac_cred_label_externalize_audit(struct proc *p, struct mac *mac) 160 { 161 kauth_cred_t cr; 162 int error; 163 164 cr = kauth_cred_proc_ref(p); 165 166 error = MAC_EXTERNALIZE_AUDIT(cred, mac_cred_label(cr), 167 mac->m_string, mac->m_buflen); 168 169 kauth_cred_unref(&cr); 170 return error; 171 } 172 173 void 174 mac_cred_label_destroy(kauth_cred_t cred) 175 { 176 struct label *label = mac_cred_label(cred); 177 cred->cr_label = NULL; 178 mac_cred_label_free(label); 179 } 180 181 int 182 mac_cred_label_externalize(struct label *label, char *elements, 183 char *outbuf, size_t outbuflen, int flags __unused) 184 { 185 int error = 0; 186 187 error = MAC_EXTERNALIZE(cred, label, elements, outbuf, outbuflen); 188 189 return error; 190 } 191 192 int 193 mac_cred_label_internalize(struct label *label, char *string) 194 { 195 int error; 196 197 error = MAC_INTERNALIZE(cred, label, string); 198 199 return error; 200 } 201 202 /* 203 * By default, fork just adds a reference to the parent 204 * credential. Policies may need to know about this reference 205 * if they are tracking exit calls to know when to free the 206 * label. 207 */ 208 void 209 mac_cred_label_associate_fork(kauth_cred_t cred, proc_t proc) 210 { 211 MAC_PERFORM(cred_label_associate_fork, cred, proc); 212 } 213 214 /* 215 * Initialize MAC label for the first kernel process, from which other 216 * kernel processes and threads are spawned. 217 */ 218 void 219 mac_cred_label_associate_kernel(kauth_cred_t cred) 220 { 221 MAC_PERFORM(cred_label_associate_kernel, cred); 222 } 223 224 /* 225 * Initialize MAC label for the first userland process, from which other 226 * userland processes and threads are spawned. 227 */ 228 void 229 mac_cred_label_associate_user(kauth_cred_t cred) 230 { 231 MAC_PERFORM(cred_label_associate_user, cred); 232 } 233 234 /* 235 * When a new process is created, its label must be initialized. Generally, 236 * this involves inheritence from the parent process, modulo possible 237 * deltas. This function allows that processing to take place. 238 */ 239 void 240 mac_cred_label_associate(struct ucred *parent_cred, struct ucred *child_cred) 241 { 242 MAC_PERFORM(cred_label_associate, parent_cred, child_cred); 243 } 244 245 int 246 mac_execve_enter(user_addr_t mac_p, struct image_params *imgp) 247 { 248 if (mac_p == USER_ADDR_NULL) { 249 return 0; 250 } 251 252 return mac_do_set(current_proc(), mac_p, 253 ^(char *input, __unused size_t len) { 254 struct label *execlabel; 255 int error; 256 257 execlabel = mac_cred_label_alloc(); 258 if ((error = mac_cred_label_internalize(execlabel, input))) { 259 mac_cred_label_free(execlabel); 260 execlabel = NULL; 261 } 262 263 imgp->ip_execlabelp = execlabel; 264 return error; 265 }); 266 } 267 268 /* 269 * When the subject's label changes, it may require revocation of privilege 270 * to mapped objects. This can't be done on-the-fly later with a unified 271 * buffer cache. 272 * 273 * XXX: CRF_MAC_ENFORCE should be in a kauth_cred_t field, rather 274 * XXX: than a posix_cred_t field. 275 */ 276 void 277 mac_cred_label_update(kauth_cred_t cred, struct label *newlabel) 278 { 279 posix_cred_t pcred = posix_cred_get(cred); 280 281 /* force label to be part of "matching" for credential */ 282 pcred->cr_flags |= CRF_MAC_ENFORCE; 283 284 /* inform the policies of the update */ 285 MAC_PERFORM(cred_label_update, cred, newlabel); 286 } 287 288 int 289 mac_cred_check_label_update(kauth_cred_t cred, struct label *newlabel) 290 { 291 int error; 292 293 #if SECURITY_MAC_CHECK_ENFORCE 294 /* 21167099 - only check if we allow write */ 295 if (!mac_proc_enforce) { 296 return 0; 297 } 298 #endif 299 300 MAC_CHECK(cred_check_label_update, cred, newlabel); 301 302 return error; 303 } 304 305 int 306 mac_cred_check_visible(kauth_cred_t u1, kauth_cred_t u2) 307 { 308 int error; 309 310 #if SECURITY_MAC_CHECK_ENFORCE 311 /* 21167099 - only check if we allow write */ 312 if (!mac_proc_enforce) { 313 return 0; 314 } 315 #endif 316 317 MAC_CHECK(cred_check_visible, u1, u2); 318 319 return error; 320 } 321 322 int 323 mac_proc_check_debug(proc_ident_t tracing_ident, kauth_cred_t tracing_cred, proc_ident_t traced_ident) 324 { 325 int error; 326 bool enforce; 327 proc_t tracingp; 328 329 #if SECURITY_MAC_CHECK_ENFORCE 330 /* 21167099 - only check if we allow write */ 331 if (!mac_proc_enforce) { 332 return 0; 333 } 334 #endif 335 /* 336 * Once all mac hooks adopt proc_ident_t, finding proc_t and releasing 337 * it below should go to mac_proc_check_enforce(). 338 */ 339 if ((tracingp = proc_find_ident(tracing_ident)) == PROC_NULL) { 340 return ESRCH; 341 } 342 enforce = mac_proc_check_enforce(tracingp); 343 proc_rele(tracingp); 344 345 if (!enforce) { 346 return 0; 347 } 348 MAC_CHECK(proc_check_debug, tracing_cred, traced_ident); 349 350 return error; 351 } 352 353 int 354 mac_proc_check_dump_core(struct proc *proc) 355 { 356 int error; 357 358 #if SECURITY_MAC_CHECK_ENFORCE 359 /* 21167099 - only check if we allow write */ 360 if (!mac_proc_enforce) { 361 return 0; 362 } 363 #endif 364 if (!mac_proc_check_enforce(proc)) { 365 return 0; 366 } 367 368 MAC_CHECK(proc_check_dump_core, proc); 369 370 return error; 371 } 372 373 int 374 mac_proc_check_remote_thread_create(struct task *task, int flavor, thread_state_t new_state, mach_msg_type_number_t new_state_count) 375 { 376 proc_t curp = current_proc(); 377 proc_t proc; 378 int error; 379 380 #if SECURITY_MAC_CHECK_ENFORCE 381 /* 21167099 - only check if we allow write */ 382 if (!mac_proc_enforce) { 383 return 0; 384 } 385 #endif 386 if (!mac_proc_check_enforce(curp)) { 387 return 0; 388 } 389 390 proc = proc_find(task_pid(task)); 391 if (proc == PROC_NULL) { 392 return ESRCH; 393 } 394 395 MAC_CHECK(proc_check_remote_thread_create, current_cached_proc_cred(curp), 396 proc, flavor, new_state, new_state_count); 397 proc_rele(proc); 398 399 return error; 400 } 401 402 void 403 mac_proc_notify_service_port_derive(struct mach_service_port_info *sp_info) 404 { 405 MAC_PERFORM(proc_notify_service_port_derive, 406 current_cached_proc_cred(PROC_NULL), sp_info); 407 } 408 409 int 410 mac_proc_check_fork(proc_t curp) 411 { 412 int error; 413 414 #if SECURITY_MAC_CHECK_ENFORCE 415 /* 21167099 - only check if we allow write */ 416 if (!mac_proc_enforce) { 417 return 0; 418 } 419 #endif 420 if (!mac_proc_check_enforce(curp)) { 421 return 0; 422 } 423 424 MAC_CHECK(proc_check_fork, current_cached_proc_cred(curp), curp); 425 426 return error; 427 } 428 429 int 430 mac_proc_check_get_task(struct ucred *cred, proc_ident_t pident, mach_task_flavor_t flavor) 431 { 432 int error; 433 434 assert(flavor <= TASK_FLAVOR_NAME); 435 436 MAC_CHECK(proc_check_get_task_with_flavor, cred, pident, flavor); 437 438 return error; 439 } 440 441 int 442 mac_proc_check_expose_task(struct ucred *cred, proc_ident_t pident, mach_task_flavor_t flavor) 443 { 444 int error; 445 446 assert(flavor <= TASK_FLAVOR_NAME); 447 448 MAC_CHECK(proc_check_expose_task_with_flavor, cred, pident, flavor); 449 450 return error; 451 } 452 453 int 454 mac_proc_check_inherit_ipc_ports( 455 struct proc *p, 456 struct vnode *cur_vp, 457 off_t cur_offset, 458 struct vnode *img_vp, 459 off_t img_offset, 460 struct vnode *scriptvp) 461 { 462 int error; 463 464 MAC_CHECK(proc_check_inherit_ipc_ports, p, cur_vp, cur_offset, img_vp, img_offset, scriptvp); 465 466 return error; 467 } 468 469 /* 470 * The type of maxprot in proc_check_map_anon must be equivalent to vm_prot_t 471 * (defined in <mach/vm_prot.h>). mac_policy.h does not include any header 472 * files, so cannot use the typedef itself. 473 */ 474 int 475 mac_proc_check_map_anon(proc_t proc, kauth_cred_t cred, user_addr_t u_addr, 476 user_size_t u_size, int prot, int flags, int *maxprot) 477 { 478 int error; 479 480 #if SECURITY_MAC_CHECK_ENFORCE 481 /* 21167099 - only check if we allow write */ 482 if (!mac_vm_enforce) { 483 return 0; 484 } 485 #endif 486 if (!mac_proc_check_enforce(proc)) { 487 return 0; 488 } 489 490 MAC_CHECK(proc_check_map_anon, proc, cred, u_addr, u_size, prot, flags, maxprot); 491 492 return error; 493 } 494 495 496 int 497 mac_proc_check_memorystatus_control(proc_t proc, uint32_t command, pid_t pid) 498 { 499 int error; 500 501 #if SECURITY_MAC_CHECK_ENFORCE 502 /* 21167099 - only check if we allow write */ 503 if (!mac_proc_enforce) { 504 return 0; 505 } 506 #endif 507 if (!mac_proc_check_enforce(proc)) { 508 return 0; 509 } 510 511 MAC_CHECK(proc_check_memorystatus_control, current_cached_proc_cred(proc), 512 command, pid); 513 514 return error; 515 } 516 517 int 518 mac_proc_check_mprotect(proc_t proc, 519 user_addr_t addr, user_size_t size, int prot) 520 { 521 int error; 522 523 #if SECURITY_MAC_CHECK_ENFORCE 524 /* 21167099 - only check if we allow write */ 525 if (!mac_vm_enforce) { 526 return 0; 527 } 528 #endif 529 if (!mac_proc_check_enforce(proc)) { 530 return 0; 531 } 532 533 MAC_CHECK(proc_check_mprotect, current_cached_proc_cred(proc), 534 proc, addr, size, prot); 535 536 return error; 537 } 538 539 int 540 mac_proc_check_run_cs_invalid(proc_t proc) 541 { 542 int error; 543 544 #if SECURITY_MAC_CHECK_ENFORCE 545 /* 21167099 - only check if we allow write */ 546 if (!mac_vm_enforce) { 547 return 0; 548 } 549 #endif 550 551 MAC_CHECK(proc_check_run_cs_invalid, proc); 552 553 return error; 554 } 555 556 void 557 mac_proc_notify_cs_invalidated(proc_t proc) 558 { 559 MAC_PERFORM(proc_notify_cs_invalidated, proc); 560 } 561 562 int 563 mac_proc_check_sched(proc_t curp, struct proc *proc) 564 { 565 int error; 566 567 #if SECURITY_MAC_CHECK_ENFORCE 568 /* 21167099 - only check if we allow write */ 569 if (!mac_proc_enforce) { 570 return 0; 571 } 572 #endif 573 if (!mac_proc_check_enforce(curp)) { 574 return 0; 575 } 576 577 MAC_CHECK(proc_check_sched, current_cached_proc_cred(curp), proc); 578 579 return error; 580 } 581 582 int 583 mac_proc_check_signal(proc_t curp, struct proc *proc, int signum) 584 { 585 int error; 586 587 #if SECURITY_MAC_CHECK_ENFORCE 588 /* 21167099 - only check if we allow write */ 589 if (!mac_proc_enforce) { 590 return 0; 591 } 592 #endif 593 if (!mac_proc_check_enforce(curp)) { 594 return 0; 595 } 596 597 MAC_CHECK(proc_check_signal, current_cached_proc_cred(curp), proc, signum); 598 599 return error; 600 } 601 602 int 603 mac_proc_check_delegated_signal(proc_t curp, audit_token_t instigator, audit_token_t target, int signum) 604 { 605 int error = 0; 606 607 #if SECURITY_MAC_CHECK_ENFORCE 608 /* 21167099 - only check if we allow write */ 609 if (!mac_proc_enforce) { 610 return 0; 611 } 612 #endif 613 if (!mac_proc_check_enforce(curp)) { 614 return 0; 615 } 616 617 MAC_CHECK(proc_check_delegated_signal, current_cached_proc_cred(curp), instigator, target, signum); 618 return error; 619 } 620 621 int 622 mac_proc_check_syscall_unix(proc_t curp, int scnum) 623 { 624 int error; 625 626 #if SECURITY_MAC_CHECK_ENFORCE 627 /* 21167099 - only check if we allow write */ 628 if (!mac_proc_enforce) { 629 return 0; 630 } 631 #endif 632 if (!mac_proc_check_enforce(curp)) { 633 return 0; 634 } 635 636 MAC_CHECK(proc_check_syscall_unix, curp, scnum); 637 638 return error; 639 } 640 641 int 642 mac_proc_check_wait(proc_t curp, struct proc *proc) 643 { 644 int error; 645 646 #if SECURITY_MAC_CHECK_ENFORCE 647 /* 21167099 - only check if we allow write */ 648 if (!mac_proc_enforce) { 649 return 0; 650 } 651 #endif 652 if (!mac_proc_check_enforce(curp)) { 653 return 0; 654 } 655 656 MAC_CHECK(proc_check_wait, current_cached_proc_cred(curp), proc); 657 658 return error; 659 } 660 661 void 662 mac_proc_notify_exit(struct proc *proc) 663 { 664 MAC_PERFORM(proc_notify_exit, proc); 665 } 666 667 int 668 mac_proc_check_suspend_resume(proc_t proc, int sr) 669 { 670 proc_t curp = current_proc(); 671 int error; 672 673 #if SECURITY_MAC_CHECK_ENFORCE 674 /* 21167099 - only check if we allow write */ 675 if (!mac_proc_enforce) { 676 return 0; 677 } 678 #endif 679 if (!mac_proc_check_enforce(curp)) { 680 return 0; 681 } 682 683 MAC_CHECK(proc_check_suspend_resume, current_cached_proc_cred(curp), 684 proc, sr); 685 686 return error; 687 } 688 689 int 690 mac_proc_check_ledger(proc_t curp, proc_t proc, int ledger_op) 691 { 692 int error = 0; 693 694 #if SECURITY_MAC_CHECK_ENFORCE 695 /* 21167099 - only check if we allow write */ 696 if (!mac_proc_enforce) { 697 return 0; 698 } 699 #endif 700 if (!mac_proc_check_enforce(curp)) { 701 return 0; 702 } 703 704 MAC_CHECK(proc_check_ledger, current_cached_proc_cred(curp), 705 proc, ledger_op); 706 707 return error; 708 } 709 710 int 711 mac_proc_check_proc_info(proc_t curp, proc_t target, int callnum, int flavor) 712 { 713 int error = 0; 714 715 #if SECURITY_MAC_CHECK_ENFORCE 716 /* 21167099 - only check if we allow write */ 717 if (!mac_proc_enforce) { 718 return 0; 719 } 720 #endif 721 if (!mac_proc_check_enforce(curp)) { 722 return 0; 723 } 724 725 MAC_CHECK(proc_check_proc_info, current_cached_proc_cred(curp), 726 target, callnum, flavor); 727 728 return error; 729 } 730 731 int 732 mac_proc_check_get_cs_info(proc_t curp, proc_t target, unsigned int op) 733 { 734 int error = 0; 735 736 #if SECURITY_MAC_CHECK_ENFORCE 737 /* 21167099 - only check if we allow write */ 738 if (!mac_proc_enforce) { 739 return 0; 740 } 741 #endif 742 if (!mac_proc_check_enforce(curp)) { 743 return 0; 744 } 745 746 MAC_CHECK(proc_check_get_cs_info, current_cached_proc_cred(curp), 747 target, op); 748 749 return error; 750 } 751 752 int 753 mac_proc_check_set_cs_info(proc_t curp, proc_t target, unsigned int op) 754 { 755 int error = 0; 756 757 #if SECURITY_MAC_CHECK_ENFORCE 758 /* 21167099 - only check if we allow write */ 759 if (!mac_proc_enforce) { 760 return 0; 761 } 762 #endif 763 if (!mac_proc_check_enforce(curp)) { 764 return 0; 765 } 766 767 MAC_CHECK(proc_check_set_cs_info, current_cached_proc_cred(curp), 768 target, op); 769 770 return error; 771 } 772 773 int 774 mac_proc_check_setuid(proc_t curp, kauth_cred_t cred, uid_t uid) 775 { 776 int error = 0; 777 778 #if SECURITY_MAC_CHECK_ENFORCE 779 /* 21167099 - only check if we allow write */ 780 if (!mac_proc_enforce) { 781 return 0; 782 } 783 #endif 784 if (!mac_proc_check_enforce(curp)) { 785 return 0; 786 } 787 788 MAC_CHECK(proc_check_setuid, cred, uid); 789 790 return error; 791 } 792 793 int 794 mac_proc_check_seteuid(proc_t curp, kauth_cred_t cred, uid_t euid) 795 { 796 int error = 0; 797 798 #if SECURITY_MAC_CHECK_ENFORCE 799 /* 21167099 - only check if we allow write */ 800 if (!mac_proc_enforce) { 801 return 0; 802 } 803 #endif 804 if (!mac_proc_check_enforce(curp)) { 805 return 0; 806 } 807 808 MAC_CHECK(proc_check_seteuid, cred, euid); 809 810 return error; 811 } 812 813 int 814 mac_proc_check_setreuid(proc_t curp, kauth_cred_t cred, uid_t ruid, uid_t euid) 815 { 816 int error = 0; 817 818 #if SECURITY_MAC_CHECK_ENFORCE 819 /* 21167099 - only check if we allow write */ 820 if (!mac_proc_enforce) { 821 return 0; 822 } 823 #endif 824 if (!mac_proc_check_enforce(curp)) { 825 return 0; 826 } 827 828 MAC_CHECK(proc_check_setreuid, cred, ruid, euid); 829 830 return error; 831 } 832 833 int 834 mac_proc_check_setgid(proc_t curp, kauth_cred_t cred, gid_t gid) 835 { 836 int error = 0; 837 838 #if SECURITY_MAC_CHECK_ENFORCE 839 /* 21167099 - only check if we allow write */ 840 if (!mac_proc_enforce) { 841 return 0; 842 } 843 #endif 844 if (!mac_proc_check_enforce(curp)) { 845 return 0; 846 } 847 848 MAC_CHECK(proc_check_setgid, cred, gid); 849 850 return error; 851 } 852 853 int 854 mac_proc_check_setegid(proc_t curp, kauth_cred_t cred, gid_t egid) 855 { 856 int error = 0; 857 858 #if SECURITY_MAC_CHECK_ENFORCE 859 /* 21167099 - only check if we allow write */ 860 if (!mac_proc_enforce) { 861 return 0; 862 } 863 #endif 864 if (!mac_proc_check_enforce(curp)) { 865 return 0; 866 } 867 868 MAC_CHECK(proc_check_setegid, cred, egid); 869 870 return error; 871 } 872 873 int 874 mac_proc_check_setregid(proc_t curp, kauth_cred_t cred, gid_t rgid, gid_t egid) 875 { 876 int error = 0; 877 878 #if SECURITY_MAC_CHECK_ENFORCE 879 /* 21167099 - only check if we allow write */ 880 if (!mac_proc_enforce) { 881 return 0; 882 } 883 #endif 884 if (!mac_proc_check_enforce(curp)) { 885 return 0; 886 } 887 888 MAC_CHECK(proc_check_setregid, cred, rgid, egid); 889 890 return error; 891 } 892 893 int 894 mac_proc_check_settid(proc_t curp, uid_t uid, gid_t gid) 895 { 896 int error = 0; 897 898 #if SECURITY_MAC_CHECK_ENFORCE 899 /* 21167099 - only check if we allow write */ 900 if (!mac_proc_enforce) { 901 return 0; 902 } 903 #endif 904 if (!mac_proc_check_enforce(curp)) { 905 return 0; 906 } 907 908 MAC_CHECK(proc_check_settid, current_cached_proc_cred(curp), 909 kauth_cred_get(), uid, gid); 910 911 return error; 912 } 913 914 int 915 mac_proc_check_launch_constraints(proc_t curp, struct image_params *imgp, os_reason_t *reasonp) 916 { 917 char *fatal_failure_desc = NULL; 918 size_t fatal_failure_desc_len = 0; 919 920 pid_t original_parent_id = proc_original_ppid(curp); 921 922 pid_t responsible_pid = curp->p_responsible_pid; 923 924 int error = 0; 925 926 /* Vnode of the file */ 927 struct vnode *vp = imgp->ip_vp; 928 929 char *vn_path = NULL; 930 vm_size_t vn_pathlen = MAXPATHLEN; 931 #if SECURITY_MAC_CHECK_ENFORCE 932 /* 21167099 - only check if we allow write */ 933 if (!mac_proc_enforce || !mac_vnode_enforce) { 934 return 0; 935 } 936 #endif 937 938 MAC_POLICY_ITERATE({ 939 mpo_proc_check_launch_constraints_t *hook = mpc->mpc_ops->mpo_proc_check_launch_constraints; 940 if (hook == NULL) { 941 continue; 942 } 943 944 size_t spawnattrlen = 0; 945 void *spawnattr = exec_spawnattr_getmacpolicyinfo(&imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen); 946 struct _posix_spawnattr *psa = (struct _posix_spawnattr *) imgp->ip_px_sa; 947 struct launch_constraint_data lcd; 948 lcd.launch_type = CS_LAUNCH_TYPE_NONE; 949 950 /* Check to see if psa_launch_type was initalized */ 951 if (psa != (struct _posix_spawnattr*)NULL) { 952 lcd.launch_type = psa->psa_launch_type; 953 } 954 955 error = mac_error_select( 956 hook(curp, original_parent_id, responsible_pid, 957 spawnattr, spawnattrlen, &lcd, &fatal_failure_desc, &fatal_failure_desc_len), error); 958 959 /* 960 * Early exit in case of failure in case we have multiple registered callers. 961 * This is to avoid other MACF policies from stomping on each other's failure description 962 */ 963 if (fatal_failure_desc_len) { 964 goto policy_fail; 965 } 966 }); 967 968 policy_fail: 969 if (fatal_failure_desc_len) { 970 /* 971 * A fatal code signature validation failure occured, formulate a crash 972 * reason. 973 */ 974 975 char const *path = NULL; 976 977 vn_path = zalloc(ZV_NAMEI); 978 if (vn_getpath(vp, vn_path, (int*)&vn_pathlen) == 0) { 979 path = vn_path; 980 } else { 981 path = "(get vnode path failed)"; 982 } 983 984 if (error == 0) { 985 panic("%s: MAC hook returned no error, but status is claimed to be fatal? " 986 "path: '%s', fatal_failure_desc_len: %ld, fatal_failure_desc:\n%s\n", 987 __func__, path, fatal_failure_desc_len, fatal_failure_desc); 988 } 989 990 os_reason_t reason = os_reason_create(OS_REASON_CODESIGNING, 991 CODESIGNING_EXIT_REASON_LAUNCH_CONSTRAINT_VIOLATION); 992 993 *reasonp = reason; 994 995 reason->osr_flags = (OS_REASON_FLAG_GENERATE_CRASH_REPORT | 996 OS_REASON_FLAG_CONSISTENT_FAILURE); 997 998 if (fatal_failure_desc != NULL) { 999 mach_vm_address_t data_addr = 0; 1000 1001 int reason_error = 0; 1002 int kcdata_error = 0; 1003 1004 if ((reason_error = os_reason_alloc_buffer_noblock(reason, 1005 kcdata_estimate_required_buffer_size(1, 1006 (uint32_t)fatal_failure_desc_len))) == 0) { 1007 if ((kcdata_error = kcdata_get_memory_addr(&reason->osr_kcd_descriptor, 1008 EXIT_REASON_USER_DESC, (uint32_t)fatal_failure_desc_len, 1009 &data_addr)) == KERN_SUCCESS) { 1010 kcdata_memcpy(&reason->osr_kcd_descriptor, (mach_vm_address_t)data_addr, 1011 fatal_failure_desc, (uint32_t)fatal_failure_desc_len); 1012 } 1013 } 1014 } 1015 } 1016 1017 if (vn_path) { 1018 zfree(ZV_NAMEI, vn_path); 1019 } 1020 1021 if (fatal_failure_desc_len > 0 && fatal_failure_desc != NULL) { 1022 kfree_data(fatal_failure_desc, fatal_failure_desc_len); 1023 } 1024 1025 return error; 1026 } 1027