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