The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/security/mac_base.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: fbe7b5f9fdd084677ca1d44ae4a5574b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.