2  * Copyright (c) 2007 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  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. 
  34  * This software was developed by Robert Watson and Ilmar Habibulin for the 
  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. 
  42  * Redistribution and use in source and binary forms, with or without 
  43  * modification, are permitted provided that the following conditions 
  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. 
  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 
  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*. 
  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> 
  84 #include <sys/file_internal.h> 
  85 #include <sys/filedesc.h> 
  87 #include <sys/proc_internal.h> 
  88 #include <sys/kauth.h> 
  89 #include <sys/sysproto.h> 
  91 #include <mach/vm_types.h> 
  92 #include <mach/vm_prot.h> 
  94 #include <kern/zalloc.h> 
  95 #include <kern/sched_prim.h> 
  96 #include <osfmk/kern/task.h> 
  97 #include <osfmk/kern/kalloc.h> 
 100 #include <security/mac.h> 
 101 #include <security/mac_policy.h> 
 102 #include <security/mac_framework.h> 
 103 #include <security/mac_internal.h> 
 104 #include <security/mac_mach_internal.h> 
 109  * define MB_DEBUG to display run-time debugging information 
 114 #define DPRINTF(x)      printf x 
 121 SYSCTL_NODE(, OID_AUTO
, security
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0,  
 122     "Security Controls"); 
 123 SYSCTL_NODE(_security
, OID_AUTO
, mac
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, 
 124     "TrustedBSD MAC policy controls"); 
 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. 
 134 MODULE_VERSION(kernel_mac_support
, 1); 
 137 #if MAC_MAX_SLOTS > 32 
 138 #error "MAC_MAX_SLOTS too large" 
 141 static unsigned int mac_max_slots 
= MAC_MAX_SLOTS
; 
 142 static unsigned int mac_slot_offsets_free 
= (1 << MAC_MAX_SLOTS
) - 1; 
 143 SYSCTL_UINT(_security_mac
, OID_AUTO
, max_slots
, CTLFLAG_RD 
| CTLFLAG_LOCKED
, 
 144     &mac_max_slots
, 0, ""); 
 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. 
 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? 
 165 unsigned int mac_label_mbufs    
= 1; 
 166 SYSCTL_UINT(_security_mac
, OID_AUTO
, label_mbufs
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 167         &mac_label_mbufs
, 0, "Label all MBUFs"); 
 172  * Flag to indicate whether or not we should allocate label storage for 
 173  * new vnodes.  Since most dynamic policies we currently work with don't 
 174  * rely on vnode labeling, try to avoid paying the cost of mtag allocation 
 175  * unless specifically notified of interest.  One result of this is 
 176  * that if a dynamically loaded policy requests vnode labels, it must 
 177  * be able to deal with a NULL label being returned on any vnodes that 
 178  * were already in flight when the policy was loaded.  Since the policy 
 179  * already has to deal with uninitialized labels, this probably won't 
 182 unsigned int    mac_label_vnodes 
= 0; 
 183 SYSCTL_UINT(_security_mac
, OID_AUTO
, labelvnodes
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 184     &mac_label_vnodes
, 0, "Label all vnodes"); 
 187 unsigned int    mac_mmap_revocation 
