1 /*- 2 * Copyright (c) 1999-2002 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5 * Copyright (c) 2005 SPARTA, Inc. 6 * All rights reserved. 7 * 8 * This software was developed by Robert Watson and Ilmar Habibulin for the 9 * TrustedBSD Project. 10 * 11 * This software was developed for the FreeBSD Project in part by Network 12 * Associates Laboratories, the Security Research Division of Network 13 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 14 * as part of the DARPA CHATS research program. 15 * 16 * This software was enhanced by SPARTA ISSO under SPAWAR contract 17 * N66001-04-C-6019 ("SEFOS"). 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 /*- 42 * Framework for extensible kernel access control. This file contains 43 * Kernel and userland interface to the framework, policy registration 44 * and composition. Per-object interfaces, controls, and labeling may be 45 * found in src/sys/security/mac/. Sample policies may be found in 46 * src/sys/security/mac_*. 47 */ 48 49 #include <sys/cdefs.h> 50 __FBSDID("$FreeBSD$"); 51 52 #include "opt_mac.h" 53 54 #include <sys/param.h> 55 #include <sys/condvar.h> 56 #include <sys/extattr.h> 57 #include <sys/imgact.h> 58 #include <sys/kernel.h> 59 #include <sys/lock.h> 60 #include <sys/malloc.h> 61 #include <sys/mutex.h> 62 #include <sys/mac.h> 63 #include <sys/module.h> 64 #include <sys/proc.h> 65 #include <sys/sbuf.h> 66 #include <sys/systm.h> 67 #include <sys/sysproto.h> 68 #include <sys/sysent.h> 69 #include <sys/vnode.h> 70 #include <sys/mount.h> 71 #include <sys/file.h> 72 #include <sys/namei.h> 73 #include <sys/socket.h> 74 #include <sys/pipe.h> 75 #include <sys/socketvar.h> 76 #include <sys/sysctl.h> 77 78 #include <vm/vm.h> 79 #include <vm/pmap.h> 80 #include <vm/vm_map.h> 81 #include <vm/vm_object.h> 82 83 #include <sys/mac_policy.h> 84 85 #include <fs/devfs/devfs.h> 86 87 #include <net/bpfdesc.h> 88 #include <net/if.h> 89 #include <net/if_var.h> 90 91 #include <netinet/in.h> 92 #include <netinet/ip_var.h> 93 94 #include <security/mac/mac_internal.h> 95 96 #ifdef MAC 97 98 /* 99 * Declare that the kernel provides MAC support, version 1. This permits 100 * modules to refuse to be loaded if the necessary support isn't present, 101 * even if it's pre-boot. 102 */ 103 MODULE_VERSION(kernel_mac_support, 3); 104 105 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 106 "TrustedBSD MAC policy controls"); 107 108 #if MAC_MAX_SLOTS > 32 109 #error "MAC_MAX_SLOTS too large" 110 #endif 111 112 static unsigned int mac_max_slots = MAC_MAX_SLOTS; 113 static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 114 SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 115 &mac_max_slots, 0, ""); 116 117 /* 118 * Has the kernel started generating labeled objects yet? All read/write 119 * access to this variable is serialized during the boot process. Following 120 * the end of serialization, we don't update this flag; no locking. 121 */ 122 int mac_late = 0; 123 124 /* 125 * Flag to indicate whether or not we should allocate label storage for 126 * new mbufs. Since most dynamic policies we currently work with don't 127 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 128 * unless specifically notified of interest. One result of this is 129 * that if a dynamically loaded policy requests mbuf labels, it must 130 * be able to deal with a NULL label being returned on any mbufs that 131 * were already in flight when the policy was loaded. Since the policy 132 * already has to deal with uninitialized labels, this probably won't 133 * be a problem. Note: currently no locking. Will this be a problem? 134 */ 135 #ifndef MAC_ALWAYS_LABEL_MBUF 136 int mac_labelmbufs = 0; 137 #endif 138 139 #ifdef MAC_DEBUG 140 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 141 "TrustedBSD MAC debug info"); 142 SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 143 "TrustedBSD MAC object counters"); 144 145 static unsigned int nmactemp; 146 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 147 &nmactemp, 0, "number of temporary labels in use"); 148 #endif 149 150 static int mac_policy_register(struct mac_policy_conf *mpc); 151 static int mac_policy_unregister(struct mac_policy_conf *mpc); 152 153 MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 154 155 /* 156 * mac_static_policy_list holds a list of policy modules that are not 157 * loaded while the system is "live", and cannot be unloaded. These 158 * policies can be invoked without holding the busy count. 159 * 160 * mac_policy_list stores the list of dynamic policies. A busy count is 161 * maintained for the list, stored in mac_policy_busy. The busy count 162 * is protected by mac_policy_mtx; the list may be modified only 163 * while the busy count is 0, requiring that the lock be held to 164 * prevent new references to the list from being acquired. For almost 165 * all operations, incrementing the busy count is sufficient to 166 * guarantee consistency, as the list cannot be modified while the 167 * busy count is elevated. For a few special operations involving a 168 * change to the list of active policies, the mtx itself must be held. 169 * A condition variable, mac_policy_cv, is used to signal potential 170 * exclusive consumers that they should try to acquire the lock if a 171 * first attempt at exclusive access fails. 172 */ 173 #ifndef MAC_STATIC 174 static struct mtx mac_policy_mtx; 175 static struct cv mac_policy_cv; 176 static int mac_policy_count; 177 #endif 178 struct mac_policy_list_head mac_policy_list; 179 struct mac_policy_list_head mac_static_policy_list; 180 181 /* 182 * We manually invoke WITNESS_WARN() to allow Witness to generate 183 * warnings even if we don't end up ever triggering the wait at 184 * run-time. The consumer of the exclusive interface must not hold 185 * any locks (other than potentially Giant) since we may sleep for 186 * long (potentially indefinite) periods of time waiting for the 187 * framework to become quiescent so that a policy list change may 188 * be made. 189 */ 190 void 191 mac_policy_grab_exclusive(void) 192 { 193 194 #ifndef MAC_STATIC 195 if (!mac_late) 196 return; 197 198 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 199 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 200 mtx_lock(&mac_policy_mtx); 201 while (mac_policy_count != 0) 202 cv_wait(&mac_policy_cv, &mac_policy_mtx); 203 #endif 204 } 205 206 void 207 mac_policy_assert_exclusive(void) 208 { 209 210 #ifndef MAC_STATIC 211 if (!mac_late) 212 return; 213 214 mtx_assert(&mac_policy_mtx, MA_OWNED); 215 KASSERT(mac_policy_count == 0, 216 ("mac_policy_assert_exclusive(): not exclusive")); 217 #endif 218 } 219 220 void 221 mac_policy_release_exclusive(void) 222 { 223 224 #ifndef MAC_STATIC 225 if (!mac_late) 226 return; 227 228 KASSERT(mac_policy_count == 0, 229 ("mac_policy_release_exclusive(): not exclusive")); 230 mtx_unlock(&mac_policy_mtx); 231 cv_signal(&mac_policy_cv); 232 #endif 233 } 234 235 void 236 mac_policy_list_busy(void) 237 { 238 239 #ifndef MAC_STATIC 240 if (!mac_late) 241 return; 242 243 mtx_lock(&mac_policy_mtx); 244 mac_policy_count++; 245 mtx_unlock(&mac_policy_mtx); 246 #endif 247 } 248 249 int 250 mac_policy_list_conditional_busy(void) 251 { 252 #ifndef MAC_STATIC 253 int ret; 254 255 if (!mac_late) 256 return (1); 257 258 mtx_lock(&mac_policy_mtx); 259 if (!LIST_EMPTY(&mac_policy_list)) { 260 mac_policy_count++; 261 ret = 1; 262 } else 263 ret = 0; 264 mtx_unlock(&mac_policy_mtx); 265 return (ret); 266 #else 267 if (!mac_late) 268 return (1); 269 270 return (1); 271 #endif 272 } 273 274 void 275 mac_policy_list_unbusy(void) 276 { 277 278 #ifndef MAC_STATIC 279 if (!mac_late) 280 return; 281 282 mtx_lock(&mac_policy_mtx); 283 mac_policy_count--; 284 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 285 if (mac_policy_count == 0) 286 cv_signal(&mac_policy_cv); 287 mtx_unlock(&mac_policy_mtx); 288 #endif 289 } 290 291 /* 292 * Initialize the MAC subsystem, including appropriate SMP locks. 293 */ 294 static void 295 mac_init(void) 296 { 297 298 LIST_INIT(&mac_static_policy_list); 299 LIST_INIT(&mac_policy_list); 300 mac_labelzone_init(); 301 302 #ifndef MAC_STATIC 303 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 304 cv_init(&mac_policy_cv, "mac_policy_cv"); 305 #endif 306 } 307 308 /* 309 * For the purposes of modules that want to know if they were loaded 310 * "early", set the mac_late flag once we've processed modules either 311 * linked into the kernel, or loaded before the kernel startup. 312 */ 313 static void 314 mac_late_init(void) 315 { 316 317 mac_late = 1; 318 } 319 320 /* 321 * After the policy list has changed, walk the list to update any global 322 * flags. Currently, we support only one flag, and it's conditionally 323 * defined; as a result, the entire function is conditional. Eventually, 324 * the #else case might also iterate across the policies. 325 */ 326 static void 327 mac_policy_updateflags(void) 328 { 329 #ifndef MAC_ALWAYS_LABEL_MBUF 330 struct mac_policy_conf *tmpc; 331 int labelmbufs; 332 333 mac_policy_assert_exclusive(); 334 335 labelmbufs = 0; 336 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 337 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 338 labelmbufs++; 339 } 340 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 341 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 342 labelmbufs++; 343 } 344 mac_labelmbufs = (labelmbufs != 0); 345 #endif 346 } 347 348 /* 349 * Allow MAC policy modules to register during boot, etc. 350 */ 351 int 352 mac_policy_modevent(module_t mod, int type, void *data) 353 { 354 struct mac_policy_conf *mpc; 355 int error; 356 357 error = 0; 358 mpc = (struct mac_policy_conf *) data; 359 360 #ifdef MAC_STATIC 361 if (mac_late) { 362 printf("mac_policy_modevent: MAC_STATIC and late\n"); 363 return (EBUSY); 364 } 365 #endif 366 367 switch (type) { 368 case MOD_LOAD: 369 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 370 mac_late) { 371 printf("mac_policy_modevent: can't load %s policy " 372 "after booting\n", mpc->mpc_name); 373 error = EBUSY; 374 break; 375 } 376 error = mac_policy_register(mpc); 377 break; 378 case MOD_UNLOAD: 379 /* Don't unregister the module if it was never registered. */ 380 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 381 != 0) 382 error = mac_policy_unregister(mpc); 383 else 384 error = 0; 385 break; 386 default: 387 error = EOPNOTSUPP; 388 break; 389 } 390 391 return (error); 392 } 393 394 static int 395 mac_policy_register(struct mac_policy_conf *mpc) 396 { 397 struct mac_policy_conf *tmpc; 398 int error, slot, static_entry; 399 400 error = 0; 401 402 /* 403 * We don't technically need exclusive access while !mac_late, 404 * but hold it for assertion consistency. 405 */ 406 mac_policy_grab_exclusive(); 407 408 /* 409 * If the module can potentially be unloaded, or we're loading 410 * late, we have to stick it in the non-static list and pay 411 * an extra performance overhead. Otherwise, we can pay a 412 * light locking cost and stick it in the static list. 413 */ 414 static_entry = (!mac_late && 415 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 416 417 if (static_entry) { 418 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 419 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 420 error = EEXIST; 421 goto out; 422 } 423 } 424 } else { 425 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 426 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 427 error = EEXIST; 428 goto out; 429 } 430 } 431 } 432 if (mpc->mpc_field_off != NULL) { 433 slot = ffs(mac_slot_offsets_free); 434 if (slot == 0) { 435 error = ENOMEM; 436 goto out; 437 } 438 slot--; 439 mac_slot_offsets_free &= ~(1 << slot); 440 *mpc->mpc_field_off = slot; 441 } 442 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 443 444 /* 445 * If we're loading a MAC module after the framework has 446 * initialized, it has to go into the dynamic list. If 447 * we're loading it before we've finished initializing, 448 * it can go into the static list with weaker locker 449 * requirements. 450 */ 451 if (static_entry) 452 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 453 else 454 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 455 456 /* Per-policy initialization. */ 457 if (mpc->mpc_ops->mpo_init != NULL) 458 (*(mpc->mpc_ops->mpo_init))(mpc); 459 mac_policy_updateflags(); 460 461 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 462 mpc->mpc_name); 463 464 out: 465 mac_policy_release_exclusive(); 466 return (error); 467 } 468 469 static int 470 mac_policy_unregister(struct mac_policy_conf *mpc) 471 { 472 473 /* 474 * If we fail the load, we may get a request to unload. Check 475 * to see if we did the run-time registration, and if not, 476 * silently succeed. 477 */ 478 mac_policy_grab_exclusive(); 479 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 480 mac_policy_release_exclusive(); 481 return (0); 482 } 483 #if 0 484 /* 485 * Don't allow unloading modules with private data. 486 */ 487 if (mpc->mpc_field_off != NULL) { 488 MAC_POLICY_LIST_UNLOCK(); 489 return (EBUSY); 490 } 491 #endif 492 /* 493 * Only allow the unload to proceed if the module is unloadable 494 * by its own definition. 495 */ 496 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 497 mac_policy_release_exclusive(); 498 return (EBUSY); 499 } 500 if (mpc->mpc_ops->mpo_destroy != NULL) 501 (*(mpc->mpc_ops->mpo_destroy))(mpc); 502 503 LIST_REMOVE(mpc, mpc_list); 504 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 505 mac_policy_updateflags(); 506 507 mac_policy_release_exclusive(); 508 509 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 510 mpc->mpc_name); 511 512 return (0); 513 } 514 515 /* 516 * Define an error value precedence, and given two arguments, selects the 517 * value with the higher precedence. 518 */ 519 int 520 mac_error_select(int error1, int error2) 521 { 522 523 /* Certain decision-making errors take top priority. */ 524 if (error1 == EDEADLK || error2 == EDEADLK) 525 return (EDEADLK); 526 527 /* Invalid arguments should be reported where possible. */ 528 if (error1 == EINVAL || error2 == EINVAL) 529 return (EINVAL); 530 531 /* Precedence goes to "visibility", with both process and file. */ 532 if (error1 == ESRCH || error2 == ESRCH) 533 return (ESRCH); 534 535 if (error1 == ENOENT || error2 == ENOENT) 536 return (ENOENT); 537 538 /* Precedence goes to DAC/MAC protections. */ 539 if (error1 == EACCES || error2 == EACCES) 540 return (EACCES); 541 542 /* Precedence goes to privilege. */ 543 if (error1 == EPERM || error2 == EPERM) 544 return (EPERM); 545 546 /* Precedence goes to error over success; otherwise, arbitrary. */ 547 if (error1 != 0) 548 return (error1); 549 return (error2); 550 } 551 552 void 553 mac_init_label(struct label *label) 554 { 555 556 bzero(label, sizeof(*label)); 557 label->l_flags = MAC_FLAG_INITIALIZED; 558 } 559 560 void 561 mac_destroy_label(struct label *label) 562 { 563 564 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 565 ("destroying uninitialized label")); 566 567 bzero(label, sizeof(*label)); 568 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 569 } 570 571 int 572 mac_check_structmac_consistent(struct mac *mac) 573 { 574 575 if (mac->m_buflen < 0 || 576 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 577 return (EINVAL); 578 579 return (0); 580 } 581 582 /* 583 * MPSAFE 584 */ 585 int 586 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 587 { 588 char *elements, *buffer; 589 struct mac mac; 590 struct proc *tproc; 591 struct ucred *tcred; 592 int error; 593 594 error = copyin(uap->mac_p, &mac, sizeof(mac)); 595 if (error) 596 return (error); 597 598 error = mac_check_structmac_consistent(&mac); 599 if (error) 600 return (error); 601 602 tproc = pfind(uap->pid); 603 if (tproc == NULL) 604 return (ESRCH); 605 606 tcred = NULL; /* Satisfy gcc. */ 607 error = p_cansee(td, tproc); 608 if (error == 0) 609 tcred = crhold(tproc->p_ucred); 610 PROC_UNLOCK(tproc); 611 if (error) 612 return (error); 613 614 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 615 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 616 if (error) { 617 free(elements, M_MACTEMP); 618 crfree(tcred); 619 return (error); 620 } 621 622 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 623 error = mac_externalize_cred_label(tcred->cr_label, elements, 624 buffer, mac.m_buflen); 625 if (error == 0) 626 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 627 628 free(buffer, M_MACTEMP); 629 free(elements, M_MACTEMP); 630 crfree(tcred); 631 return (error); 632 } 633 634 /* 635 * MPSAFE 636 */ 637 int 638 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 639 { 640 char *elements, *buffer; 641 struct mac mac; 642 int error; 643 644 error = copyin(uap->mac_p, &mac, sizeof(mac)); 645 if (error) 646 return (error); 647 648 error = mac_check_structmac_consistent(&mac); 649 if (error) 650 return (error); 651 652 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 653 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 654 if (error) { 655 free(elements, M_MACTEMP); 656 return (error); 657 } 658 659 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 660 error = mac_externalize_cred_label(td->td_ucred->cr_label, 661 elements, buffer, mac.m_buflen); 662 if (error == 0) 663 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 664 665 free(buffer, M_MACTEMP); 666 free(elements, M_MACTEMP); 667 return (error); 668 } 669 670 /* 671 * MPSAFE 672 */ 673 int 674 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 675 { 676 struct ucred *newcred, *oldcred; 677 struct label *intlabel; 678 struct proc *p; 679 struct mac mac; 680 char *buffer; 681 int error; 682 683 error = copyin(uap->mac_p, &mac, sizeof(mac)); 684 if (error) 685 return (error); 686 687 error = mac_check_structmac_consistent(&mac); 688 if (error) 689 return (error); 690 691 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 692 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 693 if (error) { 694 free(buffer, M_MACTEMP); 695 return (error); 696 } 697 698 intlabel = mac_cred_label_alloc(); 699 error = mac_internalize_cred_label(intlabel, buffer); 700 free(buffer, M_MACTEMP); 701 if (error) 702 goto out; 703 704 newcred = crget(); 705 706 p = td->td_proc; 707 PROC_LOCK(p); 708 oldcred = p->p_ucred; 709 710 error = mac_check_cred_relabel(oldcred, intlabel); 711 if (error) { 712 PROC_UNLOCK(p); 713 crfree(newcred); 714 goto out; 715 } 716 717 setsugid(p); 718 crcopy(newcred, oldcred); 719 mac_relabel_cred(newcred, intlabel); 720 p->p_ucred = newcred; 721 722 /* 723 * Grab additional reference for use while revoking mmaps, prior 724 * to releasing the proc lock and sharing the cred. 725 */ 726 crhold(newcred); 727 PROC_UNLOCK(p); 728 729 if (mac_enforce_vm) { 730 mac_cred_mmapped_drop_perms(td, newcred); 731 } 732 733 crfree(newcred); /* Free revocation reference. */ 734 crfree(oldcred); 735 736 out: 737 mac_cred_label_free(intlabel); 738 return (error); 739 } 740 741 /* 742 * MPSAFE 743 */ 744 int 745 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 746 { 747 char *elements, *buffer; 748 struct label *intlabel; 749 struct file *fp; 750 struct mac mac; 751 struct vnode *vp; 752 struct pipe *pipe; 753 struct socket *so; 754 short label_type; 755 int vfslocked, error; 756 757 error = copyin(uap->mac_p, &mac, sizeof(mac)); 758 if (error) 759 return (error); 760 761 error = mac_check_structmac_consistent(&mac); 762 if (error) 763 return (error); 764 765 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 766 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 767 if (error) { 768 free(elements, M_MACTEMP); 769 return (error); 770 } 771 772 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 773 error = fget(td, uap->fd, &fp); 774 if (error) 775 goto out; 776 777 label_type = fp->f_type; 778 switch (fp->f_type) { 779 case DTYPE_FIFO: 780 case DTYPE_VNODE: 781 vp = fp->f_vnode; 782 intlabel = mac_vnode_label_alloc(); 783 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 784 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 785 mac_copy_vnode_label(vp->v_label, intlabel); 786 VOP_UNLOCK(vp, 0, td); 787 VFS_UNLOCK_GIANT(vfslocked); 788 error = mac_externalize_vnode_label(intlabel, elements, 789 buffer, mac.m_buflen); 790 mac_vnode_label_free(intlabel); 791 break; 792 793 case DTYPE_PIPE: 794 pipe = fp->f_data; 795 intlabel = mac_pipe_label_alloc(); 796 PIPE_LOCK(pipe); 797 mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 798 PIPE_UNLOCK(pipe); 799 error = mac_externalize_pipe_label(intlabel, elements, 800 buffer, mac.m_buflen); 801 mac_pipe_label_free(intlabel); 802 break; 803 804 case DTYPE_SOCKET: 805 so = fp->f_data; 806 intlabel = mac_socket_label_alloc(M_WAITOK); 807 NET_LOCK_GIANT(); 808 SOCK_LOCK(so); 809 mac_copy_socket_label(so->so_label, intlabel); 810 SOCK_UNLOCK(so); 811 NET_UNLOCK_GIANT(); 812 error = mac_externalize_socket_label(intlabel, elements, 813 buffer, mac.m_buflen); 814 mac_socket_label_free(intlabel); 815 break; 816 817 default: 818 error = EINVAL; 819 } 820 fdrop(fp, td); 821 if (error == 0) 822 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 823 824 out: 825 free(buffer, M_MACTEMP); 826 free(elements, M_MACTEMP); 827 return (error); 828 } 829 830 /* 831 * MPSAFE 832 */ 833 int 834 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 835 { 836 char *elements, *buffer; 837 struct nameidata nd; 838 struct label *intlabel; 839 struct mac mac; 840 int vfslocked, error; 841 842 error = copyin(uap->mac_p, &mac, sizeof(mac)); 843 if (error) 844 return (error); 845 846 error = mac_check_structmac_consistent(&mac); 847 if (error) 848 return (error); 849 850 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 851 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 852 if (error) { 853 free(elements, M_MACTEMP); 854 return (error); 855 } 856 857 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 858 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 859 uap->path_p, td); 860 error = namei(&nd); 861 if (error) 862 goto out; 863 864 intlabel = mac_vnode_label_alloc(); 865 vfslocked = NDHASGIANT(&nd); 866 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 867 error = mac_externalize_vnode_label(intlabel, elements, buffer, 868 mac.m_buflen); 869 870 NDFREE(&nd, 0); 871 VFS_UNLOCK_GIANT(vfslocked); 872 mac_vnode_label_free(intlabel); 873 if (error == 0) 874 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 875 876 out: 877 free(buffer, M_MACTEMP); 878 free(elements, M_MACTEMP); 879 880 return (error); 881 } 882 883 /* 884 * MPSAFE 885 */ 886 int 887 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 888 { 889 char *elements, *buffer; 890 struct nameidata nd; 891 struct label *intlabel; 892 struct mac mac; 893 int vfslocked, error; 894 895 error = copyin(uap->mac_p, &mac, sizeof(mac)); 896 if (error) 897 return (error); 898 899 error = mac_check_structmac_consistent(&mac); 900 if (error) 901 return (error); 902 903 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 904 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 905 if (error) { 906 free(elements, M_MACTEMP); 907 return (error); 908 } 909 910 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 911 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 912 uap->path_p, td); 913 error = namei(&nd); 914 if (error) 915 goto out; 916 917 intlabel = mac_vnode_label_alloc(); 918 vfslocked = NDHASGIANT(&nd); 919 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 920 error = mac_externalize_vnode_label(intlabel, elements, buffer, 921 mac.m_buflen); 922 NDFREE(&nd, 0); 923 VFS_UNLOCK_GIANT(vfslocked); 924 mac_vnode_label_free(intlabel); 925 926 if (error == 0) 927 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 928 929 out: 930 free(buffer, M_MACTEMP); 931 free(elements, M_MACTEMP); 932 933 return (error); 934 } 935 936 /* 937 * MPSAFE 938 */ 939 int 940 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 941 { 942 struct label *intlabel; 943 struct pipe *pipe; 944 struct socket *so; 945 struct file *fp; 946 struct mount *mp; 947 struct vnode *vp; 948 struct mac mac; 949 char *buffer; 950 int error, vfslocked; 951 952 error = copyin(uap->mac_p, &mac, sizeof(mac)); 953 if (error) 954 return (error); 955 956 error = mac_check_structmac_consistent(&mac); 957 if (error) 958 return (error); 959 960 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 961 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 962 if (error) { 963 free(buffer, M_MACTEMP); 964 return (error); 965 } 966 967 error = fget(td, uap->fd, &fp); 968 if (error) 969 goto out; 970 971 switch (fp->f_type) { 972 case DTYPE_FIFO: 973 case DTYPE_VNODE: 974 intlabel = mac_vnode_label_alloc(); 975 error = mac_internalize_vnode_label(intlabel, buffer); 976 if (error) { 977 mac_vnode_label_free(intlabel); 978 break; 979 } 980 vp = fp->f_vnode; 981 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 982 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 983 if (error != 0) { 984 VFS_UNLOCK_GIANT(vfslocked); 985 mac_vnode_label_free(intlabel); 986 break; 987 } 988 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 989 error = vn_setlabel(vp, intlabel, td->td_ucred); 990 VOP_UNLOCK(vp, 0, td); 991 vn_finished_write(mp); 992 VFS_UNLOCK_GIANT(vfslocked); 993 mac_vnode_label_free(intlabel); 994 break; 995 996 case DTYPE_PIPE: 997 intlabel = mac_pipe_label_alloc(); 998 error = mac_internalize_pipe_label(intlabel, buffer); 999 if (error == 0) { 1000 pipe = fp->f_data; 1001 PIPE_LOCK(pipe); 1002 error = mac_pipe_label_set(td->td_ucred, 1003 pipe->pipe_pair, intlabel); 1004 PIPE_UNLOCK(pipe); 1005 } 1006 mac_pipe_label_free(intlabel); 1007 break; 1008 1009 case DTYPE_SOCKET: 1010 intlabel = mac_socket_label_alloc(M_WAITOK); 1011 error = mac_internalize_socket_label(intlabel, buffer); 1012 if (error == 0) { 1013 so = fp->f_data; 1014 NET_LOCK_GIANT(); 1015 error = mac_socket_label_set(td->td_ucred, so, 1016 intlabel); 1017 NET_UNLOCK_GIANT(); 1018 } 1019 mac_socket_label_free(intlabel); 1020 break; 1021 1022 default: 1023 error = EINVAL; 1024 } 1025 fdrop(fp, td); 1026 out: 1027 free(buffer, M_MACTEMP); 1028 return (error); 1029 } 1030 1031 /* 1032 * MPSAFE 1033 */ 1034 int 1035 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1036 { 1037 struct label *intlabel; 1038 struct nameidata nd; 1039 struct mount *mp; 1040 struct mac mac; 1041 char *buffer; 1042 int vfslocked, error; 1043 1044 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1045 if (error) 1046 return (error); 1047 1048 error = mac_check_structmac_consistent(&mac); 1049 if (error) 1050 return (error); 1051 1052 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1053 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1054 if (error) { 1055 free(buffer, M_MACTEMP); 1056 return (error); 1057 } 1058 1059 intlabel = mac_vnode_label_alloc(); 1060 error = mac_internalize_vnode_label(intlabel, buffer); 1061 free(buffer, M_MACTEMP); 1062 if (error) 1063 goto out; 1064 1065 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE, 1066 uap->path_p, td); 1067 error = namei(&nd); 1068 vfslocked = NDHASGIANT(&nd); 1069 if (error == 0) { 1070 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1071 if (error == 0) { 1072 error = vn_setlabel(nd.ni_vp, intlabel, 1073 td->td_ucred); 1074 vn_finished_write(mp); 1075 } 1076 } 1077 1078 NDFREE(&nd, 0); 1079 VFS_UNLOCK_GIANT(vfslocked); 1080 out: 1081 mac_vnode_label_free(intlabel); 1082 return (error); 1083 } 1084 1085 /* 1086 * MPSAFE 1087 */ 1088 int 1089 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1090 { 1091 struct label *intlabel; 1092 struct nameidata nd; 1093 struct mount *mp; 1094 struct mac mac; 1095 char *buffer; 1096 int vfslocked, error; 1097 1098 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1099 if (error) 1100 return (error); 1101 1102 error = mac_check_structmac_consistent(&mac); 1103 if (error) 1104 return (error); 1105 1106 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1107 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1108 if (error) { 1109 free(buffer, M_MACTEMP); 1110 return (error); 1111 } 1112 1113 intlabel = mac_vnode_label_alloc(); 1114 error = mac_internalize_vnode_label(intlabel, buffer); 1115 free(buffer, M_MACTEMP); 1116 if (error) 1117 goto out; 1118 1119 NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE, 1120 uap->path_p, td); 1121 error = namei(&nd); 1122 vfslocked = NDHASGIANT(&nd); 1123 if (error == 0) { 1124 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1125 if (error == 0) { 1126 error = vn_setlabel(nd.ni_vp, intlabel, 1127 td->td_ucred); 1128 vn_finished_write(mp); 1129 } 1130 } 1131 1132 NDFREE(&nd, 0); 1133 VFS_UNLOCK_GIANT(vfslocked); 1134 out: 1135 mac_vnode_label_free(intlabel); 1136 return (error); 1137 } 1138 1139 /* 1140 * MPSAFE 1141 */ 1142 int 1143 mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1144 { 1145 struct mac_policy_conf *mpc; 1146 char target[MAC_MAX_POLICY_NAME]; 1147 int entrycount, error; 1148 1149 error = copyinstr(uap->policy, target, sizeof(target), NULL); 1150 if (error) 1151 return (error); 1152 1153 error = ENOSYS; 1154 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1155 if (strcmp(mpc->mpc_name, target) == 0 && 1156 mpc->mpc_ops->mpo_syscall != NULL) { 1157 error = mpc->mpc_ops->mpo_syscall(td, 1158 uap->call, uap->arg); 1159 goto out; 1160 } 1161 } 1162 1163 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1164 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1165 if (strcmp(mpc->mpc_name, target) == 0 && 1166 mpc->mpc_ops->mpo_syscall != NULL) { 1167 error = mpc->mpc_ops->mpo_syscall(td, 1168 uap->call, uap->arg); 1169 break; 1170 } 1171 } 1172 mac_policy_list_unbusy(); 1173 } 1174 out: 1175 return (error); 1176 } 1177 1178 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1179 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1180 1181 #else /* !MAC */ 1182 1183 int 1184 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1185 { 1186 1187 return (ENOSYS); 1188 } 1189 1190 int 1191 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1192 { 1193 1194 return (ENOSYS); 1195 } 1196 1197 int 1198 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1199 { 1200 1201 return (ENOSYS); 1202 } 1203 1204 int 1205 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1206 { 1207 1208 return (ENOSYS); 1209 } 1210 1211 int 1212 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1213 { 1214 1215 return (ENOSYS); 1216 } 1217 1218 int 1219 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1220 { 1221 1222 return (ENOSYS); 1223 } 1224 1225 int 1226 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1227 { 1228 1229 return (ENOSYS); 1230 } 1231 1232 int 1233 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1234 { 1235 1236 return (ENOSYS); 1237 } 1238 1239 int 1240 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1241 { 1242 1243 return (ENOSYS); 1244 } 1245 1246 int 1247 mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1248 { 1249 1250 return (ENOSYS); 1251 } 1252 1253 #endif /* !MAC */ 1254