236 mtx_lock(&mac_policy_mtx); 237 mac_policy_count--; 238 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 239 if (mac_policy_count == 0) 240 cv_signal(&mac_policy_cv); 241 mtx_unlock(&mac_policy_mtx); 242} 243 244/* 245 * Initialize the MAC subsystem, including appropriate SMP locks. 246 */ 247static void 248mac_init(void) 249{ 250 251 LIST_INIT(&mac_static_policy_list); 252 LIST_INIT(&mac_policy_list); 253 254 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 255 cv_init(&mac_policy_cv, "mac_policy_cv"); 256} 257 258/* 259 * For the purposes of modules that want to know if they were loaded 260 * "early", set the mac_late flag once we've processed modules either 261 * linked into the kernel, or loaded before the kernel startup. 262 */ 263static void 264mac_late_init(void) 265{ 266 267 mac_late = 1; 268} 269 270/* 271 * After the policy list has changed, walk the list to update any global 272 * flags. Currently, we support only one flag, and it's conditionally 273 * defined; as a result, the entire function is conditional. Eventually, 274 * the #else case might also iterate across the policies. 275 */ 276static void 277mac_policy_updateflags(void) 278{ 279#ifndef MAC_ALWAYS_LABEL_MBUF 280 struct mac_policy_conf *tmpc; 281 int labelmbufs; 282 283 mac_policy_assert_exclusive(); 284 285 labelmbufs = 0; 286 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 287 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 288 labelmbufs++; 289 } 290 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 291 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 292 labelmbufs++; 293 } 294 mac_labelmbufs = (labelmbufs != 0); 295#endif 296} 297 298/* 299 * Allow MAC policy modules to register during boot, etc. 300 */ 301int 302mac_policy_modevent(module_t mod, int type, void *data) 303{ 304 struct mac_policy_conf *mpc; 305 int error; 306 307 error = 0; 308 mpc = (struct mac_policy_conf *) data; 309 310 switch (type) { 311 case MOD_LOAD: 312 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 313 mac_late) { 314 printf("mac_policy_modevent: can't load %s policy " 315 "after booting\n", mpc->mpc_name); 316 error = EBUSY; 317 break; 318 } 319 error = mac_policy_register(mpc); 320 break; 321 case MOD_UNLOAD: 322 /* Don't unregister the module if it was never registered. */ 323 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 324 != 0) 325 error = mac_policy_unregister(mpc); 326 else 327 error = 0; 328 break; 329 default: 330 break; 331 } 332 333 return (error); 334} 335 336static int 337mac_policy_register(struct mac_policy_conf *mpc) 338{ 339 struct mac_policy_conf *tmpc; 340 int error, slot, static_entry; 341 342 error = 0; 343 344 /* 345 * We don't technically need exclusive access while !mac_late, 346 * but hold it for assertion consistency. 347 */ 348 mac_policy_grab_exclusive(); 349 350 /* 351 * If the module can potentially be unloaded, or we're loading 352 * late, we have to stick it in the non-static list and pay 353 * an extra performance overhead. Otherwise, we can pay a 354 * light locking cost and stick it in the static list. 355 */ 356 static_entry = (!mac_late && 357 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 358 359 if (static_entry) { 360 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 361 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 362 error = EEXIST; 363 goto out; 364 } 365 } 366 } else { 367 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 368 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 369 error = EEXIST; 370 goto out; 371 } 372 } 373 } 374 if (mpc->mpc_field_off != NULL) { 375 slot = ffs(mac_slot_offsets_free); 376 if (slot == 0) { 377 error = ENOMEM; 378 goto out; 379 } 380 slot--; 381 mac_slot_offsets_free &= ~(1 << slot); 382 *mpc->mpc_field_off = slot; 383 } 384 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 385 386 /* 387 * If we're loading a MAC module after the framework has 388 * initialized, it has to go into the dynamic list. If 389 * we're loading it before we've finished initializing, 390 * it can go into the static list with weaker locker 391 * requirements. 392 */ 393 if (static_entry) 394 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 395 else 396 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 397 398 /* Per-policy initialization. */ 399 if (mpc->mpc_ops->mpo_init != NULL) 400 (*(mpc->mpc_ops->mpo_init))(mpc); 401 mac_policy_updateflags(); 402 403 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 404 mpc->mpc_name); 405 406out: 407 mac_policy_release_exclusive(); 408 return (error); 409} 410 411static int 412mac_policy_unregister(struct mac_policy_conf *mpc) 413{ 414 415 /* 416 * If we fail the load, we may get a request to unload. Check 417 * to see if we did the run-time registration, and if not, 418 * silently succeed. 419 */ 420 mac_policy_grab_exclusive(); 421 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 422 mac_policy_release_exclusive(); 423 return (0); 424 } 425#if 0 426 /* 427 * Don't allow unloading modules with private data. 428 */ 429 if (mpc->mpc_field_off != NULL) { 430 MAC_POLICY_LIST_UNLOCK(); 431 return (EBUSY); 432 } 433#endif 434 /* 435 * Only allow the unload to proceed if the module is unloadable 436 * by its own definition. 437 */ 438 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 439 mac_policy_release_exclusive(); 440 return (EBUSY); 441 } 442 if (mpc->mpc_ops->mpo_destroy != NULL) 443 (*(mpc->mpc_ops->mpo_destroy))(mpc); 444 445 LIST_REMOVE(mpc, mpc_list); 446 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 447 mac_policy_updateflags(); 448 449 mac_policy_release_exclusive(); 450 451 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 452 mpc->mpc_name); 453 454 return (0); 455} 456 457/* 458 * Define an error value precedence, and given two arguments, selects the 459 * value with the higher precedence. 460 */ 461int 462mac_error_select(int error1, int error2) 463{ 464 465 /* Certain decision-making errors take top priority. */ 466 if (error1 == EDEADLK || error2 == EDEADLK) 467 return (EDEADLK); 468 469 /* Invalid arguments should be reported where possible. */ 470 if (error1 == EINVAL || error2 == EINVAL) 471 return (EINVAL); 472 473 /* Precedence goes to "visibility", with both process and file. */ 474 if (error1 == ESRCH || error2 == ESRCH) 475 return (ESRCH); 476 477 if (error1 == ENOENT || error2 == ENOENT) 478 return (ENOENT); 479 480 /* Precedence goes to DAC/MAC protections. */ 481 if (error1 == EACCES || error2 == EACCES) 482 return (EACCES); 483 484 /* Precedence goes to privilege. */ 485 if (error1 == EPERM || error2 == EPERM) 486 return (EPERM); 487 488 /* Precedence goes to error over success; otherwise, arbitrary. */ 489 if (error1 != 0) 490 return (error1); 491 return (error2); 492} 493 494void 495mac_init_label(struct label *label) 496{ 497 498 bzero(label, sizeof(*label)); 499 label->l_flags = MAC_FLAG_INITIALIZED; 500} 501 502void 503mac_destroy_label(struct label *label) 504{ 505 506 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 507 ("destroying uninitialized label")); 508 509 bzero(label, sizeof(*label)); 510 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 511} 512 513int 514mac_check_structmac_consistent(struct mac *mac) 515{ 516 517 if (mac->m_buflen < 0 || 518 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 519 return (EINVAL); 520 521 return (0); 522} 523 524int 525__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 526{ 527 char *elements, *buffer; 528 struct mac mac; 529 struct proc *tproc; 530 struct ucred *tcred; 531 int error; 532 533 error = copyin(uap->mac_p, &mac, sizeof(mac)); 534 if (error) 535 return (error); 536 537 error = mac_check_structmac_consistent(&mac); 538 if (error) 539 return (error); 540 541 tproc = pfind(uap->pid); 542 if (tproc == NULL) 543 return (ESRCH); 544 545 tcred = NULL; /* Satisfy gcc. */ 546 error = p_cansee(td, tproc); 547 if (error == 0) 548 tcred = crhold(tproc->p_ucred); 549 PROC_UNLOCK(tproc); 550 if (error) 551 return (error); 552 553 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 554 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 555 if (error) { 556 free(elements, M_MACTEMP); 557 crfree(tcred); 558 return (error); 559 } 560 561 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 562 error = mac_externalize_cred_label(&tcred->cr_label, elements, 563 buffer, mac.m_buflen); 564 if (error == 0) 565 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 566 567 free(buffer, M_MACTEMP); 568 free(elements, M_MACTEMP); 569 crfree(tcred); 570 return (error); 571} 572 573/* 574 * MPSAFE 575 */ 576int 577__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 578{ 579 char *elements, *buffer; 580 struct mac mac; 581 int error; 582 583 error = copyin(uap->mac_p, &mac, sizeof(mac)); 584 if (error) 585 return (error); 586 587 error = mac_check_structmac_consistent(&mac); 588 if (error) 589 return (error); 590 591 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 592 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 593 if (error) { 594 free(elements, M_MACTEMP); 595 return (error); 596 } 597 598 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 599 error = mac_externalize_cred_label(&td->td_ucred->cr_label, 600 elements, buffer, mac.m_buflen); 601 if (error == 0) 602 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 603 604 free(buffer, M_MACTEMP); 605 free(elements, M_MACTEMP); 606 return (error); 607} 608 609/* 610 * MPSAFE 611 */ 612int 613__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 614{ 615 struct ucred *newcred, *oldcred; 616 struct label intlabel; 617 struct proc *p; 618 struct mac mac; 619 char *buffer; 620 int error; 621 622 error = copyin(uap->mac_p, &mac, sizeof(mac)); 623 if (error) 624 return (error); 625 626 error = mac_check_structmac_consistent(&mac); 627 if (error) 628 return (error); 629 630 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 631 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 632 if (error) { 633 free(buffer, M_MACTEMP); 634 return (error); 635 } 636 637 mac_init_cred_label(&intlabel); 638 error = mac_internalize_cred_label(&intlabel, buffer); 639 free(buffer, M_MACTEMP); 640 if (error) { 641 mac_destroy_cred_label(&intlabel); 642 return (error); 643 } 644 645 newcred = crget(); 646 647 p = td->td_proc; 648 PROC_LOCK(p); 649 oldcred = p->p_ucred; 650 651 error = mac_check_cred_relabel(oldcred, &intlabel); 652 if (error) { 653 PROC_UNLOCK(p); 654 crfree(newcred); 655 goto out; 656 } 657 658 setsugid(p); 659 crcopy(newcred, oldcred); 660 mac_relabel_cred(newcred, &intlabel); 661 p->p_ucred = newcred; 662 663 /* 664 * Grab additional reference for use while revoking mmaps, prior 665 * to releasing the proc lock and sharing the cred. 666 */ 667 crhold(newcred); 668 PROC_UNLOCK(p); 669 670 if (mac_enforce_vm) { 671 mtx_lock(&Giant); 672 mac_cred_mmapped_drop_perms(td, newcred); 673 mtx_unlock(&Giant); 674 } 675 676 crfree(newcred); /* Free revocation reference. */ 677 crfree(oldcred); 678 679out: 680 mac_destroy_cred_label(&intlabel); 681 return (error); 682} 683 684/* 685 * MPSAFE 686 */ 687int 688__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 689{ 690 char *elements, *buffer; 691 struct label intlabel; 692 struct file *fp; 693 struct mac mac; 694 struct vnode *vp; 695 struct pipe *pipe; 696 short label_type; 697 int error; 698 699 error = copyin(uap->mac_p, &mac, sizeof(mac)); 700 if (error) 701 return (error); 702 703 error = mac_check_structmac_consistent(&mac); 704 if (error) 705 return (error); 706 707 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 708 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 709 if (error) { 710 free(elements, M_MACTEMP); 711 return (error); 712 } 713 714 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 715 mtx_lock(&Giant); /* VFS */ 716 error = fget(td, uap->fd, &fp); 717 if (error) 718 goto out; 719 720 label_type = fp->f_type; 721 switch (fp->f_type) { 722 case DTYPE_FIFO: 723 case DTYPE_VNODE: 724 vp = fp->f_vnode; 725 726 mac_init_vnode_label(&intlabel); 727 728 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 729 mac_copy_vnode_label(&vp->v_label, &intlabel); 730 VOP_UNLOCK(vp, 0, td); 731 732 break; 733 case DTYPE_PIPE: 734 pipe = fp->f_data; 735 736 mac_init_pipe_label(&intlabel); 737 738 PIPE_LOCK(pipe); 739 mac_copy_pipe_label(pipe->pipe_label, &intlabel); 740 PIPE_UNLOCK(pipe); 741 break; 742 default: 743 error = EINVAL; 744 fdrop(fp, td); 745 goto out; 746 } 747 fdrop(fp, td); 748 749 switch (label_type) { 750 case DTYPE_FIFO: 751 case DTYPE_VNODE: 752 if (error == 0) 753 error = mac_externalize_vnode_label(&intlabel, 754 elements, buffer, mac.m_buflen); 755 mac_destroy_vnode_label(&intlabel); 756 break; 757 case DTYPE_PIPE: 758 error = mac_externalize_pipe_label(&intlabel, elements, 759 buffer, mac.m_buflen); 760 mac_destroy_pipe_label(&intlabel); 761 break; 762 default: 763 panic("__mac_get_fd: corrupted label_type"); 764 } 765 766 if (error == 0) 767 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 768 769out: 770 mtx_unlock(&Giant); /* VFS */ 771 free(buffer, M_MACTEMP); 772 free(elements, M_MACTEMP); 773 774 return (error); 775} 776 777/* 778 * MPSAFE 779 */ 780int 781__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 782{ 783 char *elements, *buffer; 784 struct nameidata nd; 785 struct label intlabel; 786 struct mac mac; 787 int error; 788 789 error = copyin(uap->mac_p, &mac, sizeof(mac)); 790 if (error) 791 return (error); 792 793 error = mac_check_structmac_consistent(&mac); 794 if (error) 795 return (error); 796 797 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 798 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 799 if (error) { 800 free(elements, M_MACTEMP); 801 return (error); 802 } 803 804 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 805 mtx_lock(&Giant); /* VFS */ 806 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 807 td); 808 error = namei(&nd); 809 if (error) 810 goto out; 811 812 mac_init_vnode_label(&intlabel); 813 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 814 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 815 mac.m_buflen); 816 817 NDFREE(&nd, 0); 818 mac_destroy_vnode_label(&intlabel); 819 820 if (error == 0) 821 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 822 823out: 824 mtx_unlock(&Giant); /* VFS */ 825 826 free(buffer, M_MACTEMP); 827 free(elements, M_MACTEMP); 828 829 return (error); 830} 831 832/* 833 * MPSAFE 834 */ 835int 836__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 837{ 838 char *elements, *buffer; 839 struct nameidata nd; 840 struct label intlabel; 841 struct mac mac; 842 int error; 843 844 error = copyin(uap->mac_p, &mac, sizeof(mac)); 845 if (error) 846 return (error); 847 848 error = mac_check_structmac_consistent(&mac); 849 if (error) 850 return (error); 851 852 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 853 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 854 if (error) { 855 free(elements, M_MACTEMP); 856 return (error); 857 } 858 859 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 860 mtx_lock(&Giant); /* VFS */ 861 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 862 td); 863 error = namei(&nd); 864 if (error) 865 goto out; 866 867 mac_init_vnode_label(&intlabel); 868 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 869 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 870 mac.m_buflen); 871 NDFREE(&nd, 0); 872 mac_destroy_vnode_label(&intlabel); 873 874 if (error == 0) 875 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 876 877out: 878 mtx_unlock(&Giant); /* VFS */ 879 880 free(buffer, M_MACTEMP); 881 free(elements, M_MACTEMP); 882 883 return (error); 884} 885 886/* 887 * MPSAFE 888 */ 889int 890__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 891{ 892 struct label intlabel; 893 struct pipe *pipe; 894 struct file *fp; 895 struct mount *mp; 896 struct vnode *vp; 897 struct mac mac; 898 char *buffer; 899 int error; 900 901 error = copyin(uap->mac_p, &mac, sizeof(mac)); 902 if (error) 903 return (error); 904 905 error = mac_check_structmac_consistent(&mac); 906 if (error) 907 return (error); 908 909 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 910 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 911 if (error) { 912 free(buffer, M_MACTEMP); 913 return (error); 914 } 915 916 mtx_lock(&Giant); /* VFS */ 917 918 error = fget(td, uap->fd, &fp); 919 if (error) 920 goto out; 921 922 switch (fp->f_type) { 923 case DTYPE_FIFO: 924 case DTYPE_VNODE: 925 mac_init_vnode_label(&intlabel); 926 error = mac_internalize_vnode_label(&intlabel, buffer); 927 if (error) { 928 mac_destroy_vnode_label(&intlabel); 929 break; 930 } 931 932 vp = fp->f_vnode; 933 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 934 if (error != 0) { 935 mac_destroy_vnode_label(&intlabel); 936 break; 937 } 938 939 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 940 error = vn_setlabel(vp, &intlabel, td->td_ucred); 941 VOP_UNLOCK(vp, 0, td); 942 vn_finished_write(mp); 943 944 mac_destroy_vnode_label(&intlabel); 945 break; 946 947 case DTYPE_PIPE: 948 mac_init_pipe_label(&intlabel); 949 error = mac_internalize_pipe_label(&intlabel, buffer); 950 if (error == 0) { 951 pipe = fp->f_data; 952 PIPE_LOCK(pipe); 953 error = mac_pipe_label_set(td->td_ucred, pipe, 954 &intlabel); 955 PIPE_UNLOCK(pipe); 956 } 957 958 mac_destroy_pipe_label(&intlabel); 959 break; 960 961 default: 962 error = EINVAL; 963 } 964 965 fdrop(fp, td); 966out: 967 mtx_unlock(&Giant); /* VFS */ 968 969 free(buffer, M_MACTEMP); 970 971 return (error); 972} 973 974/* 975 * MPSAFE 976 */ 977int 978__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 979{ 980 struct label intlabel; 981 struct nameidata nd; 982 struct mount *mp; 983 struct mac mac; 984 char *buffer; 985 int error; 986 987 error = copyin(uap->mac_p, &mac, sizeof(mac)); 988 if (error) 989 return (error); 990 991 error = mac_check_structmac_consistent(&mac); 992 if (error) 993 return (error); 994 995 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 996 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 997 if (error) { 998 free(buffer, M_MACTEMP); 999 return (error); 1000 } 1001 1002 mac_init_vnode_label(&intlabel); 1003 error = mac_internalize_vnode_label(&intlabel, buffer); 1004 free(buffer, M_MACTEMP); 1005 if (error) { 1006 mac_destroy_vnode_label(&intlabel); 1007 return (error); 1008 } 1009 1010 mtx_lock(&Giant); /* VFS */ 1011 1012 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1013 td); 1014 error = namei(&nd); 1015 if (error == 0) { 1016 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1017 if (error == 0) 1018 error = vn_setlabel(nd.ni_vp, &intlabel, 1019 td->td_ucred); 1020 vn_finished_write(mp); 1021 } 1022 1023 NDFREE(&nd, 0); 1024 mtx_unlock(&Giant); /* VFS */ 1025 mac_destroy_vnode_label(&intlabel); 1026 1027 return (error); 1028} 1029 1030/* 1031 * MPSAFE 1032 */ 1033int 1034__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1035{ 1036 struct label intlabel; 1037 struct nameidata nd; 1038 struct mount *mp; 1039 struct mac mac; 1040 char *buffer; 1041 int error; 1042 1043 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1044 if (error) 1045 return (error); 1046 1047 error = mac_check_structmac_consistent(&mac); 1048 if (error) 1049 return (error); 1050 1051 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1052 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1053 if (error) { 1054 free(buffer, M_MACTEMP); 1055 return (error); 1056 } 1057 1058 mac_init_vnode_label(&intlabel); 1059 error = mac_internalize_vnode_label(&intlabel, buffer); 1060 free(buffer, M_MACTEMP); 1061 if (error) { 1062 mac_destroy_vnode_label(&intlabel); 1063 return (error); 1064 } 1065 1066 mtx_lock(&Giant); /* VFS */ 1067 1068 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1069 td); 1070 error = namei(&nd); 1071 if (error == 0) { 1072 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1073 if (error == 0) 1074 error = vn_setlabel(nd.ni_vp, &intlabel, 1075 td->td_ucred); 1076 vn_finished_write(mp); 1077 } 1078 1079 NDFREE(&nd, 0); 1080 mtx_unlock(&Giant); /* VFS */ 1081 mac_destroy_vnode_label(&intlabel); 1082 1083 return (error); 1084} 1085 1086/* 1087 * MPSAFE 1088 */ 1089int 1090mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1091{ 1092 struct mac_policy_conf *mpc; 1093 char target[MAC_MAX_POLICY_NAME]; 1094 int entrycount, error; 1095 1096 error = copyinstr(uap->policy, target, sizeof(target), NULL); 1097 if (error) 1098 return (error); 1099 1100 error = ENOSYS; 1101 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1102 if (strcmp(mpc->mpc_name, target) == 0 && 1103 mpc->mpc_ops->mpo_syscall != NULL) { 1104 error = mpc->mpc_ops->mpo_syscall(td, 1105 uap->call, uap->arg); 1106 goto out; 1107 } 1108 } 1109 1110 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1111 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1112 if (strcmp(mpc->mpc_name, target) == 0 && 1113 mpc->mpc_ops->mpo_syscall != NULL) { 1114 error = mpc->mpc_ops->mpo_syscall(td, 1115 uap->call, uap->arg); 1116 break; 1117 } 1118 } 1119 mac_policy_list_unbusy(); 1120 } 1121out: 1122 return (error); 1123} 1124 1125SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1126SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1127 1128#else /* !MAC */ 1129 1130int 1131__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1132{ 1133 1134 return (ENOSYS); 1135} 1136 1137int 1138__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1139{ 1140 1141 return (ENOSYS); 1142} 1143 1144int 1145__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1146{ 1147 1148 return (ENOSYS); 1149} 1150 1151int 1152__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1153{ 1154 1155 return (ENOSYS); 1156} 1157 1158int 1159__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1160{ 1161 1162 return (ENOSYS); 1163} 1164 1165int 1166__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1167{ 1168 1169 return (ENOSYS); 1170} 1171 1172int 1173__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1174{ 1175 1176 return (ENOSYS); 1177} 1178 1179int 1180__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1181{ 1182 1183 return (ENOSYS); 1184} 1185 1186int 1187__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1188{ 1189 1190 return (ENOSYS); 1191} 1192 1193int 1194mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1195{ 1196 1197 return (ENOSYS); 1198} 1199 1200#endif
| 242 mtx_lock(&mac_policy_mtx); 243 mac_policy_count--; 244 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 245 if (mac_policy_count == 0) 246 cv_signal(&mac_policy_cv); 247 mtx_unlock(&mac_policy_mtx); 248} 249 250/* 251 * Initialize the MAC subsystem, including appropriate SMP locks. 252 */ 253static void 254mac_init(void) 255{ 256 257 LIST_INIT(&mac_static_policy_list); 258 LIST_INIT(&mac_policy_list); 259 260 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 261 cv_init(&mac_policy_cv, "mac_policy_cv"); 262} 263 264/* 265 * For the purposes of modules that want to know if they were loaded 266 * "early", set the mac_late flag once we've processed modules either 267 * linked into the kernel, or loaded before the kernel startup. 268 */ 269static void 270mac_late_init(void) 271{ 272 273 mac_late = 1; 274} 275 276/* 277 * After the policy list has changed, walk the list to update any global 278 * flags. Currently, we support only one flag, and it's conditionally 279 * defined; as a result, the entire function is conditional. Eventually, 280 * the #else case might also iterate across the policies. 281 */ 282static void 283mac_policy_updateflags(void) 284{ 285#ifndef MAC_ALWAYS_LABEL_MBUF 286 struct mac_policy_conf *tmpc; 287 int labelmbufs; 288 289 mac_policy_assert_exclusive(); 290 291 labelmbufs = 0; 292 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 293 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 294 labelmbufs++; 295 } 296 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 297 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 298 labelmbufs++; 299 } 300 mac_labelmbufs = (labelmbufs != 0); 301#endif 302} 303 304/* 305 * Allow MAC policy modules to register during boot, etc. 306 */ 307int 308mac_policy_modevent(module_t mod, int type, void *data) 309{ 310 struct mac_policy_conf *mpc; 311 int error; 312 313 error = 0; 314 mpc = (struct mac_policy_conf *) data; 315 316 switch (type) { 317 case MOD_LOAD: 318 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 319 mac_late) { 320 printf("mac_policy_modevent: can't load %s policy " 321 "after booting\n", mpc->mpc_name); 322 error = EBUSY; 323 break; 324 } 325 error = mac_policy_register(mpc); 326 break; 327 case MOD_UNLOAD: 328 /* Don't unregister the module if it was never registered. */ 329 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 330 != 0) 331 error = mac_policy_unregister(mpc); 332 else 333 error = 0; 334 break; 335 default: 336 break; 337 } 338 339 return (error); 340} 341 342static int 343mac_policy_register(struct mac_policy_conf *mpc) 344{ 345 struct mac_policy_conf *tmpc; 346 int error, slot, static_entry; 347 348 error = 0; 349 350 /* 351 * We don't technically need exclusive access while !mac_late, 352 * but hold it for assertion consistency. 353 */ 354 mac_policy_grab_exclusive(); 355 356 /* 357 * If the module can potentially be unloaded, or we're loading 358 * late, we have to stick it in the non-static list and pay 359 * an extra performance overhead. Otherwise, we can pay a 360 * light locking cost and stick it in the static list. 361 */ 362 static_entry = (!mac_late && 363 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 364 365 if (static_entry) { 366 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 367 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 368 error = EEXIST; 369 goto out; 370 } 371 } 372 } else { 373 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 374 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 375 error = EEXIST; 376 goto out; 377 } 378 } 379 } 380 if (mpc->mpc_field_off != NULL) { 381 slot = ffs(mac_slot_offsets_free); 382 if (slot == 0) { 383 error = ENOMEM; 384 goto out; 385 } 386 slot--; 387 mac_slot_offsets_free &= ~(1 << slot); 388 *mpc->mpc_field_off = slot; 389 } 390 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 391 392 /* 393 * If we're loading a MAC module after the framework has 394 * initialized, it has to go into the dynamic list. If 395 * we're loading it before we've finished initializing, 396 * it can go into the static list with weaker locker 397 * requirements. 398 */ 399 if (static_entry) 400 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 401 else 402 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 403 404 /* Per-policy initialization. */ 405 if (mpc->mpc_ops->mpo_init != NULL) 406 (*(mpc->mpc_ops->mpo_init))(mpc); 407 mac_policy_updateflags(); 408 409 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 410 mpc->mpc_name); 411 412out: 413 mac_policy_release_exclusive(); 414 return (error); 415} 416 417static int 418mac_policy_unregister(struct mac_policy_conf *mpc) 419{ 420 421 /* 422 * If we fail the load, we may get a request to unload. Check 423 * to see if we did the run-time registration, and if not, 424 * silently succeed. 425 */ 426 mac_policy_grab_exclusive(); 427 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 428 mac_policy_release_exclusive(); 429 return (0); 430 } 431#if 0 432 /* 433 * Don't allow unloading modules with private data. 434 */ 435 if (mpc->mpc_field_off != NULL) { 436 MAC_POLICY_LIST_UNLOCK(); 437 return (EBUSY); 438 } 439#endif 440 /* 441 * Only allow the unload to proceed if the module is unloadable 442 * by its own definition. 443 */ 444 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 445 mac_policy_release_exclusive(); 446 return (EBUSY); 447 } 448 if (mpc->mpc_ops->mpo_destroy != NULL) 449 (*(mpc->mpc_ops->mpo_destroy))(mpc); 450 451 LIST_REMOVE(mpc, mpc_list); 452 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 453 mac_policy_updateflags(); 454 455 mac_policy_release_exclusive(); 456 457 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 458 mpc->mpc_name); 459 460 return (0); 461} 462 463/* 464 * Define an error value precedence, and given two arguments, selects the 465 * value with the higher precedence. 466 */ 467int 468mac_error_select(int error1, int error2) 469{ 470 471 /* Certain decision-making errors take top priority. */ 472 if (error1 == EDEADLK || error2 == EDEADLK) 473 return (EDEADLK); 474 475 /* Invalid arguments should be reported where possible. */ 476 if (error1 == EINVAL || error2 == EINVAL) 477 return (EINVAL); 478 479 /* Precedence goes to "visibility", with both process and file. */ 480 if (error1 == ESRCH || error2 == ESRCH) 481 return (ESRCH); 482 483 if (error1 == ENOENT || error2 == ENOENT) 484 return (ENOENT); 485 486 /* Precedence goes to DAC/MAC protections. */ 487 if (error1 == EACCES || error2 == EACCES) 488 return (EACCES); 489 490 /* Precedence goes to privilege. */ 491 if (error1 == EPERM || error2 == EPERM) 492 return (EPERM); 493 494 /* Precedence goes to error over success; otherwise, arbitrary. */ 495 if (error1 != 0) 496 return (error1); 497 return (error2); 498} 499 500void 501mac_init_label(struct label *label) 502{ 503 504 bzero(label, sizeof(*label)); 505 label->l_flags = MAC_FLAG_INITIALIZED; 506} 507 508void 509mac_destroy_label(struct label *label) 510{ 511 512 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 513 ("destroying uninitialized label")); 514 515 bzero(label, sizeof(*label)); 516 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 517} 518 519int 520mac_check_structmac_consistent(struct mac *mac) 521{ 522 523 if (mac->m_buflen < 0 || 524 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 525 return (EINVAL); 526 527 return (0); 528} 529 530int 531__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 532{ 533 char *elements, *buffer; 534 struct mac mac; 535 struct proc *tproc; 536 struct ucred *tcred; 537 int error; 538 539 error = copyin(uap->mac_p, &mac, sizeof(mac)); 540 if (error) 541 return (error); 542 543 error = mac_check_structmac_consistent(&mac); 544 if (error) 545 return (error); 546 547 tproc = pfind(uap->pid); 548 if (tproc == NULL) 549 return (ESRCH); 550 551 tcred = NULL; /* Satisfy gcc. */ 552 error = p_cansee(td, tproc); 553 if (error == 0) 554 tcred = crhold(tproc->p_ucred); 555 PROC_UNLOCK(tproc); 556 if (error) 557 return (error); 558 559 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 560 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 561 if (error) { 562 free(elements, M_MACTEMP); 563 crfree(tcred); 564 return (error); 565 } 566 567 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 568 error = mac_externalize_cred_label(&tcred->cr_label, elements, 569 buffer, mac.m_buflen); 570 if (error == 0) 571 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 572 573 free(buffer, M_MACTEMP); 574 free(elements, M_MACTEMP); 575 crfree(tcred); 576 return (error); 577} 578 579/* 580 * MPSAFE 581 */ 582int 583__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 584{ 585 char *elements, *buffer; 586 struct mac mac; 587 int error; 588 589 error = copyin(uap->mac_p, &mac, sizeof(mac)); 590 if (error) 591 return (error); 592 593 error = mac_check_structmac_consistent(&mac); 594 if (error) 595 return (error); 596 597 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 598 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 599 if (error) { 600 free(elements, M_MACTEMP); 601 return (error); 602 } 603 604 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 605 error = mac_externalize_cred_label(&td->td_ucred->cr_label, 606 elements, buffer, mac.m_buflen); 607 if (error == 0) 608 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 609 610 free(buffer, M_MACTEMP); 611 free(elements, M_MACTEMP); 612 return (error); 613} 614 615/* 616 * MPSAFE 617 */ 618int 619__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 620{ 621 struct ucred *newcred, *oldcred; 622 struct label intlabel; 623 struct proc *p; 624 struct mac mac; 625 char *buffer; 626 int error; 627 628 error = copyin(uap->mac_p, &mac, sizeof(mac)); 629 if (error) 630 return (error); 631 632 error = mac_check_structmac_consistent(&mac); 633 if (error) 634 return (error); 635 636 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 637 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 638 if (error) { 639 free(buffer, M_MACTEMP); 640 return (error); 641 } 642 643 mac_init_cred_label(&intlabel); 644 error = mac_internalize_cred_label(&intlabel, buffer); 645 free(buffer, M_MACTEMP); 646 if (error) { 647 mac_destroy_cred_label(&intlabel); 648 return (error); 649 } 650 651 newcred = crget(); 652 653 p = td->td_proc; 654 PROC_LOCK(p); 655 oldcred = p->p_ucred; 656 657 error = mac_check_cred_relabel(oldcred, &intlabel); 658 if (error) { 659 PROC_UNLOCK(p); 660 crfree(newcred); 661 goto out; 662 } 663 664 setsugid(p); 665 crcopy(newcred, oldcred); 666 mac_relabel_cred(newcred, &intlabel); 667 p->p_ucred = newcred; 668 669 /* 670 * Grab additional reference for use while revoking mmaps, prior 671 * to releasing the proc lock and sharing the cred. 672 */ 673 crhold(newcred); 674 PROC_UNLOCK(p); 675 676 if (mac_enforce_vm) { 677 mtx_lock(&Giant); 678 mac_cred_mmapped_drop_perms(td, newcred); 679 mtx_unlock(&Giant); 680 } 681 682 crfree(newcred); /* Free revocation reference. */ 683 crfree(oldcred); 684 685out: 686 mac_destroy_cred_label(&intlabel); 687 return (error); 688} 689 690/* 691 * MPSAFE 692 */ 693int 694__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 695{ 696 char *elements, *buffer; 697 struct label intlabel; 698 struct file *fp; 699 struct mac mac; 700 struct vnode *vp; 701 struct pipe *pipe; 702 short label_type; 703 int error; 704 705 error = copyin(uap->mac_p, &mac, sizeof(mac)); 706 if (error) 707 return (error); 708 709 error = mac_check_structmac_consistent(&mac); 710 if (error) 711 return (error); 712 713 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 714 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 715 if (error) { 716 free(elements, M_MACTEMP); 717 return (error); 718 } 719 720 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 721 mtx_lock(&Giant); /* VFS */ 722 error = fget(td, uap->fd, &fp); 723 if (error) 724 goto out; 725 726 label_type = fp->f_type; 727 switch (fp->f_type) { 728 case DTYPE_FIFO: 729 case DTYPE_VNODE: 730 vp = fp->f_vnode; 731 732 mac_init_vnode_label(&intlabel); 733 734 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 735 mac_copy_vnode_label(&vp->v_label, &intlabel); 736 VOP_UNLOCK(vp, 0, td); 737 738 break; 739 case DTYPE_PIPE: 740 pipe = fp->f_data; 741 742 mac_init_pipe_label(&intlabel); 743 744 PIPE_LOCK(pipe); 745 mac_copy_pipe_label(pipe->pipe_label, &intlabel); 746 PIPE_UNLOCK(pipe); 747 break; 748 default: 749 error = EINVAL; 750 fdrop(fp, td); 751 goto out; 752 } 753 fdrop(fp, td); 754 755 switch (label_type) { 756 case DTYPE_FIFO: 757 case DTYPE_VNODE: 758 if (error == 0) 759 error = mac_externalize_vnode_label(&intlabel, 760 elements, buffer, mac.m_buflen); 761 mac_destroy_vnode_label(&intlabel); 762 break; 763 case DTYPE_PIPE: 764 error = mac_externalize_pipe_label(&intlabel, elements, 765 buffer, mac.m_buflen); 766 mac_destroy_pipe_label(&intlabel); 767 break; 768 default: 769 panic("__mac_get_fd: corrupted label_type"); 770 } 771 772 if (error == 0) 773 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 774 775out: 776 mtx_unlock(&Giant); /* VFS */ 777 free(buffer, M_MACTEMP); 778 free(elements, M_MACTEMP); 779 780 return (error); 781} 782 783/* 784 * MPSAFE 785 */ 786int 787__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 788{ 789 char *elements, *buffer; 790 struct nameidata nd; 791 struct label intlabel; 792 struct mac mac; 793 int error; 794 795 error = copyin(uap->mac_p, &mac, sizeof(mac)); 796 if (error) 797 return (error); 798 799 error = mac_check_structmac_consistent(&mac); 800 if (error) 801 return (error); 802 803 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 804 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 805 if (error) { 806 free(elements, M_MACTEMP); 807 return (error); 808 } 809 810 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 811 mtx_lock(&Giant); /* VFS */ 812 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 813 td); 814 error = namei(&nd); 815 if (error) 816 goto out; 817 818 mac_init_vnode_label(&intlabel); 819 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 820 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 821 mac.m_buflen); 822 823 NDFREE(&nd, 0); 824 mac_destroy_vnode_label(&intlabel); 825 826 if (error == 0) 827 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 828 829out: 830 mtx_unlock(&Giant); /* VFS */ 831 832 free(buffer, M_MACTEMP); 833 free(elements, M_MACTEMP); 834 835 return (error); 836} 837 838/* 839 * MPSAFE 840 */ 841int 842__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 843{ 844 char *elements, *buffer; 845 struct nameidata nd; 846 struct label intlabel; 847 struct mac mac; 848 int error; 849 850 error = copyin(uap->mac_p, &mac, sizeof(mac)); 851 if (error) 852 return (error); 853 854 error = mac_check_structmac_consistent(&mac); 855 if (error) 856 return (error); 857 858 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 859 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 860 if (error) { 861 free(elements, M_MACTEMP); 862 return (error); 863 } 864 865 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 866 mtx_lock(&Giant); /* VFS */ 867 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 868 td); 869 error = namei(&nd); 870 if (error) 871 goto out; 872 873 mac_init_vnode_label(&intlabel); 874 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 875 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 876 mac.m_buflen); 877 NDFREE(&nd, 0); 878 mac_destroy_vnode_label(&intlabel); 879 880 if (error == 0) 881 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 882 883out: 884 mtx_unlock(&Giant); /* VFS */ 885 886 free(buffer, M_MACTEMP); 887 free(elements, M_MACTEMP); 888 889 return (error); 890} 891 892/* 893 * MPSAFE 894 */ 895int 896__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 897{ 898 struct label intlabel; 899 struct pipe *pipe; 900 struct file *fp; 901 struct mount *mp; 902 struct vnode *vp; 903 struct mac mac; 904 char *buffer; 905 int error; 906 907 error = copyin(uap->mac_p, &mac, sizeof(mac)); 908 if (error) 909 return (error); 910 911 error = mac_check_structmac_consistent(&mac); 912 if (error) 913 return (error); 914 915 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 916 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 917 if (error) { 918 free(buffer, M_MACTEMP); 919 return (error); 920 } 921 922 mtx_lock(&Giant); /* VFS */ 923 924 error = fget(td, uap->fd, &fp); 925 if (error) 926 goto out; 927 928 switch (fp->f_type) { 929 case DTYPE_FIFO: 930 case DTYPE_VNODE: 931 mac_init_vnode_label(&intlabel); 932 error = mac_internalize_vnode_label(&intlabel, buffer); 933 if (error) { 934 mac_destroy_vnode_label(&intlabel); 935 break; 936 } 937 938 vp = fp->f_vnode; 939 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 940 if (error != 0) { 941 mac_destroy_vnode_label(&intlabel); 942 break; 943 } 944 945 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 946 error = vn_setlabel(vp, &intlabel, td->td_ucred); 947 VOP_UNLOCK(vp, 0, td); 948 vn_finished_write(mp); 949 950 mac_destroy_vnode_label(&intlabel); 951 break; 952 953 case DTYPE_PIPE: 954 mac_init_pipe_label(&intlabel); 955 error = mac_internalize_pipe_label(&intlabel, buffer); 956 if (error == 0) { 957 pipe = fp->f_data; 958 PIPE_LOCK(pipe); 959 error = mac_pipe_label_set(td->td_ucred, pipe, 960 &intlabel); 961 PIPE_UNLOCK(pipe); 962 } 963 964 mac_destroy_pipe_label(&intlabel); 965 break; 966 967 default: 968 error = EINVAL; 969 } 970 971 fdrop(fp, td); 972out: 973 mtx_unlock(&Giant); /* VFS */ 974 975 free(buffer, M_MACTEMP); 976 977 return (error); 978} 979 980/* 981 * MPSAFE 982 */ 983int 984__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 985{ 986 struct label intlabel; 987 struct nameidata nd; 988 struct mount *mp; 989 struct mac mac; 990 char *buffer; 991 int error; 992 993 error = copyin(uap->mac_p, &mac, sizeof(mac)); 994 if (error) 995 return (error); 996 997 error = mac_check_structmac_consistent(&mac); 998 if (error) 999 return (error); 1000 1001 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1002 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1003 if (error) { 1004 free(buffer, M_MACTEMP); 1005 return (error); 1006 } 1007 1008 mac_init_vnode_label(&intlabel); 1009 error = mac_internalize_vnode_label(&intlabel, buffer); 1010 free(buffer, M_MACTEMP); 1011 if (error) { 1012 mac_destroy_vnode_label(&intlabel); 1013 return (error); 1014 } 1015 1016 mtx_lock(&Giant); /* VFS */ 1017 1018 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1019 td); 1020 error = namei(&nd); 1021 if (error == 0) { 1022 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1023 if (error == 0) 1024 error = vn_setlabel(nd.ni_vp, &intlabel, 1025 td->td_ucred); 1026 vn_finished_write(mp); 1027 } 1028 1029 NDFREE(&nd, 0); 1030 mtx_unlock(&Giant); /* VFS */ 1031 mac_destroy_vnode_label(&intlabel); 1032 1033 return (error); 1034} 1035 1036/* 1037 * MPSAFE 1038 */ 1039int 1040__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1041{ 1042 struct label intlabel; 1043 struct nameidata nd; 1044 struct mount *mp; 1045 struct mac mac; 1046 char *buffer; 1047 int error; 1048 1049 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1050 if (error) 1051 return (error); 1052 1053 error = mac_check_structmac_consistent(&mac); 1054 if (error) 1055 return (error); 1056 1057 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1058 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1059 if (error) { 1060 free(buffer, M_MACTEMP); 1061 return (error); 1062 } 1063 1064 mac_init_vnode_label(&intlabel); 1065 error = mac_internalize_vnode_label(&intlabel, buffer); 1066 free(buffer, M_MACTEMP); 1067 if (error) { 1068 mac_destroy_vnode_label(&intlabel); 1069 return (error); 1070 } 1071 1072 mtx_lock(&Giant); /* VFS */ 1073 1074 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1075 td); 1076 error = namei(&nd); 1077 if (error == 0) { 1078 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1079 if (error == 0) 1080 error = vn_setlabel(nd.ni_vp, &intlabel, 1081 td->td_ucred); 1082 vn_finished_write(mp); 1083 } 1084 1085 NDFREE(&nd, 0); 1086 mtx_unlock(&Giant); /* VFS */ 1087 mac_destroy_vnode_label(&intlabel); 1088 1089 return (error); 1090} 1091 1092/* 1093 * MPSAFE 1094 */ 1095int 1096mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1097{ 1098 struct mac_policy_conf *mpc; 1099 char target[MAC_MAX_POLICY_NAME]; 1100 int entrycount, error; 1101 1102 error = copyinstr(uap->policy, target, sizeof(target), NULL); 1103 if (error) 1104 return (error); 1105 1106 error = ENOSYS; 1107 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1108 if (strcmp(mpc->mpc_name, target) == 0 && 1109 mpc->mpc_ops->mpo_syscall != NULL) { 1110 error = mpc->mpc_ops->mpo_syscall(td, 1111 uap->call, uap->arg); 1112 goto out; 1113 } 1114 } 1115 1116 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1117 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1118 if (strcmp(mpc->mpc_name, target) == 0 && 1119 mpc->mpc_ops->mpo_syscall != NULL) { 1120 error = mpc->mpc_ops->mpo_syscall(td, 1121 uap->call, uap->arg); 1122 break; 1123 } 1124 } 1125 mac_policy_list_unbusy(); 1126 } 1127out: 1128 return (error); 1129} 1130 1131SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1132SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1133 1134#else /* !MAC */ 1135 1136int 1137__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1138{ 1139 1140 return (ENOSYS); 1141} 1142 1143int 1144__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1145{ 1146 1147 return (ENOSYS); 1148} 1149 1150int 1151__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1152{ 1153 1154 return (ENOSYS); 1155} 1156 1157int 1158__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1159{ 1160 1161 return (ENOSYS); 1162} 1163 1164int 1165__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1166{ 1167 1168 return (ENOSYS); 1169} 1170 1171int 1172__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1173{ 1174 1175 return (ENOSYS); 1176} 1177 1178int 1179__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1180{ 1181 1182 return (ENOSYS); 1183} 1184 1185int 1186__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1187{ 1188 1189 return (ENOSYS); 1190} 1191 1192int 1193__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1194{ 1195 1196 return (ENOSYS); 1197} 1198 1199int 1200mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1201{ 1202 1203 return (ENOSYS); 1204} 1205 1206#endif
|