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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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,
  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                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1350         } else {
 1351                 struct mac mac32;
 1352                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1353                 mac.m_buflen = mac32.m_buflen;
 1354                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1355         }
 1356         if (error)
 1357                 return (error);
 1358 
 1359         error = mac_check_structmac_consistent(&mac);
 1360         if (error)
 1361                 return (error);
 1362 
 1363         tproc = proc_find(uap->pid);
 1364         if (tproc == NULL)
 1365                 return (ESRCH);
 1366         tcred = kauth_cred_proc_ref(tproc);
 1367         proc_rele(tproc);
 1368 
 1369         MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1370         error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
 1371         if (error) {
 1372                 FREE(elements, M_MACTEMP);
 1373                 kauth_cred_unref(&tcred);
 1374                 return (error);
 1375         }
 1376         AUDIT_ARG(mac_string, elements);
 1377 
 1378         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 1379         error = mac_cred_label_externalize(tcred->cr_label, elements,
 1380             buffer, mac.m_buflen, M_WAITOK);
 1381         if (error == 0)
 1382                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 1383 
 1384         FREE(buffer, M_MACTEMP);
 1385         FREE(elements, M_MACTEMP);
 1386         kauth_cred_unref(&tcred);
 1387         return (error);
 1388 }
 1389 
 1390 int
 1391 __mac_get_proc(proc_t p, struct __mac_get_proc_args *uap, int *ret __unused)
 1392 {
 1393         char *elements, *buffer;
 1394         struct user_mac mac;
 1395         kauth_cred_t cr;
 1396         int error;
 1397         size_t ulen;
 1398 
 1399         if (IS_64BIT_PROCESS(p)) {
 1400                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1401         } else {
 1402                 struct mac mac32;
 1403                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1404                 mac.m_buflen = mac32.m_buflen;
 1405                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1406         }
 1407         if (error)
 1408                 return (error);
 1409 
 1410         error = mac_check_structmac_consistent(&mac);
 1411         if (error)
 1412                 return (error);
 1413 
 1414         MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1415         error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
 1416         if (error) {
 1417                 FREE(elements, M_MACTEMP);
 1418                 return (error);
 1419         }
 1420         AUDIT_ARG(mac_string, elements);
 1421 
 1422         cr = kauth_cred_proc_ref(p);
 1423 
 1424         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 1425         error = mac_cred_label_externalize(cr->cr_label,
 1426             elements, buffer, mac.m_buflen, M_WAITOK);
 1427         if (error == 0)
 1428                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 1429 
 1430         FREE(buffer, M_MACTEMP);
 1431         FREE(elements, M_MACTEMP);
 1432         kauth_cred_unref(&cr);
 1433         return (error);
 1434 }
 1435 
 1436 int
 1437 __mac_set_proc(proc_t p, struct __mac_set_proc_args *uap, int *ret __unused)
 1438 {
 1439         kauth_cred_t newcred;
 1440         struct label *intlabel;
 1441         struct user_mac mac;
 1442         char *buffer;
 1443         int error;
 1444         size_t ulen;
 1445 
 1446         if (IS_64BIT_PROCESS(p)) {
 1447                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1448         } else {
 1449                 struct mac mac32;
 1450                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1451                 mac.m_buflen = mac32.m_buflen;
 1452                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1453         }
 1454         if (error)
 1455                 return (error);
 1456 
 1457         error = mac_check_structmac_consistent(&mac);
 1458         if (error)
 1459                 return (error);
 1460 
 1461         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1462         error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
 1463         if (error) {
 1464                 FREE(buffer, M_MACTEMP);
 1465                 return (error);
 1466         }
 1467         AUDIT_ARG(mac_string, buffer);
 1468 
 1469         intlabel = mac_cred_label_alloc();
 1470         error = mac_cred_label_internalize(intlabel, buffer);
 1471         FREE(buffer, M_MACTEMP);
 1472         if (error)
 1473                 goto out;
 1474 
 1475         error = mac_cred_check_label_update(kauth_cred_get(), intlabel);
 1476         if (error) {
 1477                 goto out;
 1478         }
 1479 
 1480         error = kauth_proc_label_update(p, intlabel);
 1481         if (error)
 1482                 goto out;
 1483 
 1484         newcred = kauth_cred_proc_ref(p);
 1485         mac_task_label_update_cred(newcred, p->task);
 1486 
 1487 #if 0
 1488         if (mac_vm_enforce) {
 1489                 mutex_lock(Giant);                      /* XXX FUNNEL? */
 1490                 mac_cred_mmapped_drop_perms(p, newcred);
 1491                 mutex_unlock(Giant);                    /* XXX FUNNEL? */
 1492         }
 1493 #endif
 1494 
 1495         kauth_cred_unref(&newcred);
 1496 out:
 1497         mac_cred_label_free(intlabel);
 1498         return (error);
 1499 }
 1500 
 1501 #if CONFIG_LCTX
 1502 /*
 1503  * __mac_get_lcid: 
 1504  *      Get login context ID.  A login context associates a BSD process 
 1505  *      with an instance of a user.  For more information see getlcid(2) man page.
 1506  *
 1507  * Parameters:    p                        Process requesting the get
 1508  *                uap                      User argument descriptor (see below)
 1509  *                ret                      (ignored)
 1510  *
 1511  * Indirect:      uap->lcid                login context ID to search
 1512  *                uap->mac_p.m_buflen      MAC info buffer size
 1513  *                uap->mac_p.m_string      MAC info user address
 1514  *
 1515  * Returns:        0                       Success
 1516  *                !0                       Not success
 1517  */
 1518 int
 1519 __mac_get_lcid(proc_t p, struct __mac_get_lcid_args *uap, int *ret __unused)
 1520 {
 1521         char *elements, *buffer;
 1522         struct user_mac mac;
 1523         struct lctx *l;
 1524         int error;
 1525         size_t ulen;
 1526 
 1527         AUDIT_ARG(value32, uap->lcid);
 1528         if (IS_64BIT_PROCESS(p)) {
 1529                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1530         } else {
 1531                 struct mac mac32;
 1532                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1533                 mac.m_buflen = mac32.m_buflen;
 1534                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1535         }
 1536 
 1537         if (error)
 1538                 return (error);
 1539 
 1540         error = mac_check_structmac_consistent(&mac);
 1541         if (error)
 1542                 return (error);
 1543 
 1544         l = lcfind(uap->lcid);
 1545         if (l == NULL)
 1546                 return (ESRCH);
 1547 
 1548         MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1549         error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
 1550         if (error) {
 1551                 LCTX_UNLOCK(l);
 1552                 FREE(elements, M_MACTEMP);
 1553                 return (error);
 1554         }
 1555         AUDIT_ARG(mac_string, elements);
 1556         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1557         error = mac_lctx_label_externalize(l->lc_label, elements,
 1558                                            buffer, mac.m_buflen);
 1559         if (error == 0)
 1560                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 1561 
 1562         LCTX_UNLOCK(l);
 1563         FREE(buffer, M_MACTEMP);
 1564         FREE(elements, M_MACTEMP);
 1565         return (error);
 1566 }
 1567 
 1568 /*
 1569  * __mac_get_lctx:
 1570  *      Get login context label.  A login context associates a BSD process
 1571  *      associated with an instance of a user.
 1572  *
 1573  * Parameters:    p                        Process requesting the get
 1574  *                uap                      User argument descriptor (see below)
 1575  *                ret                      (ignored)
 1576  *
 1577  * Indirect:      uap->lcid                login context ID to search
 1578  *                uap->mac_p               MAC info 
 1579  *
 1580  * Returns:        0                       Success
 1581  *                !0                       Not success
 1582  *
 1583  */
 1584 int
 1585 __mac_get_lctx(proc_t p, struct __mac_get_lctx_args *uap, int *ret __unused)
 1586 {
 1587         char *elements, *buffer;
 1588         struct user_mac mac;
 1589         int error;
 1590         size_t ulen;
 1591 
 1592         if (IS_64BIT_PROCESS(p)) {
 1593                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1594         } else {
 1595                 struct mac mac32;
 1596                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1597                 mac.m_buflen = mac32.m_buflen;
 1598                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1599         }
 1600 
 1601         if (error)
 1602                 return (error);
 1603 
 1604         error = mac_check_structmac_consistent(&mac);
 1605         if (error)
 1606                 return (error);
 1607 
 1608         MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1609         error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
 1610         if (error) {
 1611                 FREE(elements, M_MACTEMP);
 1612                 return (error);
 1613         }
 1614         AUDIT_ARG(mac_string, elements);
 1615         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1616 
 1617         proc_lock(p);
 1618         if (p->p_lctx == NULL) {
 1619                 proc_unlock(p);
 1620                 error = ENOENT;
 1621                 goto out;
 1622         }
 1623 
 1624         error = mac_lctx_label_externalize(p->p_lctx->lc_label,
 1625                                            elements, buffer, mac.m_buflen);
 1626         proc_unlock(p);
 1627         if (error == 0)
 1628                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 1629 
 1630 out:
 1631         FREE(buffer, M_MACTEMP);
 1632         FREE(elements, M_MACTEMP);
 1633         return (error);
 1634 }
 1635 
 1636 int
 1637 __mac_set_lctx(proc_t p, struct __mac_set_lctx_args *uap, int *ret __unused)
 1638 {
 1639         struct user_mac mac;
 1640         struct label *intlabel;
 1641         char *buffer;
 1642         int error;
 1643         size_t ulen;
 1644 
 1645         if (IS_64BIT_PROCESS(p)) {
 1646                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1647         } else {
 1648                 struct mac mac32;
 1649                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1650                 mac.m_buflen = mac32.m_buflen;
 1651                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1652         }
 1653         if (error)
 1654                 return (error);
 1655 
 1656         error = mac_check_structmac_consistent(&mac);
 1657         if (error)
 1658                 return (error);
 1659 
 1660         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1661         error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
 1662         if (error) {
 1663                 FREE(buffer, M_MACTEMP);
 1664                 return (error);
 1665         }
 1666         AUDIT_ARG(mac_string, buffer);
 1667 
 1668         intlabel = mac_lctx_label_alloc();
 1669         error = mac_lctx_label_internalize(intlabel, buffer);
 1670         FREE(buffer, M_MACTEMP);
 1671         if (error)
 1672                 goto out;
 1673 
 1674         proc_lock(p);
 1675         if (p->p_lctx == NULL) {
 1676                 proc_unlock(p);
 1677                 error = ENOENT;
 1678                 goto out;
 1679         }
 1680 
 1681         error = mac_lctx_check_label_update(p->p_lctx, intlabel);
 1682         if (error) {
 1683                 proc_unlock(p);
 1684                 goto out;
 1685         }
 1686         mac_lctx_label_update(p->p_lctx, intlabel);
 1687         proc_unlock(p);
 1688 out:
 1689         mac_lctx_label_free(intlabel);
 1690         return (error);
 1691 }
 1692 
 1693 #else   /* LCTX */
 1694 
 1695 int
 1696 __mac_get_lcid(proc_t p __unused, struct __mac_get_lcid_args *uap __unused, int *ret __unused)
 1697 {
 1698 
 1699         return (ENOSYS);
 1700 }
 1701 
 1702 int
 1703 __mac_get_lctx(proc_t p __unused, struct __mac_get_lctx_args *uap __unused, int *ret __unused)
 1704 {
 1705 
 1706         return (ENOSYS);
 1707 }
 1708 
 1709 int
 1710 __mac_set_lctx(proc_t p __unused, struct __mac_set_lctx_args *uap __unused, int *ret __unused)
 1711 {
 1712 
 1713         return (ENOSYS);
 1714 }
 1715 #endif  /* !LCTX */
 1716 
 1717 int
 1718 __mac_get_fd(proc_t p, struct __mac_get_fd_args *uap, int *ret __unused)
 1719 {
 1720         struct fileproc *fp;
 1721         struct vnode *vp;
 1722         struct user_mac mac;
 1723         char *elements, *buffer;
 1724         int error;
 1725         size_t ulen;
 1726         kauth_cred_t my_cred;
 1727 #if CONFIG_MACF_SOCKET
 1728         struct socket *so;
 1729 #endif  /* MAC_SOCKET */
 1730         struct label *intlabel;
 1731 
 1732         AUDIT_ARG(fd, uap->fd);
 1733 
 1734         if (IS_64BIT_PROCESS(p)) {
 1735                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1736         } else {
 1737                 struct mac mac32;
 1738                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1739                 mac.m_buflen = mac32.m_buflen;
 1740                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1741         }
 1742 
 1743         if (error) 
 1744                 return (error);
 1745 
 1746         error = mac_check_structmac_consistent(&mac);
 1747         if (error)
 1748                 return (error);
 1749                         
 1750         MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1751         error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
 1752         if (error) {
 1753                 FREE(elements, M_MACTEMP);
 1754                 return (error);
 1755         }
 1756         AUDIT_ARG(mac_string, elements);
 1757 
 1758         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1759         error = fp_lookup(p, uap->fd, &fp, 0);
 1760         if (error) {
 1761                 FREE(buffer, M_MACTEMP);
 1762                 FREE(elements, M_MACTEMP);
 1763                 return (error);
 1764         }
 1765         
 1766         my_cred = kauth_cred_proc_ref(p);
 1767         error = mac_file_check_get(my_cred, fp->f_fglob, elements, mac.m_buflen);
 1768         kauth_cred_unref(&my_cred);
 1769         if (error) {
 1770                 fp_drop(p, uap->fd, fp, 0);
 1771                 FREE(buffer, M_MACTEMP);
 1772                 FREE(elements, M_MACTEMP);
 1773                 return (error);
 1774         }
 1775         
 1776         switch (fp->f_fglob->fg_type) {
 1777                 case DTYPE_VNODE:
 1778                         intlabel = mac_vnode_label_alloc();
 1779                         if (intlabel == NULL) {
 1780                                 error = ENOMEM;
 1781                                 break;
 1782                         }
 1783                         vp = (struct vnode *)fp->f_fglob->fg_data;
 1784                         error = vnode_getwithref(vp);
 1785                         if (error == 0) {
 1786                                 mac_vnode_label_copy(vp->v_label, intlabel);
 1787                                 error = mac_vnode_label_externalize(intlabel,
 1788                                                 elements, buffer,
 1789                                                 mac.m_buflen, M_WAITOK);
 1790                                 vnode_put(vp);
 1791                         }
 1792                         mac_vnode_label_free(intlabel);
 1793                         break;
 1794                 case DTYPE_SOCKET:
 1795 #if CONFIG_MACF_SOCKET
 1796                         so = (struct socket *) fp->f_fglob->fg_data;
 1797                         intlabel = mac_socket_label_alloc(MAC_WAITOK);
 1798                         sock_lock(so, 1);
 1799                         mac_socket_label_copy(so->so_label, intlabel);
 1800                         sock_unlock(so, 1);
 1801                         error = mac_socket_label_externalize(intlabel, elements, buffer, mac.m_buflen);
 1802                         mac_socket_label_free(intlabel);
 1803                         break;
 1804 #endif
 1805                 case DTYPE_PSXSHM:
 1806                 case DTYPE_PSXSEM:
 1807                 case DTYPE_PIPE:
 1808                 case DTYPE_KQUEUE:
 1809                 case DTYPE_FSEVENTS:
 1810                 default:
 1811                         error = ENOSYS;   // only sockets/vnodes so far
 1812                         break;
 1813         }
 1814         fp_drop(p, uap->fd, fp, 0);
 1815         
 1816         if (error == 0)
 1817                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 1818                 
 1819         FREE(buffer, M_MACTEMP);
 1820         FREE(elements, M_MACTEMP);
 1821         return (error);
 1822 }
 1823 
 1824 static int
 1825 mac_get_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p, int follow)
 1826 {
 1827         struct vnode *vp;
 1828         vfs_context_t ctx;
 1829         char *elements, *buffer;
 1830         struct nameidata nd;
 1831         struct label *intlabel;
 1832         struct user_mac mac;
 1833         int error;
 1834         size_t ulen;
 1835 
 1836         if (IS_64BIT_PROCESS(p)) {
 1837                 error = copyin(mac_p, &mac, sizeof(mac));
 1838         } else {
 1839                 struct mac mac32;
 1840                 error = copyin(mac_p, &mac32, sizeof(mac32));
 1841                 mac.m_buflen = mac32.m_buflen;
 1842                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1843         }
 1844 
 1845         if (error)
 1846                 return (error);
 1847 
 1848         error = mac_check_structmac_consistent(&mac);
 1849         if (error)
 1850                 return (error);
 1851 
 1852         MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1853         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 1854 
 1855         error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
 1856         if (error) {
 1857                 FREE(buffer, M_MACTEMP);
 1858                 FREE(elements, M_MACTEMP);
 1859                 return (error);
 1860         }
 1861         AUDIT_ARG(mac_string, elements);
 1862 
 1863         ctx = vfs_context_current();
 1864 
 1865         NDINIT(&nd, LOOKUP,
 1866                 LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1,
 1867                 UIO_USERSPACE, path_p, ctx);
 1868         error = namei(&nd);
 1869         if (error) {
 1870                 FREE(buffer, M_MACTEMP);
 1871                 FREE(elements, M_MACTEMP);
 1872                 return (error);
 1873         }
 1874         vp = nd.ni_vp;
 1875 
 1876         nameidone(&nd);
 1877 
 1878         intlabel = mac_vnode_label_alloc();
 1879         mac_vnode_label_copy(vp->v_label, intlabel);
 1880         error = mac_vnode_label_externalize(intlabel, elements, buffer,
 1881                                             mac.m_buflen, M_WAITOK);
 1882         mac_vnode_label_free(intlabel);
 1883         if (error == 0)
 1884                 error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
 1885 
 1886         vnode_put(vp);
 1887 
 1888         FREE(buffer, M_MACTEMP);
 1889         FREE(elements, M_MACTEMP);
 1890 
 1891         return (error);
 1892 }
 1893 
 1894 int
 1895 __mac_get_file(proc_t p, struct __mac_get_file_args *uap,
 1896                int *ret __unused)
 1897 {
 1898 
 1899         return (mac_get_filelink(p, uap->mac_p, uap->path_p, 1));
 1900 }
 1901 
 1902 int
 1903 __mac_get_link(proc_t p, struct __mac_get_link_args *uap,
 1904                int *ret __unused)
 1905 {
 1906 
 1907         return (mac_get_filelink(p, uap->mac_p, uap->path_p, 0));
 1908 }
 1909 
 1910 int
 1911 __mac_set_fd(proc_t p, struct __mac_set_fd_args *uap, int *ret __unused)
 1912 {
 1913 
 1914         struct fileproc *fp;
 1915         struct user_mac mac;
 1916         struct vfs_context *ctx = vfs_context_current();
 1917         int error;
 1918         size_t ulen;
 1919         char *buffer;
 1920         struct label *intlabel;
 1921 #if CONFIG_MACF_SOCKET
 1922         struct socket *so;
 1923 #endif
 1924         struct vnode *vp;
 1925 
 1926         AUDIT_ARG(fd, uap->fd);
 1927 
 1928         if (IS_64BIT_PROCESS(p)) {
 1929                 error = copyin(uap->mac_p, &mac, sizeof(mac));
 1930         } else {
 1931                 struct mac mac32;
 1932                 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
 1933                 mac.m_buflen = mac32.m_buflen;
 1934                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 1935         }
 1936         if (error) 
 1937                 return (error);
 1938                 
 1939         error = mac_check_structmac_consistent(&mac);
 1940         if (error)
 1941                 return (error);
 1942         
 1943         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 1944         error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
 1945         if (error) {
 1946                 FREE(buffer, M_MACTEMP);
 1947                 return (error);
 1948         }
 1949         AUDIT_ARG(mac_string, buffer);
 1950         
 1951         error = fp_lookup(p, uap->fd, &fp, 0);
 1952         if (error) {
 1953                 FREE(buffer, M_MACTEMP);
 1954                 return (error);
 1955         }
 1956         
 1957 
 1958         error = mac_file_check_set(vfs_context_ucred(ctx), fp->f_fglob, buffer, mac.m_buflen);
 1959         if (error) {
 1960                 fp_drop(p, uap->fd, fp, 0);
 1961                 FREE(buffer, M_MACTEMP);
 1962                 return (error);
 1963         }
 1964         
 1965         switch (fp->f_fglob->fg_type) {
 1966 
 1967                 case DTYPE_VNODE:
 1968                         if (mac_label_vnodes == 0) {
 1969                                 error = ENOSYS;
 1970                                 break;
 1971                         }
 1972 
 1973                         intlabel = mac_vnode_label_alloc();
 1974 
 1975                         error = mac_vnode_label_internalize(intlabel, buffer);
 1976                         if (error) {
 1977                                 mac_vnode_label_free(intlabel);
 1978                                 break;
 1979                         }
 1980 
 1981 
 1982                         vp = (struct vnode *)fp->f_fglob->fg_data;
 1983 
 1984                         error = vnode_getwithref(vp);
 1985                         if (error == 0) {
 1986                                 error = vn_setlabel(vp, intlabel, ctx);
 1987                                 vnode_put(vp);
 1988                         }
 1989                         mac_vnode_label_free(intlabel);
 1990                         break;
 1991 
 1992                 case DTYPE_SOCKET:
 1993 #if CONFIG_MACF_SOCKET
 1994                         intlabel = mac_socket_label_alloc(MAC_WAITOK);
 1995                         error = mac_socket_label_internalize(intlabel, buffer);
 1996                         if (error == 0) {
 1997                                 so = (struct socket *) fp->f_fglob->fg_data;
 1998                                 SOCK_LOCK(so);
 1999                                 error = mac_socket_label_update(vfs_context_ucred(ctx), so, intlabel);
 2000                                 SOCK_UNLOCK(so);
 2001                         }
 2002                         mac_socket_label_free(intlabel);
 2003                         break;
 2004 #endif
 2005                 case DTYPE_PSXSHM:
 2006                 case DTYPE_PSXSEM:
 2007                 case DTYPE_PIPE:
 2008                 case DTYPE_KQUEUE:
 2009                 case DTYPE_FSEVENTS:
 2010                 default:
 2011                         error = ENOSYS;  // only sockets/vnodes so far
 2012                         break;
 2013         }
 2014 
 2015         fp_drop(p, uap->fd, fp, 0);
 2016         FREE(buffer, M_MACTEMP);
 2017         return (error);
 2018 }
 2019 
 2020 static int
 2021 mac_set_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p,
 2022                  int follow)
 2023 {
 2024         register struct vnode *vp;
 2025         struct vfs_context *ctx = vfs_context_current();
 2026         struct label *intlabel;
 2027         struct nameidata nd;
 2028         struct user_mac mac;
 2029         char *buffer;
 2030         int error;
 2031         size_t ulen;
 2032 
 2033         if (mac_label_vnodes == 0)
 2034                 return ENOSYS;
 2035 
 2036         if (IS_64BIT_PROCESS(p)) {
 2037                 error = copyin(mac_p, &mac, sizeof(mac));
 2038         } else {
 2039                 struct mac mac32;
 2040                 error = copyin(mac_p, &mac32, sizeof(mac32));
 2041                 mac.m_buflen = mac32.m_buflen;
 2042                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 2043         }
 2044         if (error)
 2045                 return (error);
 2046 
 2047         error = mac_check_structmac_consistent(&mac);
 2048         if (error) {
 2049                 printf("mac_set_file: failed structure consistency check\n");
 2050                 return (error);
 2051         }
 2052 
 2053         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 2054         error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
 2055         if (error) {
 2056                 FREE(buffer, M_MACTEMP);
 2057                 return (error);
 2058         }
 2059         AUDIT_ARG(mac_string, buffer);
 2060 
 2061         intlabel = mac_vnode_label_alloc();
 2062         error = mac_vnode_label_internalize(intlabel, buffer);
 2063         FREE(buffer, M_MACTEMP);
 2064         if (error) {
 2065                 mac_vnode_label_free(intlabel);
 2066                 return (error);
 2067         }
 2068 
 2069         NDINIT(&nd, LOOKUP,
 2070                 LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1,
 2071                 UIO_USERSPACE, path_p, ctx);
 2072         error = namei(&nd);
 2073         if (error) {
 2074                 mac_vnode_label_free(intlabel);
 2075                 return (error);
 2076         }
 2077         vp = nd.ni_vp;
 2078 
 2079         nameidone(&nd);
 2080 
 2081         error = vn_setlabel(vp, intlabel, ctx);
 2082         vnode_put(vp);
 2083         mac_vnode_label_free(intlabel);
 2084 
 2085         return (error);
 2086 }
 2087 
 2088 int
 2089 __mac_set_file(proc_t p, struct __mac_set_file_args *uap,
 2090                int *ret __unused)
 2091 {
 2092 
 2093         return (mac_set_filelink(p, uap->mac_p, uap->path_p, 1));
 2094 }
 2095 
 2096 int
 2097 __mac_set_link(proc_t p, struct __mac_set_link_args *uap,
 2098                int *ret __unused)
 2099 {
 2100 
 2101         return (mac_set_filelink(p, uap->mac_p, uap->path_p, 0));
 2102 }
 2103 
 2104 /*
 2105  * __mac_syscall: Perform a MAC policy system call
 2106  *
 2107  * Parameters:    p                       Process calling this routine
 2108  *                uap                     User argument descriptor (see below)
 2109  *                retv                    (Unused)
 2110  *
 2111  * Indirect:      uap->policy             Name of target MAC policy
 2112  *                uap->call               MAC policy-specific system call to perform
 2113  *                uap->arg                MAC policy-specific system call arguments
 2114  *                
 2115  * Returns:        0                      Success
 2116  *                !0                      Not success
 2117  *
 2118  */
 2119 int
 2120 __mac_syscall(proc_t p, struct __mac_syscall_args *uap, int *retv __unused)
 2121 {
 2122         struct mac_policy_conf *mpc;
 2123         char target[MAC_MAX_POLICY_NAME];
 2124         int error;
 2125         u_int i;
 2126         size_t ulen;
 2127 
 2128         error = copyinstr(uap->policy, target, sizeof(target), &ulen);
 2129         if (error)
 2130                 return (error);
 2131         AUDIT_ARG(value32, uap->call);
 2132         AUDIT_ARG(mac_string, target);
 2133 
 2134         error = ENOPOLICY;
 2135 
 2136         for (i = 0; i < mac_policy_list.staticmax; i++) {
 2137                 mpc = mac_policy_list.entries[i].mpc;
 2138                 if (mpc == NULL)
 2139                         continue;
 2140 
 2141                 if (strcmp(mpc->mpc_name, target) == 0 &&
 2142                     mpc->mpc_ops->mpo_policy_syscall != NULL) {
 2143                         error = mpc->mpc_ops->mpo_policy_syscall(p,
 2144                             uap->call, uap->arg);
 2145                         goto done;
 2146                 }
 2147         }
 2148         if (mac_policy_list_conditional_busy() != 0) {
 2149                 for (; i <= mac_policy_list.maxindex; i++) {
 2150                         mpc = mac_policy_list.entries[i].mpc;
 2151                         if (mpc == NULL)
 2152                                 continue;
 2153 
 2154                         if (strcmp(mpc->mpc_name, target) == 0 &&
 2155                             mpc->mpc_ops->mpo_policy_syscall != NULL) {
 2156                                 error = mpc->mpc_ops->mpo_policy_syscall(p,
 2157                                     uap->call, uap->arg);
 2158                                 break;
 2159                         }
 2160                 }
 2161                 mac_policy_list_unbusy();
 2162         }
 2163 
 2164 done:
 2165         return (error);
 2166 }
 2167 
 2168 int
 2169 mac_mount_label_get(struct mount *mp, user_addr_t mac_p)
 2170 {
 2171         char *elements, *buffer;
 2172         struct label *label;
 2173         struct user_mac mac;
 2174         int error;
 2175         size_t ulen;
 2176 
 2177         if (IS_64BIT_PROCESS(current_proc())) {
 2178                 error = copyin(mac_p, &mac, sizeof(mac));
 2179         } else {
 2180                 struct mac mac32;
 2181                 error = copyin(mac_p, &mac32, sizeof(mac32));
 2182                 mac.m_buflen = mac32.m_buflen;
 2183                 mac.m_string = CAST_USER_ADDR_T(mac32.m_string);
 2184         }
 2185         if (error)
 2186                 return (error);
 2187 
 2188         error = mac_check_structmac_consistent(&mac);
 2189         if (error)
 2190                 return (error);
 2191 
 2192         MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
 2193         error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
 2194         if (error) {
 2195                 FREE(elements, M_MACTEMP);
 2196                 return (error);
 2197         }
 2198         AUDIT_ARG(mac_string, elements);
 2199 
 2200         label = mp->mnt_mntlabel;
 2201         MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 2202         error = mac_mount_label_externalize(label, elements, buffer,
 2203             mac.m_buflen);
 2204         FREE(elements, M_MACTEMP);
 2205 
 2206         if (error == 0)
 2207                 error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
 2208         FREE(buffer, M_MACTEMP);
 2209 
 2210         return (error);
 2211 }
 2212 
 2213 /*
 2214  * __mac_get_mount: Get mount point label information for a given pathname
 2215  *
 2216  * Parameters:    p                        (ignored)
 2217  *                uap                      User argument descriptor (see below)
 2218  *                ret                      (ignored)
 2219  *
 2220  * Indirect:      uap->path                Pathname
 2221  *                uap->mac_p               MAC info 
 2222  *
 2223  * Returns:        0                       Success
 2224  *                !0                       Not success
 2225  */
 2226 int
 2227 __mac_get_mount(proc_t p __unused, struct __mac_get_mount_args *uap,
 2228     int *ret __unused)
 2229 {
 2230         struct nameidata nd;
 2231         struct vfs_context *ctx = vfs_context_current();
 2232         struct mount *mp;
 2233         int error;
 2234 
 2235         NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNPATH1,
 2236                 UIO_USERSPACE, uap->path, ctx);
 2237         error = namei(&nd);
 2238         if (error) {
 2239                 return (error);
 2240         }
 2241         mp = nd.ni_vp->v_mount;
 2242         nameidone(&nd);
 2243 
 2244         return mac_mount_label_get(mp, uap->mac_p);
 2245 }
 2246 
 2247 #else /* MAC */
 2248 
 2249 int
 2250 mac_policy_register(struct mac_policy_conf *mpc __unused, 
 2251         mac_policy_handle_t *handlep __unused, void *xd __unused)
 2252 {
 2253 
 2254         return (0);
 2255 }
 2256 
 2257 int
 2258 mac_policy_unregister(mac_policy_handle_t handle __unused)
 2259 {
 2260 
 2261         return (0);
 2262 }
 2263 
 2264 int
 2265 mac_audit_text(char *text __unused, mac_policy_handle_t handle __unused)
 2266 {
 2267 
 2268         return (0);
 2269 }
 2270 
 2271 int
 2272 mac_mount_label_get(struct mount *mp __unused, user_addr_t mac_p __unused)
 2273 {
 2274         return (ENOSYS);
 2275 }
 2276 
 2277 int
 2278 mac_vnop_setxattr(struct vnode *vp __unused, const char *name __unused, char *buf __unused, size_t len __unused)
 2279 {
 2280 
 2281         return (ENOENT);
 2282 }
 2283 
 2284 int
 2285 mac_vnop_getxattr(struct vnode *vp __unused, const char *name __unused, 
 2286         char *buf __unused, size_t len __unused, size_t *attrlen __unused)
 2287 {
 2288 
 2289         return (ENOENT);
 2290 }
 2291 
 2292 int
 2293 mac_vnop_removexattr(struct vnode *vp __unused, const char *name __unused)
 2294 {
 2295 
 2296         return (ENOENT);
 2297 }
 2298 
 2299 int
 2300 __mac_get_pid(proc_t p __unused, struct __mac_get_pid_args *uap __unused, int *ret __unused)
 2301 {
 2302 
 2303         return (ENOSYS);
 2304 }
 2305 
 2306 int
 2307 __mac_get_proc(proc_t p __unused, struct __mac_get_proc_args *uap __unused, int *ret __unused)
 2308 {
 2309 
 2310         return (ENOSYS);
 2311 }
 2312 
 2313 int
 2314 __mac_set_proc(proc_t p __unused, struct __mac_set_proc_args *uap __unused, int *ret __unused)
 2315 {
 2316 
 2317         return (ENOSYS);
 2318 }
 2319 
 2320 int
 2321 __mac_get_file(proc_t p __unused, struct __mac_get_file_args *uap __unused, int *ret __unused)
 2322 {
 2323 
 2324         return (ENOSYS);
 2325 }
 2326 
 2327 int
 2328 __mac_get_link(proc_t p __unused, struct __mac_get_link_args *uap __unused, int *ret __unused)
 2329 {
 2330 
 2331         return (ENOSYS);
 2332 }
 2333 
 2334 int
 2335 __mac_set_file(proc_t p __unused, struct __mac_set_file_args *uap __unused, int *ret __unused)
 2336 {
 2337 
 2338         return (ENOSYS);
 2339 }
 2340 
 2341 int
 2342 __mac_set_link(proc_t p __unused, struct __mac_set_link_args *uap __unused, int *ret __unused)
 2343 {
 2344 
 2345         return (ENOSYS);
 2346 }
 2347 
 2348 int
 2349 __mac_get_fd(proc_t p __unused, struct __mac_get_fd_args *uap __unused, int *ret __unused)
 2350 {
 2351 
 2352         return (ENOSYS);
 2353 }
 2354 
 2355 int
 2356 __mac_set_fd(proc_t p __unused, struct __mac_set_fd_args *uap __unused, int *ret __unused)
 2357 {
 2358 
 2359         return (ENOSYS);
 2360 }
 2361 
 2362 int
 2363 __mac_syscall(proc_t p __unused, struct __mac_syscall_args *uap __unused, int *ret __unused)
 2364 {
 2365 
 2366         return (ENOSYS);
 2367 }
 2368 
 2369 int
 2370 __mac_get_lcid(proc_t p __unused, struct __mac_get_lcid_args *uap __unused, int *ret __unused)
 2371 {
 2372 
 2373         return (ENOSYS);
 2374 }
 2375 
 2376 int
 2377 __mac_get_lctx(proc_t p __unused, struct __mac_get_lctx_args *uap __unused, int *ret __unused)
 2378 {
 2379 
 2380         return (ENOSYS);
 2381 }
 2382 
 2383 int
 2384 __mac_set_lctx(proc_t p __unused, struct __mac_set_lctx_args *uap __unused, int *ret __unused)
 2385 {
 2386 
 2387         return (ENOSYS);
 2388 }
 2389 
 2390 int
 2391 __mac_get_mount(proc_t p __unused,
 2392     struct __mac_get_mount_args *uap __unused, int *ret __unused)
 2393 {
 2394 
 2395         return (ENOSYS);
 2396 }
 2397 #endif /* !MAC */

Cache object: 03629dd7da39ac7761bb7fa22573e567


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