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