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