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

Cache object: ac405163362aece90666711d7bf95b20


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