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