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