133static int mac_enforce_network = 1; 134SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 135 &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 136TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 137 138static int mac_enforce_pipe = 1; 139SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 140 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 141TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 142 143static int mac_enforce_process = 1; 144SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 145 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 146TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 147 148static int mac_enforce_socket = 1; 149SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 150 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 151TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 152 153static int mac_enforce_system = 1; 154SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 155 &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 156TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 157 158static int mac_enforce_vm = 1; 159SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 160 &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 161TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 162 163static int mac_mmap_revocation = 1; 164SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 165 &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 166 "relabel"); 167static int mac_mmap_revocation_via_cow = 0; 168SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 169 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 170 "copy-on-write semantics, or by removing all write access"); 171 172#ifdef MAC_DEBUG 173SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 174 "TrustedBSD MAC debug info"); 175 176static int mac_debug_label_fallback = 0; 177SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 178 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 179 "when label is corrupted."); 180TUNABLE_INT("security.mac.debug_label_fallback", 181 &mac_debug_label_fallback); 182 183SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 184 "TrustedBSD MAC object counters"); 185 186static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 187 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 188 nmacipqs, nmacpipes; 189 190SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 191 &nmacmbufs, 0, "number of mbufs in use"); 192SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 193 &nmaccreds, 0, "number of ucreds in use"); 194SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 195 &nmacifnets, 0, "number of ifnets in use"); 196SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 197 &nmacipqs, 0, "number of ipqs in use"); 198SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 199 &nmacbpfdescs, 0, "number of bpfdescs in use"); 200SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 201 &nmacsockets, 0, "number of sockets in use"); 202SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 203 &nmacpipes, 0, "number of pipes in use"); 204SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 205 &nmacmounts, 0, "number of mounts in use"); 206SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 207 &nmactemp, 0, "number of temporary labels in use"); 208SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 209 &nmacvnodes, 0, "number of vnodes in use"); 210SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 211 &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 212#endif 213 214static int error_select(int error1, int error2); 215static int mac_policy_register(struct mac_policy_conf *mpc); 216static int mac_policy_unregister(struct mac_policy_conf *mpc); 217 218static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 219 struct vnode *vp, int *prot); 220static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 221 struct ucred *cred, struct vm_map *map); 222 223static void mac_destroy_socket_label(struct label *label); 224 225static int mac_setlabel_vnode_extattr(struct ucred *cred, 226 struct vnode *vp, struct label *intlabel); 227 228MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 229MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 230 231/* 232 * mac_policy_list stores the list of active policies. A busy count is 233 * maintained for the list, stored in mac_policy_busy. The busy count 234 * is protected by mac_policy_list_lock; the list may be modified only 235 * while the busy count is 0, requiring that the lock be held to 236 * prevent new references to the list from being acquired. For almost 237 * all operations, incrementing the busy count is sufficient to 238 * guarantee consistency, as the list cannot be modified while the 239 * busy count is elevated. For a few special operations involving a 240 * change to the list of active policies, the lock itself must be held. 241 * A condition variable, mac_policy_list_not_busy, is used to signal 242 * potential exclusive consumers that they should try to acquire the 243 * lock if a first attempt at exclusive access fails. 244 */ 245static struct mtx mac_policy_list_lock; 246static struct cv mac_policy_list_not_busy; 247static LIST_HEAD(, mac_policy_conf) mac_policy_list; 248static int mac_policy_list_busy; 249 250#define MAC_POLICY_LIST_LOCKINIT() do { \ 251 mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL, \ 252 MTX_DEF); \ 253 cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy"); \ 254} while (0) 255 256#define MAC_POLICY_LIST_LOCK() do { \ 257 mtx_lock(&mac_policy_list_lock); \ 258} while (0) 259 260#define MAC_POLICY_LIST_UNLOCK() do { \ 261 mtx_unlock(&mac_policy_list_lock); \ 262} while (0) 263 264/* 265 * We manually invoke WITNESS_SLEEP() to allow Witness to generate 266 * warnings even if we don't end up ever triggering the wait at 267 * run-time. The consumer of the exclusive interface must not hold 268 * any locks (other than potentially Giant) since we may sleep for 269 * long (potentially indefinite) periods of time waiting for the 270 * framework to become quiescent so that a policy list change may 271 * be made. 272 */ 273#define MAC_POLICY_LIST_EXCLUSIVE() do { \ 274 WITNESS_SLEEP(1, NULL); \ 275 mtx_lock(&mac_policy_list_lock); \ 276 while (mac_policy_list_busy != 0) \ 277 cv_wait(&mac_policy_list_not_busy, \ 278 &mac_policy_list_lock); \ 279} while (0) 280 281#define MAC_POLICY_LIST_BUSY() do { \ 282 MAC_POLICY_LIST_LOCK(); \ 283 mac_policy_list_busy++; \ 284 MAC_POLICY_LIST_UNLOCK(); \ 285} while (0) 286 287#define MAC_POLICY_LIST_UNBUSY() do { \ 288 MAC_POLICY_LIST_LOCK(); \ 289 mac_policy_list_busy--; \ 290 KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK")); \ 291 if (mac_policy_list_busy == 0) \ 292 cv_signal(&mac_policy_list_not_busy); \ 293 MAC_POLICY_LIST_UNLOCK(); \ 294} while (0) 295 296/* 297 * MAC_CHECK performs the designated check by walking the policy 298 * module list and checking with each as to how it feels about the 299 * request. Note that it returns its value via 'error' in the scope 300 * of the caller. 301 */ 302#define MAC_CHECK(check, args...) do { \ 303 struct mac_policy_conf *mpc; \ 304 \ 305 error = 0; \ 306 MAC_POLICY_LIST_BUSY(); \ 307 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 308 if (mpc->mpc_ops->mpo_ ## check != NULL) \ 309 error = error_select( \ 310 mpc->mpc_ops->mpo_ ## check (args), \ 311 error); \ 312 } \ 313 MAC_POLICY_LIST_UNBUSY(); \ 314} while (0) 315 316/* 317 * MAC_BOOLEAN performs the designated boolean composition by walking 318 * the module list, invoking each instance of the operation, and 319 * combining the results using the passed C operator. Note that it 320 * returns its value via 'result' in the scope of the caller, which 321 * should be initialized by the caller in a meaningful way to get 322 * a meaningful result. 323 */ 324#define MAC_BOOLEAN(operation, composition, args...) do { \ 325 struct mac_policy_conf *mpc; \ 326 \ 327 MAC_POLICY_LIST_BUSY(); \ 328 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 329 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 330 result = result composition \ 331 mpc->mpc_ops->mpo_ ## operation (args); \ 332 } \ 333 MAC_POLICY_LIST_UNBUSY(); \ 334} while (0) 335 336#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 337 outbuflen) do { \ 338 char *curptr, *curptr_start, *element_name, *element_temp; \ 339 size_t left, left_start, len; \ 340 int claimed, first, first_start, ignorenotfound; \ 341 \ 342 error = 0; \ 343 element_temp = elementlist; \ 344 curptr = outbuf; \ 345 curptr[0] = '\0'; \ 346 left = outbuflen; \ 347 first = 1; \ 348 while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 349 curptr_start = curptr; \ 350 left_start = left; \ 351 first_start = first; \ 352 if (element_name[0] == '?') { \ 353 element_name++; \ 354 ignorenotfound = 1; \ 355 } else \ 356 ignorenotfound = 0; \ 357 claimed = 0; \ 358 if (first) { \ 359 len = snprintf(curptr, left, "%s/", \ 360 element_name); \ 361 first = 0; \ 362 } else \ 363 len = snprintf(curptr, left, ",%s/", \ 364 element_name); \ 365 if (len >= left) { \ 366 error = EINVAL; /* XXXMAC: E2BIG */ \ 367 break; \ 368 } \ 369 curptr += len; \ 370 left -= len; \ 371 \ 372 MAC_CHECK(externalize_ ## type, label, element_name, \ 373 curptr, left, &len, &claimed); \ 374 if (error) \ 375 break; \ 376 if (claimed == 1) { \ 377 if (len >= outbuflen) { \ 378 error = EINVAL; /* XXXMAC: E2BIG */ \ 379 break; \ 380 } \ 381 curptr += len; \ 382 left -= len; \ 383 } else if (claimed == 0 && ignorenotfound) { \ 384 /* \ 385 * Revert addition of the label element \ 386 * name. \ 387 */ \ 388 curptr = curptr_start; \ 389 *curptr = '\0'; \ 390 left = left_start; \ 391 first = first_start; \ 392 } else { \ 393 error = EINVAL; /* XXXMAC: ENOLABEL */ \ 394 break; \ 395 } \ 396 } \ 397} while (0) 398 399#define MAC_INTERNALIZE(type, label, instring) do { \ 400 char *element, *element_name, *element_data; \ 401 int claimed; \ 402 \ 403 error = 0; \ 404 element = instring; \ 405 while ((element_name = strsep(&element, ",")) != NULL) { \ 406 element_data = element_name; \ 407 element_name = strsep(&element_data, "/"); \ 408 if (element_data == NULL) { \ 409 error = EINVAL; \ 410 break; \ 411 } \ 412 claimed = 0; \ 413 MAC_CHECK(internalize_ ## type, label, element_name, \ 414 element_data, &claimed); \ 415 if (error) \ 416 break; \ 417 if (claimed != 1) { \ 418 /* XXXMAC: Another error here? */ \ 419 error = EINVAL; \ 420 break; \ 421 } \ 422 } \ 423} while (0) 424 425/* 426 * MAC_PERFORM performs the designated operation by walking the policy 427 * module list and invoking that operation for each policy. 428 */ 429#define MAC_PERFORM(operation, args...) do { \ 430 struct mac_policy_conf *mpc; \ 431 \ 432 MAC_POLICY_LIST_BUSY(); \ 433 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 434 if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 435 mpc->mpc_ops->mpo_ ## operation (args); \ 436 } \ 437 MAC_POLICY_LIST_UNBUSY(); \ 438} while (0) 439 440/* 441 * Initialize the MAC subsystem, including appropriate SMP locks. 442 */ 443static void 444mac_init(void) 445{ 446 447 LIST_INIT(&mac_policy_list); 448 MAC_POLICY_LIST_LOCKINIT(); 449} 450 451/* 452 * For the purposes of modules that want to know if they were loaded 453 * "early", set the mac_late flag once we've processed modules either 454 * linked into the kernel, or loaded before the kernel startup. 455 */ 456static void 457mac_late_init(void) 458{ 459 460 mac_late = 1; 461} 462 463/* 464 * Allow MAC policy modules to register during boot, etc. 465 */ 466int 467mac_policy_modevent(module_t mod, int type, void *data) 468{ 469 struct mac_policy_conf *mpc; 470 int error; 471 472 error = 0; 473 mpc = (struct mac_policy_conf *) data; 474 475 switch (type) { 476 case MOD_LOAD: 477 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 478 mac_late) { 479 printf("mac_policy_modevent: can't load %s policy " 480 "after booting\n", mpc->mpc_name); 481 error = EBUSY; 482 break; 483 } 484 error = mac_policy_register(mpc); 485 break; 486 case MOD_UNLOAD: 487 /* Don't unregister the module if it was never registered. */ 488 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 489 != 0) 490 error = mac_policy_unregister(mpc); 491 else 492 error = 0; 493 break; 494 default: 495 break; 496 } 497 498 return (error); 499} 500 501static int 502mac_policy_register(struct mac_policy_conf *mpc) 503{ 504 struct mac_policy_conf *tmpc; 505 int slot; 506 507 MAC_POLICY_LIST_EXCLUSIVE(); 508 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 509 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 510 MAC_POLICY_LIST_UNLOCK(); 511 return (EEXIST); 512 } 513 } 514 if (mpc->mpc_field_off != NULL) { 515 slot = ffs(mac_policy_offsets_free); 516 if (slot == 0) { 517 MAC_POLICY_LIST_UNLOCK(); 518 return (ENOMEM); 519 } 520 slot--; 521 mac_policy_offsets_free &= ~(1 << slot); 522 *mpc->mpc_field_off = slot; 523 } 524 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 525 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 526 527 /* Per-policy initialization. */ 528 if (mpc->mpc_ops->mpo_init != NULL) 529 (*(mpc->mpc_ops->mpo_init))(mpc); 530 MAC_POLICY_LIST_UNLOCK(); 531 532 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 533 mpc->mpc_name); 534 535 return (0); 536} 537 538static int 539mac_policy_unregister(struct mac_policy_conf *mpc) 540{ 541 542 /* 543 * If we fail the load, we may get a request to unload. Check 544 * to see if we did the run-time registration, and if not, 545 * silently succeed. 546 */ 547 MAC_POLICY_LIST_EXCLUSIVE(); 548 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 549 MAC_POLICY_LIST_UNLOCK(); 550 return (0); 551 } 552#if 0 553 /* 554 * Don't allow unloading modules with private data. 555 */ 556 if (mpc->mpc_field_off != NULL) { 557 MAC_POLICY_LIST_UNLOCK(); 558 return (EBUSY); 559 } 560#endif 561 /* 562 * Only allow the unload to proceed if the module is unloadable 563 * by its own definition. 564 */ 565 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 566 MAC_POLICY_LIST_UNLOCK(); 567 return (EBUSY); 568 } 569 if (mpc->mpc_ops->mpo_destroy != NULL) 570 (*(mpc->mpc_ops->mpo_destroy))(mpc); 571 572 LIST_REMOVE(mpc, mpc_list); 573 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 574 575 MAC_POLICY_LIST_UNLOCK(); 576 577 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 578 mpc->mpc_name); 579 580 return (0); 581} 582 583/* 584 * Define an error value precedence, and given two arguments, selects the 585 * value with the higher precedence. 586 */ 587static int 588error_select(int error1, int error2) 589{ 590 591 /* Certain decision-making errors take top priority. */ 592 if (error1 == EDEADLK || error2 == EDEADLK) 593 return (EDEADLK); 594 595 /* Invalid arguments should be reported where possible. */ 596 if (error1 == EINVAL || error2 == EINVAL) 597 return (EINVAL); 598 599 /* Precedence goes to "visibility", with both process and file. */ 600 if (error1 == ESRCH || error2 == ESRCH) 601 return (ESRCH); 602 603 if (error1 == ENOENT || error2 == ENOENT) 604 return (ENOENT); 605 606 /* Precedence goes to DAC/MAC protections. */ 607 if (error1 == EACCES || error2 == EACCES) 608 return (EACCES); 609 610 /* Precedence goes to privilege. */ 611 if (error1 == EPERM || error2 == EPERM) 612 return (EPERM); 613 614 /* Precedence goes to error over success; otherwise, arbitrary. */ 615 if (error1 != 0) 616 return (error1); 617 return (error2); 618} 619 620static void 621mac_init_label(struct label *label) 622{ 623 624 bzero(label, sizeof(*label)); 625 label->l_flags = MAC_FLAG_INITIALIZED; 626} 627 628static void 629mac_destroy_label(struct label *label) 630{ 631 632 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 633 ("destroying uninitialized label")); 634 635 bzero(label, sizeof(*label)); 636 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 637} 638 639void 640mac_init_bpfdesc(struct bpf_d *bpf_d) 641{ 642 643 mac_init_label(&bpf_d->bd_label); 644 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 645#ifdef MAC_DEBUG 646 atomic_add_int(&nmacbpfdescs, 1); 647#endif 648} 649 650static void 651mac_init_cred_label(struct label *label) 652{ 653 654 mac_init_label(label); 655 MAC_PERFORM(init_cred_label, label); 656#ifdef MAC_DEBUG 657 atomic_add_int(&nmaccreds, 1); 658#endif 659} 660 661void 662mac_init_cred(struct ucred *cred) 663{ 664 665 mac_init_cred_label(&cred->cr_label); 666} 667 668void 669mac_init_devfsdirent(struct devfs_dirent *de) 670{ 671 672 mac_init_label(&de->de_label); 673 MAC_PERFORM(init_devfsdirent_label, &de->de_label); 674#ifdef MAC_DEBUG 675 atomic_add_int(&nmacdevfsdirents, 1); 676#endif 677} 678 679static void 680mac_init_ifnet_label(struct label *label) 681{ 682 683 mac_init_label(label); 684 MAC_PERFORM(init_ifnet_label, label); 685#ifdef MAC_DEBUG 686 atomic_add_int(&nmacifnets, 1); 687#endif 688} 689 690void 691mac_init_ifnet(struct ifnet *ifp) 692{ 693 694 mac_init_ifnet_label(&ifp->if_label); 695} 696 697void 698mac_init_ipq(struct ipq *ipq) 699{ 700 701 mac_init_label(&ipq->ipq_label); 702 MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 703#ifdef MAC_DEBUG 704 atomic_add_int(&nmacipqs, 1); 705#endif 706} 707 708int 709mac_init_mbuf(struct mbuf *m, int flag) 710{ 711 int error; 712 713 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 714 715 mac_init_label(&m->m_pkthdr.label); 716 717 MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 718 if (error) { 719 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 720 mac_destroy_label(&m->m_pkthdr.label); 721 } 722 723#ifdef MAC_DEBUG 724 if (error == 0) 725 atomic_add_int(&nmacmbufs, 1); 726#endif 727 return (error); 728} 729 730void 731mac_init_mount(struct mount *mp) 732{ 733 734 mac_init_label(&mp->mnt_mntlabel); 735 mac_init_label(&mp->mnt_fslabel); 736 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 737 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 738#ifdef MAC_DEBUG 739 atomic_add_int(&nmacmounts, 1); 740#endif 741} 742 743static void 744mac_init_pipe_label(struct label *label) 745{ 746 747 mac_init_label(label); 748 MAC_PERFORM(init_pipe_label, label); 749#ifdef MAC_DEBUG 750 atomic_add_int(&nmacpipes, 1); 751#endif 752} 753 754void 755mac_init_pipe(struct pipe *pipe) 756{ 757 struct label *label; 758 759 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 760 pipe->pipe_label = label; 761 pipe->pipe_peer->pipe_label = label; 762 mac_init_pipe_label(label); 763} 764 765static int 766mac_init_socket_label(struct label *label, int flag) 767{ 768 int error; 769 770 mac_init_label(label); 771 772 MAC_CHECK(init_socket_label, label, flag); 773 if (error) { 774 MAC_PERFORM(destroy_socket_label, label); 775 mac_destroy_label(label); 776 } 777 778#ifdef MAC_DEBUG 779 if (error == 0) 780 atomic_add_int(&nmacsockets, 1); 781#endif 782 783 return (error); 784} 785 786static int 787mac_init_socket_peer_label(struct label *label, int flag) 788{ 789 int error; 790 791 mac_init_label(label); 792 793 MAC_CHECK(init_socket_peer_label, label, flag); 794 if (error) { 795 MAC_PERFORM(destroy_socket_label, label); 796 mac_destroy_label(label); 797 } 798 799 return (error); 800} 801 802int 803mac_init_socket(struct socket *socket, int flag) 804{ 805 int error; 806 807 error = mac_init_socket_label(&socket->so_label, flag); 808 if (error) 809 return (error); 810 811 error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 812 if (error) 813 mac_destroy_socket_label(&socket->so_label); 814 815 return (error); 816} 817 818void 819mac_init_vnode_label(struct label *label) 820{ 821 822 mac_init_label(label); 823 MAC_PERFORM(init_vnode_label, label); 824#ifdef MAC_DEBUG 825 atomic_add_int(&nmacvnodes, 1); 826#endif 827} 828 829void 830mac_init_vnode(struct vnode *vp) 831{ 832 833 mac_init_vnode_label(&vp->v_label); 834} 835 836void 837mac_destroy_bpfdesc(struct bpf_d *bpf_d) 838{ 839 840 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 841 mac_destroy_label(&bpf_d->bd_label); 842#ifdef MAC_DEBUG 843 atomic_subtract_int(&nmacbpfdescs, 1); 844#endif 845} 846 847static void 848mac_destroy_cred_label(struct label *label) 849{ 850 851 MAC_PERFORM(destroy_cred_label, label); 852 mac_destroy_label(label); 853#ifdef MAC_DEBUG 854 atomic_subtract_int(&nmaccreds, 1); 855#endif 856} 857 858void 859mac_destroy_cred(struct ucred *cred) 860{ 861 862 mac_destroy_cred_label(&cred->cr_label); 863} 864 865void 866mac_destroy_devfsdirent(struct devfs_dirent *de) 867{ 868 869 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 870 mac_destroy_label(&de->de_label); 871#ifdef MAC_DEBUG 872 atomic_subtract_int(&nmacdevfsdirents, 1); 873#endif 874} 875 876static void 877mac_destroy_ifnet_label(struct label *label) 878{ 879 880 MAC_PERFORM(destroy_ifnet_label, label); 881 mac_destroy_label(label); 882#ifdef MAC_DEBUG 883 atomic_subtract_int(&nmacifnets, 1); 884#endif 885} 886 887void 888mac_destroy_ifnet(struct ifnet *ifp) 889{ 890 891 mac_destroy_ifnet_label(&ifp->if_label); 892} 893 894void 895mac_destroy_ipq(struct ipq *ipq) 896{ 897 898 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 899 mac_destroy_label(&ipq->ipq_label); 900#ifdef MAC_DEBUG 901 atomic_subtract_int(&nmacipqs, 1); 902#endif 903} 904 905void 906mac_destroy_mbuf(struct mbuf *m) 907{ 908 909 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 910 mac_destroy_label(&m->m_pkthdr.label); 911#ifdef MAC_DEBUG 912 atomic_subtract_int(&nmacmbufs, 1); 913#endif 914} 915 916void 917mac_destroy_mount(struct mount *mp) 918{ 919 920 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 921 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 922 mac_destroy_label(&mp->mnt_fslabel); 923 mac_destroy_label(&mp->mnt_mntlabel); 924#ifdef MAC_DEBUG 925 atomic_subtract_int(&nmacmounts, 1); 926#endif 927} 928 929static void 930mac_destroy_pipe_label(struct label *label) 931{ 932 933 MAC_PERFORM(destroy_pipe_label, label); 934 mac_destroy_label(label); 935#ifdef MAC_DEBUG 936 atomic_subtract_int(&nmacpipes, 1); 937#endif 938} 939 940void 941mac_destroy_pipe(struct pipe *pipe) 942{ 943 944 mac_destroy_pipe_label(pipe->pipe_label); 945 free(pipe->pipe_label, M_MACPIPELABEL); 946} 947 948static void 949mac_destroy_socket_label(struct label *label) 950{ 951 952 MAC_PERFORM(destroy_socket_label, label); 953 mac_destroy_label(label); 954#ifdef MAC_DEBUG 955 atomic_subtract_int(&nmacsockets, 1); 956#endif 957} 958 959static void 960mac_destroy_socket_peer_label(struct label *label) 961{ 962 963 MAC_PERFORM(destroy_socket_peer_label, label); 964 mac_destroy_label(label); 965} 966 967void 968mac_destroy_socket(struct socket *socket) 969{ 970 971 mac_destroy_socket_label(&socket->so_label); 972 mac_destroy_socket_peer_label(&socket->so_peerlabel); 973} 974 975void 976mac_destroy_vnode_label(struct label *label) 977{ 978 979 MAC_PERFORM(destroy_vnode_label, label); 980 mac_destroy_label(label); 981#ifdef MAC_DEBUG 982 atomic_subtract_int(&nmacvnodes, 1); 983#endif 984} 985 986void 987mac_destroy_vnode(struct vnode *vp) 988{ 989 990 mac_destroy_vnode_label(&vp->v_label); 991} 992 993static void 994mac_copy_pipe_label(struct label *src, struct label *dest) 995{ 996 997 MAC_PERFORM(copy_pipe_label, src, dest); 998} 999 1000void 1001mac_copy_vnode_label(struct label *src, struct label *dest) 1002{ 1003 1004 MAC_PERFORM(copy_vnode_label, src, dest); 1005} 1006 1007static int 1008mac_check_structmac_consistent(struct mac *mac) 1009{ 1010 1011 if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1012 return (EINVAL); 1013 1014 return (0); 1015} 1016 1017static int 1018mac_externalize_cred_label(struct label *label, char *elements, 1019 char *outbuf, size_t outbuflen, int flags) 1020{ 1021 int error; 1022 1023 MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 1024 1025 return (error); 1026} 1027 1028static int 1029mac_externalize_ifnet_label(struct label *label, char *elements, 1030 char *outbuf, size_t outbuflen, int flags) 1031{ 1032 int error; 1033 1034 MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1035 1036 return (error); 1037} 1038 1039static int 1040mac_externalize_pipe_label(struct label *label, char *elements, 1041 char *outbuf, size_t outbuflen, int flags) 1042{ 1043 int error; 1044 1045 MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1046 1047 return (error); 1048} 1049 1050static int 1051mac_externalize_socket_label(struct label *label, char *elements, 1052 char *outbuf, size_t outbuflen, int flags) 1053{ 1054 int error; 1055 1056 MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1057 1058 return (error); 1059} 1060 1061static int 1062mac_externalize_socket_peer_label(struct label *label, char *elements, 1063 char *outbuf, size_t outbuflen, int flags) 1064{ 1065 int error; 1066 1067 MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1068 1069 return (error); 1070} 1071 1072static int 1073mac_externalize_vnode_label(struct label *label, char *elements, 1074 char *outbuf, size_t outbuflen, int flags) 1075{ 1076 int error; 1077 1078 MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1079 1080 return (error); 1081} 1082 1083static int 1084mac_internalize_cred_label(struct label *label, char *string) 1085{ 1086 int error; 1087 1088 MAC_INTERNALIZE(cred_label, label, string); 1089 1090 return (error); 1091} 1092 1093static int 1094mac_internalize_ifnet_label(struct label *label, char *string) 1095{ 1096 int error; 1097 1098 MAC_INTERNALIZE(ifnet_label, label, string); 1099 1100 return (error); 1101} 1102 1103static int 1104mac_internalize_pipe_label(struct label *label, char *string) 1105{ 1106 int error; 1107 1108 MAC_INTERNALIZE(pipe_label, label, string); 1109 1110 return (error); 1111} 1112 1113static int 1114mac_internalize_socket_label(struct label *label, char *string) 1115{ 1116 int error; 1117 1118 MAC_INTERNALIZE(socket_label, label, string); 1119 1120 return (error); 1121} 1122 1123static int 1124mac_internalize_vnode_label(struct label *label, char *string) 1125{ 1126 int error; 1127 1128 MAC_INTERNALIZE(vnode_label, label, string); 1129 1130 return (error); 1131} 1132 1133/* 1134 * Initialize MAC label for the first kernel process, from which other 1135 * kernel processes and threads are spawned. 1136 */ 1137void 1138mac_create_proc0(struct ucred *cred) 1139{ 1140 1141 MAC_PERFORM(create_proc0, cred); 1142} 1143 1144/* 1145 * Initialize MAC label for the first userland process, from which other 1146 * userland processes and threads are spawned. 1147 */ 1148void 1149mac_create_proc1(struct ucred *cred) 1150{ 1151 1152 MAC_PERFORM(create_proc1, cred); 1153} 1154 1155void 1156mac_thread_userret(struct thread *td) 1157{ 1158 1159 MAC_PERFORM(thread_userret, td); 1160} 1161 1162/* 1163 * When a new process is created, its label must be initialized. Generally, 1164 * this involves inheritence from the parent process, modulo possible 1165 * deltas. This function allows that processing to take place. 1166 */ 1167void 1168mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 1169{ 1170 1171 MAC_PERFORM(create_cred, parent_cred, child_cred); 1172} 1173 1174void 1175mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 1176{ 1177 1178 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 1179} 1180 1181void 1182mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1183 struct vnode *vp) 1184{ 1185 1186 MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1187 &de->de_label, vp, &vp->v_label); 1188} 1189 1190int 1191mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 1192{ 1193 int error; 1194 1195 ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1196 1197 MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1198 &vp->v_label); 1199 1200 return (error); 1201} 1202 1203void 1204mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 1205{ 1206 1207 MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1208 &vp->v_label); 1209} 1210 1211int 1212mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1213 struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 1214{ 1215 int error; 1216 1217 ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1218 ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 1219 1220 error = VOP_OPENEXTATTR(vp, cred, curthread); 1221 if (error == EOPNOTSUPP) { 1222 /* XXX: Optionally abort if transactions not supported. */ 1223 if (ea_warn_once == 0) { 1224 printf("Warning: transactions not supported " 1225 "in EA write.\n"); 1226 ea_warn_once = 1; 1227 } 1228 } else if (error) 1229 return (error); 1230 1231 MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1232 dvp, &dvp->v_label, vp, &vp->v_label, cnp); 1233 1234 if (error) { 1235 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 1236 return (error); 1237 } 1238 1239 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1240 1241 if (error == EOPNOTSUPP) 1242 error = 0; /* XXX */ 1243 1244 return (error); 1245} 1246 1247static int 1248mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1249 struct label *intlabel) 1250{ 1251 int error; 1252 1253 ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 1254 1255 error = VOP_OPENEXTATTR(vp, cred, curthread); 1256 if (error == EOPNOTSUPP) { 1257 /* XXX: Optionally abort if transactions not supported. */ 1258 if (ea_warn_once == 0) { 1259 printf("Warning: transactions not supported " 1260 "in EA write.\n"); 1261 ea_warn_once = 1; 1262 } 1263 } else if (error) 1264 return (error); 1265 1266 MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 1267 1268 if (error) { 1269 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 1270 return (error); 1271 } 1272 1273 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1274 1275 if (error == EOPNOTSUPP) 1276 error = 0; /* XXX */ 1277 1278 return (error); 1279} 1280 1281int 1282mac_execve_enter(struct image_params *imgp, struct mac *mac_p, 1283 struct label *execlabelstorage) 1284{ 1285 struct mac mac; 1286 char *buffer; 1287 int error; 1288 1289 if (mac_p == NULL) 1290 return (0); 1291 1292 error = copyin(mac_p, &mac, sizeof(mac)); 1293 if (error) 1294 return (error); 1295 1296 error = mac_check_structmac_consistent(&mac); 1297 if (error) 1298 return (error); 1299 1300 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1301 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1302 if (error) { 1303 free(buffer, M_MACTEMP); 1304 return (error); 1305 } 1306 1307 mac_init_cred_label(execlabelstorage); 1308 error = mac_internalize_cred_label(execlabelstorage, buffer); 1309 free(buffer, M_MACTEMP); 1310 if (error) { 1311 mac_destroy_cred_label(execlabelstorage); 1312 return (error); 1313 } 1314 imgp->execlabel = execlabelstorage; 1315 return (0); 1316} 1317 1318void 1319mac_execve_exit(struct image_params *imgp) 1320{ 1321 if (imgp->execlabel != NULL) 1322 mac_destroy_cred_label(imgp->execlabel); 1323} 1324 1325void 1326mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 1327 struct label *interpvnodelabel, struct image_params *imgp) 1328{ 1329 1330 ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 1331 1332 if (!mac_enforce_process && !mac_enforce_fs) 1333 return; 1334 1335 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 1336 interpvnodelabel, imgp, imgp->execlabel); 1337} 1338 1339int 1340mac_execve_will_transition(struct ucred *old, struct vnode *vp, 1341 struct label *interpvnodelabel, struct image_params *imgp) 1342{ 1343 int result; 1344 1345 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 1346 1347 if (!mac_enforce_process && !mac_enforce_fs) 1348 return (0); 1349 1350 result = 0; 1351 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 1352 interpvnodelabel, imgp, imgp->execlabel); 1353 1354 return (result); 1355} 1356 1357int 1358mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 1359{ 1360 int error; 1361 1362 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1363 1364 if (!mac_enforce_fs) 1365 return (0); 1366 1367 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 1368 return (error); 1369} 1370 1371int 1372mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1373{ 1374 int error; 1375 1376 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1377 1378 if (!mac_enforce_fs) 1379 return (0); 1380 1381 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1382 return (error); 1383} 1384 1385int 1386mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1387{ 1388 int error; 1389 1390 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1391 1392 if (!mac_enforce_fs) 1393 return (0); 1394 1395 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1396 return (error); 1397} 1398 1399int 1400mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1401 struct componentname *cnp, struct vattr *vap) 1402{ 1403 int error; 1404 1405 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1406 1407 if (!mac_enforce_fs) 1408 return (0); 1409 1410 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1411 return (error); 1412} 1413 1414int 1415mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1416 struct componentname *cnp) 1417{ 1418 int error; 1419 1420 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1421 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1422 1423 if (!mac_enforce_fs) 1424 return (0); 1425 1426 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1427 &vp->v_label, cnp); 1428 return (error); 1429} 1430 1431int 1432mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1433 acl_type_t type) 1434{ 1435 int error; 1436 1437 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1438 1439 if (!mac_enforce_fs) 1440 return (0); 1441 1442 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1443 return (error); 1444} 1445 1446int 1447mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1448 struct image_params *imgp) 1449{ 1450 int error; 1451 1452 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1453 1454 if (!mac_enforce_process && !mac_enforce_fs) 1455 return (0); 1456 1457 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 1458 imgp->execlabel); 1459 1460 return (error); 1461} 1462 1463int 1464mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1465{ 1466 int error; 1467 1468 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1469 1470 if (!mac_enforce_fs) 1471 return (0); 1472 1473 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1474 return (error); 1475} 1476 1477int 1478mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1479 int attrnamespace, const char *name, struct uio *uio) 1480{ 1481 int error; 1482 1483 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1484 1485 if (!mac_enforce_fs) 1486 return (0); 1487 1488 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1489 attrnamespace, name, uio); 1490 return (error); 1491} 1492 1493int 1494mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 1495 struct vnode *vp, struct componentname *cnp) 1496{ 1497 int error; 1498 1499 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 1500 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 1501 1502 if (!mac_enforce_fs) 1503 return (0); 1504 1505 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 1506 &vp->v_label, cnp); 1507 return (error); 1508} 1509 1510int 1511mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1512 struct componentname *cnp) 1513{ 1514 int error; 1515 1516 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1517 1518 if (!mac_enforce_fs) 1519 return (0); 1520 1521 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1522 return (error); 1523} 1524 1525int 1526mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 1527{ 1528 int error; 1529 1530 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1531 1532 if (!mac_enforce_fs || !mac_enforce_vm) 1533 return (0); 1534 1535 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1536 return (error); 1537} 1538 1539void 1540mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1541{ 1542 int result = *prot; 1543 1544 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1545 1546 if (!mac_enforce_fs || !mac_enforce_vm) 1547 return; 1548 1549 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1550 &result); 1551 1552 *prot = result; 1553} 1554 1555int 1556mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1557{ 1558 int error; 1559 1560 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1561 1562 if (!mac_enforce_fs || !mac_enforce_vm) 1563 return (0); 1564 1565 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1566 return (error); 1567} 1568 1569int 1570mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 1571{ 1572 int error; 1573 1574 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 1575 1576 if (!mac_enforce_fs) 1577 return (0); 1578 1579 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 1580 return (error); 1581} 1582 1583int 1584mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1585 struct vnode *vp) 1586{ 1587 int error; 1588 1589 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 1590 1591 if (!mac_enforce_fs) 1592 return (0); 1593 1594 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1595 &vp->v_label); 1596 1597 return (error); 1598} 1599 1600int 1601mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1602 struct vnode *vp) 1603{ 1604 int error; 1605 1606 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 1607 1608 if (!mac_enforce_fs) 1609 return (0); 1610 1611 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1612 &vp->v_label); 1613 1614 return (error); 1615} 1616 1617int 1618mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 1619{ 1620 int error; 1621 1622 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 1623 1624 if (!mac_enforce_fs) 1625 return (0); 1626 1627 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 1628 return (error); 1629} 1630 1631int 1632mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 1633{ 1634 int error; 1635 1636 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 1637 1638 if (!mac_enforce_fs) 1639 return (0); 1640 1641 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 1642 return (error); 1643} 1644 1645static int 1646mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 1647 struct label *newlabel) 1648{ 1649 int error; 1650 1651 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 1652 1653 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 1654 1655 return (error); 1656} 1657 1658int 1659mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 1660 struct vnode *vp, struct componentname *cnp) 1661{ 1662 int error; 1663 1664 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 1665 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 1666 1667 if (!mac_enforce_fs) 1668 return (0); 1669 1670 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 1671 &vp->v_label, cnp); 1672 return (error); 1673} 1674 1675int 1676mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 1677 struct vnode *vp, int samedir, struct componentname *cnp) 1678{ 1679 int error; 1680 1681 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 1682 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 1683 1684 if (!mac_enforce_fs) 1685 return (0); 1686 1687 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 1688 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 1689 return (error); 1690} 1691 1692int 1693mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 1694{ 1695 int error; 1696 1697 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 1698 1699 if (!mac_enforce_fs) 1700 return (0); 1701 1702 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 1703 return (error); 1704} 1705 1706int 1707mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 1708 struct acl *acl) 1709{ 1710 int error; 1711 1712 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 1713 1714 if (!mac_enforce_fs) 1715 return (0); 1716 1717 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 1718 return (error); 1719} 1720 1721int 1722mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 1723 int attrnamespace, const char *name, struct uio *uio) 1724{ 1725 int error; 1726 1727 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 1728 1729 if (!mac_enforce_fs) 1730 return (0); 1731 1732 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 1733 attrnamespace, name, uio); 1734 return (error); 1735} 1736 1737int 1738mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 1739{ 1740 int error; 1741 1742 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 1743 1744 if (!mac_enforce_fs) 1745 return (0); 1746 1747 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 1748 return (error); 1749} 1750 1751int 1752mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 1753{ 1754 int error; 1755 1756 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 1757 1758 if (!mac_enforce_fs) 1759 return (0); 1760 1761 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 1762 return (error); 1763} 1764 1765int 1766mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 1767 gid_t gid) 1768{ 1769 int error; 1770 1771 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 1772 1773 if (!mac_enforce_fs) 1774 return (0); 1775 1776 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 1777 return (error); 1778} 1779 1780int 1781mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 1782 struct timespec atime, struct timespec mtime) 1783{ 1784 int error; 1785 1786 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 1787 1788 if (!mac_enforce_fs) 1789 return (0); 1790 1791 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 1792 mtime); 1793 return (error); 1794} 1795 1796int 1797mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 1798 struct vnode *vp) 1799{ 1800 int error; 1801 1802 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 1803 1804 if (!mac_enforce_fs) 1805 return (0); 1806 1807 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 1808 &vp->v_label); 1809 return (error); 1810} 1811 1812int 1813mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 1814 struct vnode *vp) 1815{ 1816 int error; 1817 1818 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 1819 1820 if (!mac_enforce_fs) 1821 return (0); 1822 1823 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 1824 &vp->v_label); 1825 1826 return (error); 1827} 1828 1829/* 1830 * When relabeling a process, call out to the policies for the maximum 1831 * permission allowed for each object type we know about in its 1832 * memory space, and revoke access (in the least surprising ways we 1833 * know) when necessary. The process lock is not held here. 1834 */ 1835static void 1836mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 1837{ 1838 1839 /* XXX freeze all other threads */ 1840 mac_cred_mmapped_drop_perms_recurse(td, cred, 1841 &td->td_proc->p_vmspace->vm_map); 1842 /* XXX allow other threads to continue */ 1843} 1844 1845static __inline const char * 1846prot2str(vm_prot_t prot) 1847{ 1848 1849 switch (prot & VM_PROT_ALL) { 1850 case VM_PROT_READ: 1851 return ("r--"); 1852 case VM_PROT_READ | VM_PROT_WRITE: 1853 return ("rw-"); 1854 case VM_PROT_READ | VM_PROT_EXECUTE: 1855 return ("r-x"); 1856 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 1857 return ("rwx"); 1858 case VM_PROT_WRITE: 1859 return ("-w-"); 1860 case VM_PROT_EXECUTE: 1861 return ("--x"); 1862 case VM_PROT_WRITE | VM_PROT_EXECUTE: 1863 return ("-wx"); 1864 default: 1865 return ("---"); 1866 } 1867} 1868 1869static void 1870mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 1871 struct vm_map *map) 1872{ 1873 struct vm_map_entry *vme; 1874 int result; 1875 vm_prot_t revokeperms; 1876 vm_object_t object; 1877 vm_ooffset_t offset; 1878 struct vnode *vp; 1879 1880 if (!mac_mmap_revocation) 1881 return; 1882 1883 vm_map_lock_read(map); 1884 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 1885 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 1886 mac_cred_mmapped_drop_perms_recurse(td, cred, 1887 vme->object.sub_map); 1888 continue; 1889 } 1890 /* 1891 * Skip over entries that obviously are not shared. 1892 */ 1893 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 1894 !vme->max_protection) 1895 continue; 1896 /* 1897 * Drill down to the deepest backing object. 1898 */ 1899 offset = vme->offset; 1900 object = vme->object.vm_object; 1901 if (object == NULL) 1902 continue; 1903 while (object->backing_object != NULL) { 1904 object = object->backing_object; 1905 offset += object->backing_object_offset; 1906 } 1907 /* 1908 * At the moment, vm_maps and objects aren't considered 1909 * by the MAC system, so only things with backing by a 1910 * normal object (read: vnodes) are checked. 1911 */ 1912 if (object->type != OBJT_VNODE) 1913 continue; 1914 vp = (struct vnode *)object->handle; 1915 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1916 result = vme->max_protection; 1917 mac_check_vnode_mmap_downgrade(cred, vp, &result); 1918 VOP_UNLOCK(vp, 0, td); 1919 /* 1920 * Find out what maximum protection we may be allowing 1921 * now but a policy needs to get removed. 1922 */ 1923 revokeperms = vme->max_protection & ~result; 1924 if (!revokeperms) 1925 continue; 1926 printf("pid %ld: revoking %s perms from %#lx:%ld " 1927 "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 1928 prot2str(revokeperms), (u_long)vme->start, 1929 (long)(vme->end - vme->start), 1930 prot2str(vme->max_protection), prot2str(vme->protection)); 1931 vm_map_lock_upgrade(map); 1932 /* 1933 * This is the really simple case: if a map has more 1934 * max_protection than is allowed, but it's not being 1935 * actually used (that is, the current protection is 1936 * still allowed), we can just wipe it out and do 1937 * nothing more. 1938 */ 1939 if ((vme->protection & revokeperms) == 0) { 1940 vme->max_protection -= revokeperms; 1941 } else { 1942 if (revokeperms & VM_PROT_WRITE) { 1943 /* 1944 * In the more complicated case, flush out all 1945 * pending changes to the object then turn it 1946 * copy-on-write. 1947 */ 1948 vm_object_reference(object); 1949 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1950 vm_object_page_clean(object, 1951 OFF_TO_IDX(offset), 1952 OFF_TO_IDX(offset + vme->end - vme->start + 1953 PAGE_MASK), 1954 OBJPC_SYNC); 1955 VOP_UNLOCK(vp, 0, td); 1956 vm_object_deallocate(object); 1957 /* 1958 * Why bother if there's no read permissions 1959 * anymore? For the rest, we need to leave 1960 * the write permissions on for COW, or 1961 * remove them entirely if configured to. 1962 */ 1963 if (!mac_mmap_revocation_via_cow) { 1964 vme->max_protection &= ~VM_PROT_WRITE; 1965 vme->protection &= ~VM_PROT_WRITE; 1966 } if ((revokeperms & VM_PROT_READ) == 0) 1967 vme->eflags |= MAP_ENTRY_COW | 1968 MAP_ENTRY_NEEDS_COPY; 1969 } 1970 if (revokeperms & VM_PROT_EXECUTE) { 1971 vme->max_protection &= ~VM_PROT_EXECUTE; 1972 vme->protection &= ~VM_PROT_EXECUTE; 1973 } 1974 if (revokeperms & VM_PROT_READ) { 1975 vme->max_protection = 0; 1976 vme->protection = 0; 1977 } 1978 pmap_protect(map->pmap, vme->start, vme->end, 1979 vme->protection & ~revokeperms); 1980 vm_map_simplify_entry(map, vme); 1981 } 1982 vm_map_lock_downgrade(map); 1983 } 1984 vm_map_unlock_read(map); 1985} 1986 1987/* 1988 * When the subject's label changes, it may require revocation of privilege 1989 * to mapped objects. This can't be done on-the-fly later with a unified 1990 * buffer cache. 1991 */ 1992static void 1993mac_relabel_cred(struct ucred *cred, struct label *newlabel) 1994{ 1995 1996 MAC_PERFORM(relabel_cred, cred, newlabel); 1997} 1998 1999void 2000mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 2001{ 2002 2003 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 2004} 2005 2006void 2007mac_create_ifnet(struct ifnet *ifnet) 2008{ 2009 2010 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 2011} 2012 2013void 2014mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 2015{ 2016 2017 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 2018} 2019 2020void 2021mac_create_socket(struct ucred *cred, struct socket *socket) 2022{ 2023 2024 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 2025} 2026 2027void 2028mac_create_pipe(struct ucred *cred, struct pipe *pipe) 2029{ 2030 2031 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 2032} 2033 2034void 2035mac_create_socket_from_socket(struct socket *oldsocket, 2036 struct socket *newsocket) 2037{ 2038 2039 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 2040 newsocket, &newsocket->so_label); 2041} 2042 2043static void 2044mac_relabel_socket(struct ucred *cred, struct socket *socket, 2045 struct label *newlabel) 2046{ 2047 2048 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 2049} 2050 2051static void 2052mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 2053{ 2054 2055 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 2056} 2057 2058void 2059mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 2060{ 2061 2062 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 2063 socket, &socket->so_peerlabel); 2064} 2065 2066void 2067mac_set_socket_peer_from_socket(struct socket *oldsocket, 2068 struct socket *newsocket) 2069{ 2070 2071 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 2072 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 2073} 2074 2075void 2076mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2077{ 2078 2079 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2080 datagram, &datagram->m_pkthdr.label); 2081} 2082 2083void 2084mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2085{ 2086 2087 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 2088 fragment, &fragment->m_pkthdr.label); 2089} 2090 2091void 2092mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2093{ 2094 2095 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2096 &ipq->ipq_label); 2097} 2098 2099void 2100mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2101{ 2102 2103 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 2104 newmbuf, &newmbuf->m_pkthdr.label); 2105} 2106 2107void 2108mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2109{ 2110 2111 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2112 &mbuf->m_pkthdr.label); 2113} 2114 2115void 2116mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2117{ 2118 2119 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2120 &mbuf->m_pkthdr.label); 2121} 2122 2123void 2124mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2125{ 2126 2127 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2128 &mbuf->m_pkthdr.label); 2129} 2130 2131void 2132mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2133 struct mbuf *newmbuf) 2134{ 2135 2136 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 2137 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 2138 &newmbuf->m_pkthdr.label); 2139} 2140 2141void 2142mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2143{ 2144 2145 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 2146 newmbuf, &newmbuf->m_pkthdr.label); 2147} 2148 2149int 2150mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2151{ 2152 int result; 2153 2154 result = 1; 2155 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 2156 ipq, &ipq->ipq_label); 2157 2158 return (result); 2159} 2160 2161void 2162mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2163{ 2164 2165 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2166 &ipq->ipq_label); 2167} 2168 2169void 2170mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2171{ 2172 2173 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2174 &mbuf->m_pkthdr.label); 2175} 2176 2177void 2178mac_create_mount(struct ucred *cred, struct mount *mp) 2179{ 2180 2181 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2182 &mp->mnt_fslabel); 2183} 2184 2185void 2186mac_create_root_mount(struct ucred *cred, struct mount *mp) 2187{ 2188 2189 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2190 &mp->mnt_fslabel); 2191} 2192 2193int 2194mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2195{ 2196 int error; 2197 2198 if (!mac_enforce_network) 2199 return (0); 2200 2201 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2202 &ifnet->if_label); 2203 2204 return (error); 2205} 2206 2207static int 2208mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2209{ 2210 int error; 2211 2212 MAC_CHECK(check_cred_relabel, cred, newlabel); 2213 2214 return (error); 2215} 2216 2217int 2218mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2219{ 2220 int error; 2221 2222 if (!mac_enforce_process) 2223 return (0); 2224 2225 MAC_CHECK(check_cred_visible, u1, u2); 2226 2227 return (error); 2228} 2229 2230int 2231mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2232{ 2233 int error; 2234 2235 if (!mac_enforce_network) 2236 return (0); 2237 2238 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 2239 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 2240 if_printf(ifnet, "not initialized\n"); 2241 2242 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2243 &mbuf->m_pkthdr.label); 2244 2245 return (error); 2246} 2247 2248int 2249mac_check_kenv_dump(struct ucred *cred) 2250{ 2251 int error; 2252 2253 if (!mac_enforce_system) 2254 return (0); 2255 2256 MAC_CHECK(check_kenv_dump, cred); 2257 2258 return (error); 2259} 2260 2261int 2262mac_check_kenv_get(struct ucred *cred, char *name) 2263{ 2264 int error; 2265 2266 if (!mac_enforce_system) 2267 return (0); 2268 2269 MAC_CHECK(check_kenv_get, cred, name); 2270 2271 return (error); 2272} 2273 2274int 2275mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2276{ 2277 int error; 2278 2279 if (!mac_enforce_system) 2280 return (0); 2281 2282 MAC_CHECK(check_kenv_set, cred, name, value); 2283 2284 return (error); 2285} 2286 2287int 2288mac_check_kenv_unset(struct ucred *cred, char *name) 2289{ 2290 int error; 2291 2292 if (!mac_enforce_system) 2293 return (0); 2294 2295 MAC_CHECK(check_kenv_unset, cred, name); 2296 2297 return (error); 2298} 2299 2300int
|
2342mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2343{ 2344 int error; 2345 2346 if (!mac_enforce_fs) 2347 return (0); 2348 2349 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2350 2351 return (error); 2352} 2353 2354int 2355mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2356 void *data) 2357{ 2358 int error; 2359 2360 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2361 2362 if (!mac_enforce_pipe) 2363 return (0); 2364 2365 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2366 2367 return (error); 2368} 2369 2370int 2371mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 2372{ 2373 int error; 2374 2375 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2376 2377 if (!mac_enforce_pipe) 2378 return (0); 2379 2380 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2381 2382 return (error); 2383} 2384 2385int 2386mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2387{ 2388 int error; 2389 2390 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2391 2392 if (!mac_enforce_pipe) 2393 return (0); 2394 2395 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 2396 2397 return (error); 2398} 2399 2400static int 2401mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2402 struct label *newlabel) 2403{ 2404 int error; 2405 2406 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2407 2408 if (!mac_enforce_pipe) 2409 return (0); 2410 2411 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2412 2413 return (error); 2414} 2415 2416int 2417mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2418{ 2419 int error; 2420 2421 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2422 2423 if (!mac_enforce_pipe) 2424 return (0); 2425 2426 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2427 2428 return (error); 2429} 2430 2431int 2432mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2433{ 2434 int error; 2435 2436 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2437 2438 if (!mac_enforce_pipe) 2439 return (0); 2440 2441 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2442 2443 return (error); 2444} 2445 2446int 2447mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2448{ 2449 int error; 2450 2451 PROC_LOCK_ASSERT(proc, MA_OWNED); 2452 2453 if (!mac_enforce_process) 2454 return (0); 2455 2456 MAC_CHECK(check_proc_debug, cred, proc); 2457 2458 return (error); 2459} 2460 2461int 2462mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2463{ 2464 int error; 2465 2466 PROC_LOCK_ASSERT(proc, MA_OWNED); 2467 2468 if (!mac_enforce_process) 2469 return (0); 2470 2471 MAC_CHECK(check_proc_sched, cred, proc); 2472 2473 return (error); 2474} 2475 2476int 2477mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2478{ 2479 int error; 2480 2481 PROC_LOCK_ASSERT(proc, MA_OWNED); 2482 2483 if (!mac_enforce_process) 2484 return (0); 2485 2486 MAC_CHECK(check_proc_signal, cred, proc, signum); 2487 2488 return (error); 2489} 2490 2491int 2492mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2493 struct sockaddr *sockaddr) 2494{ 2495 int error; 2496 2497 if (!mac_enforce_socket) 2498 return (0); 2499 2500 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2501 sockaddr); 2502 2503 return (error); 2504} 2505 2506int 2507mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2508 struct sockaddr *sockaddr) 2509{ 2510 int error; 2511 2512 if (!mac_enforce_socket) 2513 return (0); 2514 2515 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2516 sockaddr); 2517 2518 return (error); 2519} 2520 2521int 2522mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2523{ 2524 int error; 2525 2526 if (!mac_enforce_socket) 2527 return (0); 2528 2529 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2530 &mbuf->m_pkthdr.label); 2531 2532 return (error); 2533} 2534 2535int 2536mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2537{ 2538 int error; 2539 2540 if (!mac_enforce_socket) 2541 return (0); 2542 2543 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2544 return (error); 2545} 2546 2547int 2548mac_check_socket_receive(struct ucred *cred, struct socket *so) 2549{ 2550 int error; 2551 2552 if (!mac_enforce_socket) 2553 return (0); 2554 2555 MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2556 2557 return (error); 2558} 2559 2560static int 2561mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2562 struct label *newlabel) 2563{ 2564 int error; 2565 2566 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2567 newlabel); 2568 2569 return (error); 2570} 2571 2572int 2573mac_check_socket_send(struct ucred *cred, struct socket *so) 2574{ 2575 int error; 2576 2577 if (!mac_enforce_socket) 2578 return (0); 2579 2580 MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2581 2582 return (error); 2583} 2584 2585int 2586mac_check_socket_visible(struct ucred *cred, struct socket *socket) 2587{ 2588 int error; 2589 2590 if (!mac_enforce_socket) 2591 return (0); 2592 2593 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 2594 2595 return (error); 2596} 2597 2598int 2599mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2600{ 2601 int error; 2602 2603 if (vp != NULL) { 2604 ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2605 } 2606 2607 if (!mac_enforce_system) 2608 return (0); 2609 2610 MAC_CHECK(check_system_acct, cred, vp, 2611 vp != NULL ? &vp->v_label : NULL); 2612 2613 return (error); 2614} 2615 2616int 2617mac_check_system_nfsd(struct ucred *cred) 2618{ 2619 int error; 2620 2621 if (!mac_enforce_system) 2622 return (0); 2623 2624 MAC_CHECK(check_system_nfsd, cred); 2625 2626 return (error); 2627} 2628 2629int 2630mac_check_system_reboot(struct ucred *cred, int howto) 2631{ 2632 int error; 2633 2634 if (!mac_enforce_system) 2635 return (0); 2636 2637 MAC_CHECK(check_system_reboot, cred, howto); 2638 2639 return (error); 2640} 2641 2642int 2643mac_check_system_settime(struct ucred *cred) 2644{ 2645 int error; 2646 2647 if (!mac_enforce_system) 2648 return (0); 2649 2650 MAC_CHECK(check_system_settime, cred); 2651 2652 return (error); 2653} 2654 2655int 2656mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 2657{ 2658 int error; 2659 2660 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 2661 2662 if (!mac_enforce_system) 2663 return (0); 2664 2665 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 2666 return (error); 2667} 2668 2669int 2670mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2671 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2672{ 2673 int error; 2674 2675 /* 2676 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2677 * but since it's not exported from kern_sysctl.c, we can't. 2678 */ 2679 if (!mac_enforce_system) 2680 return (0); 2681 2682 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2683 inkernel, new, newlen); 2684 2685 return (error); 2686} 2687 2688int 2689mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 2690 struct ifnet *ifnet) 2691{ 2692 char *elements, *buffer; 2693 struct mac mac; 2694 int error; 2695 2696 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 2697 if (error) 2698 return (error); 2699 2700 error = mac_check_structmac_consistent(&mac); 2701 if (error) 2702 return (error); 2703 2704 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2705 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2706 if (error) { 2707 free(elements, M_MACTEMP); 2708 return (error); 2709 } 2710 2711 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2712 error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 2713 buffer, mac.m_buflen, M_WAITOK); 2714 if (error == 0) 2715 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2716 2717 free(buffer, M_MACTEMP); 2718 free(elements, M_MACTEMP); 2719 2720 return (error); 2721} 2722 2723int 2724mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 2725 struct ifnet *ifnet) 2726{ 2727 struct label intlabel; 2728 struct mac mac; 2729 char *buffer; 2730 int error; 2731 2732 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 2733 if (error) 2734 return (error); 2735 2736 error = mac_check_structmac_consistent(&mac); 2737 if (error) 2738 return (error); 2739 2740 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2741 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 2742 if (error) { 2743 free(buffer, M_MACTEMP); 2744 return (error); 2745 } 2746 2747 mac_init_ifnet_label(&intlabel); 2748 error = mac_internalize_ifnet_label(&intlabel, buffer); 2749 free(buffer, M_MACTEMP); 2750 if (error) { 2751 mac_destroy_ifnet_label(&intlabel); 2752 return (error); 2753 } 2754 2755 /* 2756 * XXX: Note that this is a redundant privilege check, since 2757 * policies impose this check themselves if required by the 2758 * policy. Eventually, this should go away. 2759 */ 2760 error = suser_cred(cred, 0); 2761 if (error) { 2762 mac_destroy_ifnet_label(&intlabel); 2763 return (error); 2764 } 2765 2766 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 2767 &intlabel); 2768 if (error) { 2769 mac_destroy_ifnet_label(&intlabel); 2770 return (error); 2771 } 2772 2773 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 2774 2775 mac_destroy_ifnet_label(&intlabel); 2776 return (0); 2777} 2778 2779void 2780mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 2781{ 2782 2783 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 2784} 2785 2786void 2787mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 2788 struct devfs_dirent *de) 2789{ 2790 2791 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 2792 &de->de_label); 2793} 2794 2795void 2796mac_create_devfs_directory(char *dirname, int dirnamelen, 2797 struct devfs_dirent *de) 2798{ 2799 2800 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 2801 &de->de_label); 2802} 2803 2804int 2805mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2806 struct mac *mac) 2807{ 2808 struct label intlabel; 2809 char *buffer; 2810 int error; 2811 2812 error = mac_check_structmac_consistent(mac); 2813 if (error) 2814 return (error); 2815 2816 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2817 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 2818 if (error) { 2819 free(buffer, M_MACTEMP); 2820 return (error); 2821 } 2822 2823 mac_init_socket_label(&intlabel, M_WAITOK); 2824 error = mac_internalize_socket_label(&intlabel, buffer); 2825 free(buffer, M_MACTEMP); 2826 if (error) { 2827 mac_destroy_socket_label(&intlabel); 2828 return (error); 2829 } 2830 2831 mac_check_socket_relabel(cred, so, &intlabel); 2832 if (error) { 2833 mac_destroy_socket_label(&intlabel); 2834 return (error); 2835 } 2836 2837 mac_relabel_socket(cred, so, &intlabel); 2838 2839 mac_destroy_socket_label(&intlabel); 2840 return (0); 2841} 2842 2843int 2844mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 2845{ 2846 int error; 2847 2848 PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2849 2850 error = mac_check_pipe_relabel(cred, pipe, label); 2851 if (error) 2852 return (error); 2853 2854 mac_relabel_pipe(cred, pipe, label); 2855 2856 return (0); 2857} 2858 2859int 2860mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2861 struct mac *mac) 2862{ 2863 char *buffer, *elements; 2864 int error; 2865 2866 error = mac_check_structmac_consistent(mac); 2867 if (error) 2868 return (error); 2869 2870 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2871 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2872 if (error) { 2873 free(elements, M_MACTEMP); 2874 return (error); 2875 } 2876 2877 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2878 error = mac_externalize_socket_label(&so->so_label, elements, 2879 buffer, mac->m_buflen, M_WAITOK); 2880 if (error == 0) 2881 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2882 2883 free(buffer, M_MACTEMP); 2884 free(elements, M_MACTEMP); 2885 2886 return (error); 2887} 2888 2889int 2890mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2891 struct mac *mac) 2892{ 2893 char *elements, *buffer; 2894 int error; 2895 2896 error = mac_check_structmac_consistent(mac); 2897 if (error) 2898 return (error); 2899 2900 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2901 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2902 if (error) { 2903 free(elements, M_MACTEMP); 2904 return (error); 2905 } 2906 2907 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2908 error = mac_externalize_socket_peer_label(&so->so_peerlabel, 2909 elements, buffer, mac->m_buflen, M_WAITOK); 2910 if (error == 0) 2911 error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2912 2913 free(buffer, M_MACTEMP); 2914 free(elements, M_MACTEMP); 2915 2916 return (error); 2917} 2918 2919/* 2920 * Implementation of VOP_SETLABEL() that relies on extended attributes 2921 * to store label data. Can be referenced by filesystems supporting 2922 * extended attributes. 2923 */ 2924int 2925vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 2926{ 2927 struct vnode *vp = ap->a_vp; 2928 struct label *intlabel = ap->a_label; 2929 int error; 2930 2931 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 2932 2933 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2934 return (EOPNOTSUPP); 2935 2936 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 2937 if (error) 2938 return (error); 2939 2940 mac_relabel_vnode(ap->a_cred, vp, intlabel); 2941 2942 return (0); 2943} 2944 2945static int 2946vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 2947{ 2948 int error; 2949 2950 if (vp->v_mount == NULL) { 2951 /* printf("vn_setlabel: null v_mount\n"); */ 2952 if (vp->v_type != VNON) 2953 printf("vn_setlabel: null v_mount with non-VNON\n"); 2954 return (EBADF); 2955 } 2956 2957 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2958 return (EOPNOTSUPP); 2959 2960 /* 2961 * Multi-phase commit. First check the policies to confirm the 2962 * change is OK. Then commit via the filesystem. Finally, 2963 * update the actual vnode label. Question: maybe the filesystem 2964 * should update the vnode at the end as part of VOP_SETLABEL()? 2965 */ 2966 error = mac_check_vnode_relabel(cred, vp, intlabel); 2967 if (error) 2968 return (error); 2969 2970 /* 2971 * VADMIN provides the opportunity for the filesystem to make 2972 * decisions about who is and is not able to modify labels 2973 * and protections on files. This might not be right. We can't 2974 * assume VOP_SETLABEL() will do it, because we might implement 2975 * that as part of vop_stdsetlabel_ea(). 2976 */ 2977 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 2978 if (error) 2979 return (error); 2980 2981 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 2982 if (error) 2983 return (error); 2984 2985 return (0); 2986} 2987 2988int 2989__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 2990{ 2991 char *elements, *buffer; 2992 struct mac mac; 2993 struct proc *tproc; 2994 struct ucred *tcred; 2995 int error; 2996 2997 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 2998 if (error) 2999 return (error); 3000 3001 error = mac_check_structmac_consistent(&mac); 3002 if (error) 3003 return (error); 3004 3005 tproc = pfind(uap->pid); 3006 if (tproc == NULL) 3007 return (ESRCH); 3008 3009 tcred = NULL; /* Satisfy gcc. */ 3010 error = p_cansee(td, tproc); 3011 if (error == 0) 3012 tcred = crhold(tproc->p_ucred); 3013 PROC_UNLOCK(tproc); 3014 if (error) 3015 return (error); 3016 3017 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3018 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3019 if (error) { 3020 free(elements, M_MACTEMP); 3021 crfree(tcred); 3022 return (error); 3023 } 3024 3025 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3026 error = mac_externalize_cred_label(&tcred->cr_label, elements, 3027 buffer, mac.m_buflen, M_WAITOK); 3028 if (error == 0) 3029 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3030 3031 free(buffer, M_MACTEMP); 3032 free(elements, M_MACTEMP); 3033 crfree(tcred); 3034 return (error); 3035} 3036 3037/* 3038 * MPSAFE 3039 */ 3040int 3041__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3042{ 3043 char *elements, *buffer; 3044 struct mac mac; 3045 int error; 3046 3047 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3048 if (error) 3049 return (error); 3050 3051 error = mac_check_structmac_consistent(&mac); 3052 if (error) 3053 return (error); 3054 3055 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3056 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3057 if (error) { 3058 free(elements, M_MACTEMP); 3059 return (error); 3060 } 3061 3062 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3063 error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3064 elements, buffer, mac.m_buflen, M_WAITOK); 3065 if (error == 0) 3066 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3067 3068 free(buffer, M_MACTEMP); 3069 free(elements, M_MACTEMP); 3070 return (error); 3071} 3072 3073/* 3074 * MPSAFE 3075 */ 3076int 3077__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3078{ 3079 struct ucred *newcred, *oldcred; 3080 struct label intlabel; 3081 struct proc *p; 3082 struct mac mac; 3083 char *buffer; 3084 int error; 3085 3086 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3087 if (error) 3088 return (error); 3089 3090 error = mac_check_structmac_consistent(&mac); 3091 if (error) 3092 return (error); 3093 3094 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3095 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3096 if (error) { 3097 free(buffer, M_MACTEMP); 3098 return (error); 3099 } 3100 3101 mac_init_cred_label(&intlabel); 3102 error = mac_internalize_cred_label(&intlabel, buffer); 3103 free(buffer, M_MACTEMP); 3104 if (error) { 3105 mac_destroy_cred_label(&intlabel); 3106 return (error); 3107 } 3108 3109 newcred = crget(); 3110 3111 p = td->td_proc; 3112 PROC_LOCK(p); 3113 oldcred = p->p_ucred; 3114 3115 error = mac_check_cred_relabel(oldcred, &intlabel); 3116 if (error) { 3117 PROC_UNLOCK(p); 3118 crfree(newcred); 3119 goto out; 3120 } 3121 3122 setsugid(p); 3123 crcopy(newcred, oldcred); 3124 mac_relabel_cred(newcred, &intlabel); 3125 p->p_ucred = newcred; 3126 3127 /* 3128 * Grab additional reference for use while revoking mmaps, prior 3129 * to releasing the proc lock and sharing the cred. 3130 */ 3131 crhold(newcred); 3132 PROC_UNLOCK(p); 3133 3134 if (mac_enforce_vm) { 3135 mtx_lock(&Giant); 3136 mac_cred_mmapped_drop_perms(td, newcred); 3137 mtx_unlock(&Giant); 3138 } 3139 3140 crfree(newcred); /* Free revocation reference. */ 3141 crfree(oldcred); 3142 3143out: 3144 mac_destroy_cred_label(&intlabel); 3145 return (error); 3146} 3147 3148/* 3149 * MPSAFE 3150 */ 3151int 3152__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3153{ 3154 char *elements, *buffer; 3155 struct label intlabel; 3156 struct file *fp; 3157 struct mac mac; 3158 struct vnode *vp; 3159 struct pipe *pipe; 3160 short label_type; 3161 int error; 3162 3163 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3164 if (error) 3165 return (error); 3166 3167 error = mac_check_structmac_consistent(&mac); 3168 if (error) 3169 return (error); 3170 3171 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3172 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3173 if (error) { 3174 free(elements, M_MACTEMP); 3175 return (error); 3176 } 3177 3178 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3179 mtx_lock(&Giant); /* VFS */ 3180 error = fget(td, SCARG(uap, fd), &fp); 3181 if (error) 3182 goto out; 3183 3184 label_type = fp->f_type; 3185 switch (fp->f_type) { 3186 case DTYPE_FIFO: 3187 case DTYPE_VNODE: 3188 vp = (struct vnode *)fp->f_data; 3189 3190 mac_init_vnode_label(&intlabel); 3191 3192 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3193 mac_copy_vnode_label(&vp->v_label, &intlabel); 3194 VOP_UNLOCK(vp, 0, td); 3195 3196 break; 3197 case DTYPE_PIPE: 3198 pipe = (struct pipe *)fp->f_data; 3199 3200 mac_init_pipe_label(&intlabel); 3201 3202 PIPE_LOCK(pipe); 3203 mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3204 PIPE_UNLOCK(pipe); 3205 break; 3206 default: 3207 error = EINVAL; 3208 fdrop(fp, td); 3209 goto out; 3210 } 3211 fdrop(fp, td); 3212 3213 switch (label_type) { 3214 case DTYPE_FIFO: 3215 case DTYPE_VNODE: 3216 if (error == 0) 3217 error = mac_externalize_vnode_label(&intlabel, 3218 elements, buffer, mac.m_buflen, M_WAITOK); 3219 mac_destroy_vnode_label(&intlabel); 3220 break; 3221 case DTYPE_PIPE: 3222 error = mac_externalize_pipe_label(&intlabel, elements, 3223 buffer, mac.m_buflen, M_WAITOK); 3224 mac_destroy_pipe_label(&intlabel); 3225 break; 3226 default: 3227 panic("__mac_get_fd: corrupted label_type"); 3228 } 3229 3230 if (error == 0) 3231 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3232 3233out: 3234 mtx_unlock(&Giant); /* VFS */ 3235 free(buffer, M_MACTEMP); 3236 free(elements, M_MACTEMP); 3237 3238 return (error); 3239} 3240 3241/* 3242 * MPSAFE 3243 */ 3244int 3245__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3246{ 3247 char *elements, *buffer; 3248 struct nameidata nd; 3249 struct label intlabel; 3250 struct mac mac; 3251 int error; 3252 3253 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3254 if (error) 3255 return (error); 3256 3257 error = mac_check_structmac_consistent(&mac); 3258 if (error) 3259 return (error); 3260 3261 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3262 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3263 if (error) { 3264 free(elements, M_MACTEMP); 3265 return (error); 3266 } 3267 3268 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3269 mtx_lock(&Giant); /* VFS */ 3270 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3271 td); 3272 error = namei(&nd); 3273 if (error) 3274 goto out; 3275 3276 mac_init_vnode_label(&intlabel); 3277 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3278 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3279 mac.m_buflen, M_WAITOK); 3280 3281 NDFREE(&nd, 0); 3282 mac_destroy_vnode_label(&intlabel); 3283 3284 if (error == 0) 3285 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3286 3287out: 3288 mtx_unlock(&Giant); /* VFS */ 3289 3290 free(buffer, M_MACTEMP); 3291 free(elements, M_MACTEMP); 3292 3293 return (error); 3294} 3295 3296/* 3297 * MPSAFE 3298 */ 3299int 3300__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3301{ 3302 char *elements, *buffer; 3303 struct nameidata nd; 3304 struct label intlabel; 3305 struct mac mac; 3306 int error; 3307 3308 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3309 if (error) 3310 return (error); 3311 3312 error = mac_check_structmac_consistent(&mac); 3313 if (error) 3314 return (error); 3315 3316 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3317 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3318 if (error) { 3319 free(elements, M_MACTEMP); 3320 return (error); 3321 } 3322 3323 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3324 mtx_lock(&Giant); /* VFS */ 3325 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3326 td); 3327 error = namei(&nd); 3328 if (error) 3329 goto out; 3330 3331 mac_init_vnode_label(&intlabel); 3332 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3333 error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3334 mac.m_buflen, M_WAITOK); 3335 NDFREE(&nd, 0); 3336 mac_destroy_vnode_label(&intlabel); 3337 3338 if (error == 0) 3339 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3340 3341out: 3342 mtx_unlock(&Giant); /* VFS */ 3343 3344 free(buffer, M_MACTEMP); 3345 free(elements, M_MACTEMP); 3346 3347 return (error); 3348} 3349 3350/* 3351 * MPSAFE 3352 */ 3353int 3354__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3355{ 3356 struct label intlabel; 3357 struct pipe *pipe; 3358 struct file *fp; 3359 struct mount *mp; 3360 struct vnode *vp; 3361 struct mac mac; 3362 char *buffer; 3363 int error; 3364 3365 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3366 if (error) 3367 return (error); 3368 3369 error = mac_check_structmac_consistent(&mac); 3370 if (error) 3371 return (error); 3372 3373 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3374 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3375 if (error) { 3376 free(buffer, M_MACTEMP); 3377 return (error); 3378 } 3379 3380 mtx_lock(&Giant); /* VFS */ 3381 3382 error = fget(td, SCARG(uap, fd), &fp); 3383 if (error) 3384 goto out; 3385 3386 switch (fp->f_type) { 3387 case DTYPE_FIFO: 3388 case DTYPE_VNODE: 3389 mac_init_vnode_label(&intlabel); 3390 error = mac_internalize_vnode_label(&intlabel, buffer); 3391 if (error) { 3392 mac_destroy_vnode_label(&intlabel); 3393 break; 3394 } 3395 3396 vp = (struct vnode *)fp->f_data; 3397 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3398 if (error != 0) { 3399 mac_destroy_vnode_label(&intlabel); 3400 break; 3401 } 3402 3403 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3404 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3405 VOP_UNLOCK(vp, 0, td); 3406 vn_finished_write(mp); 3407 3408 mac_destroy_vnode_label(&intlabel); 3409 break; 3410 3411 case DTYPE_PIPE: 3412 mac_init_pipe_label(&intlabel); 3413 error = mac_internalize_pipe_label(&intlabel, buffer); 3414 if (error == 0) { 3415 pipe = (struct pipe *)fp->f_data; 3416 PIPE_LOCK(pipe); 3417 error = mac_pipe_label_set(td->td_ucred, pipe, 3418 &intlabel); 3419 PIPE_UNLOCK(pipe); 3420 } 3421 3422 mac_destroy_pipe_label(&intlabel); 3423 break; 3424 3425 default: 3426 error = EINVAL; 3427 } 3428 3429 fdrop(fp, td); 3430out: 3431 mtx_unlock(&Giant); /* VFS */ 3432 3433 free(buffer, M_MACTEMP); 3434 3435 return (error); 3436} 3437 3438/* 3439 * MPSAFE 3440 */ 3441int 3442__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3443{ 3444 struct label intlabel; 3445 struct nameidata nd; 3446 struct mount *mp; 3447 struct mac mac; 3448 char *buffer; 3449 int error; 3450 3451 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3452 if (error) 3453 return (error); 3454 3455 error = mac_check_structmac_consistent(&mac); 3456 if (error) 3457 return (error); 3458 3459 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3460 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3461 if (error) { 3462 free(buffer, M_MACTEMP); 3463 return (error); 3464 } 3465 3466 mac_init_vnode_label(&intlabel); 3467 error = mac_internalize_vnode_label(&intlabel, buffer); 3468 free(buffer, M_MACTEMP); 3469 if (error) { 3470 mac_destroy_vnode_label(&intlabel); 3471 return (error); 3472 } 3473 3474 mtx_lock(&Giant); /* VFS */ 3475 3476 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3477 td); 3478 error = namei(&nd); 3479 if (error == 0) { 3480 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3481 if (error == 0) 3482 error = vn_setlabel(nd.ni_vp, &intlabel, 3483 td->td_ucred); 3484 vn_finished_write(mp); 3485 } 3486 3487 NDFREE(&nd, 0); 3488 mtx_unlock(&Giant); /* VFS */ 3489 mac_destroy_vnode_label(&intlabel); 3490 3491 return (error); 3492} 3493 3494/* 3495 * MPSAFE 3496 */ 3497int 3498__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3499{ 3500 struct label intlabel; 3501 struct nameidata nd; 3502 struct mount *mp; 3503 struct mac mac; 3504 char *buffer; 3505 int error; 3506 3507 error = copyin(uap->mac_p, &mac, sizeof(mac)); 3508 if (error) 3509 return (error); 3510 3511 error = mac_check_structmac_consistent(&mac); 3512 if (error) 3513 return (error); 3514 3515 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3516 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3517 if (error) { 3518 free(buffer, M_MACTEMP); 3519 return (error); 3520 } 3521 3522 mac_init_vnode_label(&intlabel); 3523 error = mac_internalize_vnode_label(&intlabel, buffer); 3524 free(buffer, M_MACTEMP); 3525 if (error) { 3526 mac_destroy_vnode_label(&intlabel); 3527 return (error); 3528 } 3529 3530 mtx_lock(&Giant); /* VFS */ 3531 3532 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3533 td); 3534 error = namei(&nd); 3535 if (error == 0) { 3536 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3537 if (error == 0) 3538 error = vn_setlabel(nd.ni_vp, &intlabel, 3539 td->td_ucred); 3540 vn_finished_write(mp); 3541 } 3542 3543 NDFREE(&nd, 0); 3544 mtx_unlock(&Giant); /* VFS */ 3545 mac_destroy_vnode_label(&intlabel); 3546 3547 return (error); 3548} 3549 3550/* 3551 * MPSAFE 3552 */ 3553int 3554mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3555{ 3556 struct mac_policy_conf *mpc; 3557 char target[MAC_MAX_POLICY_NAME]; 3558 int error; 3559 3560 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 3561 if (error) 3562 return (error); 3563 3564 error = ENOSYS; 3565 MAC_POLICY_LIST_BUSY(); 3566 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 3567 if (strcmp(mpc->mpc_name, target) == 0 && 3568 mpc->mpc_ops->mpo_syscall != NULL) { 3569 error = mpc->mpc_ops->mpo_syscall(td, 3570 SCARG(uap, call), SCARG(uap, arg)); 3571 goto out; 3572 } 3573 } 3574 3575out: 3576 MAC_POLICY_LIST_UNBUSY(); 3577 return (error); 3578} 3579 3580SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3581SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3582 3583#else /* !MAC */ 3584 3585int 3586__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3587{ 3588 3589 return (ENOSYS); 3590} 3591 3592int 3593__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3594{ 3595 3596 return (ENOSYS); 3597} 3598 3599int 3600__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3601{ 3602 3603 return (ENOSYS); 3604} 3605 3606int 3607__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3608{ 3609 3610 return (ENOSYS); 3611} 3612 3613int 3614__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3615{ 3616 3617 return (ENOSYS); 3618} 3619 3620int 3621__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3622{ 3623 3624 return (ENOSYS); 3625} 3626 3627int 3628__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3629{ 3630 3631 return (ENOSYS); 3632} 3633 3634int 3635__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3636{ 3637 3638 return (ENOSYS); 3639} 3640 3641int 3642__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3643{ 3644 3645 return (ENOSYS); 3646} 3647 3648int 3649mac_syscall(struct thread *td, struct mac_syscall_args *uap) 3650{ 3651 3652 return (ENOSYS); 3653} 3654 3655#endif
|