1/* 2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/*- 29 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 30 * Copyright (c) 2001 Ilmar S. Habibulin 31 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc. 32 * Copyright (c) 2005-2006 SPARTA, Inc. 33 * 34 * This software was developed by Robert Watson and Ilmar Habibulin for the 35 * TrustedBSD Project. 36 * 37 * This software was developed for the FreeBSD Project in part by Network 38 * Associates Laboratories, the Security Research Division of Network 39 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 40 * as part of the DARPA CHATS research program. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 */ 64 65/*- 66 * Framework for extensible kernel access control. This file contains 67 * Kernel and userland interface to the framework, policy registration 68 * and composition. Per-object interfaces, controls, and labeling may be 69 * found in src/sys/mac/. Sample policies may be found in src/sys/mac*. 70 */ 71 72#include <stdarg.h> 73#include <string.h> 74#include <security/mac_internal.h> 75#include <security/mac_mach_internal.h> 76#include <sys/param.h> 77#include <sys/vnode.h> 78#include <sys/vnode_internal.h> 79#include <sys/vfs_context.h> 80#include <sys/namei.h> 81#include <bsd/bsm/audit.h> 82#include <bsd/security/audit/audit.h> 83#include <sys/file.h> 84#include <sys/file_internal.h> 85#include <sys/filedesc.h> 86#include <sys/proc.h> 87#include <sys/proc_internal.h> 88#include <sys/kauth.h> 89#include <sys/sysproto.h> 90 91#include <mach/exception_types.h> 92#include <mach/vm_types.h> 93#include <mach/vm_prot.h> 94 95#include <kern/zalloc.h> 96#include <kern/sched_prim.h> 97#include <osfmk/kern/task.h> 98#include <osfmk/kern/kalloc.h> 99 100#if CONFIG_MACF 101#include <security/mac.h> 102#include <security/mac_policy.h> 103#include <security/mac_framework.h> 104#include <security/mac_internal.h> 105#include <security/mac_mach_internal.h> 106#endif 107 108 109/* 110 * define MB_DEBUG to display run-time debugging information 111 * #define MB_DEBUG 1 112 */ 113 114#ifdef MB_DEBUG 115#define DPRINTF(x) printf x 116#else 117#define MB_DEBUG 118#define DPRINTF(x) 119#endif 120 121#if CONFIG_MACF 122SYSCTL_NODE(, OID_AUTO, security, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 123 "Security Controls"); 124SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 125 "TrustedBSD MAC policy controls"); 126 127#if DEBUG 128#define SECURITY_MAC_CTLFLAGS CTLFLAG_RW | CTLFLAG_LOCKED 129#else 130#define SECURITY_MAC_CTLFLAGS CTLFLAG_RD | CTLFLAG_LOCKED 131#endif 132 133/* 134 * Declare that the kernel provides MAC support, version 1. This permits 135 * modules to refuse to be loaded if the necessary support isn't present, 136 * even if it's pre-boot. 137 */ 138#if 0 139MODULE_VERSION(kernel_mac_support, 1); 140#endif 141 142#if MAC_MAX_SLOTS > 32 143#error "MAC_MAX_SLOTS too large" 144#endif 145 146static unsigned int mac_max_slots = MAC_MAX_SLOTS; 147static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 148SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD | CTLFLAG_LOCKED, 149 &mac_max_slots, 0, ""); 150 151/* 152 * Has the kernel started generating labeled objects yet? All read/write 153 * access to this variable is serialized during the boot process. Following 154 * the end of serialization, we don't update this flag; no locking. 155 */ 156int mac_late = 0; 157 158/* 159 * Flag to indicate whether or not we should allocate label storage for 160 * new mbufs. Since most dynamic policies we currently work with don't 161 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 162 * unless specifically notified of interest. One result of this is 163 * that if a dynamically loaded policy requests mbuf labels, it must 164 * be able to deal with a NULL label being returned on any mbufs that 165 * were already in flight when the policy was loaded. Since the policy 166 * already has to deal with uninitialized labels, this probably won't 167 * be a problem. Note: currently no locking. Will this be a problem? 168 */ 169#if CONFIG_MACF_NET 170unsigned int mac_label_mbufs = 1; 171SYSCTL_UINT(_security_mac, OID_AUTO, label_mbufs, SECURITY_MAC_CTLFLAGS, 172 &mac_label_mbufs, 0, "Label all MBUFs"); 173#endif 174 175 176/* 177 * Flag to indicate whether or not we should allocate label storage for 178 * new vnodes. Since most dynamic policies we currently work with don't 179 * rely on vnode labeling, try to avoid paying the cost of mtag allocation 180 * unless specifically notified of interest. One result of this is 181 * that if a dynamically loaded policy requests vnode labels, it must 182 * be able to deal with a NULL label being returned on any vnodes that 183 * were already in flight when the policy was loaded. Since the policy 184 * already has to deal with uninitialized labels, this probably won't 185 * be a problem. 186 */ 187unsigned int mac_label_vnodes = 0; 188SYSCTL_UINT(_security_mac, OID_AUTO, labelvnodes, SECURITY_MAC_CTLFLAGS, 189 &mac_label_vnodes, 0, "Label all vnodes"); 190 191 192unsigned int mac_mmap_revocation = 0; 193SYSCTL_UINT(_security_mac, OID_AUTO, mmap_revocation, SECURITY_MAC_CTLFLAGS, 194 &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 195 "relabel"); 196 197unsigned int mac_mmap_revocation_via_cow = 0; 198SYSCTL_UINT(_security_mac, OID_AUTO, mmap_revocation_via_cow, SECURITY_MAC_CTLFLAGS, 199 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 200 "copy-on-write semantics, or by removing all write access"); 201 202unsigned int mac_device_enforce = 1; 203SYSCTL_UINT(_security_mac, OID_AUTO, device_enforce, SECURITY_MAC_CTLFLAGS, 204 &mac_device_enforce, 0, "Enforce MAC policy on device operations"); 205 206unsigned int mac_pipe_enforce = 1; 207SYSCTL_UINT(_security_mac, OID_AUTO, pipe_enforce, SECURITY_MAC_CTLFLAGS, 208 &mac_pipe_enforce, 0, "Enforce MAC policy on pipe operations"); 209 210unsigned int mac_posixsem_enforce = 1; 211SYSCTL_UINT(_security_mac, OID_AUTO, posixsem_enforce, SECURITY_MAC_CTLFLAGS, 212 &mac_posixsem_enforce, 0, "Enforce MAC policy on POSIX semaphores"); 213 214unsigned int mac_posixshm_enforce = 1; 215SYSCTL_UINT(_security_mac, OID_AUTO, posixshm_enforce, SECURITY_MAC_CTLFLAGS, 216 &mac_posixshm_enforce, 0, "Enforce MAC policy on Posix Shared Memory"); 217 218unsigned int mac_proc_enforce = 1; 219SYSCTL_UINT(_security_mac, OID_AUTO, proc_enforce, SECURITY_MAC_CTLFLAGS, 220 &mac_proc_enforce, 0, "Enforce MAC policy on process operations"); 221 222unsigned int mac_socket_enforce = 1; 223SYSCTL_UINT(_security_mac, OID_AUTO, socket_enforce, SECURITY_MAC_CTLFLAGS, 224 &mac_socket_enforce, 0, "Enforce MAC policy on socket operations"); 225 226unsigned int mac_system_enforce = 1; 227SYSCTL_UINT(_security_mac, OID_AUTO, system_enforce, SECURITY_MAC_CTLFLAGS, 228 &mac_system_enforce, 0, "Enforce MAC policy on system-wide interfaces"); 229 230unsigned int mac_sysvmsg_enforce = 1; 231SYSCTL_UINT(_security_mac, OID_AUTO, sysvmsg_enforce, SECURITY_MAC_CTLFLAGS, 232 &mac_sysvmsg_enforce, 0, "Enforce MAC policy on System V IPC message queues"); 233 234unsigned int mac_sysvsem_enforce = 1; 235SYSCTL_UINT(_security_mac, OID_AUTO, sysvsem_enforce, SECURITY_MAC_CTLFLAGS, 236 &mac_sysvsem_enforce, 0, "Enforce MAC policy on System V IPC semaphores"); 237 238unsigned int mac_sysvshm_enforce = 1; 239SYSCTL_INT(_security_mac, OID_AUTO, sysvshm_enforce, SECURITY_MAC_CTLFLAGS, 240 &mac_sysvshm_enforce, 0, "Enforce MAC policy on System V Shared Memory"); 241 242unsigned int mac_vm_enforce = 1; 243SYSCTL_INT(_security_mac, OID_AUTO, vm_enforce, SECURITY_MAC_CTLFLAGS, 244 &mac_vm_enforce, 0, "Enforce MAC policy on VM operations"); 245 246unsigned int mac_vnode_enforce = 1; 247SYSCTL_UINT(_security_mac, OID_AUTO, vnode_enforce, SECURITY_MAC_CTLFLAGS, 248 &mac_vnode_enforce, 0, "Enforce MAC policy on vnode operations"); 249 250#if CONFIG_AUDIT 251/* 252 * mac_audit_data_zone is the zone used for data pushed into the audit 253 * record by policies. Using a zone simplifies memory management of this 254 * data, and allows tracking of the amount of data in flight. 255 */ 256extern zone_t mac_audit_data_zone; 257#endif 258 259/* 260 * mac_policy_list holds the list of policy modules. Modules with a 261 * handle lower than staticmax are considered "static" and cannot be 262 * unloaded. Such policies can be invoked without holding the busy count. 263 * 264 * Modules with a handle at or above the staticmax high water mark 265 * are considered to be "dynamic" policies. A busy count is maintained 266 * for the list, stored in mac_policy_busy. The busy count is protected 267 * by mac_policy_mtx; the list may be modified only while the busy 268 * count is 0, requiring that the lock be held to prevent new references 269 * to the list from being acquired. For almost all operations, 270 * incrementing the busy count is sufficient to guarantee consistency, 271 * as the list cannot be modified while the busy count is elevated. 272 * For a few special operations involving a change to the list of 273 * active policies, the mtx itself must be held. 274 */ 275static lck_mtx_t *mac_policy_mtx; 276 277/* 278 * Policy list array allocation chunk size. Trying to set this so that we 279 * allocate a page at a time. 280 */ 281#define MAC_POLICY_LIST_CHUNKSIZE 512 282 283static int mac_policy_busy; 284 285mac_policy_list_t mac_policy_list; 286 287/* 288 * mac_label_element_list holds the master list of label namespaces for 289 * all the policies. When a policy is loaded, each of it's label namespace 290 * elements is added to the master list if not already present. When a 291 * policy is unloaded, the namespace elements are removed if no other 292 * policy is interested in that namespace element. 293 */ 294struct mac_label_element_list_t mac_label_element_list; 295struct mac_label_element_list_t mac_static_label_element_list; 296 297static __inline void 298mac_policy_grab_exclusive(void) 299{ 300 lck_mtx_lock(mac_policy_mtx); 301 while (mac_policy_busy != 0) { 302 lck_mtx_sleep(mac_policy_mtx, LCK_SLEEP_UNLOCK, 303 (event_t)&mac_policy_busy, THREAD_UNINT); 304 lck_mtx_lock(mac_policy_mtx); 305 } 306} 307 308static __inline void 309mac_policy_release_exclusive(void) 310{ 311 312 KASSERT(mac_policy_busy == 0, 313 ("mac_policy_release_exclusive(): not exclusive")); 314 lck_mtx_unlock(mac_policy_mtx); 315 thread_wakeup((event_t) &mac_policy_busy); 316} 317 318void 319mac_policy_list_busy(void) 320{ 321 lck_mtx_lock(mac_policy_mtx); 322 mac_policy_busy++; 323 lck_mtx_unlock(mac_policy_mtx); 324} 325 326int 327mac_policy_list_conditional_busy(void) 328{ 329 int ret; 330 331 if (mac_policy_list.numloaded <= mac_policy_list.staticmax) 332 return(0); 333 334 lck_mtx_lock(mac_policy_mtx); 335 if (mac_policy_list.numloaded > mac_policy_list.staticmax) { 336 mac_policy_busy++; 337 ret = 1; 338 } else 339 ret = 0; 340 lck_mtx_unlock(mac_policy_mtx); 341 return (ret); 342} 343 344void 345mac_policy_list_unbusy(void) 346{ 347 lck_mtx_lock(mac_policy_mtx); 348 mac_policy_busy--; 349 KASSERT(mac_policy_busy >= 0, ("MAC_POLICY_LIST_LOCK")); 350 if (mac_policy_busy == 0) 351 thread_wakeup(&mac_policy_busy); 352 lck_mtx_unlock(mac_policy_mtx); 353} 354 355/* 356 * Early pre-malloc MAC initialization, including appropriate SMP locks. 357 */ 358void 359mac_policy_init(void) 360{ 361 lck_grp_attr_t *mac_lck_grp_attr; 362 lck_attr_t *mac_lck_attr; 363 lck_grp_t *mac_lck_grp; 364 365 mac_policy_list.numloaded = 0; 366 mac_policy_list.max = MAC_POLICY_LIST_CHUNKSIZE; 367 mac_policy_list.maxindex = 0; 368 mac_policy_list.staticmax = 0; 369 mac_policy_list.freehint = 0; 370 mac_policy_list.chunks = 1; 371 372 mac_policy_list.entries = kalloc(sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE); 373 bzero(mac_policy_list.entries, sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE); 374 375 LIST_INIT(&mac_label_element_list); 376 LIST_INIT(&mac_static_label_element_list); 377 378 mac_lck_grp_attr = lck_grp_attr_alloc_init(); 379 lck_grp_attr_setstat(mac_lck_grp_attr); 380 mac_lck_grp = lck_grp_alloc_init("MAC lock", mac_lck_grp_attr); 381 mac_lck_attr = lck_attr_alloc_init(); 382 lck_attr_setdefault(mac_lck_attr); 383 mac_policy_mtx = lck_mtx_alloc_init(mac_lck_grp, mac_lck_attr); 384 lck_attr_free(mac_lck_attr); 385 lck_grp_attr_free(mac_lck_grp_attr); 386 lck_grp_free(mac_lck_grp); 387 388 mac_labelzone_init(); 389} 390 391/* Function pointer set up for loading security extensions. 392 * It is set to an actual function after OSlibkernInit() 393 * has been called, and is set back to 0 by OSKextRemoveKextBootstrap() 394 * after bsd_init(). 395 */ 396void (*load_security_extensions_function)(void) = 0; 397 398/* 399 * Init after early Mach startup, but before BSD 400 */ 401void 402mac_policy_initmach(void) 403{ 404 405 /* 406 * For the purposes of modules that want to know if they were 407 * loaded "early", set the mac_late flag once we've processed 408 * modules either linked into the kernel, or loaded before the 409 * kernel startup. 410 */ 411 412 if (load_security_extensions_function) { 413 load_security_extensions_function(); 414 } 415 mac_late = 1; 416} 417 418/* 419 * BSD startup. 420 */ 421void 422mac_policy_initbsd(void) 423{ 424 struct mac_policy_conf *mpc; 425 u_int i; 426 427#if CONFIG_AUDIT 428 mac_audit_data_zone = zinit(MAC_AUDIT_DATA_LIMIT, 429 AQ_HIWATER * MAC_AUDIT_DATA_LIMIT, 430 8192, "mac_audit_data_zone"); 431#endif 432 433 printf("MAC Framework successfully initialized\n"); 434 435 /* Call bsd init functions of already loaded policies */ 436 437 /* 438 * Using the exclusive lock means no other framework entry 439 * points can proceed while initializations are running. 440 * This may not be necessary. 441 */ 442 mac_policy_grab_exclusive(); 443 444 for (i = 0; i <= mac_policy_list.maxindex; i++) { 445 mpc = mac_get_mpc(i); 446 if ((mpc != NULL) && (mpc->mpc_ops->mpo_policy_initbsd != NULL)) 447 (*(mpc->mpc_ops->mpo_policy_initbsd))(mpc); 448 } 449 450 mac_policy_release_exclusive(); 451} 452 453/* 454 * After a policy has been loaded, add the label namespaces managed by the 455 * policy to either the static or non-static label namespace list. 456 * A namespace is added to the the list only if it is not already on one of 457 * the lists. 458 */ 459void 460mac_policy_addto_labellist(mac_policy_handle_t handle, int static_entry) 461{ 462 struct mac_label_listener **new_mlls; 463 struct mac_label_element *mle, **new_mles; 464 struct mac_label_element_list_t *list; 465 struct mac_policy_conf *mpc; 466 const char *name, *name2; 467 u_int idx, mle_free, mll_free; 468 469 mpc = mac_get_mpc(handle); 470 471 if (mpc->mpc_labelnames == NULL) 472 return; 473 474 if (mpc->mpc_labelname_count == 0) 475 return; 476 477 if (static_entry) 478 list = &mac_static_label_element_list; 479 else 480 list = &mac_label_element_list; 481 482 /* 483 * Before we grab the policy list lock, allocate enough memory 484 * to contain the potential new elements so we don't have to 485 * give up the lock, or allocate with the lock held. 486 */ 487 MALLOC(new_mles, struct mac_label_element **, 488 sizeof(struct mac_label_element *) * 489 mpc->mpc_labelname_count, M_MACTEMP, M_WAITOK | M_ZERO); 490 for (idx = 0; idx < mpc->mpc_labelname_count; idx++) 491 MALLOC(new_mles[idx], struct mac_label_element *, 492 sizeof(struct mac_label_element), 493 M_MACTEMP, M_WAITOK); 494 mle_free = 0; 495 MALLOC(new_mlls, struct mac_label_listener **, 496 sizeof(struct mac_label_listener *) * 497 mpc->mpc_labelname_count, M_MACTEMP, M_WAITOK); 498 for (idx = 0; idx < mpc->mpc_labelname_count; idx++) 499 MALLOC(new_mlls[idx], struct mac_label_listener *, 500 sizeof(struct mac_label_listener), M_MACTEMP, M_WAITOK); 501 mll_free = 0; 502 503 if (mac_late) 504 mac_policy_grab_exclusive(); 505 for (idx = 0; idx < mpc->mpc_labelname_count; idx++) { 506 507 if (*(name = mpc->mpc_labelnames[idx]) == '?') 508 name++; 509 /* 510 * Check both label element lists and add to the 511 * appropriate list only if not already on a list. 512 */ 513 LIST_FOREACH(mle, &mac_static_label_element_list, mle_list) { 514 if (*(name2 = mle->mle_name) == '?') 515 name2++; 516 if (strcmp(name, name2) == 0) 517 break; 518 } 519 if (mle == NULL) { 520 LIST_FOREACH(mle, &mac_label_element_list, mle_list) { 521 if (*(name2 = mle->mle_name) == '?') 522 name2++; 523 if (strcmp(name, name2) == 0) 524 break; 525 } 526 } 527 if (mle == NULL) { 528 mle = new_mles[mle_free]; 529 strlcpy(mle->mle_name, mpc->mpc_labelnames[idx], 530 MAC_MAX_LABEL_ELEMENT_NAME); 531 LIST_INIT(&mle->mle_listeners); 532 LIST_INSERT_HEAD(list, mle, mle_list); 533 mle_free++; 534 } 535 /* Add policy handler as a listener. */ 536 new_mlls[mll_free]->mll_handle = handle; 537 LIST_INSERT_HEAD(&mle->mle_listeners, new_mlls[mll_free], 538 mll_list); 539 mll_free++; 540 } 541 if (mac_late) 542 mac_policy_release_exclusive(); 543 544 /* Free up any unused label elements and listeners */ 545 for (idx = mle_free; idx < mpc->mpc_labelname_count; idx++) 546 FREE(new_mles[idx], M_MACTEMP); 547 FREE(new_mles, M_MACTEMP); 548 for (idx = mll_free; idx < mpc->mpc_labelname_count; idx++) 549 FREE(new_mlls[idx], M_MACTEMP); 550 FREE(new_mlls, M_MACTEMP); 551} 552 553/* 554 * After a policy has been unloaded, remove the label namespaces that the 555 * the policy manages from the non-static list of namespaces. 556 * The removal only takes place when no other policy is interested in the 557 * namespace. 558 * 559 * Must be called with the policy exclusive lock held. 560 */ 561void 562mac_policy_removefrom_labellist(mac_policy_handle_t handle) 563{ 564 struct mac_label_listener *mll; 565 struct mac_label_element *mle; 566 struct mac_policy_conf *mpc; 567 568 mpc = mac_get_mpc(handle); 569 570 if (mpc->mpc_labelnames == NULL) 571 return; 572 573 if (mpc->mpc_labelname_count == 0) 574 return; 575 576 /* 577 * Unregister policy as being interested in any label 578 * namespaces. If no other policy is listening, remove 579 * that label element from the list. Note that we only 580 * have to worry about the non-static list. 581 */ 582 LIST_FOREACH(mle, &mac_label_element_list, mle_list) { 583 LIST_FOREACH(mll, &mle->mle_listeners, mll_list) { 584 if (mll->mll_handle == handle) { 585 LIST_REMOVE(mll, mll_list); 586 FREE(mll, M_MACTEMP); 587 if (LIST_EMPTY(&mle->mle_listeners)) { 588 LIST_REMOVE(mle, mle_list); 589 FREE(mle, M_MACTEMP); 590 } 591 return; 592 } 593 } 594 } 595} 596 597/* 598 * After the policy list has changed, walk the list to update any global 599 * flags. 600 */ 601static void 602mac_policy_updateflags(void) 603{ 604} 605 606static __inline void 607mac_policy_fixup_mmd_list(struct mac_module_data *new) 608{ 609 struct mac_module_data *old; 610 struct mac_module_data_element *ele, *aele; 611 struct mac_module_data_list *arr, *dict; 612 unsigned int i, j, k; 613 614 old = new->base_addr; 615 DPRINTF(("fixup_mmd: old %p new %p\n", old, new)); 616 for (i = 0; i < new->count; i++) { 617 ele = &(new->data[i]); 618 DPRINTF(("fixup_mmd: ele %p\n", ele)); 619 DPRINTF((" key %p value %p\n", ele->key, ele->value)); 620 mmd_fixup_ele(old, new, ele); /* Fix up key/value ptrs. */ 621 DPRINTF((" key %p value %p\n", ele->key, ele->value)); 622 if (ele->value_type == MAC_DATA_TYPE_ARRAY) { 623 arr = (struct mac_module_data_list *)ele->value; 624 DPRINTF(("fixup_mmd: array @%p\n", arr)); 625 for (j = 0; j < arr->count; j++) { 626 aele = &(arr->list[j]); 627 DPRINTF(("fixup_mmd: aele %p\n", aele)); 628 DPRINTF((" key %p value %p\n", aele->key, aele->value)); 629 mmd_fixup_ele(old, new, aele); 630 DPRINTF((" key %p value %p\n", aele->key, aele->value)); 631 if (arr->type == MAC_DATA_TYPE_DICT) { 632 dict = (struct mac_module_data_list *)aele->value; 633 DPRINTF(("fixup_mmd: dict @%p\n", dict)); 634 for (k = 0; k < dict->count; k++) 635 mmd_fixup_ele(old, new, 636 &(dict->list[k])); 637 } 638 } 639 } 640 } 641 new->base_addr = new; 642} 643 644int 645mac_policy_register(struct mac_policy_conf *mpc, mac_policy_handle_t *handlep, 646 void *xd) 647{ 648 struct mac_policy_list_element *tmac_policy_list_element; 649 int error, slot, static_entry = 0; 650 u_int i; 651 652 /* 653 * Some preliminary checks to make sure the policy's conf structure 654 * contains the required fields. 655 */ 656 if (mpc->mpc_name == NULL) 657 panic("policy's name is not set\n"); 658 659 if (mpc->mpc_fullname == NULL) 660 panic("policy's full name is not set\n"); 661 662 if (mpc->mpc_labelname_count > MAC_MAX_MANAGED_NAMESPACES) 663 panic("policy's managed label namespaces exceeds maximum\n"); 664 665 if (mpc->mpc_ops == NULL) 666 panic("policy's OPs field is NULL\n"); 667 668 error = 0; 669 670 if (mac_late) { 671 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE) { 672 printf("Module %s does not support late loading.\n", 673 mpc->mpc_name); 674 return (EPERM); 675 } 676 mac_policy_grab_exclusive(); 677 } 678 679 if (mac_policy_list.numloaded >= mac_policy_list.max) { 680 /* allocate new policy list array, zero new chunk */ 681 tmac_policy_list_element = 682 kalloc((sizeof(struct mac_policy_list_element) * 683 MAC_POLICY_LIST_CHUNKSIZE) * (mac_policy_list.chunks + 1)); 684 bzero(&tmac_policy_list_element[mac_policy_list.max], 685 sizeof(struct mac_policy_list_element) * 686 MAC_POLICY_LIST_CHUNKSIZE); 687 688 /* copy old entries into new list */ 689 memcpy(tmac_policy_list_element, mac_policy_list.entries, 690 sizeof(struct mac_policy_list_element) * 691 MAC_POLICY_LIST_CHUNKSIZE * mac_policy_list.chunks); 692 693 /* free old array */ 694 kfree(mac_policy_list.entries, 695 sizeof(struct mac_policy_list_element) * 696 MAC_POLICY_LIST_CHUNKSIZE * mac_policy_list.chunks); 697 698 mac_policy_list.entries = tmac_policy_list_element; 699 700 /* Update maximums, etc */ 701 mac_policy_list.max += MAC_POLICY_LIST_CHUNKSIZE; 702 mac_policy_list.chunks++; 703 } 704 705 /* Check for policy with same name already loaded */ 706 for (i = 0; i <= mac_policy_list.maxindex; i++) { 707 if (mac_policy_list.entries[i].mpc == NULL) 708 continue; 709 710 if (strcmp(mac_policy_list.entries[i].mpc->mpc_name, 711 mpc->mpc_name) == 0) { 712 error = EEXIST; 713 goto out; 714 } 715 } 716 717 if (mpc->mpc_field_off != NULL) { 718 slot = ffs(mac_slot_offsets_free); 719 if (slot == 0) { 720 error = ENOMEM; 721 goto out; 722 } 723 slot--; 724 mac_slot_offsets_free &= ~(1 << slot); 725 *mpc->mpc_field_off = slot; 726 } 727 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 728 729 if (xd) { 730 struct mac_module_data *mmd = xd; /* module data from plist */ 731 732 /* Make a copy of the data. */ 733 mpc->mpc_data = (void *)kalloc(mmd->size); 734 if (mpc->mpc_data != NULL) { 735 memcpy(mpc->mpc_data, mmd, mmd->size); 736 737 /* Fix up pointers after copy. */ 738 mac_policy_fixup_mmd_list(mpc->mpc_data); 739 } 740 } 741 742 /* Find the first free handle in the list (using our hint). */ 743 for (i = mac_policy_list.freehint; i < mac_policy_list.max; i++) { 744 if (mac_policy_list.entries[i].mpc == NULL) { 745 *handlep = i; 746 mac_policy_list.freehint = ++i; 747 break; 748 } 749 } 750 751 /* 752 * If we are loading a MAC module before the framework has 753 * finished initializing or the module is not unloadable and 754 * we can place its handle adjacent to the last static entry, 755 * bump the static policy high water mark. 756 * Static policies can get by with weaker locking requirements. 757 */ 758 if (!mac_late || 759 ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0 && 760 *handlep == mac_policy_list.staticmax)) { 761 static_entry = 1; 762 mac_policy_list.staticmax++; 763 } 764 765 mac_policy_list.entries[*handlep].mpc = mpc; 766 767 /* Update counters, etc */ 768 if (*handlep > mac_policy_list.maxindex) 769 mac_policy_list.maxindex = *handlep; 770 mac_policy_list.numloaded++; 771 772 /* Per-policy initialization. */ 773 printf ("calling mpo_policy_init for %s\n", mpc->mpc_name); 774 if (mpc->mpc_ops->mpo_policy_init != NULL) 775 (*(mpc->mpc_ops->mpo_policy_init))(mpc); 776 777 if (mac_late && mpc->mpc_ops->mpo_policy_initbsd != NULL) { 778 printf ("calling mpo_policy_initbsd for %s\n", mpc->mpc_name); 779 (*(mpc->mpc_ops->mpo_policy_initbsd))(mpc); 780 } 781 782 mac_policy_updateflags(); 783 784 if (mac_late) 785 mac_policy_release_exclusive(); 786 787 mac_policy_addto_labellist(*handlep, static_entry); 788 789 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 790 mpc->mpc_name); 791 792 return (0); 793 794out: 795 if (mac_late) 796 mac_policy_release_exclusive(); 797 798 return (error); 799} 800 801int 802mac_policy_unregister(mac_policy_handle_t handle) 803{ 804 struct mac_policy_conf *mpc; 805 806 /* 807 * If we fail the load, we may get a request to unload. Check 808 * to see if we did the run-time registration, and if not, 809 * silently succeed. 810 */ 811 mac_policy_grab_exclusive(); 812 mpc = mac_get_mpc(handle); 813 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 814 mac_policy_release_exclusive(); 815 return (0); 816 } 817 818#if 0 819 /* 820 * Don't allow unloading modules with private data. 821 */ 822 if (mpc->mpc_field_off != NULL) { 823 MAC_POLICY_LIST_UNLOCK(); 824 return (EBUSY); 825 } 826#endif 827 /* 828 * Only allow the unload to proceed if the module is unloadable 829 * by its own definition. 830 */ 831 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 832 mac_policy_release_exclusive(); 833 return (EBUSY); 834 } 835 836 mac_policy_removefrom_labellist(handle); 837 838 mac_get_mpc(handle) = NULL; 839 if (handle < mac_policy_list.freehint && 840 handle >= mac_policy_list.staticmax) 841 mac_policy_list.freehint = handle; 842 843 if (handle == mac_policy_list.maxindex) 844 mac_policy_list.maxindex--; 845 846 mac_policy_list.numloaded--; 847 if (mpc->mpc_field_off != NULL) { 848 mac_slot_offsets_free |= (1 << *mpc->mpc_field_off); 849 } 850 851 if (mpc->mpc_ops->mpo_policy_destroy != NULL) 852 (*(mpc->mpc_ops->mpo_policy_destroy))(mpc); 853 854 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 855 mac_policy_updateflags(); 856 857 mac_policy_release_exclusive(); 858 859 if (mpc->mpc_data) { 860 struct mac_module_data *mmd = mpc->mpc_data; 861 kfree(mmd, mmd->size); 862 mpc->mpc_data = NULL; 863 } 864 865 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 866 mpc->mpc_name); 867 868 return (0); 869} 870 871/* 872 * Define an error value precedence, and given two arguments, selects the 873 * value with the higher precedence. 874 */ 875int 876mac_error_select(int error1, int error2) 877{ 878 879 /* Certain decision-making errors take top priority. */ 880 if (error1 == EDEADLK || error2 == EDEADLK) 881 return (EDEADLK); 882 883 /* Invalid arguments should be reported where possible. */ 884 if (error1 == EINVAL || error2 == EINVAL) 885 return (EINVAL); 886 887 /* Precedence goes to "visibility", with both process and file. */ 888 if (error1 == ESRCH || error2 == ESRCH) 889 return (ESRCH); 890 891 if (error1 == ENOENT || error2 == ENOENT) 892 return (ENOENT); 893 894 /* Precedence goes to DAC/MAC protections. */ 895 if (error1 == EACCES || error2 == EACCES) 896 return (EACCES); 897 898 /* Precedence goes to privilege. */ 899 if (error1 == EPERM || error2 == EPERM) 900 return (EPERM); 901 902 /* Precedence goes to error over success; otherwise, arbitrary. */ 903 if (error1 != 0) 904 return (error1); 905 return (error2); 906} 907 908void 909mac_label_init(struct label *label) 910{ 911 912 bzero(label, sizeof(*label)); 913 label->l_flags = MAC_FLAG_INITIALIZED; 914} 915 916void 917mac_label_destroy(struct label *label) 918{ 919 920 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 921 ("destroying uninitialized label")); 922 923 bzero(label, sizeof(*label)); 924 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 925} 926 927int 928mac_check_structmac_consistent(struct user_mac *mac) 929{ 930 931 if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN || mac->m_buflen == 0) 932 return (EINVAL); 933 934 return (0); 935} 936 937/* 938 * Get the external forms of labels from all policies, for a single 939 * label namespace or "*" for all namespaces. Returns ENOENT if no policy 940 * is registered for the namespace, unless the namespace begins with a '?'. 941 */ 942static int 943mac_label_externalize(size_t mpo_externalize_off, struct label *label, 944 const char *element, struct sbuf *sb) 945{ 946 struct mac_policy_conf *mpc; 947 struct mac_label_listener *mll; 948 struct mac_label_element *mle; 949 struct mac_label_element_list_t *element_list; 950 const char *name; 951 int (*mpo_externalize)(struct label *, char *, struct sbuf *); 952 int all_labels = 0, ignorenotfound = 0, error = 0, busy = FALSE; 953 unsigned int count = 0; 954 955 if (element[0] == '?') { 956 element++; 957 ignorenotfound = 1; 958 } else if (element[0] == '*' && element[1] == '\0') 959 all_labels = 1; 960 961 element_list = &mac_static_label_element_list; 962element_loop: 963 LIST_FOREACH(mle, element_list, mle_list) { 964 name = mle->mle_name; 965 if (all_labels) { 966 if (*name == '?') 967 continue; 968 } else { 969 if (*name == '?') 970 name++; 971 if (strcmp(name, element) != 0) 972 continue; 973 } 974 LIST_FOREACH(mll, &mle->mle_listeners, mll_list) { 975 mpc = mac_policy_list.entries[mll->mll_handle].mpc; 976 if (mpc == NULL) 977 continue; 978 mpo_externalize = *(typeof(mpo_externalize) *) 979 ((char *)mpc->mpc_ops + mpo_externalize_off); 980 if (mpo_externalize == NULL) 981 continue; 982 error = sbuf_printf(sb, "%s/", name); 983 if (error) 984 goto done; 985 error = mpo_externalize(label, mle->mle_name, sb); 986 if (error) { 987 if (error != ENOENT) 988 goto done; 989 /* 990 * If a policy doesn't have a label to 991 * externalize it returns ENOENT. This 992 * may occur for policies that support 993 * multiple label elements for some 994 * (but not all) object types. 995 */ 996 sbuf_setpos(sb, sbuf_len(sb) - 997 (strlen(name) + 1)); 998 error = 0; 999 continue; 1000 } 1001 error = sbuf_putc(sb, ','); 1002 if (error) 1003 goto done; 1004 count++; 1005 } 1006 } 1007 /* If there are dynamic policies present, check their elements too. */ 1008 if (!busy && mac_policy_list_conditional_busy() == 1) { 1009 element_list = &mac_label_element_list; 1010 busy = TRUE; 1011 goto element_loop; 1012 } 1013done: 1014 if (busy) 1015 mac_policy_list_unbusy(); 1016 if (!error && count == 0) { 1017 if (!all_labels && !ignorenotfound) 1018 error = ENOENT; /* XXX: ENOLABEL? */ 1019 } 1020 return (error); 1021} 1022 1023/* 1024 * Get the external forms of labels from all policies, for all label 1025 * namespaces contained in a list. 1026 * 1027 * XXX This may be leaking an sbuf. 1028 */ 1029int 1030mac_externalize(size_t mpo_externalize_off, struct label *label, 1031 const char *elementlist, char *outbuf, size_t outbuflen) 1032{ 1033 char *element; 1034 char *scratch_base; 1035 char *scratch; 1036 struct sbuf sb; 1037 int error = 0, len; 1038 1039 /* allocate a scratch buffer the size of the string */ 1040 MALLOC(scratch_base, char *, strlen(elementlist)+1, M_MACTEMP, M_WAITOK); 1041 if (scratch_base == NULL) { 1042 error = ENOMEM; 1043 goto out; 1044 } 1045 1046 /* copy the elementlist to the scratch buffer */ 1047 strlcpy(scratch_base, elementlist, strlen(elementlist)+1); 1048 1049 /* 1050 * set up a temporary pointer that can be used to iterate the 1051 * scratch buffer without losing the allocation address 1052 */ 1053 scratch = scratch_base; 1054 1055 /* get an sbuf */ 1056 if (sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN) == NULL) { 1057 /* could not allocate interior buffer */ 1058 error = ENOMEM; 1059 goto out; 1060 } 1061 /* iterate the scratch buffer; NOTE: buffer contents modified! */ 1062 while ((element = strsep(&scratch, ",")) != NULL) { 1063 error = mac_label_externalize(mpo_externalize_off, label, 1064 element, &sb); 1065 if (error) 1066 break; 1067 } 1068 if ((len = sbuf_len(&sb)) > 0) 1069 sbuf_setpos(&sb, len - 1); /* trim trailing comma */ 1070 sbuf_finish(&sb); 1071 1072out: 1073 if (scratch_base != NULL) 1074 FREE(scratch_base, M_MACTEMP); 1075 1076 return (error); 1077} 1078 1079/* 1080 * Have all policies set the internal form of a label, for a single 1081 * label namespace. 1082 */ 1083static int 1084mac_label_internalize(size_t mpo_internalize_off, struct label *label, 1085 char *element_name, char *element_data) 1086{ 1087 struct mac_policy_conf *mpc; 1088 struct mac_label_listener *mll; 1089 struct mac_label_element *mle; 1090 struct mac_label_element_list_t *element_list; 1091 int (*mpo_internalize)(struct label *, char *, char *); 1092 int error = 0, busy = FALSE; 1093 unsigned int count = 0; 1094 const char *name; 1095 1096 element_list = &mac_static_label_element_list; 1097element_loop: 1098 LIST_FOREACH(mle, element_list, mle_list) { 1099 if (*(name = mle->mle_name) == '?') 1100 name++; 1101 if (strcmp(element_name, name) != 0) 1102 continue; 1103 LIST_FOREACH(mll, &mle->mle_listeners, mll_list) { 1104 mpc = mac_policy_list.entries[mll->mll_handle].mpc; 1105 if (mpc == NULL) 1106 continue; 1107 mpo_internalize = *(typeof(mpo_internalize) *) 1108 ((char *)mpc->mpc_ops + mpo_internalize_off); 1109 if (mpo_internalize == NULL) 1110 continue; 1111 error = mpo_internalize(label, element_name, 1112 element_data); 1113 if (error) 1114 goto done; 1115 count++; 1116 } 1117 } 1118 /* If there are dynamic policies present, check their elements too. */ 1119 if (!busy && mac_policy_list_conditional_busy() == 1) { 1120 element_list = &mac_label_element_list; 1121 busy = TRUE; 1122 goto element_loop; 1123 } 1124done: 1125 if (busy) 1126 mac_policy_list_unbusy(); 1127 if (!error && count == 0) 1128 error = ENOPOLICY; 1129 return (error); 1130} 1131 1132int 1133mac_internalize(size_t mpo_internalize_off, struct label *label, 1134 char *textlabels) 1135{ 1136 char *element_name, *element_data; 1137 int error = 0; 1138 1139 while (!error && (element_name = strsep(&textlabels, ",")) != NULL) { 1140 element_data = strchr(element_name, '/'); 1141 if (element_data == NULL) { 1142 error = EINVAL; 1143 break; 1144 } 1145 *element_data++ = '\0'; 1146 error = mac_label_internalize(mpo_internalize_off, label, 1147 element_name, element_data); 1148 } 1149 return (error); 1150} 1151 1152/* system calls */ 1153 1154int 1155__mac_get_pid(struct proc *p, struct __mac_get_pid_args *uap, int *ret __unused) 1156{ 1157 char *elements, *buffer; 1158 struct user_mac mac; 1159 struct proc *tproc; 1160 struct ucred *tcred; 1161 int error; 1162 size_t ulen; 1163 1164 AUDIT_ARG(pid, uap->pid); 1165 if (IS_64BIT_PROCESS(p)) { 1166 struct user64_mac mac64; 1167 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1168 mac.m_buflen = mac64.m_buflen; 1169 mac.m_string = mac64.m_string; 1170 } else { 1171 struct user32_mac mac32; 1172 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1173 mac.m_buflen = mac32.m_buflen; 1174 mac.m_string = mac32.m_string; 1175 } 1176 if (error) 1177 return (error); 1178 1179 error = mac_check_structmac_consistent(&mac); 1180 if (error) 1181 return (error); 1182 1183 tproc = proc_find(uap->pid); 1184 if (tproc == NULL) 1185 return (ESRCH); 1186 tcred = kauth_cred_proc_ref(tproc); 1187 proc_rele(tproc); 1188 1189 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1190 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen); 1191 if (error) { 1192 FREE(elements, M_MACTEMP); 1193 kauth_cred_unref(&tcred); 1194 return (error); 1195 } 1196 AUDIT_ARG(mac_string, elements); 1197 1198 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 1199 error = mac_cred_label_externalize(tcred->cr_label, elements, 1200 buffer, mac.m_buflen, M_WAITOK); 1201 if (error == 0) 1202 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 1203 1204 FREE(buffer, M_MACTEMP); 1205 FREE(elements, M_MACTEMP); 1206 kauth_cred_unref(&tcred); 1207 return (error); 1208} 1209 1210int 1211__mac_get_proc(proc_t p, struct __mac_get_proc_args *uap, int *ret __unused) 1212{ 1213 char *elements, *buffer; 1214 struct user_mac mac; 1215 kauth_cred_t cr; 1216 int error; 1217 size_t ulen; 1218 1219 if (IS_64BIT_PROCESS(p)) { 1220 struct user64_mac mac64; 1221 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1222 mac.m_buflen = mac64.m_buflen; 1223 mac.m_string = mac64.m_string; 1224 } else { 1225 struct user32_mac mac32; 1226 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1227 mac.m_buflen = mac32.m_buflen; 1228 mac.m_string = mac32.m_string; 1229 } 1230 if (error) 1231 return (error); 1232 1233 error = mac_check_structmac_consistent(&mac); 1234 if (error) 1235 return (error); 1236 1237 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1238 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen); 1239 if (error) { 1240 FREE(elements, M_MACTEMP); 1241 return (error); 1242 } 1243 AUDIT_ARG(mac_string, elements); 1244 1245 cr = kauth_cred_proc_ref(p); 1246 1247 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 1248 error = mac_cred_label_externalize(cr->cr_label, 1249 elements, buffer, mac.m_buflen, M_WAITOK); 1250 if (error == 0) 1251 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 1252 1253 FREE(buffer, M_MACTEMP); 1254 FREE(elements, M_MACTEMP); 1255 kauth_cred_unref(&cr); 1256 return (error); 1257} 1258 1259int 1260__mac_set_proc(proc_t p, struct __mac_set_proc_args *uap, int *ret __unused) 1261{ 1262 struct label *intlabel; 1263 struct user_mac mac; 1264 char *buffer; 1265 int error; 1266 size_t ulen; 1267 1268 if (IS_64BIT_PROCESS(p)) { 1269 struct user64_mac mac64; 1270 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1271 mac.m_buflen = mac64.m_buflen; 1272 mac.m_string = mac64.m_string; 1273 } else { 1274 struct user32_mac mac32; 1275 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1276 mac.m_buflen = mac32.m_buflen; 1277 mac.m_string = mac32.m_string; 1278 } 1279 if (error) 1280 return (error); 1281 1282 error = mac_check_structmac_consistent(&mac); 1283 if (error) 1284 return (error); 1285 1286 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1287 error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen); 1288 if (error) { 1289 FREE(buffer, M_MACTEMP); 1290 return (error); 1291 } 1292 AUDIT_ARG(mac_string, buffer); 1293 1294 intlabel = mac_cred_label_alloc(); 1295 error = mac_cred_label_internalize(intlabel, buffer); 1296 FREE(buffer, M_MACTEMP); 1297 if (error) 1298 goto out; 1299 1300 error = mac_cred_check_label_update(kauth_cred_get(), intlabel); 1301 if (error) { 1302 goto out; 1303 } 1304 1305 error = kauth_proc_label_update(p, intlabel); 1306 if (error) 1307 goto out; 1308 1309out: 1310 mac_cred_label_free(intlabel); 1311 return (error); 1312} 1313 1314#if CONFIG_LCTX 1315/* 1316 * __mac_get_lcid: 1317 * Get login context ID. A login context associates a BSD process 1318 * with an instance of a user. For more information see getlcid(2) man page. 1319 * 1320 * Parameters: p Process requesting the get 1321 * uap User argument descriptor (see below) 1322 * ret (ignored) 1323 * 1324 * Indirect: uap->lcid login context ID to search 1325 * uap->mac_p.m_buflen MAC info buffer size 1326 * uap->mac_p.m_string MAC info user address 1327 * 1328 * Returns: 0 Success 1329 * !0 Not success 1330 */ 1331int 1332__mac_get_lcid(proc_t p, struct __mac_get_lcid_args *uap, int *ret __unused) 1333{ 1334 char *elements, *buffer; 1335 struct user_mac mac; 1336 struct lctx *l; 1337 int error; 1338 size_t ulen; 1339 1340 AUDIT_ARG(value32, uap->lcid); 1341 if (IS_64BIT_PROCESS(p)) { 1342 struct user64_mac mac64; 1343 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1344 mac.m_buflen = mac64.m_buflen; 1345 mac.m_string = mac64.m_string; 1346 } else { 1347 struct user32_mac mac32; 1348 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1349 mac.m_buflen = mac32.m_buflen; 1350 mac.m_string = mac32.m_string; 1351 } 1352 1353 if (error) 1354 return (error); 1355 1356 error = mac_check_structmac_consistent(&mac); 1357 if (error) 1358 return (error); 1359 1360 l = lcfind(uap->lcid); 1361 if (l == NULL) 1362 return (ESRCH); 1363 1364 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1365 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen); 1366 if (error) { 1367 LCTX_UNLOCK(l); 1368 FREE(elements, M_MACTEMP); 1369 return (error); 1370 } 1371 AUDIT_ARG(mac_string, elements); 1372 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1373 error = mac_lctx_label_externalize(l->lc_label, elements, 1374 buffer, mac.m_buflen); 1375 if (error == 0) 1376 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 1377 1378 LCTX_UNLOCK(l); 1379 FREE(buffer, M_MACTEMP); 1380 FREE(elements, M_MACTEMP); 1381 return (error); 1382} 1383 1384/* 1385 * __mac_get_lctx: 1386 * Get login context label. A login context associates a BSD process 1387 * associated with an instance of a user. 1388 * 1389 * Parameters: p Process requesting the get 1390 * uap User argument descriptor (see below) 1391 * ret (ignored) 1392 * 1393 * Indirect: uap->lcid login context ID to search 1394 * uap->mac_p MAC info 1395 * 1396 * Returns: 0 Success 1397 * !0 Not success 1398 * 1399 */ 1400int 1401__mac_get_lctx(proc_t p, struct __mac_get_lctx_args *uap, int *ret __unused) 1402{ 1403 char *elements, *buffer; 1404 struct user_mac mac; 1405 int error; 1406 size_t ulen; 1407 1408 if (IS_64BIT_PROCESS(p)) { 1409 struct user64_mac mac64; 1410 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1411 mac.m_buflen = mac64.m_buflen; 1412 mac.m_string = mac64.m_string; 1413 } else { 1414 struct user32_mac mac32; 1415 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1416 mac.m_buflen = mac32.m_buflen; 1417 mac.m_string = mac32.m_string; 1418 } 1419 1420 if (error) 1421 return (error); 1422 1423 error = mac_check_structmac_consistent(&mac); 1424 if (error) 1425 return (error); 1426 1427 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1428 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen); 1429 if (error) { 1430 FREE(elements, M_MACTEMP); 1431 return (error); 1432 } 1433 AUDIT_ARG(mac_string, elements); 1434 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1435 1436 proc_lock(p); 1437 if (p->p_lctx == NULL) { 1438 proc_unlock(p); 1439 error = ENOENT; 1440 goto out; 1441 } 1442 1443 error = mac_lctx_label_externalize(p->p_lctx->lc_label, 1444 elements, buffer, mac.m_buflen); 1445 proc_unlock(p); 1446 if (error == 0) 1447 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 1448 1449out: 1450 FREE(buffer, M_MACTEMP); 1451 FREE(elements, M_MACTEMP); 1452 return (error); 1453} 1454 1455int 1456__mac_set_lctx(proc_t p, struct __mac_set_lctx_args *uap, int *ret __unused) 1457{ 1458 struct user_mac mac; 1459 struct label *intlabel; 1460 char *buffer; 1461 int error; 1462 size_t ulen; 1463 1464 if (IS_64BIT_PROCESS(p)) { 1465 struct user64_mac mac64; 1466 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1467 mac.m_buflen = mac64.m_buflen; 1468 mac.m_string = mac64.m_string; 1469 } else { 1470 struct user32_mac mac32; 1471 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1472 mac.m_buflen = mac32.m_buflen; 1473 mac.m_string = mac32.m_string; 1474 } 1475 if (error) 1476 return (error); 1477 1478 error = mac_check_structmac_consistent(&mac); 1479 if (error) 1480 return (error); 1481 1482 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1483 error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen); 1484 if (error) { 1485 FREE(buffer, M_MACTEMP); 1486 return (error); 1487 } 1488 AUDIT_ARG(mac_string, buffer); 1489 1490 intlabel = mac_lctx_label_alloc(); 1491 error = mac_lctx_label_internalize(intlabel, buffer); 1492 FREE(buffer, M_MACTEMP); 1493 if (error) 1494 goto out; 1495 1496 proc_lock(p); 1497 if (p->p_lctx == NULL) { 1498 proc_unlock(p); 1499 error = ENOENT; 1500 goto out; 1501 } 1502 1503 error = mac_lctx_check_label_update(p->p_lctx, intlabel); 1504 if (error) { 1505 proc_unlock(p); 1506 goto out; 1507 } 1508 mac_lctx_label_update(p->p_lctx, intlabel); 1509 proc_unlock(p); 1510out: 1511 mac_lctx_label_free(intlabel); 1512 return (error); 1513} 1514 1515#else /* LCTX */ 1516 1517int 1518__mac_get_lcid(proc_t p __unused, struct __mac_get_lcid_args *uap __unused, int *ret __unused) 1519{ 1520 1521 return (ENOSYS); 1522} 1523 1524int 1525__mac_get_lctx(proc_t p __unused, struct __mac_get_lctx_args *uap __unused, int *ret __unused) 1526{ 1527 1528 return (ENOSYS); 1529} 1530 1531int 1532__mac_set_lctx(proc_t p __unused, struct __mac_set_lctx_args *uap __unused, int *ret __unused) 1533{ 1534 1535 return (ENOSYS); 1536} 1537#endif /* !LCTX */ 1538 1539int 1540__mac_get_fd(proc_t p, struct __mac_get_fd_args *uap, int *ret __unused) 1541{ 1542 struct fileproc *fp; 1543 struct vnode *vp; 1544 struct user_mac mac; 1545 char *elements, *buffer; 1546 int error; 1547 size_t ulen; 1548 kauth_cred_t my_cred; 1549#if CONFIG_MACF_SOCKET 1550 struct socket *so; 1551#endif /* MAC_SOCKET */ 1552 struct label *intlabel; 1553 1554 AUDIT_ARG(fd, uap->fd); 1555 1556 if (IS_64BIT_PROCESS(p)) { 1557 struct user64_mac mac64; 1558 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1559 mac.m_buflen = mac64.m_buflen; 1560 mac.m_string = mac64.m_string; 1561 } else { 1562 struct user32_mac mac32; 1563 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1564 mac.m_buflen = mac32.m_buflen; 1565 mac.m_string = mac32.m_string; 1566 } 1567 1568 if (error) 1569 return (error); 1570 1571 error = mac_check_structmac_consistent(&mac); 1572 if (error) 1573 return (error); 1574 1575 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1576 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen); 1577 if (error) { 1578 FREE(elements, M_MACTEMP); 1579 return (error); 1580 } 1581 AUDIT_ARG(mac_string, elements); 1582 1583 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1584 error = fp_lookup(p, uap->fd, &fp, 0); 1585 if (error) { 1586 FREE(buffer, M_MACTEMP); 1587 FREE(elements, M_MACTEMP); 1588 return (error); 1589 } 1590 1591 my_cred = kauth_cred_proc_ref(p); 1592 error = mac_file_check_get(my_cred, fp->f_fglob, elements, mac.m_buflen); 1593 kauth_cred_unref(&my_cred); 1594 if (error) { 1595 fp_drop(p, uap->fd, fp, 0); 1596 FREE(buffer, M_MACTEMP); 1597 FREE(elements, M_MACTEMP); 1598 return (error); 1599 } 1600 1601 switch (FILEGLOB_DTYPE(fp->f_fglob)) { 1602 case DTYPE_VNODE: 1603 intlabel = mac_vnode_label_alloc(); 1604 if (intlabel == NULL) { 1605 error = ENOMEM; 1606 break; 1607 } 1608 vp = (struct vnode *)fp->f_fglob->fg_data; 1609 error = vnode_getwithref(vp); 1610 if (error == 0) { 1611 mac_vnode_label_copy(vp->v_label, intlabel); 1612 error = mac_vnode_label_externalize(intlabel, 1613 elements, buffer, 1614 mac.m_buflen, M_WAITOK); 1615 vnode_put(vp); 1616 } 1617 mac_vnode_label_free(intlabel); 1618 break; 1619 case DTYPE_SOCKET: 1620#if CONFIG_MACF_SOCKET 1621 so = (struct socket *) fp->f_fglob->fg_data; 1622 intlabel = mac_socket_label_alloc(MAC_WAITOK); 1623 sock_lock(so, 1); 1624 mac_socket_label_copy(so->so_label, intlabel); 1625 sock_unlock(so, 1); 1626 error = mac_socket_label_externalize(intlabel, elements, buffer, mac.m_buflen); 1627 mac_socket_label_free(intlabel); 1628 break; 1629#endif 1630 case DTYPE_PSXSHM: 1631 case DTYPE_PSXSEM: 1632 case DTYPE_PIPE: 1633 case DTYPE_KQUEUE: 1634 case DTYPE_FSEVENTS: 1635 default: 1636 error = ENOSYS; // only sockets/vnodes so far 1637 break; 1638 } 1639 fp_drop(p, uap->fd, fp, 0); 1640 1641 if (error == 0) 1642 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 1643 1644 FREE(buffer, M_MACTEMP); 1645 FREE(elements, M_MACTEMP); 1646 return (error); 1647} 1648 1649static int 1650mac_get_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p, int follow) 1651{ 1652 struct vnode *vp; 1653 vfs_context_t ctx; 1654 char *elements, *buffer; 1655 struct nameidata nd; 1656 struct label *intlabel; 1657 struct user_mac mac; 1658 int error; 1659 size_t ulen; 1660 1661 if (IS_64BIT_PROCESS(p)) { 1662 struct user64_mac mac64; 1663 error = copyin(mac_p, &mac64, sizeof(mac64)); 1664 mac.m_buflen = mac64.m_buflen; 1665 mac.m_string = mac64.m_string; 1666 } else { 1667 struct user32_mac mac32; 1668 error = copyin(mac_p, &mac32, sizeof(mac32)); 1669 mac.m_buflen = mac32.m_buflen; 1670 mac.m_string = mac32.m_string; 1671 } 1672 1673 if (error) 1674 return (error); 1675 1676 error = mac_check_structmac_consistent(&mac); 1677 if (error) 1678 return (error); 1679 1680 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1681 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 1682 1683 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen); 1684 if (error) { 1685 FREE(buffer, M_MACTEMP); 1686 FREE(elements, M_MACTEMP); 1687 return (error); 1688 } 1689 AUDIT_ARG(mac_string, elements); 1690 1691 ctx = vfs_context_current(); 1692 1693 NDINIT(&nd, LOOKUP, OP_LOOKUP, 1694 LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1, 1695 UIO_USERSPACE, path_p, ctx); 1696 error = namei(&nd); 1697 if (error) { 1698 FREE(buffer, M_MACTEMP); 1699 FREE(elements, M_MACTEMP); 1700 return (error); 1701 } 1702 vp = nd.ni_vp; 1703 1704 nameidone(&nd); 1705 1706 intlabel = mac_vnode_label_alloc(); 1707 mac_vnode_label_copy(vp->v_label, intlabel); 1708 error = mac_vnode_label_externalize(intlabel, elements, buffer, 1709 mac.m_buflen, M_WAITOK); 1710 mac_vnode_label_free(intlabel); 1711 if (error == 0) 1712 error = copyout(buffer, mac.m_string, strlen(buffer) + 1); 1713 1714 vnode_put(vp); 1715 1716 FREE(buffer, M_MACTEMP); 1717 FREE(elements, M_MACTEMP); 1718 1719 return (error); 1720} 1721 1722int 1723__mac_get_file(proc_t p, struct __mac_get_file_args *uap, 1724 int *ret __unused) 1725{ 1726 1727 return (mac_get_filelink(p, uap->mac_p, uap->path_p, 1)); 1728} 1729 1730int 1731__mac_get_link(proc_t p, struct __mac_get_link_args *uap, 1732 int *ret __unused) 1733{ 1734 1735 return (mac_get_filelink(p, uap->mac_p, uap->path_p, 0)); 1736} 1737 1738int 1739__mac_set_fd(proc_t p, struct __mac_set_fd_args *uap, int *ret __unused) 1740{ 1741 1742 struct fileproc *fp; 1743 struct user_mac mac; 1744 struct vfs_context *ctx = vfs_context_current(); 1745 int error; 1746 size_t ulen; 1747 char *buffer; 1748 struct label *intlabel; 1749#if CONFIG_MACF_SOCKET 1750 struct socket *so; 1751#endif 1752 struct vnode *vp; 1753 1754 AUDIT_ARG(fd, uap->fd); 1755 1756 if (IS_64BIT_PROCESS(p)) { 1757 struct user64_mac mac64; 1758 error = copyin(uap->mac_p, &mac64, sizeof(mac64)); 1759 mac.m_buflen = mac64.m_buflen; 1760 mac.m_string = mac64.m_string; 1761 } else { 1762 struct user32_mac mac32; 1763 error = copyin(uap->mac_p, &mac32, sizeof(mac32)); 1764 mac.m_buflen = mac32.m_buflen; 1765 mac.m_string = mac32.m_string; 1766 } 1767 if (error) 1768 return (error); 1769 1770 error = mac_check_structmac_consistent(&mac); 1771 if (error) 1772 return (error); 1773 1774 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1775 error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen); 1776 if (error) { 1777 FREE(buffer, M_MACTEMP); 1778 return (error); 1779 } 1780 AUDIT_ARG(mac_string, buffer); 1781 1782 error = fp_lookup(p, uap->fd, &fp, 0); 1783 if (error) { 1784 FREE(buffer, M_MACTEMP); 1785 return (error); 1786 } 1787 1788 1789 error = mac_file_check_set(vfs_context_ucred(ctx), fp->f_fglob, buffer, mac.m_buflen); 1790 if (error) { 1791 fp_drop(p, uap->fd, fp, 0); 1792 FREE(buffer, M_MACTEMP); 1793 return (error); 1794 } 1795 1796 switch (FILEGLOB_DTYPE(fp->f_fglob)) { 1797 1798 case DTYPE_VNODE: 1799 if (mac_label_vnodes == 0) { 1800 error = ENOSYS; 1801 break; 1802 } 1803 1804 intlabel = mac_vnode_label_alloc(); 1805 1806 error = mac_vnode_label_internalize(intlabel, buffer); 1807 if (error) { 1808 mac_vnode_label_free(intlabel); 1809 break; 1810 } 1811 1812 1813 vp = (struct vnode *)fp->f_fglob->fg_data; 1814 1815 error = vnode_getwithref(vp); 1816 if (error == 0) { 1817 error = vn_setlabel(vp, intlabel, ctx); 1818 vnode_put(vp); 1819 } 1820 mac_vnode_label_free(intlabel); 1821 break; 1822 1823 case DTYPE_SOCKET: 1824#if CONFIG_MACF_SOCKET 1825 intlabel = mac_socket_label_alloc(MAC_WAITOK); 1826 error = mac_socket_label_internalize(intlabel, buffer); 1827 if (error == 0) { 1828 so = (struct socket *) fp->f_fglob->fg_data; 1829 SOCK_LOCK(so); 1830 error = mac_socket_label_update(vfs_context_ucred(ctx), so, intlabel); 1831 SOCK_UNLOCK(so); 1832 } 1833 mac_socket_label_free(intlabel); 1834 break; 1835#endif 1836 case DTYPE_PSXSHM: 1837 case DTYPE_PSXSEM: 1838 case DTYPE_PIPE: 1839 case DTYPE_KQUEUE: 1840 case DTYPE_FSEVENTS: 1841 default: 1842 error = ENOSYS; // only sockets/vnodes so far 1843 break; 1844 } 1845 1846 fp_drop(p, uap->fd, fp, 0); 1847 FREE(buffer, M_MACTEMP); 1848 return (error); 1849} 1850 1851static int 1852mac_set_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p, 1853 int follow) 1854{ 1855 register struct vnode *vp; 1856 struct vfs_context *ctx = vfs_context_current(); 1857 struct label *intlabel; 1858 struct nameidata nd; 1859 struct user_mac mac; 1860 char *buffer; 1861 int error; 1862 size_t ulen; 1863 1864 if (mac_label_vnodes == 0) 1865 return ENOSYS; 1866 1867 if (IS_64BIT_PROCESS(p)) { 1868 struct user64_mac mac64; 1869 error = copyin(mac_p, &mac64, sizeof(mac64)); 1870 mac.m_buflen = mac64.m_buflen; 1871 mac.m_string = mac64.m_string; 1872 } else { 1873 struct user32_mac mac32; 1874 error = copyin(mac_p, &mac32, sizeof(mac32)); 1875 mac.m_buflen = mac32.m_buflen; 1876 mac.m_string = mac32.m_string; 1877 } 1878 if (error) 1879 return (error); 1880 1881 error = mac_check_structmac_consistent(&mac); 1882 if (error) { 1883 printf("mac_set_file: failed structure consistency check\n"); 1884 return (error); 1885 } 1886 1887 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 1888 error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen); 1889 if (error) { 1890 FREE(buffer, M_MACTEMP); 1891 return (error); 1892 } 1893 AUDIT_ARG(mac_string, buffer); 1894 1895 intlabel = mac_vnode_label_alloc(); 1896 error = mac_vnode_label_internalize(intlabel, buffer); 1897 FREE(buffer, M_MACTEMP); 1898 if (error) { 1899 mac_vnode_label_free(intlabel); 1900 return (error); 1901 } 1902 1903 NDINIT(&nd, LOOKUP, OP_LOOKUP, 1904 LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1, 1905 UIO_USERSPACE, path_p, ctx); 1906 error = namei(&nd); 1907 if (error) { 1908 mac_vnode_label_free(intlabel); 1909 return (error); 1910 } 1911 vp = nd.ni_vp; 1912 1913 nameidone(&nd); 1914 1915 error = vn_setlabel(vp, intlabel, ctx); 1916 vnode_put(vp); 1917 mac_vnode_label_free(intlabel); 1918 1919 return (error); 1920} 1921 1922int 1923__mac_set_file(proc_t p, struct __mac_set_file_args *uap, 1924 int *ret __unused) 1925{ 1926 1927 return (mac_set_filelink(p, uap->mac_p, uap->path_p, 1)); 1928} 1929 1930int 1931__mac_set_link(proc_t p, struct __mac_set_link_args *uap, 1932 int *ret __unused) 1933{ 1934 1935 return (mac_set_filelink(p, uap->mac_p, uap->path_p, 0)); 1936} 1937 1938/* 1939 * __mac_syscall: Perform a MAC policy system call 1940 * 1941 * Parameters: p Process calling this routine 1942 * uap User argument descriptor (see below) 1943 * retv (Unused) 1944 * 1945 * Indirect: uap->policy Name of target MAC policy 1946 * uap->call MAC policy-specific system call to perform 1947 * uap->arg MAC policy-specific system call arguments 1948 * 1949 * Returns: 0 Success 1950 * !0 Not success 1951 * 1952 */ 1953int 1954__mac_syscall(proc_t p, struct __mac_syscall_args *uap, int *retv __unused) 1955{ 1956 struct mac_policy_conf *mpc; 1957 char target[MAC_MAX_POLICY_NAME]; 1958 int error; 1959 u_int i; 1960 size_t ulen; 1961 1962 error = copyinstr(uap->policy, target, sizeof(target), &ulen); 1963 if (error) 1964 return (error); 1965 AUDIT_ARG(value32, uap->call); 1966 AUDIT_ARG(mac_string, target); 1967 1968 error = ENOPOLICY; 1969 1970 for (i = 0; i < mac_policy_list.staticmax; i++) { 1971 mpc = mac_policy_list.entries[i].mpc; 1972 if (mpc == NULL) 1973 continue; 1974 1975 if (strcmp(mpc->mpc_name, target) == 0 && 1976 mpc->mpc_ops->mpo_policy_syscall != NULL) { 1977 error = mpc->mpc_ops->mpo_policy_syscall(p, 1978 uap->call, uap->arg); 1979 goto done; 1980 } 1981 } 1982 if (mac_policy_list_conditional_busy() != 0) { 1983 for (; i <= mac_policy_list.maxindex; i++) { 1984 mpc = mac_policy_list.entries[i].mpc; 1985 if (mpc == NULL) 1986 continue; 1987 1988 if (strcmp(mpc->mpc_name, target) == 0 && 1989 mpc->mpc_ops->mpo_policy_syscall != NULL) { 1990 error = mpc->mpc_ops->mpo_policy_syscall(p, 1991 uap->call, uap->arg); 1992 break; 1993 } 1994 } 1995 mac_policy_list_unbusy(); 1996 } 1997 1998done: 1999 return (error); 2000} 2001 2002int 2003mac_mount_label_get(struct mount *mp, user_addr_t mac_p) 2004{ 2005 char *elements, *buffer; 2006 struct label *label; 2007 struct user_mac mac; 2008 int error; 2009 size_t ulen; 2010 2011 if (IS_64BIT_PROCESS(current_proc())) { 2012 struct user64_mac mac64; 2013 error = copyin(mac_p, &mac64, sizeof(mac64)); 2014 mac.m_buflen = mac64.m_buflen; 2015 mac.m_string = mac64.m_string; 2016 } else { 2017 struct user32_mac mac32; 2018 error = copyin(mac_p, &mac32, sizeof(mac32)); 2019 mac.m_buflen = mac32.m_buflen; 2020 mac.m_string = mac32.m_string; 2021 } 2022 if (error) 2023 return (error); 2024 2025 error = mac_check_structmac_consistent(&mac); 2026 if (error) 2027 return (error); 2028 2029 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK); 2030 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen); 2031 if (error) { 2032 FREE(elements, M_MACTEMP); 2033 return (error); 2034 } 2035 AUDIT_ARG(mac_string, elements); 2036 2037 label = mp->mnt_mntlabel; 2038 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2039 error = mac_mount_label_externalize(label, elements, buffer, 2040 mac.m_buflen); 2041 FREE(elements, M_MACTEMP); 2042 2043 if (error == 0) 2044 error = copyout(buffer, mac.m_string, strlen(buffer) + 1); 2045 FREE(buffer, M_MACTEMP); 2046 2047 return (error); 2048} 2049 2050/* 2051 * __mac_get_mount: Get mount point label information for a given pathname 2052 * 2053 * Parameters: p (ignored) 2054 * uap User argument descriptor (see below) 2055 * ret (ignored) 2056 * 2057 * Indirect: uap->path Pathname 2058 * uap->mac_p MAC info 2059 * 2060 * Returns: 0 Success 2061 * !0 Not success 2062 */ 2063int 2064__mac_get_mount(proc_t p __unused, struct __mac_get_mount_args *uap, 2065 int *ret __unused) 2066{ 2067 struct nameidata nd; 2068 struct vfs_context *ctx = vfs_context_current(); 2069 struct mount *mp; 2070 int error; 2071 2072 NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | AUDITVNPATH1, 2073 UIO_USERSPACE, uap->path, ctx); 2074 error = namei(&nd); 2075 if (error) { 2076 return (error); 2077 } 2078 mp = nd.ni_vp->v_mount; 2079 vnode_put(nd.ni_vp); 2080 nameidone(&nd); 2081 2082 return mac_mount_label_get(mp, uap->mac_p); 2083} 2084 2085/* 2086 * mac_schedule_userret() 2087 * 2088 * Schedule a callback to the mpo_thread_userret hook. The mpo_thread_userret 2089 * hook is called just before the thread exit from the kernel in ast_taken(). 2090 * 2091 * Returns: 0 Success 2092 * !0 Not successful 2093 */ 2094int 2095mac_schedule_userret(void) 2096{ 2097 2098 act_set_astmacf(current_thread()); 2099 return (0); 2100} 2101 2102/* 2103 * mac_do_machexc() 2104 * 2105 * Do a Mach exception. This should only be done in the mpo_thread_userret 2106 * callback. 2107 * 2108 * params: code exception code 2109 * subcode exception subcode 2110 * flags flags: 2111 * MAC_DOEXCF_TRACED Only do exception if being 2112 * ptrace()'ed. 2113 * 2114 * 2115 * Returns: 0 Success 2116 * !0 Not successful 2117 */ 2118int 2119mac_do_machexc(int64_t code, int64_t subcode, uint32_t flags) 2120{ 2121 mach_exception_data_type_t codes[EXCEPTION_CODE_MAX]; 2122 proc_t p = current_proc(); 2123 2124 /* Only allow execption codes in MACF's reserved range. */ 2125 if ((code < EXC_MACF_MIN) || (code > EXC_MACF_MAX)) 2126 return (1); 2127 2128 if (flags & MAC_DOEXCF_TRACED && 2129 !(p->p_lflag & P_LTRACED && (p->p_lflag & P_LPPWAIT) == 0)) 2130 return (0); 2131 2132 2133 /* Send the Mach exception */ 2134 codes[0] = (mach_exception_data_type_t)code; 2135 codes[1] = (mach_exception_data_type_t)subcode; 2136 2137 return (bsd_exception(EXC_SOFTWARE, codes, 2) != KERN_SUCCESS); 2138} 2139 2140#else /* MAC */ 2141 2142void (*load_security_extensions_function)(void) = 0; 2143 2144struct sysctl_oid_list sysctl__security_mac_children; 2145 2146int 2147mac_policy_register(struct mac_policy_conf *mpc __unused, 2148 mac_policy_handle_t *handlep __unused, void *xd __unused) 2149{ 2150 2151 return (0); 2152} 2153 2154int 2155mac_policy_unregister(mac_policy_handle_t handle __unused) 2156{ 2157 2158 return (0); 2159} 2160 2161int 2162mac_audit_text(char *text __unused, mac_policy_handle_t handle __unused) 2163{ 2164 2165 return (0); 2166} 2167 2168int 2169mac_vnop_setxattr(struct vnode *vp __unused, const char *name __unused, char *buf __unused, size_t len __unused) 2170{ 2171 2172 return (ENOENT); 2173} 2174 2175int 2176mac_vnop_getxattr(struct vnode *vp __unused, const char *name __unused, 2177 char *buf __unused, size_t len __unused, size_t *attrlen __unused) 2178{ 2179 2180 return (ENOENT); 2181} 2182 2183int 2184mac_vnop_removexattr(struct vnode *vp __unused, const char *name __unused) 2185{ 2186 2187 return (ENOENT); 2188} 2189 2190intptr_t mac_label_get(struct label *l __unused, int slot __unused) 2191{ 2192 return 0; 2193} 2194 2195void mac_label_set(struct label *l __unused, int slot __unused, intptr_t v __unused) 2196{ 2197 return; 2198} 2199 2200struct label *mac_thread_get_threadlabel(struct thread *thread __unused) 2201{ 2202 return NULL; 2203} 2204 2205struct label *mac_thread_get_uthreadlabel(struct uthread *uthread __unused) 2206{ 2207 return NULL; 2208} 2209 2210void mac_proc_set_enforce(proc_t p, int enforce_flags); 2211void mac_proc_set_enforce(proc_t p __unused, int enforce_flags __unused) 2212{ 2213 return; 2214} 2215 2216int mac_iokit_check_hid_control(kauth_cred_t cred __unused); 2217int mac_iokit_check_hid_control(kauth_cred_t cred __unused) 2218{ 2219 return 0; 2220} 2221 2222#endif /* !MAC */ 2223