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