1 /*- 2 * Copyright (c) 1999-2002 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001-2003 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 static struct mtx mac_policy_mtx; 170 static struct cv mac_policy_cv; 171 static int mac_policy_count; 172 struct mac_policy_list_head mac_policy_list; 173 struct mac_policy_list_head mac_static_policy_list; 174 175 /* 176 * We manually invoke WITNESS_WARN() to allow Witness to generate 177 * warnings even if we don't end up ever triggering the wait at 178 * run-time. The consumer of the exclusive interface must not hold 179 * any locks (other than potentially Giant) since we may sleep for 180 * long (potentially indefinite) periods of time waiting for the 181 * framework to become quiescent so that a policy list change may 182 * be made. 183 */ 184 void 185 mac_policy_grab_exclusive(void) 186 { 187 188 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 189 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 190 mtx_lock(&mac_policy_mtx); 191 while (mac_policy_count != 0) 192 cv_wait(&mac_policy_cv, &mac_policy_mtx); 193 } 194 195 void 196 mac_policy_assert_exclusive(void) 197 { 198 199 mtx_assert(&mac_policy_mtx, MA_OWNED); 200 KASSERT(mac_policy_count == 0, 201 ("mac_policy_assert_exclusive(): not exclusive")); 202 } 203 204 void 205 mac_policy_release_exclusive(void) 206 { 207 208 KASSERT(mac_policy_count == 0, 209 ("mac_policy_release_exclusive(): not exclusive")); 210 mtx_unlock(&mac_policy_mtx); 211 cv_signal(&mac_policy_cv); 212 } 213 214 void 215 mac_policy_list_busy(void) 216 { 217 218 mtx_lock(&mac_policy_mtx); 219 mac_policy_count++; 220 mtx_unlock(&mac_policy_mtx); 221 } 222 223 int 224 mac_policy_list_conditional_busy(void) 225 { 226 int ret; 227 228 mtx_lock(&mac_policy_mtx); 229 if (!LIST_EMPTY(&mac_policy_list)) { 230 mac_policy_count++; 231 ret = 1; 232 } else 233 ret = 0; 234 mtx_unlock(&mac_policy_mtx); 235 return (ret); 236 } 237 238 void 239 mac_policy_list_unbusy(void) 240 { 241 242 mtx_lock(&mac_policy_mtx); 243 mac_policy_count--; 244 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 245 if (mac_policy_count == 0) 246 cv_signal(&mac_policy_cv); 247 mtx_unlock(&mac_policy_mtx); 248 } 249 250 /* 251 * Initialize the MAC subsystem, including appropriate SMP locks. 252 */ 253 static void 254 mac_init(void) 255 { 256 257 LIST_INIT(&mac_static_policy_list); 258 LIST_INIT(&mac_policy_list); 259 mac_labelzone_init(); 260 261 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 262 cv_init(&mac_policy_cv, "mac_policy_cv"); 263 } 264 265 /* 266 * For the purposes of modules that want to know if they were loaded 267 * "early", set the mac_late flag once we've processed modules either 268 * linked into the kernel, or loaded before the kernel startup. 269 */ 270 static void 271 mac_late_init(void) 272 { 273 274 mac_late = 1; 275 } 276 277 /* 278 * After the policy list has changed, walk the list to update any global 279 * flags. Currently, we support only one flag, and it's conditionally 280 * defined; as a result, the entire function is conditional. Eventually, 281 * the #else case might also iterate across the policies. 282 */ 283 static void 284 mac_policy_updateflags(void) 285 { 286 #ifndef MAC_ALWAYS_LABEL_MBUF 287 struct mac_policy_conf *tmpc; 288 int labelmbufs; 289 290 mac_policy_assert_exclusive(); 291 292 labelmbufs = 0; 293 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 294 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 295 labelmbufs++; 296 } 297 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 298 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 299 labelmbufs++; 300 } 301 mac_labelmbufs = (labelmbufs != 0); 302 #endif 303 } 304 305 /* 306 * Allow MAC policy modules to register during boot, etc. 307 */ 308 int 309 mac_policy_modevent(module_t mod, int type, void *data) 310 { 311 struct mac_policy_conf *mpc; 312 int error; 313 314 error = 0; 315 mpc = (struct mac_policy_conf *) data; 316 317 switch (type) { 318 case MOD_LOAD: 319 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 320 mac_late) { 321 printf("mac_policy_modevent: can't load %s policy " 322 "after booting\n", mpc->mpc_name); 323 error = EBUSY; 324 break; 325 } 326 error = mac_policy_register(mpc); 327 break; 328 case MOD_UNLOAD: 329 /* Don't unregister the module if it was never registered. */ 330 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 331 != 0) 332 error = mac_policy_unregister(mpc); 333 else 334 error = 0; 335 break; 336 default: 337 break; 338 } 339 340 return (error); 341 } 342 343 static int 344 mac_policy_register(struct mac_policy_conf *mpc) 345 { 346 struct mac_policy_conf *tmpc; 347 int error, slot, static_entry; 348 349 error = 0; 350 351 /* 352 * We don't technically need exclusive access while !mac_late, 353 * but hold it for assertion consistency. 354 */ 355 mac_policy_grab_exclusive(); 356 357 /* 358 * If the module can potentially be unloaded, or we're loading 359 * late, we have to stick it in the non-static list and pay 360 * an extra performance overhead. Otherwise, we can pay a 361 * light locking cost and stick it in the static list. 362 */ 363 static_entry = (!mac_late && 364 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 365 366 if (static_entry) { 367 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 368 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 369 error = EEXIST; 370 goto out; 371 } 372 } 373 } else { 374 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 375 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 376 error = EEXIST; 377 goto out; 378 } 379 } 380 } 381 if (mpc->mpc_field_off != NULL) { 382 slot = ffs(mac_slot_offsets_free); 383 if (slot == 0) { 384 error = ENOMEM; 385 goto out; 386 } 387 slot--; 388 mac_slot_offsets_free &= ~(1 << slot); 389 *mpc->mpc_field_off = slot; 390 } 391 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 392 393 /* 394 * If we're loading a MAC module after the framework has 395 * initialized, it has to go into the dynamic list. If 396 * we're loading it before we've finished initializing, 397 * it can go into the static list with weaker locker 398 * requirements. 399 */ 400 if (static_entry) 401 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 402 else 403 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 404 405 /* Per-policy initialization. */ 406 if (mpc->mpc_ops->mpo_init != NULL) 407 (*(mpc->mpc_ops->mpo_init))(mpc); 408 mac_policy_updateflags(); 409 410 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 411 mpc->mpc_name); 412 413 out: 414 mac_policy_release_exclusive(); 415 return (error); 416 } 417 418 static int 419 mac_policy_unregister(struct mac_policy_conf *mpc) 420 { 421 422 /* 423 * If we fail the load, we may get a request to unload. Check 424 * to see if we did the run-time registration, and if not, 425 * silently succeed. 426 */ 427 mac_policy_grab_exclusive(); 428 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 429 mac_policy_release_exclusive(); 430 return (0); 431 } 432 #if 0 433 /* 434 * Don't allow unloading modules with private data. 435 */ 436 if (mpc->mpc_field_off != NULL) { 437 MAC_POLICY_LIST_UNLOCK(); 438 return (EBUSY); 439 } 440 #endif 441 /* 442 * Only allow the unload to proceed if the module is unloadable 443 * by its own definition. 444 */ 445 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 446 mac_policy_release_exclusive(); 447 return (EBUSY); 448 } 449 if (mpc->mpc_ops->mpo_destroy != NULL) 450 (*(mpc->mpc_ops->mpo_destroy))(mpc); 451 452 LIST_REMOVE(mpc, mpc_list); 453 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 454 mac_policy_updateflags(); 455 456 mac_policy_release_exclusive(); 457 458 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 459 mpc->mpc_name); 460 461 return (0); 462 } 463 464 /* 465 * Define an error value precedence, and given two arguments, selects the 466 * value with the higher precedence. 467 */ 468 int 469 mac_error_select(int error1, int error2) 470 { 471 472 /* Certain decision-making errors take top priority. */ 473 if (error1 == EDEADLK || error2 == EDEADLK) 474 return (EDEADLK); 475 476 /* Invalid arguments should be reported where possible. */ 477 if (error1 == EINVAL || error2 == EINVAL) 478 return (EINVAL); 479 480 /* Precedence goes to "visibility", with both process and file. */ 481 if (error1 == ESRCH || error2 == ESRCH) 482 return (ESRCH); 483 484 if (error1 == ENOENT || error2 == ENOENT) 485 return (ENOENT); 486 487 /* Precedence goes to DAC/MAC protections. */ 488 if (error1 == EACCES || error2 == EACCES) 489 return (EACCES); 490 491 /* Precedence goes to privilege. */ 492 if (error1 == EPERM || error2 == EPERM) 493 return (EPERM); 494 495 /* Precedence goes to error over success; otherwise, arbitrary. */ 496 if (error1 != 0) 497 return (error1); 498 return (error2); 499 } 500 501 void 502 mac_init_label(struct label *label) 503 { 504 505 bzero(label, sizeof(*label)); 506 label->l_flags = MAC_FLAG_INITIALIZED; 507 } 508 509 void 510 mac_destroy_label(struct label *label) 511 { 512 513 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 514 ("destroying uninitialized label")); 515 516 bzero(label, sizeof(*label)); 517 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 518 } 519 520 int 521 mac_check_structmac_consistent(struct mac *mac) 522 { 523 524 if (mac->m_buflen < 0 || 525 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 526 return (EINVAL); 527 528 return (0); 529 } 530 531 /* 532 * MPSAFE 533 */ 534 int 535 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 536 { 537 char *elements, *buffer; 538 struct mac mac; 539 struct proc *tproc; 540 struct ucred *tcred; 541 int error; 542 543 error = copyin(uap->mac_p, &mac, sizeof(mac)); 544 if (error) 545 return (error); 546 547 error = mac_check_structmac_consistent(&mac); 548 if (error) 549 return (error); 550 551 tproc = pfind(uap->pid); 552 if (tproc == NULL) 553 return (ESRCH); 554 555 tcred = NULL; /* Satisfy gcc. */ 556 error = p_cansee(td, tproc); 557 if (error == 0) 558 tcred = crhold(tproc->p_ucred); 559 PROC_UNLOCK(tproc); 560 if (error) 561 return (error); 562 563 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 564 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 565 if (error) { 566 free(elements, M_MACTEMP); 567 crfree(tcred); 568 return (error); 569 } 570 571 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 572 error = mac_externalize_cred_label(tcred->cr_label, elements, 573 buffer, mac.m_buflen); 574 if (error == 0) 575 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 576 577 free(buffer, M_MACTEMP); 578 free(elements, M_MACTEMP); 579 crfree(tcred); 580 return (error); 581 } 582 583 /* 584 * MPSAFE 585 */ 586 int 587 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 588 { 589 char *elements, *buffer; 590 struct mac mac; 591 int error; 592 593 error = copyin(uap->mac_p, &mac, sizeof(mac)); 594 if (error) 595 return (error); 596 597 error = mac_check_structmac_consistent(&mac); 598 if (error) 599 return (error); 600 601 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 602 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 603 if (error) { 604 free(elements, M_MACTEMP); 605 return (error); 606 } 607 608 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 609 error = mac_externalize_cred_label(td->td_ucred->cr_label, 610 elements, buffer, mac.m_buflen); 611 if (error == 0) 612 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 613 614 free(buffer, M_MACTEMP); 615 free(elements, M_MACTEMP); 616 return (error); 617 } 618 619 /* 620 * MPSAFE 621 */ 622 int 623 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 624 { 625 struct ucred *newcred, *oldcred; 626 struct label *intlabel; 627 struct proc *p; 628 struct mac mac; 629 char *buffer; 630 int error; 631 632 error = copyin(uap->mac_p, &mac, sizeof(mac)); 633 if (error) 634 return (error); 635 636 error = mac_check_structmac_consistent(&mac); 637 if (error) 638 return (error); 639 640 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 641 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 642 if (error) { 643 free(buffer, M_MACTEMP); 644 return (error); 645 } 646 647 intlabel = mac_cred_label_alloc(); 648 error = mac_internalize_cred_label(intlabel, buffer); 649 free(buffer, M_MACTEMP); 650 if (error) 651 goto out; 652 653 newcred = crget(); 654 655 p = td->td_proc; 656 PROC_LOCK(p); 657 oldcred = p->p_ucred; 658 659 error = mac_check_cred_relabel(oldcred, intlabel); 660 if (error) { 661 PROC_UNLOCK(p); 662 crfree(newcred); 663 goto out; 664 } 665 666 setsugid(p); 667 crcopy(newcred, oldcred); 668 mac_relabel_cred(newcred, intlabel); 669 p->p_ucred = newcred; 670 671 /* 672 * Grab additional reference for use while revoking mmaps, prior 673 * to releasing the proc lock and sharing the cred. 674 */ 675 crhold(newcred); 676 PROC_UNLOCK(p); 677 678 if (mac_enforce_vm) { 679 mtx_lock(&Giant); 680 mac_cred_mmapped_drop_perms(td, newcred); 681 mtx_unlock(&Giant); 682 } 683 684 crfree(newcred); /* Free revocation reference. */ 685 crfree(oldcred); 686 687 out: 688 mac_cred_label_free(intlabel); 689 return (error); 690 } 691 692 /* 693 * MPSAFE 694 */ 695 int 696 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 697 { 698 char *elements, *buffer; 699 struct label *intlabel; 700 struct file *fp; 701 struct mac mac; 702 struct vnode *vp; 703 struct pipe *pipe; 704 struct socket *so; 705 short label_type; 706 int error; 707 708 error = copyin(uap->mac_p, &mac, sizeof(mac)); 709 if (error) 710 return (error); 711 712 error = mac_check_structmac_consistent(&mac); 713 if (error) 714 return (error); 715 716 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 717 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 718 if (error) { 719 free(elements, M_MACTEMP); 720 return (error); 721 } 722 723 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 724 error = fget(td, uap->fd, &fp); 725 if (error) 726 goto out; 727 728 label_type = fp->f_type; 729 switch (fp->f_type) { 730 case DTYPE_FIFO: 731 case DTYPE_VNODE: 732 vp = fp->f_vnode; 733 intlabel = mac_vnode_label_alloc(); 734 mtx_lock(&Giant); /* VFS */ 735 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 736 mac_copy_vnode_label(vp->v_label, intlabel); 737 VOP_UNLOCK(vp, 0, td); 738 mtx_unlock(&Giant); /* VFS */ 739 error = mac_externalize_vnode_label(intlabel, elements, 740 buffer, mac.m_buflen); 741 mac_vnode_label_free(intlabel); 742 break; 743 744 case DTYPE_PIPE: 745 pipe = fp->f_data; 746 intlabel = mac_pipe_label_alloc(); 747 PIPE_LOCK(pipe); 748 mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel); 749 PIPE_UNLOCK(pipe); 750 error = mac_externalize_pipe_label(intlabel, elements, 751 buffer, mac.m_buflen); 752 mac_pipe_label_free(intlabel); 753 break; 754 755 case DTYPE_SOCKET: 756 so = fp->f_data; 757 intlabel = mac_socket_label_alloc(M_WAITOK); 758 mtx_lock(&Giant); /* Sockets */ 759 /* XXX: Socket lock here. */ 760 mac_copy_socket_label(so->so_label, intlabel); 761 /* XXX: Socket unlock here. */ 762 mtx_unlock(&Giant); /* Sockets */ 763 error = mac_externalize_socket_label(intlabel, elements, 764 buffer, mac.m_buflen); 765 mac_socket_label_free(intlabel); 766 break; 767 768 default: 769 error = EINVAL; 770 } 771 fdrop(fp, td); 772 if (error == 0) 773 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 774 775 out: 776 free(buffer, M_MACTEMP); 777 free(elements, M_MACTEMP); 778 return (error); 779 } 780 781 /* 782 * MPSAFE 783 */ 784 int 785 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 786 { 787 char *elements, *buffer; 788 struct nameidata nd; 789 struct label *intlabel; 790 struct mac mac; 791 int error; 792 793 error = copyin(uap->mac_p, &mac, sizeof(mac)); 794 if (error) 795 return (error); 796 797 error = mac_check_structmac_consistent(&mac); 798 if (error) 799 return (error); 800 801 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 802 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 803 if (error) { 804 free(elements, M_MACTEMP); 805 return (error); 806 } 807 808 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 809 mtx_lock(&Giant); /* VFS */ 810 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 811 td); 812 error = namei(&nd); 813 if (error) 814 goto out; 815 816 intlabel = mac_vnode_label_alloc(); 817 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 818 error = mac_externalize_vnode_label(intlabel, elements, buffer, 819 mac.m_buflen); 820 821 NDFREE(&nd, 0); 822 mac_vnode_label_free(intlabel); 823 824 if (error == 0) 825 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 826 827 out: 828 mtx_unlock(&Giant); /* VFS */ 829 830 free(buffer, M_MACTEMP); 831 free(elements, M_MACTEMP); 832 833 return (error); 834 } 835 836 /* 837 * MPSAFE 838 */ 839 int 840 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 841 { 842 char *elements, *buffer; 843 struct nameidata nd; 844 struct label *intlabel; 845 struct mac mac; 846 int error; 847 848 error = copyin(uap->mac_p, &mac, sizeof(mac)); 849 if (error) 850 return (error); 851 852 error = mac_check_structmac_consistent(&mac); 853 if (error) 854 return (error); 855 856 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 857 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 858 if (error) { 859 free(elements, M_MACTEMP); 860 return (error); 861 } 862 863 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 864 mtx_lock(&Giant); /* VFS */ 865 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 866 td); 867 error = namei(&nd); 868 if (error) 869 goto out; 870 871 intlabel = mac_vnode_label_alloc(); 872 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 873 error = mac_externalize_vnode_label(intlabel, elements, buffer, 874 mac.m_buflen); 875 NDFREE(&nd, 0); 876 mac_vnode_label_free(intlabel); 877 878 if (error == 0) 879 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 880 881 out: 882 mtx_unlock(&Giant); /* VFS */ 883 884 free(buffer, M_MACTEMP); 885 free(elements, M_MACTEMP); 886 887 return (error); 888 } 889 890 /* 891 * MPSAFE 892 */ 893 int 894 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 895 { 896 struct label *intlabel; 897 struct pipe *pipe; 898 struct socket *so; 899 struct file *fp; 900 struct mount *mp; 901 struct vnode *vp; 902 struct mac mac; 903 char *buffer; 904 int error; 905 906 error = copyin(uap->mac_p, &mac, sizeof(mac)); 907 if (error) 908 return (error); 909 910 error = mac_check_structmac_consistent(&mac); 911 if (error) 912 return (error); 913 914 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 915 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 916 if (error) { 917 free(buffer, M_MACTEMP); 918 return (error); 919 } 920 921 error = fget(td, uap->fd, &fp); 922 if (error) 923 goto out; 924 925 switch (fp->f_type) { 926 case DTYPE_FIFO: 927 case DTYPE_VNODE: 928 intlabel = mac_vnode_label_alloc(); 929 error = mac_internalize_vnode_label(intlabel, buffer); 930 if (error) { 931 mac_vnode_label_free(intlabel); 932 break; 933 } 934 vp = fp->f_vnode; 935 mtx_lock(&Giant); /* VFS */ 936 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 937 if (error != 0) { 938 mtx_unlock(&Giant); /* VFS */ 939 mac_vnode_label_free(intlabel); 940 break; 941 } 942 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 943 error = vn_setlabel(vp, intlabel, td->td_ucred); 944 VOP_UNLOCK(vp, 0, td); 945 vn_finished_write(mp); 946 mtx_unlock(&Giant); /* VFS */ 947 mac_vnode_label_free(intlabel); 948 break; 949 950 case DTYPE_PIPE: 951 intlabel = mac_pipe_label_alloc(); 952 error = mac_internalize_pipe_label(intlabel, buffer); 953 if (error == 0) { 954 pipe = fp->f_data; 955 PIPE_LOCK(pipe); 956 error = mac_pipe_label_set(td->td_ucred, 957 pipe->pipe_pair, intlabel); 958 PIPE_UNLOCK(pipe); 959 } 960 mac_pipe_label_free(intlabel); 961 break; 962 963 case DTYPE_SOCKET: 964 intlabel = mac_socket_label_alloc(M_WAITOK); 965 error = mac_internalize_socket_label(intlabel, buffer); 966 if (error == 0) { 967 so = fp->f_data; 968 mtx_lock(&Giant); /* Sockets */ 969 /* XXX: Socket lock here. */ 970 error = mac_socket_label_set(td->td_ucred, so, 971 intlabel); 972 /* XXX: Socket unlock here. */ 973 mtx_unlock(&Giant); /* Sockets */ 974 } 975 mac_socket_label_free(intlabel); 976 break; 977 978 default: 979 error = EINVAL; 980 } 981 fdrop(fp, td); 982 out: 983 free(buffer, M_MACTEMP); 984 return (error); 985 } 986 987 /* 988 * MPSAFE 989 */ 990 int 991 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 992 { 993 struct label *intlabel; 994 struct nameidata nd; 995 struct mount *mp; 996 struct mac mac; 997 char *buffer; 998 int error; 999 1000 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1001 if (error) 1002 return (error); 1003 1004 error = mac_check_structmac_consistent(&mac); 1005 if (error) 1006 return (error); 1007 1008 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1009 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1010 if (error) { 1011 free(buffer, M_MACTEMP); 1012 return (error); 1013 } 1014 1015 intlabel = mac_vnode_label_alloc(); 1016 error = mac_internalize_vnode_label(intlabel, buffer); 1017 free(buffer, M_MACTEMP); 1018 if (error) 1019 goto out; 1020 1021 mtx_lock(&Giant); /* VFS */ 1022 1023 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1024 td); 1025 error = namei(&nd); 1026 if (error == 0) { 1027 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1028 if (error == 0) 1029 error = vn_setlabel(nd.ni_vp, intlabel, 1030 td->td_ucred); 1031 vn_finished_write(mp); 1032 } 1033 1034 NDFREE(&nd, 0); 1035 mtx_unlock(&Giant); /* VFS */ 1036 out: 1037 mac_vnode_label_free(intlabel); 1038 return (error); 1039 } 1040 1041 /* 1042 * MPSAFE 1043 */ 1044 int 1045 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1046 { 1047 struct label *intlabel; 1048 struct nameidata nd; 1049 struct mount *mp; 1050 struct mac mac; 1051 char *buffer; 1052 int error; 1053 1054 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1055 if (error) 1056 return (error); 1057 1058 error = mac_check_structmac_consistent(&mac); 1059 if (error) 1060 return (error); 1061 1062 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1063 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1064 if (error) { 1065 free(buffer, M_MACTEMP); 1066 return (error); 1067 } 1068 1069 intlabel = mac_vnode_label_alloc(); 1070 error = mac_internalize_vnode_label(intlabel, buffer); 1071 free(buffer, M_MACTEMP); 1072 if (error) 1073 goto out; 1074 1075 mtx_lock(&Giant); /* VFS */ 1076 1077 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1078 td); 1079 error = namei(&nd); 1080 if (error == 0) { 1081 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1082 if (error == 0) 1083 error = vn_setlabel(nd.ni_vp, intlabel, 1084 td->td_ucred); 1085 vn_finished_write(mp); 1086 } 1087 1088 NDFREE(&nd, 0); 1089 mtx_unlock(&Giant); /* VFS */ 1090 out: 1091 mac_vnode_label_free(intlabel); 1092 return (error); 1093 } 1094 1095 /* 1096 * MPSAFE 1097 */ 1098 int 1099 mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1100 { 1101 struct mac_policy_conf *mpc; 1102 char target[MAC_MAX_POLICY_NAME]; 1103 int entrycount, error; 1104 1105 error = copyinstr(uap->policy, target, sizeof(target), NULL); 1106 if (error) 1107 return (error); 1108 1109 error = ENOSYS; 1110 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1111 if (strcmp(mpc->mpc_name, target) == 0 && 1112 mpc->mpc_ops->mpo_syscall != NULL) { 1113 error = mpc->mpc_ops->mpo_syscall(td, 1114 uap->call, uap->arg); 1115 goto out; 1116 } 1117 } 1118 1119 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1120 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1121 if (strcmp(mpc->mpc_name, target) == 0 && 1122 mpc->mpc_ops->mpo_syscall != NULL) { 1123 error = mpc->mpc_ops->mpo_syscall(td, 1124 uap->call, uap->arg); 1125 break; 1126 } 1127 } 1128 mac_policy_list_unbusy(); 1129 } 1130 out: 1131 return (error); 1132 } 1133 1134 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1135 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1136 1137 #else /* !MAC */ 1138 1139 int 1140 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1141 { 1142 1143 return (ENOSYS); 1144 } 1145 1146 int 1147 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1148 { 1149 1150 return (ENOSYS); 1151 } 1152 1153 int 1154 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1155 { 1156 1157 return (ENOSYS); 1158 } 1159 1160 int 1161 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1162 { 1163 1164 return (ENOSYS); 1165 } 1166 1167 int 1168 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1169 { 1170 1171 return (ENOSYS); 1172 } 1173 1174 int 1175 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1176 { 1177 1178 return (ENOSYS); 1179 } 1180 1181 int 1182 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1183 { 1184 1185 return (ENOSYS); 1186 } 1187 1188 int 1189 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1190 { 1191 1192 return (ENOSYS); 1193 } 1194 1195 int 1196 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1197 { 1198 1199 return (ENOSYS); 1200 } 1201 1202 int 1203 mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1204 { 1205 1206 return (ENOSYS); 1207 } 1208 1209 #endif 1210