= 0; 
 188 SYSCTL_UINT(_security_mac
, OID_AUTO
, mmap_revocation
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 189     &mac_mmap_revocation
, 0, "Revoke mmap access to files on subject " 
 192 unsigned int    mac_mmap_revocation_via_cow 
= 0; 
 193 SYSCTL_UINT(_security_mac
, OID_AUTO
, mmap_revocation_via_cow
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 194     &mac_mmap_revocation_via_cow
, 0, "Revoke mmap access to files via " 
 195     "copy-on-write semantics, or by removing all write access"); 
 197 unsigned int mac_device_enforce 
= 1; 
 198 SYSCTL_UINT(_security_mac
, OID_AUTO
, device_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 199            &mac_device_enforce
, 0, "Enforce MAC policy on device operations"); 
 201 unsigned int mac_file_enforce 
= 0; 
 202 SYSCTL_UINT(_security_mac
, OID_AUTO
, file_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 203         &mac_file_enforce
, 0, "Enforce MAC policy on file operations"); 
 205 unsigned int mac_iokit_enforce 
= 0; 
 206 SYSCTL_UINT(_security_mac
, OID_AUTO
, iokit_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 207         &mac_file_enforce
, 0, "Enforce MAC policy on IOKit operations"); 
 209 unsigned int    mac_pipe_enforce 
= 1; 
 210 SYSCTL_UINT(_security_mac
, OID_AUTO
, pipe_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 211     &mac_pipe_enforce
, 0, "Enforce MAC policy on pipe operations"); 
 213 unsigned int    mac_posixsem_enforce 
= 1; 
 214 SYSCTL_UINT(_security_mac
, OID_AUTO
, posixsem_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 215     &mac_posixsem_enforce
, 0, "Enforce MAC policy on POSIX semaphores"); 
 217 unsigned int mac_posixshm_enforce 
= 1; 
 218 SYSCTL_UINT(_security_mac
, OID_AUTO
, posixshm_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 219     &mac_posixshm_enforce
, 0, "Enforce MAC policy on Posix Shared Memory"); 
 221 unsigned int    mac_proc_enforce 
= 1; 
 222 SYSCTL_UINT(_security_mac
, OID_AUTO
, proc_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 223            &mac_proc_enforce
, 0, "Enforce MAC policy on process operations"); 
 225 unsigned int mac_socket_enforce 
= 1; 
 226 SYSCTL_UINT(_security_mac
, OID_AUTO
, socket_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 227         &mac_socket_enforce
, 0, "Enforce MAC policy on socket operations"); 
 229 unsigned int    mac_system_enforce 
= 1; 
 230 SYSCTL_UINT(_security_mac
, OID_AUTO
, system_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 231     &mac_system_enforce
, 0, "Enforce MAC policy on system-wide interfaces"); 
 233 unsigned int    mac_sysvmsg_enforce 
= 1; 
 234 SYSCTL_UINT(_security_mac
, OID_AUTO
, sysvmsg_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 235     &mac_sysvmsg_enforce
, 0, "Enforce MAC policy on System V IPC message queues"); 
 237 unsigned int    mac_sysvsem_enforce 
= 1; 
 238 SYSCTL_UINT(_security_mac
, OID_AUTO
, sysvsem_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 239     &mac_sysvsem_enforce
, 0, "Enforce MAC policy on System V IPC semaphores"); 
 241 unsigned int    mac_sysvshm_enforce 
= 1; 
 242 SYSCTL_INT(_security_mac
, OID_AUTO
, sysvshm_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 243     &mac_sysvshm_enforce
, 0, "Enforce MAC policy on System V Shared Memory"); 
 245 unsigned int    mac_vm_enforce 
= 1; 
 246 SYSCTL_INT(_security_mac
, OID_AUTO
, vm_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 247            &mac_vm_enforce
, 0, "Enforce MAC policy on VM operations"); 
 249 unsigned int    mac_vnode_enforce 
= 1; 
 250 SYSCTL_UINT(_security_mac
, OID_AUTO
, vnode_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 251            &mac_vnode_enforce
, 0, "Enforce MAC policy on vnode operations"); 
 255 unsigned int    mac_port_enforce 
= 0; 
 256 SYSCTL_UINT(_security_mac
, OID_AUTO
, port_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 257     &mac_port_enforce
, 0, "Enforce MAC policy on Mach port operations"); 
 259 unsigned int    mac_task_enforce 
= 0; 
 260 SYSCTL_UINT(_security_mac
, OID_AUTO
, task_enforce
, CTLFLAG_RW 
| CTLFLAG_LOCKED
, 
 261     &mac_task_enforce
, 0, "Enforce MAC policy on Mach task operations"); 
 266  * mac_audit_data_zone is the zone used for data pushed into the audit 
 267  * record by policies. Using a zone simplifies memory management of this 
 268  * data, and allows tracking of the amount of data in flight. 
 270 extern zone_t mac_audit_data_zone
; 
 274  * mac_policy_list holds the list of policy modules.  Modules with a 
 275  * handle lower than staticmax are considered "static" and cannot be 
 276  * unloaded.  Such policies can be invoked without holding the busy count. 
 278  * Modules with a handle at or above the staticmax high water mark 
 279  * are considered to be "dynamic" policies.  A busy count is maintained 
 280  * for the list, stored in mac_policy_busy.  The busy count is protected 
 281  * by mac_policy_mtx; the list may be modified only while the busy 
 282  * count is 0, requiring that the lock be held to prevent new references 
 283  * to the list from being acquired.  For almost all operations, 
 284  * incrementing the busy count is sufficient to guarantee consistency, 
 285  * as the list cannot be modified while the busy count is elevated. 
 286  * For a few special operations involving a change to the list of 
 287  * active policies, the mtx itself must be held. 
 289 static lck_mtx_t 
*mac_policy_mtx
; 
 292  * Policy list array allocation chunk size. Trying to set this so that we 
 293  * allocate a page at a time. 
 295 #define MAC_POLICY_LIST_CHUNKSIZE 512 
 297 static int mac_policy_busy
; 
 299 mac_policy_list_t mac_policy_list
; 
 302  * mac_label_element_list holds the master list of label namespaces for 
 303  * all the policies. When a policy is loaded, each of it's label namespace 
 304  * elements is added to the master list if not already present. When a 
 305  * policy is unloaded, the namespace elements are removed if no other  
 306  * policy is interested in that namespace element. 
 308 struct mac_label_element_list_t mac_label_element_list
; 
 309 struct mac_label_element_list_t mac_static_label_element_list
; 
 312  * Journal of label operations that occur before policies are loaded. 
 314 struct mac_label_journal_list_t mac_label_journal_list
; 
 317 mac_label_journal_add (struct label 
*l
, int type
) 
 319         struct mac_label_journal 
*mlj
; 
 321         if (mac_label_journal_find(l
)) 
 324         MALLOC(mlj
, struct mac_label_journal 
*, 
 325                 sizeof(struct mac_label_journal
), M_MACTEMP
, M_WAITOK
); 
 328         TAILQ_INSERT_TAIL(&mac_label_journal_list
, mlj
, link
); 
 334 mac_label_journal_remove (struct label 
*l
) 
 336         struct mac_label_journal 
*mlj
; 
 338         mlj 
= mac_label_journal_find(l
); 
 342         TAILQ_REMOVE(&mac_label_journal_list
, mlj
, link
); 
 343         FREE(mlj
, M_MACTEMP
); 
 347 struct mac_label_journal 
* 
 348 mac_label_journal_find (struct label 
*l
) 
 350         struct mac_label_journal 
*mlj
; 
 352         TAILQ_FOREACH(mlj
, &mac_label_journal_list
, link
) { 
 361 mac_label_journal (struct label 
*l
, int op
, ...) 
 363         struct mac_label_journal 
*mlj
; 
 366         mlj 
= mac_label_journal_find(l
); 
 368                 printf("%s(): Label not in list!\n", __func__
); 
 372         if (op 
== MLJ_PORT_OP_UPDATE
) { 
 374                 mlj
->kotype 
= va_arg(ap
, int); 
 383  * The assumption during replay is that the system is totally 
 384  * serialized and no additional tasks/ports will be created. 
 387 mac_label_journal_replay (void) 
 389         struct mac_label_journal 
*mlj
; 
 391         TAILQ_FOREACH(mlj
, &mac_label_journal_list
, link
) { 
 394                         if (mlj
->ops 
& MLJ_PORT_OP_INIT
) 
 395                                 MAC_PERFORM(port_label_init
, mlj
->l
); 
 396                         if (mlj
->ops 
& MLJ_PORT_OP_CREATE_K
) 
 397                                 MAC_PERFORM(port_label_associate_kernel
, mlj
->l
, 0); 
 398                         if (mlj
->ops 
& MLJ_PORT_OP_UPDATE
) 
 399                                 MAC_PERFORM(port_label_update_kobject
, mlj
->l
, 
 403                         if (mlj
->ops 
& MLJ_TASK_OP_INIT
) 
 404                                 MAC_PERFORM(task_label_init
, mlj
->l
); 
 406                         /* Not enough context to replay. */ 
 407                         if (mlj
->ops 
& MLJ_TASK_OP_CREATE_K
) 
 417         while (!TAILQ_EMPTY(&mac_label_journal_list
)) { 
 418                 mlj 
= TAILQ_FIRST(&mac_label_journal_list
); 
 419                 TAILQ_REMOVE(&mac_label_journal_list
, mlj
, link
); 
 420                 FREE(mlj
, M_MACTEMP
); 
 426 mac_policy_grab_exclusive(void) 
 428         lck_mtx_lock(mac_policy_mtx
); 
 429         while (mac_policy_busy 
!= 0) { 
 430                 lck_mtx_sleep(mac_policy_mtx
, LCK_SLEEP_UNLOCK
, 
 431                               (event_t
)&mac_policy_busy
, THREAD_UNINT
); 
 432                 lck_mtx_lock(mac_policy_mtx
); 
 437 mac_policy_assert_exclusive(void) 
 439         lck_mtx_assert(mac_policy_mtx
, LCK_MTX_ASSERT_OWNED
); 
 440         KASSERT(mac_policy_busy 
== 0, 
 441             ("mac_policy_assert_exclusive(): not exclusive")); 
 445 mac_policy_release_exclusive(void) 
 448         KASSERT(mac_policy_busy 
== 0, 
 449             ("mac_policy_release_exclusive(): not exclusive")); 
 450         lck_mtx_unlock(mac_policy_mtx
); 
 451         thread_wakeup((event_t
) &mac_policy_busy
); 
 455 mac_policy_list_busy(void) 
 457         lck_mtx_lock(mac_policy_mtx
); 
 459         lck_mtx_unlock(mac_policy_mtx
); 
 463 mac_policy_list_conditional_busy(void) 
 467         if (mac_policy_list
.numloaded 
<= mac_policy_list
.staticmax
) 
 470         lck_mtx_lock(mac_policy_mtx
); 
 471         if (mac_policy_list
.numloaded 
> mac_policy_list
.staticmax
) { 
 476         lck_mtx_unlock(mac_policy_mtx
); 
 481 mac_policy_list_unbusy(void) 
 483         lck_mtx_lock(mac_policy_mtx
); 
 485         KASSERT(mac_policy_busy 
>= 0, ("MAC_POLICY_LIST_LOCK")); 
 486         if (mac_policy_busy 
== 0) 
 487                 thread_wakeup(&mac_policy_busy
); 
 488         lck_mtx_unlock(mac_policy_mtx
); 
 492  * Early pre-malloc MAC initialization, including appropriate SMP locks. 
 495 mac_policy_init(void) 
 497         lck_grp_attr_t 
*mac_lck_grp_attr
; 
 498         lck_attr_t 
*mac_lck_attr
; 
 499         lck_grp_t 
*mac_lck_grp
; 
 501         mac_policy_list
.numloaded 
= 0; 
 502         mac_policy_list
.max 
= MAC_POLICY_LIST_CHUNKSIZE
; 
 503         mac_policy_list
.maxindex 
= 0; 
 504         mac_policy_list
.staticmax 
= 0; 
 505         mac_policy_list
.freehint 
= 0; 
 506         mac_policy_list
.chunks 
= 1; 
 508         mac_policy_list
.entries 
= kalloc(sizeof(struct mac_policy_list_element
) * MAC_POLICY_LIST_CHUNKSIZE
); 
 509         bzero(mac_policy_list
.entries
, sizeof(struct mac_policy_list_element
) * MAC_POLICY_LIST_CHUNKSIZE
);  
 511         LIST_INIT(&mac_label_element_list
); 
 512         LIST_INIT(&mac_static_label_element_list
); 
 513         TAILQ_INIT(&mac_label_journal_list
); 
 515         mac_lck_grp_attr 
= lck_grp_attr_alloc_init(); 
 516         lck_grp_attr_setstat(mac_lck_grp_attr
); 
 517         mac_lck_grp 
= lck_grp_alloc_init("MAC lock", mac_lck_grp_attr
); 
 518         mac_lck_attr 
= lck_attr_alloc_init(); 
 519         lck_attr_setdefault(mac_lck_attr
); 
 520         mac_policy_mtx 
= lck_mtx_alloc_init(mac_lck_grp
, mac_lck_attr
); 
 521         lck_attr_free(mac_lck_attr
); 
 522         lck_grp_attr_free(mac_lck_grp_attr
); 
 523         lck_grp_free(mac_lck_grp
); 
 525         mac_labelzone_init(); 
 528 /* Function pointer set up for loading security extensions. 
 529  * It is set to an actual function after OSlibkernInit() 
 530  * has been called, and is set back to 0 by OSKextRemoveKextBootstrap() 
 533 void (*load_security_extensions_function
)(void) = 0; 
 536  * Init after early Mach startup, but before BSD 
 539 mac_policy_initmach(void) 
 543          * For the purposes of modules that want to know if they were 
 544          * loaded "early", set the mac_late flag once we've processed 
 545          * modules either linked into the kernel, or loaded before the 
 549         if (load_security_extensions_function
) { 
 550                 load_security_extensions_function(); 
 554         mac_label_journal_replay(); 
 562 mac_policy_initbsd(void) 
 564         struct mac_policy_conf 
*mpc
; 
 568         mac_audit_data_zone 
= zinit(MAC_AUDIT_DATA_LIMIT
, 
 569                                     AQ_HIWATER 
* MAC_AUDIT_DATA_LIMIT
, 
 570                                     8192, "mac_audit_data_zone"); 
 573         printf("MAC Framework successfully initialized\n"); 
 575         /* Call bsd init functions of already loaded policies */ 
 578          * Using the exclusive lock means no other framework entry 
 579          * points can proceed while initializations are running. 
 580          * This may not be necessary. 
 582         mac_policy_grab_exclusive(); 
 584         for (i 
= 0; i 
<= mac_policy_list
.maxindex
; i
++) { 
 585                 mpc 
= mac_get_mpc(i
); 
 586                 if ((mpc 
!= NULL
) && (mpc
->mpc_ops
->mpo_policy_initbsd 
!= NULL
)) 
 587                         (*(mpc
->mpc_ops
->mpo_policy_initbsd
))(mpc
); 
 590         mac_policy_release_exclusive(); 
 594  * After a policy has been loaded, add the label namespaces managed by the 
 595  * policy to either the static or non-static label namespace list.   
 596  * A namespace is added to the the list only if it is not already on one of  
 600 mac_policy_addto_labellist(mac_policy_handle_t handle
, int static_entry
) 
 602         struct mac_label_listener 
**new_mlls
; 
 603         struct mac_label_element 
*mle
, **new_mles
; 
 604         struct mac_label_element_list_t 
*list
; 
 605         struct mac_policy_conf 
*mpc
; 
 606         const char *name
, *name2
; 
 607         u_int idx
, mle_free
, mll_free
; 
 609         mpc 
= mac_get_mpc(handle
); 
 611         if (mpc
->mpc_labelnames 
== NULL
) 
 614         if (mpc
->mpc_labelname_count 
== 0) 
 618                 list 
= &mac_static_label_element_list
; 
 620                 list 
= &mac_label_element_list
; 
 623          * Before we grab the policy list lock, allocate enough memory 
 624          * to contain the potential new elements so we don't have to  
 625          * give up the lock, or allocate with the lock held. 
 627         MALLOC(new_mles
, struct mac_label_element 
**, 
 628             sizeof(struct mac_label_element 
*) * 
 629             mpc
->mpc_labelname_count
, M_MACTEMP
, M_WAITOK 
| M_ZERO
); 
 630         for (idx 
= 0; idx 
< mpc
->mpc_labelname_count
; idx
++) 
 631                 MALLOC(new_mles
[idx
], struct mac_label_element 
*,  
 632                     sizeof(struct mac_label_element
), 
 633                     M_MACTEMP
, M_WAITOK
); 
 635         MALLOC(new_mlls
, struct mac_label_listener 
**, 
 636             sizeof(struct mac_label_listener 
*) * 
 637             mpc
->mpc_labelname_count
, M_MACTEMP
, M_WAITOK
); 
 638         for (idx 
= 0; idx 
< mpc
->mpc_labelname_count
; idx
++) 
 639                 MALLOC(new_mlls
[idx
], struct mac_label_listener 
*, 
 640                     sizeof(struct mac_label_listener
), M_MACTEMP
, M_WAITOK
); 
 644                 mac_policy_grab_exclusive(); 
 645         for (idx 
= 0; idx 
< mpc
->mpc_labelname_count
; idx
++) { 
 647                 if (*(name 
= mpc
->mpc_labelnames
[idx
]) == '?') 
 650                  * Check both label element lists and add to the  
 651                  * appropriate list only if not already on a list. 
 653                 LIST_FOREACH(mle
, &mac_static_label_element_list
, mle_list
) { 
 654                         if (*(name2 
= mle
->mle_name
) == '?') 
 656                         if (strcmp(name
, name2
) == 0) 
 660                         LIST_FOREACH(mle
, &mac_label_element_list
, mle_list
) { 
 661                                 if (*(name2 
= mle
->mle_name
) == '?') 
 663                                 if (strcmp(name
, name2
) == 0) 
 668                         mle 
= new_mles
[mle_free
]; 
 669                         strlcpy(mle
->mle_name
, mpc
->mpc_labelnames
[idx
], 
 670                                         MAC_MAX_LABEL_ELEMENT_NAME
); 
 671                         LIST_INIT(&mle
->mle_listeners
); 
 672                         LIST_INSERT_HEAD(list
, mle
, mle_list
); 
 675                 /* Add policy handler as a listener. */ 
 676                 new_mlls
[mll_free
]->mll_handle 
= handle
; 
 677                 LIST_INSERT_HEAD(&mle
->mle_listeners
, new_mlls
[mll_free
], 
 682                 mac_policy_release_exclusive(); 
 684         /* Free up any unused label elements and listeners */ 
 685         for (idx 
= mle_free
; idx 
< mpc
->mpc_labelname_count
; idx
++) 
 686                 FREE(new_mles
[idx
], M_MACTEMP
); 
 687         FREE(new_mles
, M_MACTEMP
); 
 688         for (idx 
= mll_free
; idx 
< mpc
->mpc_labelname_count
; idx
++) 
 689                 FREE(new_mlls
[idx
], M_MACTEMP
); 
 690         FREE(new_mlls
, M_MACTEMP
); 
 694  * After a policy has been unloaded, remove the label namespaces that the 
 695  * the policy manages from the non-static list of namespaces. 
 696  * The removal only takes place when no other policy is interested in the 
 699  * Must be called with the policy exclusive lock held. 
 702 mac_policy_removefrom_labellist(mac_policy_handle_t handle
) 
 704         struct mac_label_listener 
*mll
; 
 705         struct mac_label_element 
*mle
; 
 706         struct mac_policy_conf 
*mpc
; 
 708         mpc 
= mac_get_mpc(handle
); 
 710         if (mpc
->mpc_labelnames 
== NULL
) 
 713         if (mpc
->mpc_labelname_count 
== 0) 
 717          * Unregister policy as being interested in any label 
 718          * namespaces.  If no other policy is listening, remove 
 719          * that label element from the list.  Note that we only 
 720          * have to worry about the non-static list. 
 722         LIST_FOREACH(mle
, &mac_label_element_list
, mle_list
) { 
 723                 LIST_FOREACH(mll
, &mle
->mle_listeners
, mll_list
) { 
 724                         if (mll
->mll_handle 
== handle
) { 
 725                                 LIST_REMOVE(mll
, mll_list
); 
 726                                 FREE(mll
, M_MACTEMP
); 
 727                                 if (LIST_EMPTY(&mle
->mle_listeners
)) { 
 728                                         LIST_REMOVE(mle
, mle_list
); 
 729                                         FREE(mle
, M_MACTEMP
); 
 738  * After the policy list has changed, walk the list to update any global 
 742 mac_policy_updateflags(void) 
 747 mac_policy_fixup_mmd_list(struct mac_module_data 
*new) 
 749         struct mac_module_data 
*old
; 
 750         struct mac_module_data_element 
*ele
, *aele
; 
 751         struct mac_module_data_list 
*arr
, *dict
; 
 752         unsigned int i
, j
, k
; 
 754         old 
= new->base_addr
; 
 755         DPRINTF(("fixup_mmd: old %p new %p\n", old
, new)); 
 756         for (i 
= 0; i 
< new->count
; i
++) { 
 757                 ele 
= &(new->data
[i
]); 
 758                 DPRINTF(("fixup_mmd: ele %p\n", ele
)); 
 759                 DPRINTF(("   key %p value %p\n", ele
->key
, ele
->value
)); 
 760                 mmd_fixup_ele(old
, new, ele
); /* Fix up key/value ptrs.       */ 
 761                 DPRINTF(("   key %p value %p\n", ele
->key
, ele
->value
)); 
 762                 if (ele
->value_type 
== MAC_DATA_TYPE_ARRAY
) { 
 763                         arr 
= (struct mac_module_data_list 
*)ele
->value
; 
 764                         DPRINTF(("fixup_mmd: array @%p\n", arr
)); 
 765                         for (j 
= 0; j 
< arr
->count
; j
++) { 
 766                                 aele 
= &(arr
->list
[j
]); 
 767                                 DPRINTF(("fixup_mmd: aele %p\n", aele
)); 
 768                                 DPRINTF(("   key %p value %p\n", aele
->key
, aele
->value
)); 
 769                                 mmd_fixup_ele(old
, new, aele
); 
 770                                 DPRINTF(("   key %p value %p\n", aele
->key
, aele
->value
)); 
 771                                 if (arr
->type 
== MAC_DATA_TYPE_DICT
) { 
 772                                         dict 
= (struct mac_module_data_list 
*)aele
->value
; 
 773                                         DPRINTF(("fixup_mmd: dict @%p\n", dict
)); 
 774                                         for (k 
= 0; k 
< dict
->count
; k
++) 
 775                                                 mmd_fixup_ele(old
, new, 
 781         new->base_addr 
= new; 
 785 mac_policy_register(struct mac_policy_conf 
*mpc
, mac_policy_handle_t 
*handlep
, 
 788         struct mac_policy_list_element 
*tmac_policy_list_element
; 
 789         int error
, slot
, static_entry 
= 0; 
 793          * Some preliminary checks to make sure the policy's conf structure 
 794          * contains the required fields. 
 796         if (mpc
->mpc_name 
== NULL
) 
 797                 panic("policy's name is not set\n"); 
 799         if (mpc
->mpc_fullname 
== NULL
) 
 800                 panic("policy's full name is not set\n"); 
 802         if (mpc
->mpc_labelname_count 
> MAC_MAX_MANAGED_NAMESPACES
) 
 803                 panic("policy's managed label namespaces exceeds maximum\n"); 
 805         if (mpc
->mpc_ops 
== NULL
) 
 806                 panic("policy's OPs field is NULL\n"); 
 811                 if (mpc
->mpc_loadtime_flags 
& MPC_LOADTIME_FLAG_NOTLATE
) { 
 812                         printf("Module %s does not support late loading.\n", 
 816                 mac_policy_grab_exclusive(); 
 819         if (mac_policy_list
.numloaded 
>= mac_policy_list
.max
) { 
 820                 /* allocate new policy list array, zero new chunk */ 
 821                 tmac_policy_list_element 
= 
 822                     kalloc((sizeof(struct mac_policy_list_element
) * 
 823                     MAC_POLICY_LIST_CHUNKSIZE
) * (mac_policy_list
.chunks 
+ 1)); 
 824                 bzero(&tmac_policy_list_element
[mac_policy_list
.max
], 
 825                     sizeof(struct mac_policy_list_element
) * 
 826                     MAC_POLICY_LIST_CHUNKSIZE
); 
 828                 /* copy old entries into new list */ 
 829                 memcpy(tmac_policy_list_element
, mac_policy_list
.entries
,  
 830                    sizeof(struct mac_policy_list_element
) * 
 831                    MAC_POLICY_LIST_CHUNKSIZE 
* mac_policy_list
.chunks
); 
 834                 kfree(mac_policy_list
.entries
, 
 835                     sizeof(struct mac_policy_list_element
) * 
 836                     MAC_POLICY_LIST_CHUNKSIZE 
* mac_policy_list
.chunks
); 
 838                 mac_policy_list
.entries 
= tmac_policy_list_element
; 
 840                 /* Update maximums, etc */ 
 841                 mac_policy_list
.max 
+= MAC_POLICY_LIST_CHUNKSIZE
; 
 842                 mac_policy_list
.chunks
++; 
 845         /* Check for policy with same name already loaded */ 
 846         for (i 
= 0; i 
<= mac_policy_list
.maxindex
; i
++) { 
 847                 if (mac_policy_list
.entries
[i
].mpc 
== NULL
)  
 850                 if (strcmp(mac_policy_list
.entries
[i
].mpc
->mpc_name
, 
 851                     mpc
->mpc_name
) == 0) { 
 857         if (mpc
->mpc_field_off 
!= NULL
) { 
 858                 slot 
= ffs(mac_slot_offsets_free
); 
 864                 mac_slot_offsets_free 
&= ~(1 << slot
); 
 865                 *mpc
->mpc_field_off 
= slot
; 
 867         mpc
->mpc_runtime_flags 
|= MPC_RUNTIME_FLAG_REGISTERED
; 
 870                 struct mac_module_data 
*mmd 
= xd
; /* module data from plist */ 
 872                 /* Make a copy of the data. */ 
 873                 mpc
->mpc_data 
= (void *)kalloc(mmd
->size
); 
 874                 if (mpc
->mpc_data 
!= NULL
) { 
 875                         memcpy(mpc
->mpc_data
, mmd
, mmd
->size
); 
 877                         /* Fix up pointers after copy. */ 
 878                         mac_policy_fixup_mmd_list(mpc
->mpc_data
); 
 882         /* Find the first free handle in the list (using our hint). */ 
 883         for (i 
= mac_policy_list
.freehint
; i 
< mac_policy_list
.max
; i
++) { 
 884                 if (mac_policy_list
.entries
[i
].mpc 
== NULL
) { 
 886                         mac_policy_list
.freehint 
= ++i
; 
 892          * If we are loading a MAC module before the framework has 
 893          * finished initializing or the module is not unloadable and 
 894          * we can place its handle adjacent to the last static entry, 
 895          * bump the static policy high water mark. 
 896          * Static policies can get by with weaker locking requirements. 
 899             ((mpc
->mpc_loadtime_flags 
& MPC_LOADTIME_FLAG_UNLOADOK
) == 0 && 
 900             *handlep 
== mac_policy_list
.staticmax
)) { 
 902                 mac_policy_list
.staticmax
++; 
 905         mac_policy_list
.entries
[*handlep
].mpc 
= mpc
; 
 907         /* Update counters, etc */ 
 908         if (*handlep 
> mac_policy_list
.maxindex
)  
 909                 mac_policy_list
.maxindex 
= *handlep
; 
 910         mac_policy_list
.numloaded
++; 
 912         /* Per-policy initialization. */ 
 913         printf ("calling mpo_policy_init for %s\n", mpc
->mpc_name
); 
 914         if (mpc
->mpc_ops
->mpo_policy_init 
!= NULL
) 
 915                 (*(mpc
->mpc_ops
->mpo_policy_init
))(mpc
); 
 917         if (mac_late 
&& mpc
->mpc_ops
->mpo_policy_initbsd 
!= NULL
) { 
 918                 printf ("calling mpo_policy_initbsd for %s\n", mpc
->mpc_name
); 
 919                 (*(mpc
->mpc_ops
->mpo_policy_initbsd
))(mpc
); 
 922         mac_policy_updateflags(); 
 925                 mac_policy_release_exclusive(); 
 927         mac_policy_addto_labellist(*handlep
, static_entry
); 
 929         printf("Security policy loaded: %s (%s)\n", mpc
->mpc_fullname
, 
 936                 mac_policy_release_exclusive(); 
 942 mac_policy_unregister(mac_policy_handle_t handle
) 
 944         struct mac_policy_conf 
*mpc
; 
 947          * If we fail the load, we may get a request to unload.  Check 
 948          * to see if we did the run-time registration, and if not, 
 951         mac_policy_grab_exclusive(); 
 952         mpc 
= mac_get_mpc(handle
); 
 953         if ((mpc
->mpc_runtime_flags 
& MPC_RUNTIME_FLAG_REGISTERED
) == 0) { 
 954                 mac_policy_release_exclusive(); 
 960          * Don't allow unloading modules with private data. 
 962         if (mpc
->mpc_field_off 
!= NULL
) { 
 963                 MAC_POLICY_LIST_UNLOCK(); 
 968          * Only allow the unload to proceed if the module is unloadable 
 969          * by its own definition. 
 971         if ((mpc
->mpc_loadtime_flags 
& MPC_LOADTIME_FLAG_UNLOADOK
) == 0) { 
 972                 mac_policy_release_exclusive(); 
 976         mac_policy_removefrom_labellist(handle
); 
 978         mac_get_mpc(handle
) = NULL
; 
 979         if (handle 
< mac_policy_list
.freehint 
&& 
 980             handle 
>= mac_policy_list
.staticmax
) 
 981                 mac_policy_list
.freehint 
= handle
; 
 983         if (handle 
== mac_policy_list
.maxindex
) 
 984                 mac_policy_list
.maxindex
--; 
 986         mac_policy_list
.numloaded
--;  
 987         if (mpc
->mpc_field_off 
!= NULL
) { 
 988                 mac_slot_offsets_free 
|= (1 << *mpc
->mpc_field_off
); 
 991         if (mpc
->mpc_ops
->mpo_policy_destroy 
!= NULL
) 
 992                 (*(mpc
->mpc_ops
->mpo_policy_destroy
))(mpc
); 
 994         mpc
->mpc_runtime_flags 
&= ~MPC_RUNTIME_FLAG_REGISTERED
; 
 995         mac_policy_updateflags(); 
 997         mac_policy_release_exclusive(); 
1000                 struct mac_module_data 
*mmd 
= mpc
->mpc_data
; 
1001                 kfree(mmd
, mmd
->size
); 
1002                 mpc
->mpc_data 
= NULL
; 
1005         printf("Security policy unload: %s (%s)\n", mpc
->mpc_fullname
, 
1012  * Define an error value precedence, and given two arguments, selects the 
1013  * value with the higher precedence. 
1016 mac_error_select(int error1
, int error2
) 
1019         /* Certain decision-making errors take top priority. */ 
1020         if (error1 
== EDEADLK 
|| error2 
== EDEADLK
) 
1023         /* Invalid arguments should be reported where possible. */ 
1024         if (error1 
== EINVAL 
|| error2 
== EINVAL
) 
1027         /* Precedence goes to "visibility", with both process and file. */ 
1028         if (error1 
== ESRCH 
|| error2 
== ESRCH
) 
1031         if (error1 
== ENOENT 
|| error2 
== ENOENT
) 
1034         /* Precedence goes to DAC/MAC protections. */ 
1035         if (error1 
== EACCES 
|| error2 
== EACCES
) 
1038         /* Precedence goes to privilege. */ 
1039         if (error1 
== EPERM 
|| error2 
== EPERM
) 
1042         /* Precedence goes to error over success; otherwise, arbitrary. */ 
1049 mac_label_init(struct label 
*label
) 
1052         bzero(label
, sizeof(*label
)); 
1053         label
->l_flags 
= MAC_FLAG_INITIALIZED
; 
1057 mac_label_destroy(struct label 
*label
) 
1060         KASSERT(label
->l_flags 
& MAC_FLAG_INITIALIZED
, 
1061             ("destroying uninitialized label")); 
1063         bzero(label
, sizeof(*label
)); 
1064         /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 
1068 mac_port_check_service (struct label 
*subj
, struct label 
*obj
, 
1069     const char *s
, const char *p
) 
1073         MAC_CHECK(port_check_service
, subj
, obj
, s
, p
); 
1078 mac_port_label_compute(struct label 
*subj
, struct label 
*obj
, 
1079     const char *s
, struct label 
*out
) 
1083         MAC_CHECK(port_label_compute
, subj
, obj
, s
, out
); 
1088 mac_check_structmac_consistent(struct user_mac 
*mac
) 
1091         if (mac
->m_buflen 
> MAC_MAX_LABEL_BUF_LEN 
|| mac
->m_buflen 
== 0) 
1098  * Get the external forms of labels from all policies, for a single 
1099  * label namespace or "*" for all namespaces.  Returns ENOENT if no policy 
1100  * is registered for the namespace, unless the namespace begins with a '?'. 
1103 mac_label_externalize(size_t mpo_externalize_off
, struct label 
*label
, 
1104     const char *element
, struct sbuf 
*sb
) 
1106         struct mac_policy_conf 
*mpc
; 
1107         struct mac_label_listener 
*mll
; 
1108         struct mac_label_element 
*mle
; 
1109         struct mac_label_element_list_t 
*element_list
; 
1111         int (*mpo_externalize
)(struct label 
*, char *, struct sbuf 
*); 
1112         int all_labels 
= 0, ignorenotfound 
= 0, error 
= 0, busy 
= FALSE
; 
1113         unsigned int count 
= 0; 
1115         if (element
[0] == '?') { 
1118         } else if (element
[0] == '*' && element
[1] == '\0') 
1121         element_list 
= &mac_static_label_element_list
; 
1123         LIST_FOREACH(mle
, element_list
, mle_list
) { 
1124                 name 
= mle
->mle_name
; 
1131                         if (strcmp(name
, element
) != 0) 
1134                 LIST_FOREACH(mll
, &mle
->mle_listeners
, mll_list
) { 
1135                         mpc 
= mac_policy_list
.entries
[mll
->mll_handle
].mpc
; 
1138                         mpo_externalize 
= *(typeof(mpo_externalize
) *) 
1139                             ((char *)mpc
->mpc_ops 
+ mpo_externalize_off
); 
1140                         if (mpo_externalize 
== NULL
) 
1142                         error 
= sbuf_printf(sb
, "%s/", name
); 
1145                         error 
= mpo_externalize(label
, mle
->mle_name
, sb
); 
1147                                 if (error 
!= ENOENT
) 
1150                                  * If a policy doesn't have a label to 
1151                                  * externalize it returns ENOENT.  This 
1152                                  * may occur for policies that support 
1153                                  * multiple label elements for some 
1154                                  * (but not all) object types. 
1156                                 sbuf_setpos(sb
, sbuf_len(sb
) - 
1157                                     (strlen(name
) + 1)); 
1161                         error 
= sbuf_putc(sb
, ','); 
1167         /* If there are dynamic policies present, check their elements too. */ 
1168         if (!busy 
&& mac_policy_list_conditional_busy() == 1) { 
1169                 element_list 
= &mac_label_element_list
; 
1175                 mac_policy_list_unbusy(); 
1176         if (!error 
&& count 
== 0) { 
1177                 if (!all_labels 
&& !ignorenotfound
) 
1178                         error 
= ENOENT
; /* XXX: ENOLABEL? */ 
1184  * Get the external forms of labels from all policies, for all label 
1185  * namespaces contained in a list. 
1187  * XXX This may be leaking an sbuf. 
1190 mac_externalize(size_t mpo_externalize_off
, struct label 
*label
, 
1191     const char *elementlist
, char *outbuf
, size_t outbuflen
) 
1199         /* allocate a scratch buffer the size of the string */ 
1200         MALLOC(scratch_base
, char *, strlen(elementlist
)+1, M_MACTEMP
, M_WAITOK
);  
1201         if (scratch_base 
== NULL
) { 
1206         /* copy the elementlist to the scratch buffer */ 
1207         strlcpy(scratch_base
, elementlist
, strlen(elementlist
)+1); 
1210          * set up a temporary pointer that can be used to iterate the 
1211          * scratch buffer without losing the allocation address 
1213         scratch 
= scratch_base
; 
1216         if (sbuf_new(&sb
, outbuf
, outbuflen
, SBUF_FIXEDLEN
) == NULL
) { 
1217                 /* could not allocate interior buffer */ 
1221         /* iterate the scratch buffer; NOTE: buffer contents modified! */ 
1222         while ((element 
= strsep(&scratch
, ",")) != NULL
) { 
1223                 error 
= mac_label_externalize(mpo_externalize_off
, label
, 
1228         if ((len 
= sbuf_len(&sb
)) > 0) 
1229                 sbuf_setpos(&sb
, len 
- 1);      /* trim trailing comma */ 
1233         if (scratch_base 
!= NULL
) 
1234                 FREE(scratch_base
, M_MACTEMP
); 
1240  * Have all policies set the internal form of a label, for a single 
1244 mac_label_internalize(size_t mpo_internalize_off
, struct label 
*label
, 
1245     char *element_name
, char *element_data
) 
1247         struct mac_policy_conf 
*mpc
; 
1248         struct mac_label_listener 
*mll
; 
1249         struct mac_label_element 
*mle
; 
1250         struct mac_label_element_list_t 
*element_list
; 
1251         int (*mpo_internalize
)(struct label 
*, char *, char *); 
1252         int error 
= 0, busy 
= FALSE
; 
1253         unsigned int count 
= 0; 
1256         element_list 
= &mac_static_label_element_list
; 
1258         LIST_FOREACH(mle
, element_list
, mle_list
) { 
1259                 if (*(name 
= mle
->mle_name
) == '?') 
1261                 if (strcmp(element_name
, name
) != 0) 
1263                 LIST_FOREACH(mll
, &mle
->mle_listeners
, mll_list
) { 
1264                         mpc 
= mac_policy_list
.entries
[mll
->mll_handle
].mpc
; 
1267                         mpo_internalize 
= *(typeof(mpo_internalize
) *) 
1268                             ((char *)mpc
->mpc_ops 
+ mpo_internalize_off
); 
1269                         if (mpo_internalize 
== NULL
) 
1271                         error 
= mpo_internalize(label
, element_name
, 
1278         /* If there are dynamic policies present, check their elements too. */ 
1279         if (!busy 
&& mac_policy_list_conditional_busy() == 1) { 
1280                 element_list 
= &mac_label_element_list
; 
1286                 mac_policy_list_unbusy(); 
1287         if (!error 
&& count 
== 0) 
1293 mac_internalize(size_t mpo_internalize_off
, struct label 
*label
, 
1296         char *element_name
, *element_data
; 
1299         while (!error 
&& (element_name 
= strsep(&textlabels
, ",")) != NULL
) { 
1300                 element_data 
= strchr(element_name
, '/'); 
1301                 if (element_data 
== NULL
) { 
1305                 *element_data
++ = '\0'; 
1306                 error 
= mac_label_internalize(mpo_internalize_off
, label
, 
1307                     element_name
, element_data
); 
1315 __mac_get_pid(struct proc 
*p
, struct __mac_get_pid_args 
*uap
, int *ret __unused
) 
1317         char *elements
, *buffer
; 
1318         struct user_mac mac
; 
1320         struct ucred 
*tcred
; 
1324         AUDIT_ARG(pid
, uap
->pid
); 
1325         if (IS_64BIT_PROCESS(p
)) { 
1326                 struct user64_mac mac64
; 
1327                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1328                 mac
.m_buflen 
= mac64
.m_buflen
; 
1329                 mac
.m_string 
= mac64
.m_string
; 
1331                 struct user32_mac mac32
; 
1332                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1333                 mac
.m_buflen 
= mac32
.m_buflen
; 
1334                 mac
.m_string 
= mac32
.m_string
; 
1339         error 
= mac_check_structmac_consistent(&mac
); 
1343         tproc 
= proc_find(uap
->pid
); 
1346         tcred 
= kauth_cred_proc_ref(tproc
); 
1349         MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1350         error 
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
); 
1352                 FREE(elements
, M_MACTEMP
); 
1353                 kauth_cred_unref(&tcred
); 
1356         AUDIT_ARG(mac_string
, elements
); 
1358         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK 
| M_ZERO
); 
1359         error 
= mac_cred_label_externalize(tcred
->cr_label
, elements
, 
1360             buffer
, mac
.m_buflen
, M_WAITOK
); 
1362                 error 
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1); 
1364         FREE(buffer
, M_MACTEMP
); 
1365         FREE(elements
, M_MACTEMP
); 
1366         kauth_cred_unref(&tcred
); 
1371 __mac_get_proc(proc_t p
, struct __mac_get_proc_args 
*uap
, int *ret __unused
) 
1373         char *elements
, *buffer
; 
1374         struct user_mac mac
; 
1379         if (IS_64BIT_PROCESS(p
)) { 
1380                 struct user64_mac mac64
; 
1381                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1382                 mac
.m_buflen 
= mac64
.m_buflen
; 
1383                 mac
.m_string 
= mac64
.m_string
; 
1385                 struct user32_mac mac32
; 
1386                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1387                 mac
.m_buflen 
= mac32
.m_buflen
; 
1388                 mac
.m_string 
= mac32
.m_string
; 
1393         error 
= mac_check_structmac_consistent(&mac
); 
1397         MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1398         error 
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
); 
1400                 FREE(elements
, M_MACTEMP
); 
1403         AUDIT_ARG(mac_string
, elements
); 
1405         cr 
= kauth_cred_proc_ref(p
); 
1407         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK 
| M_ZERO
); 
1408         error 
= mac_cred_label_externalize(cr
->cr_label
, 
1409             elements
, buffer
, mac
.m_buflen
, M_WAITOK
); 
1411                 error 
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1); 
1413         FREE(buffer
, M_MACTEMP
); 
1414         FREE(elements
, M_MACTEMP
); 
1415         kauth_cred_unref(&cr
); 
1420 __mac_set_proc(proc_t p
, struct __mac_set_proc_args 
*uap
, int *ret __unused
) 
1422         kauth_cred_t newcred
; 
1423         struct label 
*intlabel
; 
1424         struct user_mac mac
; 
1429         if (IS_64BIT_PROCESS(p
)) { 
1430                 struct user64_mac mac64
; 
1431                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1432                 mac
.m_buflen 
= mac64
.m_buflen
; 
1433                 mac
.m_string 
= mac64
.m_string
; 
1435                 struct user32_mac mac32
; 
1436                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1437                 mac
.m_buflen 
= mac32
.m_buflen
; 
1438                 mac
.m_string 
= mac32
.m_string
; 
1443         error 
= mac_check_structmac_consistent(&mac
); 
1447         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1448         error 
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
); 
1450                 FREE(buffer
, M_MACTEMP
); 
1453         AUDIT_ARG(mac_string
, buffer
); 
1455         intlabel 
= mac_cred_label_alloc(); 
1456         error 
= mac_cred_label_internalize(intlabel
, buffer
); 
1457         FREE(buffer
, M_MACTEMP
); 
1461         error 
= mac_cred_check_label_update(kauth_cred_get(), intlabel
); 
1466         error 
= kauth_proc_label_update(p
, intlabel
); 
1470         newcred 
= kauth_cred_proc_ref(p
); 
1471         mac_task_label_update_cred(newcred
, p
->task
); 
1474         if (mac_vm_enforce
) { 
1475                 mutex_lock(Giant
);                      /* XXX FUNNEL? */ 
1476                 mac_cred_mmapped_drop_perms(p
, newcred
); 
1477                 mutex_unlock(Giant
);                    /* XXX FUNNEL? */ 
1481         kauth_cred_unref(&newcred
); 
1483         mac_cred_label_free(intlabel
); 
1490  *      Get login context ID.  A login context associates a BSD process  
1491  *      with an instance of a user.  For more information see getlcid(2) man page. 
1493  * Parameters:    p                        Process requesting the get 
1494  *                uap                      User argument descriptor (see below) 
1497  * Indirect:      uap->lcid                login context ID to search 
1498  *                uap->mac_p.m_buflen      MAC info buffer size 
1499  *                uap->mac_p.m_string      MAC info user address 
1501  * Returns:        0                       Success 
1505 __mac_get_lcid(proc_t p
, struct __mac_get_lcid_args 
*uap
, int *ret __unused
) 
1507         char *elements
, *buffer
; 
1508         struct user_mac mac
; 
1513         AUDIT_ARG(value32
, uap
->lcid
); 
1514         if (IS_64BIT_PROCESS(p
)) { 
1515                 struct user64_mac mac64
; 
1516                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1517                 mac
.m_buflen 
= mac64
.m_buflen
; 
1518                 mac
.m_string 
= mac64
.m_string
; 
1520                 struct user32_mac mac32
; 
1521                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1522                 mac
.m_buflen 
= mac32
.m_buflen
; 
1523                 mac
.m_string 
= mac32
.m_string
; 
1529         error 
= mac_check_structmac_consistent(&mac
); 
1533         l 
= lcfind(uap
->lcid
); 
1537         MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1538         error 
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
); 
1541                 FREE(elements
, M_MACTEMP
); 
1544         AUDIT_ARG(mac_string
, elements
); 
1545         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1546         error 
= mac_lctx_label_externalize(l
->lc_label
, elements
, 
1547                                            buffer
, mac
.m_buflen
); 
1549                 error 
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1); 
1552         FREE(buffer
, M_MACTEMP
); 
1553         FREE(elements
, M_MACTEMP
); 
1559  *      Get login context label.  A login context associates a BSD process 
1560  *      associated with an instance of a user. 
1562  * Parameters:    p                        Process requesting the get 
1563  *                uap                      User argument descriptor (see below) 
1566  * Indirect:      uap->lcid                login context ID to search 
1567  *                uap->mac_p               MAC info  
1569  * Returns:        0                       Success 
1574 __mac_get_lctx(proc_t p
, struct __mac_get_lctx_args 
*uap
, int *ret __unused
) 
1576         char *elements
, *buffer
; 
1577         struct user_mac mac
; 
1581         if (IS_64BIT_PROCESS(p
)) { 
1582                 struct user64_mac mac64
; 
1583                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1584                 mac
.m_buflen 
= mac64
.m_buflen
; 
1585                 mac
.m_string 
= mac64
.m_string
; 
1587                 struct user32_mac mac32
; 
1588                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1589                 mac
.m_buflen 
= mac32
.m_buflen
; 
1590                 mac
.m_string 
= mac32
.m_string
; 
1596         error 
= mac_check_structmac_consistent(&mac
); 
1600         MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1601         error 
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
); 
1603                 FREE(elements
, M_MACTEMP
); 
1606         AUDIT_ARG(mac_string
, elements
); 
1607         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1610         if (p
->p_lctx 
== NULL
) { 
1616         error 
= mac_lctx_label_externalize(p
->p_lctx
->lc_label
, 
1617                                            elements
, buffer
, mac
.m_buflen
); 
1620                 error 
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1); 
1623         FREE(buffer
, M_MACTEMP
); 
1624         FREE(elements
, M_MACTEMP
); 
1629 __mac_set_lctx(proc_t p
, struct __mac_set_lctx_args 
*uap
, int *ret __unused
) 
1631         struct user_mac mac
; 
1632         struct label 
*intlabel
; 
1637         if (IS_64BIT_PROCESS(p
)) { 
1638                 struct user64_mac mac64
; 
1639                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1640                 mac
.m_buflen 
= mac64
.m_buflen
; 
1641                 mac
.m_string 
= mac64
.m_string
; 
1643                 struct user32_mac mac32
; 
1644                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1645                 mac
.m_buflen 
= mac32
.m_buflen
; 
1646                 mac
.m_string 
= mac32
.m_string
; 
1651         error 
= mac_check_structmac_consistent(&mac
); 
1655         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1656         error 
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
); 
1658                 FREE(buffer
, M_MACTEMP
); 
1661         AUDIT_ARG(mac_string
, buffer
); 
1663         intlabel 
= mac_lctx_label_alloc(); 
1664         error 
= mac_lctx_label_internalize(intlabel
, buffer
); 
1665         FREE(buffer
, M_MACTEMP
); 
1670         if (p
->p_lctx 
== NULL
) { 
1676         error 
= mac_lctx_check_label_update(p
->p_lctx
, intlabel
); 
1681         mac_lctx_label_update(p
->p_lctx
, intlabel
); 
1684         mac_lctx_label_free(intlabel
); 
1691 __mac_get_lcid(proc_t p __unused
, struct __mac_get_lcid_args 
*uap __unused
, int *ret __unused
) 
1698 __mac_get_lctx(proc_t p __unused
, struct __mac_get_lctx_args 
*uap __unused
, int *ret __unused
) 
1705 __mac_set_lctx(proc_t p __unused
, struct __mac_set_lctx_args 
*uap __unused
, int *ret __unused
) 
1713 __mac_get_fd(proc_t p
, struct __mac_get_fd_args 
*uap
, int *ret __unused
) 
1715         struct fileproc 
*fp
; 
1717         struct user_mac mac
; 
1718         char *elements
, *buffer
; 
1721         kauth_cred_t my_cred
; 
1722 #if CONFIG_MACF_SOCKET 
1724 #endif  /* MAC_SOCKET */ 
1725         struct label 
*intlabel
; 
1727         AUDIT_ARG(fd
, uap
->fd
); 
1729         if (IS_64BIT_PROCESS(p
)) { 
1730                 struct user64_mac mac64
; 
1731                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1732                 mac
.m_buflen 
= mac64
.m_buflen
; 
1733                 mac
.m_string 
= mac64
.m_string
; 
1735                 struct user32_mac mac32
; 
1736                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1737                 mac
.m_buflen 
= mac32
.m_buflen
; 
1738                 mac
.m_string 
= mac32
.m_string
; 
1744         error 
= mac_check_structmac_consistent(&mac
); 
1748         MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1749         error 
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
); 
1751                 FREE(elements
, M_MACTEMP
); 
1754         AUDIT_ARG(mac_string
, elements
); 
1756         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1757         error 
= fp_lookup(p
, uap
->fd
, &fp
, 0); 
1759                 FREE(buffer
, M_MACTEMP
); 
1760                 FREE(elements
, M_MACTEMP
); 
1764         my_cred 
= kauth_cred_proc_ref(p
); 
1765         error 
= mac_file_check_get(my_cred
, fp
->f_fglob
, elements
, mac
.m_buflen
); 
1766         kauth_cred_unref(&my_cred
); 
1768                 fp_drop(p
, uap
->fd
, fp
, 0); 
1769                 FREE(buffer
, M_MACTEMP
); 
1770                 FREE(elements
, M_MACTEMP
); 
1774         switch (fp
->f_fglob
->fg_type
) { 
1776                         intlabel 
= mac_vnode_label_alloc(); 
1777                         if (intlabel 
== NULL
) { 
1781                         vp 
= (struct vnode 
*)fp
->f_fglob
->fg_data
; 
1782                         error 
= vnode_getwithref(vp
); 
1784                                 mac_vnode_label_copy(vp
->v_label
, intlabel
); 
1785                                 error 
= mac_vnode_label_externalize(intlabel
, 
1787                                                 mac
.m_buflen
, M_WAITOK
); 
1790                         mac_vnode_label_free(intlabel
); 
1793 #if CONFIG_MACF_SOCKET 
1794                         so 
= (struct socket 
*) fp
->f_fglob
->fg_data
; 
1795                         intlabel 
= mac_socket_label_alloc(MAC_WAITOK
); 
1797                         mac_socket_label_copy(so
->so_label
, intlabel
); 
1799                         error 
= mac_socket_label_externalize(intlabel
, elements
, buffer
, mac
.m_buflen
); 
1800                         mac_socket_label_free(intlabel
); 
1807                 case DTYPE_FSEVENTS
: 
1809                         error 
= ENOSYS
;   // only sockets/vnodes so far 
1812         fp_drop(p
, uap
->fd
, fp
, 0); 
1815                 error 
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1); 
1817         FREE(buffer
, M_MACTEMP
); 
1818         FREE(elements
, M_MACTEMP
); 
1823 mac_get_filelink(proc_t p
, user_addr_t mac_p
, user_addr_t path_p
, int follow
) 
1827         char *elements
, *buffer
; 
1828         struct nameidata nd
; 
1829         struct label 
*intlabel
; 
1830         struct user_mac mac
; 
1834         if (IS_64BIT_PROCESS(p
)) { 
1835                 struct user64_mac mac64
; 
1836                 error 
= copyin(mac_p
, &mac64
, sizeof(mac64
)); 
1837                 mac
.m_buflen 
= mac64
.m_buflen
; 
1838                 mac
.m_string 
= mac64
.m_string
; 
1840                 struct user32_mac mac32
; 
1841                 error 
= copyin(mac_p
, &mac32
, sizeof(mac32
)); 
1842                 mac
.m_buflen 
= mac32
.m_buflen
; 
1843                 mac
.m_string 
= mac32
.m_string
; 
1849         error 
= mac_check_structmac_consistent(&mac
); 
1853         MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1854         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK 
| M_ZERO
); 
1856         error 
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
); 
1858                 FREE(buffer
, M_MACTEMP
); 
1859                 FREE(elements
, M_MACTEMP
); 
1862         AUDIT_ARG(mac_string
, elements
); 
1864         ctx 
= vfs_context_current(); 
1866         NDINIT(&nd
, LOOKUP
, OP_LOOKUP
, 
1867                 LOCKLEAF 
| (follow 
? FOLLOW 
: NOFOLLOW
) | AUDITVNPATH1
, 
1868                 UIO_USERSPACE
, path_p
, ctx
); 
1871                 FREE(buffer
, M_MACTEMP
); 
1872                 FREE(elements
, M_MACTEMP
); 
1879         intlabel 
= mac_vnode_label_alloc(); 
1880         mac_vnode_label_copy(vp
->v_label
, intlabel
); 
1881         error 
= mac_vnode_label_externalize(intlabel
, elements
, buffer
, 
1882                                             mac
.m_buflen
, M_WAITOK
); 
1883         mac_vnode_label_free(intlabel
); 
1885                 error 
= copyout(buffer
, mac
.m_string
, strlen(buffer
) + 1); 
1889         FREE(buffer
, M_MACTEMP
); 
1890         FREE(elements
, M_MACTEMP
); 
1896 __mac_get_file(proc_t p
, struct __mac_get_file_args 
*uap
, 
1900         return (mac_get_filelink(p
, uap
->mac_p
, uap
->path_p
, 1)); 
1904 __mac_get_link(proc_t p
, struct __mac_get_link_args 
*uap
, 
1908         return (mac_get_filelink(p
, uap
->mac_p
, uap
->path_p
, 0)); 
1912 __mac_set_fd(proc_t p
, struct __mac_set_fd_args 
*uap
, int *ret __unused
) 
1915         struct fileproc 
*fp
; 
1916         struct user_mac mac
; 
1917         struct vfs_context 
*ctx 
= vfs_context_current(); 
1921         struct label 
*intlabel
; 
1922 #if CONFIG_MACF_SOCKET 
1927         AUDIT_ARG(fd
, uap
->fd
); 
1929         if (IS_64BIT_PROCESS(p
)) { 
1930                 struct user64_mac mac64
; 
1931                 error 
= copyin(uap
->mac_p
, &mac64
, sizeof(mac64
)); 
1932                 mac
.m_buflen 
= mac64
.m_buflen
; 
1933                 mac
.m_string 
= mac64
.m_string
; 
1935                 struct user32_mac mac32
; 
1936                 error 
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
)); 
1937                 mac
.m_buflen 
= mac32
.m_buflen
; 
1938                 mac
.m_string 
= mac32
.m_string
; 
1943         error 
= mac_check_structmac_consistent(&mac
); 
1947         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
1948         error 
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
); 
1950                 FREE(buffer
, M_MACTEMP
); 
1953         AUDIT_ARG(mac_string
, buffer
); 
1955         error 
= fp_lookup(p
, uap
->fd
, &fp
, 0); 
1957                 FREE(buffer
, M_MACTEMP
); 
1962         error 
= mac_file_check_set(vfs_context_ucred(ctx
), fp
->f_fglob
, buffer
, mac
.m_buflen
); 
1964                 fp_drop(p
, uap
->fd
, fp
, 0); 
1965                 FREE(buffer
, M_MACTEMP
); 
1969         switch (fp
->f_fglob
->fg_type
) { 
1972                         if (mac_label_vnodes 
== 0) { 
1977                         intlabel 
= mac_vnode_label_alloc(); 
1979                         error 
= mac_vnode_label_internalize(intlabel
, buffer
); 
1981                                 mac_vnode_label_free(intlabel
); 
1986                         vp 
= (struct vnode 
*)fp
->f_fglob
->fg_data
; 
1988                         error 
= vnode_getwithref(vp
); 
1990                                 error 
= vn_setlabel(vp
, intlabel
, ctx
); 
1993                         mac_vnode_label_free(intlabel
); 
1997 #if CONFIG_MACF_SOCKET 
1998                         intlabel 
= mac_socket_label_alloc(MAC_WAITOK
); 
1999                         error 
= mac_socket_label_internalize(intlabel
, buffer
); 
2001                                 so 
= (struct socket 
*) fp
->f_fglob
->fg_data
; 
2003                                 error 
= mac_socket_label_update(vfs_context_ucred(ctx
), so
, intlabel
); 
2006                         mac_socket_label_free(intlabel
); 
2013                 case DTYPE_FSEVENTS
: 
2015                         error 
= ENOSYS
;  // only sockets/vnodes so far 
2019         fp_drop(p
, uap
->fd
, fp
, 0); 
2020         FREE(buffer
, M_MACTEMP
); 
2025 mac_set_filelink(proc_t p
, user_addr_t mac_p
, user_addr_t path_p
, 
2028         register struct vnode 
*vp
; 
2029         struct vfs_context 
*ctx 
= vfs_context_current(); 
2030         struct label 
*intlabel
; 
2031         struct nameidata nd
; 
2032         struct user_mac mac
; 
2037         if (mac_label_vnodes 
== 0) 
2040         if (IS_64BIT_PROCESS(p
)) { 
2041                 struct user64_mac mac64
; 
2042                 error 
= copyin(mac_p
, &mac64
, sizeof(mac64
)); 
2043                 mac
.m_buflen 
= mac64
.m_buflen
; 
2044                 mac
.m_string 
= mac64
.m_string
; 
2046                 struct user32_mac mac32
; 
2047                 error 
= copyin(mac_p
, &mac32
, sizeof(mac32
)); 
2048                 mac
.m_buflen 
= mac32
.m_buflen
; 
2049                 mac
.m_string 
= mac32
.m_string
; 
2054         error 
= mac_check_structmac_consistent(&mac
); 
2056                 printf("mac_set_file: failed structure consistency check\n"); 
2060         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
2061         error 
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
); 
2063                 FREE(buffer
, M_MACTEMP
); 
2066         AUDIT_ARG(mac_string
, buffer
); 
2068         intlabel 
= mac_vnode_label_alloc(); 
2069         error 
= mac_vnode_label_internalize(intlabel
, buffer
); 
2070         FREE(buffer
, M_MACTEMP
); 
2072                 mac_vnode_label_free(intlabel
); 
2076         NDINIT(&nd
, LOOKUP
, OP_LOOKUP
, 
2077                 LOCKLEAF 
| (follow 
? FOLLOW 
: NOFOLLOW
) | AUDITVNPATH1
, 
2078                 UIO_USERSPACE
, path_p
, ctx
); 
2081                 mac_vnode_label_free(intlabel
); 
2088         error 
= vn_setlabel(vp
, intlabel
, ctx
); 
2090         mac_vnode_label_free(intlabel
); 
2096 __mac_set_file(proc_t p
, struct __mac_set_file_args 
*uap
, 
2100         return (mac_set_filelink(p
, uap
->mac_p
, uap
->path_p
, 1)); 
2104 __mac_set_link(proc_t p
, struct __mac_set_link_args 
*uap
, 
2108         return (mac_set_filelink(p
, uap
->mac_p
, uap
->path_p
, 0)); 
2112  * __mac_syscall: Perform a MAC policy system call 
2114  * Parameters:    p                       Process calling this routine 
2115  *                uap                     User argument descriptor (see below) 
2118  * Indirect:      uap->policy             Name of target MAC policy 
2119  *                uap->call               MAC policy-specific system call to perform 
2120  *                uap->arg                MAC policy-specific system call arguments 
2122  * Returns:        0                      Success 
2127 __mac_syscall(proc_t p
, struct __mac_syscall_args 
*uap
, int *retv __unused
) 
2129         struct mac_policy_conf 
*mpc
; 
2130         char target
[MAC_MAX_POLICY_NAME
]; 
2135         error 
= copyinstr(uap
->policy
, target
, sizeof(target
), &ulen
); 
2138         AUDIT_ARG(value32
, uap
->call
); 
2139         AUDIT_ARG(mac_string
, target
); 
2143         for (i 
= 0; i 
< mac_policy_list
.staticmax
; i
++) { 
2144                 mpc 
= mac_policy_list
.entries
[i
].mpc
; 
2148                 if (strcmp(mpc
->mpc_name
, target
) == 0 && 
2149                     mpc
->mpc_ops
->mpo_policy_syscall 
!= NULL
) { 
2150                         error 
= mpc
->mpc_ops
->mpo_policy_syscall(p
, 
2151                             uap
->call
, uap
->arg
); 
2155         if (mac_policy_list_conditional_busy() != 0) { 
2156                 for (; i 
<= mac_policy_list
.maxindex
; i
++) { 
2157                         mpc 
= mac_policy_list
.entries
[i
].mpc
; 
2161                         if (strcmp(mpc
->mpc_name
, target
) == 0 && 
2162                             mpc
->mpc_ops
->mpo_policy_syscall 
!= NULL
) { 
2163                                 error 
= mpc
->mpc_ops
->mpo_policy_syscall(p
, 
2164                                     uap
->call
, uap
->arg
); 
2168                 mac_policy_list_unbusy(); 
2176 mac_mount_label_get(struct mount 
*mp
, user_addr_t mac_p
) 
2178         char *elements
, *buffer
; 
2179         struct label 
*label
; 
2180         struct user_mac mac
; 
2184         if (IS_64BIT_PROCESS(current_proc())) { 
2185                 struct user64_mac mac64
; 
2186                 error 
= copyin(mac_p
, &mac64
, sizeof(mac64
)); 
2187                 mac
.m_buflen 
= mac64
.m_buflen
; 
2188                 mac
.m_string 
= mac64
.m_string
; 
2190                 struct user32_mac mac32
; 
2191                 error 
= copyin(mac_p
, &mac32
, sizeof(mac32
)); 
2192                 mac
.m_buflen 
= mac32
.m_buflen
; 
2193                 mac
.m_string 
= mac32
.m_string
; 
2198         error 
= mac_check_structmac_consistent(&mac
); 
2202         MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
); 
2203         error 
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
); 
2205                 FREE(elements
, M_MACTEMP
); 
2208         AUDIT_ARG(mac_string
, elements
); 
2210         label 
= mp
->mnt_mntlabel
; 
2211         MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK 
| M_ZERO
); 
2212         error 
= mac_mount_label_externalize(label
, elements
, buffer
, 
2214         FREE(elements
, M_MACTEMP
); 
2217                 error 
= copyout(buffer
, mac
.m_string
, strlen(buffer
) + 1); 
2218         FREE(buffer
, M_MACTEMP
); 
2224  * __mac_get_mount: Get mount point label information for a given pathname 
2226  * Parameters:    p                        (ignored) 
2227  *                uap                      User argument descriptor (see below) 
2230  * Indirect:      uap->path                Pathname 
2231  *                uap->mac_p               MAC info  
2233  * Returns:        0                       Success 
2237 __mac_get_mount(proc_t p __unused
, struct __mac_get_mount_args 
*uap
, 
2240         struct nameidata nd
; 
2241         struct vfs_context 
*ctx 
= vfs_context_current(); 
2245         NDINIT(&nd
, LOOKUP
, OP_LOOKUP
, FOLLOW 
| AUDITVNPATH1
, 
2246                 UIO_USERSPACE
, uap
->path
, ctx
); 
2251         mp 
= nd
.ni_vp
->v_mount
; 
2254         return mac_mount_label_get(mp
, uap
->mac_p
); 
2260 mac_policy_register(struct mac_policy_conf 
*mpc __unused
,  
2261         mac_policy_handle_t 
*handlep __unused
, void *xd __unused
) 
2268 mac_policy_unregister(mac_policy_handle_t handle __unused
) 
2275 mac_audit_text(char *text __unused
, mac_policy_handle_t handle __unused
) 
2282 mac_mount_label_get(struct mount 
*mp __unused
, user_addr_t mac_p __unused
) 
2288 mac_vnop_setxattr(struct vnode 
*vp __unused
, const char *name __unused
, char *buf __unused
, size_t len __unused
) 
2295 mac_vnop_getxattr(struct vnode 
*vp __unused
, const char *name __unused
,  
2296         char *buf __unused
, size_t len __unused
, size_t *attrlen __unused
) 
2303 mac_vnop_removexattr(struct vnode 
*vp __unused
, const char *name __unused
) 
2310 __mac_get_pid(proc_t p __unused
, struct __mac_get_pid_args 
*uap __unused
, int *ret __unused
) 
2317 __mac_get_proc(proc_t p __unused
, struct __mac_get_proc_args 
*uap __unused
, int *ret __unused
) 
2324 __mac_set_proc(proc_t p __unused
, struct __mac_set_proc_args 
*uap __unused
, int *ret __unused
) 
2331 __mac_get_file(proc_t p __unused
, struct __mac_get_file_args 
*uap __unused
, int *ret __unused
) 
2338 __mac_get_link(proc_t p __unused
, struct __mac_get_link_args 
*uap __unused
, int *ret __unused
) 
2345 __mac_set_file(proc_t p __unused
, struct __mac_set_file_args 
*uap __unused
, int *ret __unused
) 
2352 __mac_set_link(proc_t p __unused
, struct __mac_set_link_args 
*uap __unused
, int *ret __unused
) 
2359 __mac_get_fd(proc_t p __unused
, struct __mac_get_fd_args 
*uap __unused
, int *ret __unused
) 
2366 __mac_set_fd(proc_t p __unused
, struct __mac_set_fd_args 
*uap __unused
, int *ret __unused
) 
2373 __mac_syscall(proc_t p __unused
, struct __mac_syscall_args 
*uap __unused
, int *ret __unused
) 
2380 __mac_get_lcid(proc_t p __unused
, struct __mac_get_lcid_args 
*uap __unused
, int *ret __unused
) 
2387 __mac_get_lctx(proc_t p __unused
, struct __mac_get_lctx_args 
*uap __unused
, int *ret __unused
) 
2394 __mac_set_lctx(proc_t p __unused
, struct __mac_set_lctx_args 
*uap __unused
, int *ret __unused
) 
2401 __mac_get_mount(proc_t p __unused
, 
2402     struct __mac_get_mount_args 
*uap __unused
, int *ret __unused
)