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