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

Cache object: 6213027aa514f753fb92539359c47cc3


[ 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.