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/kern/kern_mac.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) 1999, 2000, 2001, 2002 Robert N. M. Watson
    3  * Copyright (c) 2001 Ilmar S. Habibulin
    4  * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
    5  * All rights reserved.
    6  *
    7  * This software was developed by Robert Watson and Ilmar Habibulin for the
    8  * TrustedBSD Project.
    9  *
   10  * This software was developed for the FreeBSD Project in part by Network
   11  * Associates Laboratories, the Security Research Division of Network
   12  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
   13  * as part of the DARPA CHATS research program.
   14  *
   15  * Redistribution and use in source and binary forms, with or without
   16  * modification, are permitted provided that the following conditions
   17  * are met:
   18  * 1. Redistributions of source code must retain the above copyright
   19  *    notice, this list of conditions and the following disclaimer.
   20  * 2. Redistributions in binary form must reproduce the above copyright
   21  *    notice, this list of conditions and the following disclaimer in the
   22  *    documentation and/or other materials provided with the distribution.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  * $FreeBSD: releng/5.0/sys/kern/kern_mac.c 108086 2002-12-19 09:40:13Z alfred $
   37  */
   38 /*
   39  * Developed by the TrustedBSD Project.
   40  *
   41  * Framework for extensible kernel access control.  Kernel and userland
   42  * interface to the framework, policy registration and composition.
   43  */
   44 
   45 #include "opt_mac.h"
   46 #include "opt_devfs.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/condvar.h>
   50 #include <sys/extattr.h>
   51 #include <sys/imgact.h>
   52 #include <sys/kernel.h>
   53 #include <sys/lock.h>
   54 #include <sys/malloc.h>
   55 #include <sys/mutex.h>
   56 #include <sys/mac.h>
   57 #include <sys/module.h>
   58 #include <sys/proc.h>
   59 #include <sys/systm.h>
   60 #include <sys/sysproto.h>
   61 #include <sys/sysent.h>
   62 #include <sys/vnode.h>
   63 #include <sys/mount.h>
   64 #include <sys/file.h>
   65 #include <sys/namei.h>
   66 #include <sys/socket.h>
   67 #include <sys/pipe.h>
   68 #include <sys/socketvar.h>
   69 #include <sys/sysctl.h>
   70 
   71 #include <vm/vm.h>
   72 #include <vm/pmap.h>
   73 #include <vm/vm_map.h>
   74 #include <vm/vm_object.h>
   75 
   76 #include <sys/mac_policy.h>
   77 
   78 #include <fs/devfs/devfs.h>
   79 
   80 #include <net/bpfdesc.h>
   81 #include <net/if.h>
   82 #include <net/if_var.h>
   83 
   84 #include <netinet/in.h>
   85 #include <netinet/ip_var.h>
   86 
   87 #ifdef MAC
   88 
   89 /*
   90  * Declare that the kernel provides MAC support, version 1.  This permits
   91  * modules to refuse to be loaded if the necessary support isn't present,
   92  * even if it's pre-boot.
   93  */
   94 MODULE_VERSION(kernel_mac_support, 1);
   95 
   96 SYSCTL_DECL(_security);
   97 
   98 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
   99     "TrustedBSD MAC policy controls");
  100 
  101 #if MAC_MAX_POLICIES > 32
  102 #error "MAC_MAX_POLICIES too large"
  103 #endif
  104 
  105 static unsigned int mac_max_policies = MAC_MAX_POLICIES;
  106 static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
  107 SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
  108     &mac_max_policies, 0, "");
  109 
  110 /*
  111  * Has the kernel started generating labeled objects yet?  All read/write
  112  * access to this variable is serialized during the boot process.  Following
  113  * the end of serialization, we don't update this flag; no locking.
  114  */
  115 static int      mac_late = 0;
  116 
  117 /*
  118  * Warn about EA transactions only the first time they happen.
  119  * Weak coherency, no locking.
  120  */
  121 static int      ea_warn_once = 0;
  122 
  123 static int      mac_enforce_fs = 1;
  124 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
  125     &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
  126 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
  127 
  128 static int      mac_enforce_kld = 1;
  129 SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
  130     &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
  131 TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
  132 
  133 static int      mac_enforce_network = 1;
  134 SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
  135     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
  136 TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
  137 
  138 static int      mac_enforce_pipe = 1;
  139 SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
  140     &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
  141 TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
  142 
  143 static int      mac_enforce_process = 1;
  144 SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
  145     &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
  146 TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
  147 
  148 static int      mac_enforce_socket = 1;
  149 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
  150     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
  151 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
  152 
  153 static int      mac_enforce_system = 1;
  154 SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
  155     &mac_enforce_system, 0, "Enforce MAC policy on system operations");
  156 TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
  157 
  158 static int      mac_enforce_vm = 1;
  159 SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
  160     &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
  161 TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
  162 
  163 static int      mac_mmap_revocation = 1;
  164 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
  165     &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
  166     "relabel");
  167 static int      mac_mmap_revocation_via_cow = 0;
  168 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
  169     &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
  170     "copy-on-write semantics, or by removing all write access");
  171 
  172 #ifdef MAC_DEBUG
  173 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
  174     "TrustedBSD MAC debug info");
  175 
  176 static int      mac_debug_label_fallback = 0;
  177 SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
  178     &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
  179     "when label is corrupted.");
  180 TUNABLE_INT("security.mac.debug_label_fallback",
  181     &mac_debug_label_fallback);
  182 
  183 SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
  184     "TrustedBSD MAC object counters");
  185 
  186 static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
  187     nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
  188     nmacipqs, nmacpipes, nmacprocs;
  189 
  190 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
  191     &nmacmbufs, 0, "number of mbufs in use");
  192 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
  193     &nmaccreds, 0, "number of ucreds in use");
  194 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
  195     &nmacifnets, 0, "number of ifnets in use");
  196 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
  197     &nmacipqs, 0, "number of ipqs in use");
  198 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
  199     &nmacbpfdescs, 0, "number of bpfdescs in use");
  200 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
  201     &nmacsockets, 0, "number of sockets in use");
  202 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
  203     &nmacpipes, 0, "number of pipes in use");
  204 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
  205     &nmacprocs, 0, "number of procs in use");
  206 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
  207     &nmacmounts, 0, "number of mounts in use");
  208 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
  209     &nmactemp, 0, "number of temporary labels in use");
  210 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
  211     &nmacvnodes, 0, "number of vnodes in use");
  212 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
  213     &nmacdevfsdirents, 0, "number of devfs dirents inuse");
  214 #endif
  215 
  216 static int      error_select(int error1, int error2);
  217 static int      mac_policy_register(struct mac_policy_conf *mpc);
  218 static int      mac_policy_unregister(struct mac_policy_conf *mpc);
  219 
  220 static void     mac_check_vnode_mmap_downgrade(struct ucred *cred,
  221                     struct vnode *vp, int *prot);
  222 static void     mac_cred_mmapped_drop_perms_recurse(struct thread *td,
  223                     struct ucred *cred, struct vm_map *map);
  224 
  225 static void     mac_destroy_socket_label(struct label *label);
  226 
  227 static int      mac_setlabel_vnode_extattr(struct ucred *cred,
  228                     struct vnode *vp, struct label *intlabel);
  229 
  230 MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
  231 MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
  232 
  233 /*
  234  * mac_policy_list stores the list of active policies.  A busy count is
  235  * maintained for the list, stored in mac_policy_busy.  The busy count
  236  * is protected by mac_policy_list_lock; the list may be modified only
  237  * while the busy count is 0, requiring that the lock be held to
  238  * prevent new references to the list from being acquired.  For almost
  239  * all operations, incrementing the busy count is sufficient to
  240  * guarantee consistency, as the list cannot be modified while the
  241  * busy count is elevated.  For a few special operations involving a
  242  * change to the list of active policies, the lock itself must be held.
  243  * A condition variable, mac_policy_list_not_busy, is used to signal
  244  * potential exclusive consumers that they should try to acquire the
  245  * lock if a first attempt at exclusive access fails.
  246  */
  247 static struct mtx mac_policy_list_lock;
  248 static struct cv mac_policy_list_not_busy;
  249 static LIST_HEAD(, mac_policy_conf) mac_policy_list;
  250 static int mac_policy_list_busy;
  251 
  252 #define MAC_POLICY_LIST_LOCKINIT() do {                                 \
  253         mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL,   \
  254             MTX_DEF);                                                   \
  255         cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy"); \
  256 } while (0)
  257 
  258 #define MAC_POLICY_LIST_LOCK() do {                                     \
  259         mtx_lock(&mac_policy_list_lock);                                \
  260 } while (0)
  261 
  262 #define MAC_POLICY_LIST_UNLOCK() do {                                   \
  263         mtx_unlock(&mac_policy_list_lock);                              \
  264 } while (0)
  265 
  266 /*
  267  * We manually invoke WITNESS_SLEEP() to allow Witness to generate
  268  * warnings even if we don't end up ever triggering the wait at
  269  * run-time.  The consumer of the exclusive interface must not hold
  270  * any locks (other than potentially Giant) since we may sleep for
  271  * long (potentially indefinite) periods of time waiting for the
  272  * framework to become quiescent so that a policy list change may
  273  * be made.
  274  */
  275 #define MAC_POLICY_LIST_EXCLUSIVE() do {                                \
  276         WITNESS_SLEEP(1, NULL);                                         \
  277         mtx_lock(&mac_policy_list_lock);                                \
  278         while (mac_policy_list_busy != 0)                               \
  279                 cv_wait(&mac_policy_list_not_busy,                      \
  280                     &mac_policy_list_lock);                             \
  281 } while (0)
  282 
  283 #define MAC_POLICY_LIST_BUSY() do {                                     \
  284         MAC_POLICY_LIST_LOCK();                                         \
  285         mac_policy_list_busy++;                                         \
  286         MAC_POLICY_LIST_UNLOCK();                                       \
  287 } while (0)
  288 
  289 #define MAC_POLICY_LIST_UNBUSY() do {                                   \
  290         MAC_POLICY_LIST_LOCK();                                         \
  291         mac_policy_list_busy--;                                         \
  292         KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK"));   \
  293         if (mac_policy_list_busy == 0)                                  \
  294                 cv_signal(&mac_policy_list_not_busy);                   \
  295         MAC_POLICY_LIST_UNLOCK();                                       \
  296 } while (0)
  297 
  298 /*
  299  * MAC_CHECK performs the designated check by walking the policy
  300  * module list and checking with each as to how it feels about the
  301  * request.  Note that it returns its value via 'error' in the scope
  302  * of the caller.
  303  */
  304 #define MAC_CHECK(check, args...) do {                                  \
  305         struct mac_policy_conf *mpc;                                    \
  306                                                                         \
  307         error = 0;                                                      \
  308         MAC_POLICY_LIST_BUSY();                                         \
  309         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {                 \
  310                 if (mpc->mpc_ops->mpo_ ## check != NULL)                \
  311                         error = error_select(                           \
  312                             mpc->mpc_ops->mpo_ ## check (args),         \
  313                             error);                                     \
  314         }                                                               \
  315         MAC_POLICY_LIST_UNBUSY();                                       \
  316 } while (0)
  317 
  318 /*
  319  * MAC_BOOLEAN performs the designated boolean composition by walking
  320  * the module list, invoking each instance of the operation, and
  321  * combining the results using the passed C operator.  Note that it
  322  * returns its value via 'result' in the scope of the caller, which
  323  * should be initialized by the caller in a meaningful way to get
  324  * a meaningful result.
  325  */
  326 #define MAC_BOOLEAN(operation, composition, args...) do {               \
  327         struct mac_policy_conf *mpc;                                    \
  328                                                                         \
  329         MAC_POLICY_LIST_BUSY();                                         \
  330         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {                 \
  331                 if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
  332                         result = result composition                     \
  333                             mpc->mpc_ops->mpo_ ## operation (args);     \
  334         }                                                               \
  335         MAC_POLICY_LIST_UNBUSY();                                       \
  336 } while (0)
  337 
  338 #define MAC_EXTERNALIZE(type, label, elementlist, outbuf,               \
  339     outbuflen) do {                                                     \
  340         char *curptr, *curptr_start, *element_name, *element_temp;      \
  341         size_t left, left_start, len;                                   \
  342         int claimed, first, first_start, ignorenotfound;                \
  343                                                                         \
  344         error = 0;                                                      \
  345         element_temp = elementlist;                                     \
  346         curptr = outbuf;                                                \
  347         curptr[0] = '\0';                                               \
  348         left = outbuflen;                                               \
  349         first = 1;                                                      \
  350         while ((element_name = strsep(&element_temp, ",")) != NULL) {   \
  351                 curptr_start = curptr;                                  \
  352                 left_start = left;                                      \
  353                 first_start = first;                                    \
  354                 if (element_name[0] == '?') {                           \
  355                         element_name++;                                 \
  356                         ignorenotfound = 1;                             \
  357                 } else                                                  \
  358                         ignorenotfound = 0;                             \
  359                 claimed = 0;                                            \
  360                 if (first) {                                            \
  361                         len = snprintf(curptr, left, "%s/",             \
  362                             element_name);                              \
  363                         first = 0;                                      \
  364                 } else                                                  \
  365                         len = snprintf(curptr, left, ",%s/",            \
  366                             element_name);                              \
  367                 if (len >= left) {                                      \
  368                         error = EINVAL;         /* XXXMAC: E2BIG */     \
  369                         break;                                          \
  370                 }                                                       \
  371                 curptr += len;                                          \
  372                 left -= len;                                            \
  373                                                                         \
  374                 MAC_CHECK(externalize_ ## type, label, element_name,    \
  375                     curptr, left, &len, &claimed);                      \
  376                 if (error)                                              \
  377                         break;                                          \
  378                 if (claimed == 1) {                                     \
  379                         if (len >= outbuflen) {                         \
  380                                 error = EINVAL; /* XXXMAC: E2BIG */     \
  381                                 break;                                  \
  382                         }                                               \
  383                         curptr += len;                                  \
  384                         left -= len;                                    \
  385                 } else if (claimed == 0 && ignorenotfound) {            \
  386                         /*                                              \
  387                          * Revert addition of the label element         \
  388                          * name.                                        \
  389                          */                                             \
  390                         curptr = curptr_start;                          \
  391                         *curptr = '\0';                                 \
  392                         left = left_start;                              \
  393                         first = first_start;                            \
  394                 } else {                                                \
  395                         error = EINVAL;         /* XXXMAC: ENOLABEL */  \
  396                         break;                                          \
  397                 }                                                       \
  398         }                                                               \
  399 } while (0)
  400 
  401 #define MAC_INTERNALIZE(type, label, instring) do {                     \
  402         char *element, *element_name, *element_data;                    \
  403         int claimed;                                                    \
  404                                                                         \
  405         error = 0;                                                      \
  406         element = instring;                                             \
  407         while ((element_name = strsep(&element, ",")) != NULL) {        \
  408                 element_data = element_name;                            \
  409                 element_name = strsep(&element_data, "/");              \
  410                 if (element_data == NULL) {                             \
  411                         error = EINVAL;                                 \
  412                         break;                                          \
  413                 }                                                       \
  414                 claimed = 0;                                            \
  415                 MAC_CHECK(internalize_ ## type, label, element_name,    \
  416                     element_data, &claimed);                            \
  417                 if (error)                                              \
  418                         break;                                          \
  419                 if (claimed != 1) {                                     \
  420                         /* XXXMAC: Another error here? */               \
  421                         error = EINVAL;                                 \
  422                         break;                                          \
  423                 }                                                       \
  424         }                                                               \
  425 } while (0)
  426 
  427 /*
  428  * MAC_PERFORM performs the designated operation by walking the policy
  429  * module list and invoking that operation for each policy.
  430  */
  431 #define MAC_PERFORM(operation, args...) do {                            \
  432         struct mac_policy_conf *mpc;                                    \
  433                                                                         \
  434         MAC_POLICY_LIST_BUSY();                                         \
  435         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {                 \
  436                 if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
  437                         mpc->mpc_ops->mpo_ ## operation (args);         \
  438         }                                                               \
  439         MAC_POLICY_LIST_UNBUSY();                                       \
  440 } while (0)
  441 
  442 /*
  443  * Initialize the MAC subsystem, including appropriate SMP locks.
  444  */
  445 static void
  446 mac_init(void)
  447 {
  448 
  449         LIST_INIT(&mac_policy_list);
  450         MAC_POLICY_LIST_LOCKINIT();
  451 }
  452 
  453 /*
  454  * For the purposes of modules that want to know if they were loaded
  455  * "early", set the mac_late flag once we've processed modules either
  456  * linked into the kernel, or loaded before the kernel startup.
  457  */
  458 static void
  459 mac_late_init(void)
  460 {
  461 
  462         mac_late = 1;
  463 }
  464 
  465 /*
  466  * Allow MAC policy modules to register during boot, etc.
  467  */
  468 int
  469 mac_policy_modevent(module_t mod, int type, void *data)
  470 {
  471         struct mac_policy_conf *mpc;
  472         int error;
  473 
  474         error = 0;
  475         mpc = (struct mac_policy_conf *) data;
  476 
  477         switch (type) {
  478         case MOD_LOAD:
  479                 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
  480                     mac_late) {
  481                         printf("mac_policy_modevent: can't load %s policy "
  482                             "after booting\n", mpc->mpc_name);
  483                         error = EBUSY;
  484                         break;
  485                 }
  486                 error = mac_policy_register(mpc);
  487                 break;
  488         case MOD_UNLOAD:
  489                 /* Don't unregister the module if it was never registered. */
  490                 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
  491                     != 0)
  492                         error = mac_policy_unregister(mpc);
  493                 else
  494                         error = 0;
  495                 break;
  496         default:
  497                 break;
  498         }
  499 
  500         return (error);
  501 }
  502 
  503 static int
  504 mac_policy_register(struct mac_policy_conf *mpc)
  505 {
  506         struct mac_policy_conf *tmpc;
  507         int slot;
  508 
  509         MAC_POLICY_LIST_EXCLUSIVE();
  510         LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
  511                 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
  512                         MAC_POLICY_LIST_UNLOCK();
  513                         return (EEXIST);
  514                 }
  515         }
  516         if (mpc->mpc_field_off != NULL) {
  517                 slot = ffs(mac_policy_offsets_free);
  518                 if (slot == 0) {
  519                         MAC_POLICY_LIST_UNLOCK();
  520                         return (ENOMEM);
  521                 }
  522                 slot--;
  523                 mac_policy_offsets_free &= ~(1 << slot);
  524                 *mpc->mpc_field_off = slot;
  525         }
  526         mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
  527         LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
  528 
  529         /* Per-policy initialization. */
  530         if (mpc->mpc_ops->mpo_init != NULL)
  531                 (*(mpc->mpc_ops->mpo_init))(mpc);
  532         MAC_POLICY_LIST_UNLOCK();
  533 
  534         printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
  535             mpc->mpc_name);
  536 
  537         return (0);
  538 }
  539 
  540 static int
  541 mac_policy_unregister(struct mac_policy_conf *mpc)
  542 {
  543 
  544         /*
  545          * If we fail the load, we may get a request to unload.  Check
  546          * to see if we did the run-time registration, and if not,
  547          * silently succeed.
  548          */
  549         MAC_POLICY_LIST_EXCLUSIVE();
  550         if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
  551                 MAC_POLICY_LIST_UNLOCK();
  552                 return (0);
  553         }
  554 #if 0
  555         /*
  556          * Don't allow unloading modules with private data.
  557          */
  558         if (mpc->mpc_field_off != NULL) {
  559                 MAC_POLICY_LIST_UNLOCK();
  560                 return (EBUSY);
  561         }
  562 #endif
  563         /*
  564          * Only allow the unload to proceed if the module is unloadable
  565          * by its own definition.
  566          */
  567         if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
  568                 MAC_POLICY_LIST_UNLOCK();
  569                 return (EBUSY);
  570         }
  571         if (mpc->mpc_ops->mpo_destroy != NULL)
  572                 (*(mpc->mpc_ops->mpo_destroy))(mpc);
  573 
  574         LIST_REMOVE(mpc, mpc_list);
  575         mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
  576 
  577         MAC_POLICY_LIST_UNLOCK();
  578 
  579         printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
  580             mpc->mpc_name);
  581 
  582         return (0);
  583 }
  584 
  585 /*
  586  * Define an error value precedence, and given two arguments, selects the
  587  * value with the higher precedence.
  588  */
  589 static int
  590 error_select(int error1, int error2)
  591 {
  592 
  593         /* Certain decision-making errors take top priority. */
  594         if (error1 == EDEADLK || error2 == EDEADLK)
  595                 return (EDEADLK);
  596 
  597         /* Invalid arguments should be reported where possible. */
  598         if (error1 == EINVAL || error2 == EINVAL)
  599                 return (EINVAL);
  600 
  601         /* Precedence goes to "visibility", with both process and file. */
  602         if (error1 == ESRCH || error2 == ESRCH)
  603                 return (ESRCH);
  604 
  605         if (error1 == ENOENT || error2 == ENOENT)
  606                 return (ENOENT);
  607 
  608         /* Precedence goes to DAC/MAC protections. */
  609         if (error1 == EACCES || error2 == EACCES)
  610                 return (EACCES);
  611 
  612         /* Precedence goes to privilege. */
  613         if (error1 == EPERM || error2 == EPERM)
  614                 return (EPERM);
  615 
  616         /* Precedence goes to error over success; otherwise, arbitrary. */
  617         if (error1 != 0)
  618                 return (error1);
  619         return (error2);
  620 }
  621 
  622 static void
  623 mac_init_label(struct label *label)
  624 {
  625 
  626         bzero(label, sizeof(*label));
  627         label->l_flags = MAC_FLAG_INITIALIZED;
  628 }
  629 
  630 static void
  631 mac_destroy_label(struct label *label)
  632 {
  633 
  634         KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
  635             ("destroying uninitialized label"));
  636 
  637         bzero(label, sizeof(*label));
  638         /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
  639 }
  640 
  641 void
  642 mac_init_bpfdesc(struct bpf_d *bpf_d)
  643 {
  644 
  645         mac_init_label(&bpf_d->bd_label);
  646         MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
  647 #ifdef MAC_DEBUG
  648         atomic_add_int(&nmacbpfdescs, 1);
  649 #endif
  650 }
  651 
  652 static void
  653 mac_init_cred_label(struct label *label)
  654 {
  655 
  656         mac_init_label(label);
  657         MAC_PERFORM(init_cred_label, label);
  658 #ifdef MAC_DEBUG
  659         atomic_add_int(&nmaccreds, 1);
  660 #endif
  661 }
  662 
  663 void
  664 mac_init_cred(struct ucred *cred)
  665 {
  666 
  667         mac_init_cred_label(&cred->cr_label);
  668 }
  669 
  670 void
  671 mac_init_devfsdirent(struct devfs_dirent *de)
  672 {
  673 
  674         mac_init_label(&de->de_label);
  675         MAC_PERFORM(init_devfsdirent_label, &de->de_label);
  676 #ifdef MAC_DEBUG
  677         atomic_add_int(&nmacdevfsdirents, 1);
  678 #endif
  679 }
  680 
  681 static void
  682 mac_init_ifnet_label(struct label *label)
  683 {
  684 
  685         mac_init_label(label);
  686         MAC_PERFORM(init_ifnet_label, label);
  687 #ifdef MAC_DEBUG
  688         atomic_add_int(&nmacifnets, 1);
  689 #endif
  690 }
  691 
  692 void
  693 mac_init_ifnet(struct ifnet *ifp)
  694 {
  695 
  696         mac_init_ifnet_label(&ifp->if_label);
  697 }
  698 
  699 void
  700 mac_init_ipq(struct ipq *ipq)
  701 {
  702 
  703         mac_init_label(&ipq->ipq_label);
  704         MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
  705 #ifdef MAC_DEBUG
  706         atomic_add_int(&nmacipqs, 1);
  707 #endif
  708 }
  709 
  710 int
  711 mac_init_mbuf(struct mbuf *m, int flag)
  712 {
  713         int error;
  714 
  715         KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
  716 
  717         mac_init_label(&m->m_pkthdr.label);
  718 
  719         MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
  720         if (error) {
  721                 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
  722                 mac_destroy_label(&m->m_pkthdr.label);
  723         }
  724 
  725 #ifdef MAC_DEBUG
  726         if (error == 0)
  727                 atomic_add_int(&nmacmbufs, 1);
  728 #endif
  729         return (error);
  730 }
  731 
  732 void
  733 mac_init_mount(struct mount *mp)
  734 {
  735 
  736         mac_init_label(&mp->mnt_mntlabel);
  737         mac_init_label(&mp->mnt_fslabel);
  738         MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
  739         MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
  740 #ifdef MAC_DEBUG
  741         atomic_add_int(&nmacmounts, 1);
  742 #endif
  743 }
  744 
  745 static void
  746 mac_init_pipe_label(struct label *label)
  747 {
  748 
  749         mac_init_label(label);
  750         MAC_PERFORM(init_pipe_label, label);
  751 #ifdef MAC_DEBUG
  752         atomic_add_int(&nmacpipes, 1);
  753 #endif
  754 }
  755 
  756 void
  757 mac_init_pipe(struct pipe *pipe)
  758 {
  759         struct label *label;
  760 
  761         label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
  762         pipe->pipe_label = label;
  763         pipe->pipe_peer->pipe_label = label;
  764         mac_init_pipe_label(label);
  765 }
  766 
  767 void
  768 mac_init_proc(struct proc *p)
  769 {
  770 
  771         mac_init_label(&p->p_label);
  772         MAC_PERFORM(init_proc_label, &p->p_label);
  773 #ifdef MAC_DEBUG
  774         atomic_add_int(&nmacprocs, 1);
  775 #endif
  776 }
  777 
  778 static int
  779 mac_init_socket_label(struct label *label, int flag)
  780 {
  781         int error;
  782 
  783         mac_init_label(label);
  784 
  785         MAC_CHECK(init_socket_label, label, flag);
  786         if (error) {
  787                 MAC_PERFORM(destroy_socket_label, label);
  788                 mac_destroy_label(label);
  789         }
  790 
  791 #ifdef MAC_DEBUG
  792         if (error == 0)
  793                 atomic_add_int(&nmacsockets, 1);
  794 #endif
  795 
  796         return (error);
  797 }
  798 
  799 static int
  800 mac_init_socket_peer_label(struct label *label, int flag)
  801 {
  802         int error;
  803 
  804         mac_init_label(label);
  805 
  806         MAC_CHECK(init_socket_peer_label, label, flag);
  807         if (error) {
  808                 MAC_PERFORM(destroy_socket_label, label);
  809                 mac_destroy_label(label);
  810         }
  811 
  812         return (error);
  813 }
  814 
  815 int
  816 mac_init_socket(struct socket *socket, int flag)
  817 {
  818         int error;
  819 
  820         error = mac_init_socket_label(&socket->so_label, flag);
  821         if (error)
  822                 return (error);
  823 
  824         error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
  825         if (error)
  826                 mac_destroy_socket_label(&socket->so_label);
  827 
  828         return (error);
  829 }
  830 
  831 void
  832 mac_init_vnode_label(struct label *label)
  833 {
  834 
  835         mac_init_label(label);
  836         MAC_PERFORM(init_vnode_label, label);
  837 #ifdef MAC_DEBUG
  838         atomic_add_int(&nmacvnodes, 1);
  839 #endif
  840 }
  841 
  842 void
  843 mac_init_vnode(struct vnode *vp)
  844 {
  845 
  846         mac_init_vnode_label(&vp->v_label);
  847 }
  848 
  849 void
  850 mac_destroy_bpfdesc(struct bpf_d *bpf_d)
  851 {
  852 
  853         MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
  854         mac_destroy_label(&bpf_d->bd_label);
  855 #ifdef MAC_DEBUG
  856         atomic_subtract_int(&nmacbpfdescs, 1);
  857 #endif
  858 }
  859 
  860 static void
  861 mac_destroy_cred_label(struct label *label)
  862 {
  863 
  864         MAC_PERFORM(destroy_cred_label, label);
  865         mac_destroy_label(label);
  866 #ifdef MAC_DEBUG
  867         atomic_subtract_int(&nmaccreds, 1);
  868 #endif
  869 }
  870 
  871 void
  872 mac_destroy_cred(struct ucred *cred)
  873 {
  874 
  875         mac_destroy_cred_label(&cred->cr_label);
  876 }
  877 
  878 void
  879 mac_destroy_devfsdirent(struct devfs_dirent *de)
  880 {
  881 
  882         MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
  883         mac_destroy_label(&de->de_label);
  884 #ifdef MAC_DEBUG
  885         atomic_subtract_int(&nmacdevfsdirents, 1);
  886 #endif
  887 }
  888 
  889 static void
  890 mac_destroy_ifnet_label(struct label *label)
  891 {
  892 
  893         MAC_PERFORM(destroy_ifnet_label, label);
  894         mac_destroy_label(label);
  895 #ifdef MAC_DEBUG
  896         atomic_subtract_int(&nmacifnets, 1);
  897 #endif
  898 }
  899 
  900 void
  901 mac_destroy_ifnet(struct ifnet *ifp)
  902 {
  903 
  904         mac_destroy_ifnet_label(&ifp->if_label);
  905 }
  906 
  907 void
  908 mac_destroy_ipq(struct ipq *ipq)
  909 {
  910 
  911         MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
  912         mac_destroy_label(&ipq->ipq_label);
  913 #ifdef MAC_DEBUG
  914         atomic_subtract_int(&nmacipqs, 1);
  915 #endif
  916 }
  917 
  918 void
  919 mac_destroy_mbuf(struct mbuf *m)
  920 {
  921 
  922         MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
  923         mac_destroy_label(&m->m_pkthdr.label);
  924 #ifdef MAC_DEBUG
  925         atomic_subtract_int(&nmacmbufs, 1);
  926 #endif
  927 }
  928 
  929 void
  930 mac_destroy_mount(struct mount *mp)
  931 {
  932 
  933         MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
  934         MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
  935         mac_destroy_label(&mp->mnt_fslabel);
  936         mac_destroy_label(&mp->mnt_mntlabel);
  937 #ifdef MAC_DEBUG
  938         atomic_subtract_int(&nmacmounts, 1);
  939 #endif
  940 }
  941 
  942 static void
  943 mac_destroy_pipe_label(struct label *label)
  944 {
  945 
  946         MAC_PERFORM(destroy_pipe_label, label);
  947         mac_destroy_label(label);
  948 #ifdef MAC_DEBUG
  949         atomic_subtract_int(&nmacpipes, 1);
  950 #endif
  951 }
  952 
  953 void
  954 mac_destroy_pipe(struct pipe *pipe)
  955 {
  956 
  957         mac_destroy_pipe_label(pipe->pipe_label);
  958         free(pipe->pipe_label, M_MACPIPELABEL);
  959 }
  960 
  961 void
  962 mac_destroy_proc(struct proc *p)
  963 {
  964 
  965         MAC_PERFORM(destroy_proc_label, &p->p_label);
  966         mac_destroy_label(&p->p_label);
  967 #ifdef MAC_DEBUG
  968         atomic_subtract_int(&nmacprocs, 1);
  969 #endif
  970 }
  971 
  972 static void
  973 mac_destroy_socket_label(struct label *label)
  974 {
  975 
  976         MAC_PERFORM(destroy_socket_label, label);
  977         mac_destroy_label(label);
  978 #ifdef MAC_DEBUG
  979         atomic_subtract_int(&nmacsockets, 1);
  980 #endif
  981 }
  982 
  983 static void
  984 mac_destroy_socket_peer_label(struct label *label)
  985 {
  986 
  987         MAC_PERFORM(destroy_socket_peer_label, label);
  988         mac_destroy_label(label);
  989 }
  990 
  991 void
  992 mac_destroy_socket(struct socket *socket)
  993 {
  994 
  995         mac_destroy_socket_label(&socket->so_label);
  996         mac_destroy_socket_peer_label(&socket->so_peerlabel);
  997 }
  998 
  999 void
 1000 mac_destroy_vnode_label(struct label *label)
 1001 {
 1002 
 1003         MAC_PERFORM(destroy_vnode_label, label);
 1004         mac_destroy_label(label);
 1005 #ifdef MAC_DEBUG
 1006         atomic_subtract_int(&nmacvnodes, 1);
 1007 #endif
 1008 }
 1009 
 1010 void
 1011 mac_destroy_vnode(struct vnode *vp)
 1012 {
 1013 
 1014         mac_destroy_vnode_label(&vp->v_label);
 1015 }
 1016 
 1017 static void
 1018 mac_copy_pipe_label(struct label *src, struct label *dest)
 1019 {
 1020 
 1021         MAC_PERFORM(copy_pipe_label, src, dest);
 1022 }
 1023 
 1024 void
 1025 mac_copy_vnode_label(struct label *src, struct label *dest)
 1026 {
 1027 
 1028         MAC_PERFORM(copy_vnode_label, src, dest);
 1029 }
 1030 
 1031 static int
 1032 mac_check_structmac_consistent(struct mac *mac)
 1033 {
 1034 
 1035         if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
 1036                 return (EINVAL);
 1037 
 1038         return (0);
 1039 }
 1040 
 1041 static int
 1042 mac_externalize_cred_label(struct label *label, char *elements,
 1043     char *outbuf, size_t outbuflen, int flags)
 1044 {
 1045         int error;
 1046 
 1047         MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
 1048 
 1049         return (error);
 1050 }
 1051 
 1052 static int
 1053 mac_externalize_ifnet_label(struct label *label, char *elements,
 1054     char *outbuf, size_t outbuflen, int flags)
 1055 {
 1056         int error;
 1057 
 1058         MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
 1059 
 1060         return (error);
 1061 }
 1062 
 1063 static int
 1064 mac_externalize_pipe_label(struct label *label, char *elements,
 1065     char *outbuf, size_t outbuflen, int flags)
 1066 {
 1067         int error;
 1068 
 1069         MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
 1070 
 1071         return (error);
 1072 }
 1073 
 1074 static int
 1075 mac_externalize_socket_label(struct label *label, char *elements,
 1076     char *outbuf, size_t outbuflen, int flags)
 1077 {
 1078         int error;
 1079 
 1080         MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
 1081 
 1082         return (error);
 1083 }
 1084 
 1085 static int
 1086 mac_externalize_socket_peer_label(struct label *label, char *elements,
 1087     char *outbuf, size_t outbuflen, int flags)
 1088 {
 1089         int error;
 1090 
 1091         MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
 1092 
 1093         return (error);
 1094 }
 1095 
 1096 static int
 1097 mac_externalize_vnode_label(struct label *label, char *elements,
 1098     char *outbuf, size_t outbuflen, int flags)
 1099 {
 1100         int error;
 1101 
 1102         MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
 1103 
 1104         return (error);
 1105 }
 1106 
 1107 static int
 1108 mac_internalize_cred_label(struct label *label, char *string)
 1109 {
 1110         int error;
 1111 
 1112         MAC_INTERNALIZE(cred_label, label, string);
 1113 
 1114         return (error);
 1115 }
 1116 
 1117 static int
 1118 mac_internalize_ifnet_label(struct label *label, char *string)
 1119 {
 1120         int error;
 1121 
 1122         MAC_INTERNALIZE(ifnet_label, label, string);
 1123 
 1124         return (error);
 1125 }
 1126 
 1127 static int
 1128 mac_internalize_pipe_label(struct label *label, char *string)
 1129 {
 1130         int error;
 1131 
 1132         MAC_INTERNALIZE(pipe_label, label, string);
 1133 
 1134         return (error);
 1135 }
 1136 
 1137 static int
 1138 mac_internalize_socket_label(struct label *label, char *string)
 1139 {
 1140         int error;
 1141 
 1142         MAC_INTERNALIZE(socket_label, label, string);
 1143 
 1144         return (error);
 1145 }
 1146 
 1147 static int
 1148 mac_internalize_vnode_label(struct label *label, char *string)
 1149 {
 1150         int error;
 1151 
 1152         MAC_INTERNALIZE(vnode_label, label, string);
 1153 
 1154         return (error);
 1155 }
 1156 
 1157 /*
 1158  * Initialize MAC label for the first kernel process, from which other
 1159  * kernel processes and threads are spawned.
 1160  */
 1161 void
 1162 mac_create_proc0(struct ucred *cred)
 1163 {
 1164 
 1165         MAC_PERFORM(create_proc0, cred);
 1166 }
 1167 
 1168 /*
 1169  * Initialize MAC label for the first userland process, from which other
 1170  * userland processes and threads are spawned.
 1171  */
 1172 void
 1173 mac_create_proc1(struct ucred *cred)
 1174 {
 1175 
 1176         MAC_PERFORM(create_proc1, cred);
 1177 }
 1178 
 1179 void
 1180 mac_thread_userret(struct thread *td)
 1181 {
 1182 
 1183         MAC_PERFORM(thread_userret, td);
 1184 }
 1185 
 1186 /*
 1187  * When a new process is created, its label must be initialized.  Generally,
 1188  * this involves inheritence from the parent process, modulo possible
 1189  * deltas.  This function allows that processing to take place.
 1190  */
 1191 void
 1192 mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
 1193 {
 1194 
 1195         MAC_PERFORM(create_cred, parent_cred, child_cred);
 1196 }
 1197 
 1198 void
 1199 mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
 1200     struct vnode *vp)
 1201 {
 1202 
 1203         MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
 1204             &vp->v_label);
 1205 }
 1206 
 1207 void
 1208 mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
 1209     struct vnode *vp)
 1210 {
 1211 
 1212         MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
 1213             &de->de_label, vp, &vp->v_label);
 1214 }
 1215 
 1216 int
 1217 mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
 1218 {
 1219         int error;
 1220 
 1221         ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
 1222 
 1223         MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
 1224             &vp->v_label);
 1225 
 1226         return (error);
 1227 }
 1228 
 1229 void
 1230 mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
 1231 {
 1232 
 1233         MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
 1234             &vp->v_label);
 1235 }
 1236 
 1237 int
 1238 mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
 1239     struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
 1240 {
 1241         int error;
 1242 
 1243         ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
 1244         ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
 1245 
 1246         error = VOP_OPENEXTATTR(vp, cred, curthread);
 1247         if (error == EOPNOTSUPP) {
 1248                 /* XXX: Optionally abort if transactions not supported. */
 1249                 if (ea_warn_once == 0) {
 1250                         printf("Warning: transactions not supported "
 1251                             "in EA write.\n");
 1252                         ea_warn_once = 1;
 1253                 }
 1254         } else if (error)
 1255                 return (error);
 1256 
 1257         MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
 1258             dvp, &dvp->v_label, vp, &vp->v_label, cnp);
 1259 
 1260         if (error) {
 1261                 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
 1262                 return (error);
 1263         }
 1264 
 1265         error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
 1266 
 1267         if (error == EOPNOTSUPP)
 1268                 error = 0;                              /* XXX */
 1269 
 1270         return (error);
 1271 }
 1272 
 1273 static int
 1274 mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
 1275     struct label *intlabel)
 1276 {
 1277         int error;
 1278 
 1279         ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
 1280 
 1281         error = VOP_OPENEXTATTR(vp, cred, curthread);
 1282         if (error == EOPNOTSUPP) {
 1283                 /* XXX: Optionally abort if transactions not supported. */
 1284                 if (ea_warn_once == 0) {
 1285                         printf("Warning: transactions not supported "
 1286                             "in EA write.\n");
 1287                         ea_warn_once = 1;
 1288                 }
 1289         } else if (error)
 1290                 return (error);
 1291 
 1292         MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
 1293 
 1294         if (error) {
 1295                 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
 1296                 return (error);
 1297         }
 1298 
 1299         error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
 1300 
 1301         if (error == EOPNOTSUPP)
 1302                 error = 0;                              /* XXX */
 1303 
 1304         return (error);
 1305 }
 1306 
 1307 int
 1308 mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
 1309     struct label *execlabelstorage)
 1310 {
 1311         struct mac mac;
 1312         char *buffer;
 1313         int error;
 1314 
 1315         if (mac_p == NULL)
 1316                 return (0);
 1317 
 1318         error = copyin(mac_p, &mac, sizeof(mac));
 1319         if (error)
 1320                 return (error);
 1321 
 1322         error = mac_check_structmac_consistent(&mac);
 1323         if (error)
 1324                 return (error);
 1325 
 1326         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 1327         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 1328         if (error) {
 1329                 free(buffer, M_MACTEMP);
 1330                 return (error);
 1331         }
 1332 
 1333         mac_init_cred_label(execlabelstorage);
 1334         error = mac_internalize_cred_label(execlabelstorage, buffer);
 1335         free(buffer, M_MACTEMP);
 1336         if (error) {
 1337                 mac_destroy_cred_label(execlabelstorage);
 1338                 return (error);
 1339         }
 1340         imgp->execlabel = execlabelstorage;
 1341         return (0);
 1342 }
 1343 
 1344 void
 1345 mac_execve_exit(struct image_params *imgp)
 1346 {
 1347         if (imgp->execlabel != NULL)
 1348                 mac_destroy_cred_label(imgp->execlabel);
 1349 }
 1350 
 1351 void
 1352 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
 1353     struct label *interpvnodelabel, struct image_params *imgp)
 1354 {
 1355 
 1356         ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
 1357 
 1358         if (!mac_enforce_process && !mac_enforce_fs)
 1359                 return;
 1360 
 1361         MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
 1362             interpvnodelabel, imgp, imgp->execlabel);
 1363 }
 1364 
 1365 int
 1366 mac_execve_will_transition(struct ucred *old, struct vnode *vp,
 1367     struct label *interpvnodelabel, struct image_params *imgp)
 1368 {
 1369         int result;
 1370 
 1371         ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
 1372 
 1373         if (!mac_enforce_process && !mac_enforce_fs)
 1374                 return (0);
 1375 
 1376         result = 0;
 1377         MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
 1378             interpvnodelabel, imgp, imgp->execlabel);
 1379 
 1380         return (result);
 1381 }
 1382 
 1383 int
 1384 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
 1385 {
 1386         int error;
 1387 
 1388         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
 1389 
 1390         if (!mac_enforce_fs)
 1391                 return (0);
 1392 
 1393         MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
 1394         return (error);
 1395 }
 1396 
 1397 int
 1398 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
 1399 {
 1400         int error;
 1401 
 1402         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
 1403 
 1404         if (!mac_enforce_fs)
 1405                 return (0);
 1406 
 1407         MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
 1408         return (error);
 1409 }
 1410 
 1411 int
 1412 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
 1413 {
 1414         int error;
 1415 
 1416         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
 1417 
 1418         if (!mac_enforce_fs)
 1419                 return (0);
 1420 
 1421         MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
 1422         return (error);
 1423 }
 1424 
 1425 int
 1426 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
 1427     struct componentname *cnp, struct vattr *vap)
 1428 {
 1429         int error;
 1430 
 1431         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
 1432 
 1433         if (!mac_enforce_fs)
 1434                 return (0);
 1435 
 1436         MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
 1437         return (error);
 1438 }
 1439 
 1440 int
 1441 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
 1442     struct componentname *cnp)
 1443 {
 1444         int error;
 1445 
 1446         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
 1447         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
 1448 
 1449         if (!mac_enforce_fs)
 1450                 return (0);
 1451 
 1452         MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
 1453             &vp->v_label, cnp);
 1454         return (error);
 1455 }
 1456 
 1457 int
 1458 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
 1459     acl_type_t type)
 1460 {
 1461         int error;
 1462 
 1463         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
 1464 
 1465         if (!mac_enforce_fs)
 1466                 return (0);
 1467 
 1468         MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
 1469         return (error);
 1470 }
 1471 
 1472 int
 1473 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
 1474     struct image_params *imgp)
 1475 {
 1476         int error;
 1477 
 1478         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
 1479 
 1480         if (!mac_enforce_process && !mac_enforce_fs)
 1481                 return (0);
 1482 
 1483         MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
 1484             imgp->execlabel);
 1485 
 1486         return (error);
 1487 }
 1488 
 1489 int
 1490 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
 1491 {
 1492         int error;
 1493 
 1494         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
 1495 
 1496         if (!mac_enforce_fs)
 1497                 return (0);
 1498 
 1499         MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
 1500         return (error);
 1501 }
 1502 
 1503 int
 1504 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
 1505     int attrnamespace, const char *name, struct uio *uio)
 1506 {
 1507         int error;
 1508 
 1509         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
 1510 
 1511         if (!mac_enforce_fs)
 1512                 return (0);
 1513 
 1514         MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
 1515             attrnamespace, name, uio);
 1516         return (error);
 1517 }
 1518 
 1519 int
 1520 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
 1521     struct vnode *vp, struct componentname *cnp)
 1522 {
 1523         int error;
 1524 
 1525         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
 1526         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
 1527 
 1528         if (!mac_enforce_fs)
 1529                 return (0);
 1530 
 1531         MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
 1532             &vp->v_label, cnp);
 1533         return (error);
 1534 }
 1535 
 1536 int
 1537 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
 1538     struct componentname *cnp)
 1539 {
 1540         int error;
 1541 
 1542         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
 1543 
 1544         if (!mac_enforce_fs)
 1545                 return (0);
 1546 
 1547         MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
 1548         return (error);
 1549 }
 1550 
 1551 int
 1552 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
 1553 {
 1554         int error;
 1555 
 1556         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
 1557 
 1558         if (!mac_enforce_fs || !mac_enforce_vm)
 1559                 return (0);
 1560 
 1561         MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
 1562         return (error);
 1563 }
 1564 
 1565 void
 1566 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
 1567 {
 1568         int result = *prot;
 1569 
 1570         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
 1571 
 1572         if (!mac_enforce_fs || !mac_enforce_vm)
 1573                 return;
 1574 
 1575         MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
 1576             &result);
 1577 
 1578         *prot = result;
 1579 }
 1580 
 1581 int
 1582 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
 1583 {
 1584         int error;
 1585 
 1586         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
 1587 
 1588         if (!mac_enforce_fs || !mac_enforce_vm)
 1589                 return (0);
 1590 
 1591         MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
 1592         return (error);
 1593 }
 1594 
 1595 int
 1596 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
 1597 {
 1598         int error;
 1599 
 1600         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
 1601 
 1602         if (!mac_enforce_fs)
 1603                 return (0);
 1604 
 1605         MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
 1606         return (error);
 1607 }
 1608 
 1609 int
 1610 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
 1611     struct vnode *vp)
 1612 {
 1613         int error;
 1614 
 1615         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
 1616 
 1617         if (!mac_enforce_fs)
 1618                 return (0);
 1619 
 1620         MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
 1621             &vp->v_label);
 1622 
 1623         return (error);
 1624 }
 1625 
 1626 int
 1627 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
 1628     struct vnode *vp)
 1629 {
 1630         int error;
 1631 
 1632         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
 1633 
 1634         if (!mac_enforce_fs)
 1635                 return (0);
 1636 
 1637         MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
 1638             &vp->v_label);
 1639 
 1640         return (error);
 1641 }
 1642 
 1643 int
 1644 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
 1645 {
 1646         int error;
 1647 
 1648         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
 1649 
 1650         if (!mac_enforce_fs)
 1651                 return (0);
 1652 
 1653         MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
 1654         return (error);
 1655 }
 1656 
 1657 int
 1658 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
 1659 {
 1660         int error;
 1661 
 1662         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
 1663 
 1664         if (!mac_enforce_fs)
 1665                 return (0);
 1666 
 1667         MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
 1668         return (error);
 1669 }
 1670 
 1671 static int
 1672 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
 1673     struct label *newlabel)
 1674 {
 1675         int error;
 1676 
 1677         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
 1678 
 1679         MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
 1680 
 1681         return (error);
 1682 }
 1683 
 1684 int
 1685 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
 1686     struct vnode *vp, struct componentname *cnp)
 1687 {
 1688         int error;
 1689 
 1690         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
 1691         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
 1692 
 1693         if (!mac_enforce_fs)
 1694                 return (0);
 1695 
 1696         MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
 1697             &vp->v_label, cnp);
 1698         return (error);
 1699 }
 1700 
 1701 int
 1702 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
 1703     struct vnode *vp, int samedir, struct componentname *cnp)
 1704 {
 1705         int error;
 1706 
 1707         ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
 1708         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
 1709 
 1710         if (!mac_enforce_fs)
 1711                 return (0);
 1712 
 1713         MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
 1714             vp != NULL ? &vp->v_label : NULL, samedir, cnp);
 1715         return (error);
 1716 }
 1717 
 1718 int
 1719 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
 1720 {
 1721         int error;
 1722 
 1723         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
 1724 
 1725         if (!mac_enforce_fs)
 1726                 return (0);
 1727 
 1728         MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
 1729         return (error);
 1730 }
 1731 
 1732 int
 1733 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
 1734     struct acl *acl)
 1735 {
 1736         int error;
 1737 
 1738         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
 1739 
 1740         if (!mac_enforce_fs)
 1741                 return (0);
 1742 
 1743         MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
 1744         return (error);
 1745 }
 1746 
 1747 int
 1748 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
 1749     int attrnamespace, const char *name, struct uio *uio)
 1750 {
 1751         int error;
 1752 
 1753         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
 1754 
 1755         if (!mac_enforce_fs)
 1756                 return (0);
 1757 
 1758         MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
 1759             attrnamespace, name, uio);
 1760         return (error);
 1761 }
 1762 
 1763 int
 1764 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
 1765 {
 1766         int error;
 1767 
 1768         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
 1769 
 1770         if (!mac_enforce_fs)
 1771                 return (0);
 1772 
 1773         MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
 1774         return (error);
 1775 }
 1776 
 1777 int
 1778 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
 1779 {
 1780         int error;
 1781 
 1782         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
 1783 
 1784         if (!mac_enforce_fs)
 1785                 return (0);
 1786 
 1787         MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
 1788         return (error);
 1789 }
 1790 
 1791 int
 1792 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
 1793     gid_t gid)
 1794 {
 1795         int error;
 1796 
 1797         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
 1798 
 1799         if (!mac_enforce_fs)
 1800                 return (0);
 1801 
 1802         MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
 1803         return (error);
 1804 }
 1805 
 1806 int
 1807 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
 1808     struct timespec atime, struct timespec mtime)
 1809 {
 1810         int error;
 1811 
 1812         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
 1813 
 1814         if (!mac_enforce_fs)
 1815                 return (0);
 1816 
 1817         MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
 1818             mtime);
 1819         return (error);
 1820 }
 1821 
 1822 int
 1823 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
 1824     struct vnode *vp)
 1825 {
 1826         int error;
 1827 
 1828         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
 1829 
 1830         if (!mac_enforce_fs)
 1831                 return (0);
 1832 
 1833         MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
 1834             &vp->v_label);
 1835         return (error);
 1836 }
 1837 
 1838 int
 1839 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
 1840     struct vnode *vp)
 1841 {
 1842         int error;
 1843 
 1844         ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
 1845 
 1846         if (!mac_enforce_fs)
 1847                 return (0);
 1848 
 1849         MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
 1850             &vp->v_label);
 1851 
 1852         return (error);
 1853 }
 1854 
 1855 /*
 1856  * When relabeling a process, call out to the policies for the maximum
 1857  * permission allowed for each object type we know about in its
 1858  * memory space, and revoke access (in the least surprising ways we
 1859  * know) when necessary.  The process lock is not held here.
 1860  */
 1861 void
 1862 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
 1863 {
 1864 
 1865         /* XXX freeze all other threads */
 1866         mac_cred_mmapped_drop_perms_recurse(td, cred,
 1867             &td->td_proc->p_vmspace->vm_map);
 1868         /* XXX allow other threads to continue */
 1869 }
 1870 
 1871 static __inline const char *
 1872 prot2str(vm_prot_t prot)
 1873 {
 1874 
 1875         switch (prot & VM_PROT_ALL) {
 1876         case VM_PROT_READ:
 1877                 return ("r--");
 1878         case VM_PROT_READ | VM_PROT_WRITE:
 1879                 return ("rw-");
 1880         case VM_PROT_READ | VM_PROT_EXECUTE:
 1881                 return ("r-x");
 1882         case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
 1883                 return ("rwx");
 1884         case VM_PROT_WRITE:
 1885                 return ("-w-");
 1886         case VM_PROT_EXECUTE:
 1887                 return ("--x");
 1888         case VM_PROT_WRITE | VM_PROT_EXECUTE:
 1889                 return ("-wx");
 1890         default:
 1891                 return ("---");
 1892         }
 1893 }
 1894 
 1895 static void
 1896 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
 1897     struct vm_map *map)
 1898 {
 1899         struct vm_map_entry *vme;
 1900         int result;
 1901         vm_prot_t revokeperms;
 1902         vm_object_t object;
 1903         vm_ooffset_t offset;
 1904         struct vnode *vp;
 1905 
 1906         if (!mac_mmap_revocation)
 1907                 return;
 1908 
 1909         vm_map_lock_read(map);
 1910         for (vme = map->header.next; vme != &map->header; vme = vme->next) {
 1911                 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
 1912                         mac_cred_mmapped_drop_perms_recurse(td, cred,
 1913                             vme->object.sub_map);
 1914                         continue;
 1915                 }
 1916                 /*
 1917                  * Skip over entries that obviously are not shared.
 1918                  */
 1919                 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
 1920                     !vme->max_protection)
 1921                         continue;
 1922                 /*
 1923                  * Drill down to the deepest backing object.
 1924                  */
 1925                 offset = vme->offset;
 1926                 object = vme->object.vm_object;
 1927                 if (object == NULL)
 1928                         continue;
 1929                 while (object->backing_object != NULL) {
 1930                         object = object->backing_object;
 1931                         offset += object->backing_object_offset;
 1932                 }
 1933                 /*
 1934                  * At the moment, vm_maps and objects aren't considered
 1935                  * by the MAC system, so only things with backing by a
 1936                  * normal object (read: vnodes) are checked.
 1937                  */
 1938                 if (object->type != OBJT_VNODE)
 1939                         continue;
 1940                 vp = (struct vnode *)object->handle;
 1941                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1942                 result = vme->max_protection;
 1943                 mac_check_vnode_mmap_downgrade(cred, vp, &result);
 1944                 VOP_UNLOCK(vp, 0, td);
 1945                 /*
 1946                  * Find out what maximum protection we may be allowing
 1947                  * now but a policy needs to get removed.
 1948                  */
 1949                 revokeperms = vme->max_protection & ~result;
 1950                 if (!revokeperms)
 1951                         continue;
 1952                 printf("pid %ld: revoking %s perms from %#lx:%ld "
 1953                     "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
 1954                     prot2str(revokeperms), (u_long)vme->start,
 1955                     (long)(vme->end - vme->start),
 1956                     prot2str(vme->max_protection), prot2str(vme->protection));
 1957                 vm_map_lock_upgrade(map);
 1958                 /*
 1959                  * This is the really simple case: if a map has more
 1960                  * max_protection than is allowed, but it's not being
 1961                  * actually used (that is, the current protection is
 1962                  * still allowed), we can just wipe it out and do
 1963                  * nothing more.
 1964                  */
 1965                 if ((vme->protection & revokeperms) == 0) {
 1966                         vme->max_protection -= revokeperms;
 1967                 } else {
 1968                         if (revokeperms & VM_PROT_WRITE) {
 1969                                 /*
 1970                                  * In the more complicated case, flush out all
 1971                                  * pending changes to the object then turn it
 1972                                  * copy-on-write.
 1973                                  */
 1974                                 vm_object_reference(object);
 1975                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1976                                 vm_object_page_clean(object,
 1977                                     OFF_TO_IDX(offset),
 1978                                     OFF_TO_IDX(offset + vme->end - vme->start +
 1979                                         PAGE_MASK),
 1980                                     OBJPC_SYNC);
 1981                                 VOP_UNLOCK(vp, 0, td);
 1982                                 vm_object_deallocate(object);
 1983                                 /*
 1984                                  * Why bother if there's no read permissions
 1985                                  * anymore?  For the rest, we need to leave
 1986                                  * the write permissions on for COW, or
 1987                                  * remove them entirely if configured to.
 1988                                  */
 1989                                 if (!mac_mmap_revocation_via_cow) {
 1990                                         vme->max_protection &= ~VM_PROT_WRITE;
 1991                                         vme->protection &= ~VM_PROT_WRITE;
 1992                                 } if ((revokeperms & VM_PROT_READ) == 0)
 1993                                         vme->eflags |= MAP_ENTRY_COW |
 1994                                             MAP_ENTRY_NEEDS_COPY;
 1995                         }
 1996                         if (revokeperms & VM_PROT_EXECUTE) {
 1997                                 vme->max_protection &= ~VM_PROT_EXECUTE;
 1998                                 vme->protection &= ~VM_PROT_EXECUTE;
 1999                         }
 2000                         if (revokeperms & VM_PROT_READ) {
 2001                                 vme->max_protection = 0;
 2002                                 vme->protection = 0;
 2003                         }
 2004                         pmap_protect(map->pmap, vme->start, vme->end,
 2005                             vme->protection & ~revokeperms);
 2006                         vm_map_simplify_entry(map, vme);
 2007                 }
 2008                 vm_map_lock_downgrade(map);
 2009         }
 2010         vm_map_unlock_read(map);
 2011 }
 2012 
 2013 /*
 2014  * When the subject's label changes, it may require revocation of privilege
 2015  * to mapped objects.  This can't be done on-the-fly later with a unified
 2016  * buffer cache.
 2017  */
 2018 static void
 2019 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
 2020 {
 2021 
 2022         MAC_PERFORM(relabel_cred, cred, newlabel);
 2023 }
 2024 
 2025 void
 2026 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
 2027 {
 2028 
 2029         MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
 2030 }
 2031 
 2032 void
 2033 mac_create_ifnet(struct ifnet *ifnet)
 2034 {
 2035 
 2036         MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
 2037 }
 2038 
 2039 void
 2040 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
 2041 {
 2042 
 2043         MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
 2044 }
 2045 
 2046 void
 2047 mac_create_socket(struct ucred *cred, struct socket *socket)
 2048 {
 2049 
 2050         MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
 2051 }
 2052 
 2053 void
 2054 mac_create_pipe(struct ucred *cred, struct pipe *pipe)
 2055 {
 2056 
 2057         MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
 2058 }
 2059 
 2060 void
 2061 mac_create_socket_from_socket(struct socket *oldsocket,
 2062     struct socket *newsocket)
 2063 {
 2064 
 2065         MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
 2066             newsocket, &newsocket->so_label);
 2067 }
 2068 
 2069 static void
 2070 mac_relabel_socket(struct ucred *cred, struct socket *socket,
 2071     struct label *newlabel)
 2072 {
 2073 
 2074         MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
 2075 }
 2076 
 2077 static void
 2078 mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
 2079 {
 2080 
 2081         MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
 2082 }
 2083 
 2084 void
 2085 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
 2086 {
 2087 
 2088         MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
 2089             socket, &socket->so_peerlabel);
 2090 }
 2091 
 2092 void
 2093 mac_set_socket_peer_from_socket(struct socket *oldsocket,
 2094     struct socket *newsocket)
 2095 {
 2096 
 2097         MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
 2098             &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
 2099 }
 2100 
 2101 void
 2102 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
 2103 {
 2104 
 2105         MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
 2106             datagram, &datagram->m_pkthdr.label);
 2107 }
 2108 
 2109 void
 2110 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
 2111 {
 2112 
 2113         MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
 2114             fragment, &fragment->m_pkthdr.label);
 2115 }
 2116 
 2117 void
 2118 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
 2119 {
 2120 
 2121         MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
 2122             &ipq->ipq_label);
 2123 }
 2124 
 2125 void
 2126 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
 2127 {
 2128 
 2129         MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
 2130             newmbuf, &newmbuf->m_pkthdr.label);
 2131 }
 2132 
 2133 void
 2134 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
 2135 {
 2136 
 2137         MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
 2138             &mbuf->m_pkthdr.label);
 2139 }
 2140 
 2141 void
 2142 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
 2143 {
 2144 
 2145         MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
 2146             &mbuf->m_pkthdr.label);
 2147 }
 2148 
 2149 void
 2150 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
 2151 {
 2152 
 2153         MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
 2154             &mbuf->m_pkthdr.label);
 2155 }
 2156 
 2157 void
 2158 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
 2159     struct mbuf *newmbuf)
 2160 {
 2161 
 2162         MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
 2163             &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
 2164             &newmbuf->m_pkthdr.label);
 2165 }
 2166 
 2167 void
 2168 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
 2169 {
 2170 
 2171         MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
 2172             newmbuf, &newmbuf->m_pkthdr.label);
 2173 }
 2174 
 2175 int
 2176 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
 2177 {
 2178         int result;
 2179 
 2180         result = 1;
 2181         MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
 2182             ipq, &ipq->ipq_label);
 2183 
 2184         return (result);
 2185 }
 2186 
 2187 void
 2188 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
 2189 {
 2190 
 2191         MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
 2192             &ipq->ipq_label);
 2193 }
 2194 
 2195 void
 2196 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
 2197 {
 2198 
 2199         MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
 2200             &mbuf->m_pkthdr.label);
 2201 }
 2202 
 2203 void
 2204 mac_create_mount(struct ucred *cred, struct mount *mp)
 2205 {
 2206 
 2207         MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
 2208             &mp->mnt_fslabel);
 2209 }
 2210 
 2211 void
 2212 mac_create_root_mount(struct ucred *cred, struct mount *mp)
 2213 {
 2214 
 2215         MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
 2216             &mp->mnt_fslabel);
 2217 }
 2218 
 2219 int
 2220 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
 2221 {
 2222         int error;
 2223 
 2224         if (!mac_enforce_network)
 2225                 return (0);
 2226 
 2227         MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
 2228             &ifnet->if_label);
 2229 
 2230         return (error);
 2231 }
 2232 
 2233 static int
 2234 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
 2235 {
 2236         int error;
 2237 
 2238         MAC_CHECK(check_cred_relabel, cred, newlabel);
 2239 
 2240         return (error);
 2241 }
 2242 
 2243 int
 2244 mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
 2245 {
 2246         int error;
 2247 
 2248         if (!mac_enforce_process)
 2249                 return (0);
 2250 
 2251         MAC_CHECK(check_cred_visible, u1, u2);
 2252 
 2253         return (error);
 2254 }
 2255 
 2256 int
 2257 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
 2258 {
 2259         int error;
 2260 
 2261         if (!mac_enforce_network)
 2262                 return (0);
 2263 
 2264         KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
 2265         if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
 2266                 if_printf(ifnet, "not initialized\n");
 2267 
 2268         MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
 2269             &mbuf->m_pkthdr.label);
 2270 
 2271         return (error);
 2272 }
 2273 
 2274 int
 2275 mac_check_kenv_dump(struct ucred *cred)
 2276 {
 2277         int error;
 2278 
 2279         if (!mac_enforce_system)
 2280                 return (0);
 2281 
 2282         MAC_CHECK(check_kenv_dump, cred);
 2283 
 2284         return (error);
 2285 }
 2286 
 2287 int
 2288 mac_check_kenv_get(struct ucred *cred, char *name)
 2289 {
 2290         int error;
 2291 
 2292         if (!mac_enforce_system)
 2293                 return (0);
 2294 
 2295         MAC_CHECK(check_kenv_get, cred, name);
 2296 
 2297         return (error);
 2298 }
 2299 
 2300 int
 2301 mac_check_kenv_set(struct ucred *cred, char *name, char *value)
 2302 {
 2303         int error;
 2304 
 2305         if (!mac_enforce_system)
 2306                 return (0);
 2307 
 2308         MAC_CHECK(check_kenv_set, cred, name, value);
 2309 
 2310         return (error);
 2311 }
 2312 
 2313 int
 2314 mac_check_kenv_unset(struct ucred *cred, char *name)
 2315 {
 2316         int error;
 2317 
 2318         if (!mac_enforce_system)
 2319                 return (0);
 2320 
 2321         MAC_CHECK(check_kenv_unset, cred, name);
 2322 
 2323         return (error);
 2324 }
 2325 
 2326 int
 2327 mac_check_kld_load(struct ucred *cred, struct vnode *vp)
 2328 {
 2329         int error;
 2330 
 2331         ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
 2332 
 2333         if (!mac_enforce_kld)
 2334                 return (0);
 2335 
 2336         MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
 2337 
 2338         return (error);
 2339 }
 2340 
 2341 int
 2342 mac_check_kld_stat(struct ucred *cred)
 2343 {
 2344         int error;
 2345 
 2346         if (!mac_enforce_kld)
 2347                 return (0);
 2348 
 2349         MAC_CHECK(check_kld_stat, cred);
 2350 
 2351         return (error);
 2352 }
 2353 
 2354 int
 2355 mac_check_kld_unload(struct ucred *cred)
 2356 {
 2357         int error;
 2358 
 2359         if (!mac_enforce_kld)
 2360                 return (0);
 2361 
 2362         MAC_CHECK(check_kld_unload, cred);
 2363 
 2364         return (error);
 2365 }
 2366 
 2367 int
 2368 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
 2369 {
 2370         int error;
 2371 
 2372         if (!mac_enforce_fs)
 2373                 return (0);
 2374 
 2375         MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
 2376 
 2377         return (error);
 2378 }
 2379 
 2380 int
 2381 mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
 2382     void *data)
 2383 {
 2384         int error;
 2385 
 2386         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
 2387 
 2388         if (!mac_enforce_pipe)
 2389                 return (0);
 2390 
 2391         MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
 2392 
 2393         return (error);
 2394 }
 2395 
 2396 int
 2397 mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
 2398 {
 2399         int error;
 2400 
 2401         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
 2402 
 2403         if (!mac_enforce_pipe)
 2404                 return (0);
 2405 
 2406         MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
 2407 
 2408         return (error);
 2409 }
 2410 
 2411 int
 2412 mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
 2413 {
 2414         int error;
 2415 
 2416         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
 2417 
 2418         if (!mac_enforce_pipe)
 2419                 return (0);
 2420 
 2421         MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
 2422 
 2423         return (error);
 2424 }
 2425 
 2426 static int
 2427 mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
 2428     struct label *newlabel)
 2429 {
 2430         int error;
 2431 
 2432         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
 2433 
 2434         if (!mac_enforce_pipe)
 2435                 return (0);
 2436 
 2437         MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
 2438 
 2439         return (error);
 2440 }
 2441 
 2442 int
 2443 mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
 2444 {
 2445         int error;
 2446 
 2447         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
 2448 
 2449         if (!mac_enforce_pipe)
 2450                 return (0);
 2451 
 2452         MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
 2453 
 2454         return (error);
 2455 }
 2456 
 2457 int
 2458 mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
 2459 {
 2460         int error;
 2461 
 2462         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
 2463 
 2464         if (!mac_enforce_pipe)
 2465                 return (0);
 2466 
 2467         MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
 2468 
 2469         return (error);
 2470 }
 2471 
 2472 int
 2473 mac_check_proc_debug(struct ucred *cred, struct proc *proc)
 2474 {
 2475         int error;
 2476 
 2477         PROC_LOCK_ASSERT(proc, MA_OWNED);
 2478 
 2479         if (!mac_enforce_process)
 2480                 return (0);
 2481 
 2482         MAC_CHECK(check_proc_debug, cred, proc);
 2483 
 2484         return (error);
 2485 }
 2486 
 2487 int
 2488 mac_check_proc_sched(struct ucred *cred, struct proc *proc)
 2489 {
 2490         int error;
 2491 
 2492         PROC_LOCK_ASSERT(proc, MA_OWNED);
 2493 
 2494         if (!mac_enforce_process)
 2495                 return (0);
 2496 
 2497         MAC_CHECK(check_proc_sched, cred, proc);
 2498 
 2499         return (error);
 2500 }
 2501 
 2502 int
 2503 mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
 2504 {
 2505         int error;
 2506 
 2507         PROC_LOCK_ASSERT(proc, MA_OWNED);
 2508 
 2509         if (!mac_enforce_process)
 2510                 return (0);
 2511 
 2512         MAC_CHECK(check_proc_signal, cred, proc, signum);
 2513 
 2514         return (error);
 2515 }
 2516 
 2517 int
 2518 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
 2519     struct sockaddr *sockaddr)
 2520 {
 2521         int error;
 2522 
 2523         if (!mac_enforce_socket)
 2524                 return (0);
 2525 
 2526         MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
 2527             sockaddr);
 2528 
 2529         return (error);
 2530 }
 2531 
 2532 int
 2533 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
 2534     struct sockaddr *sockaddr)
 2535 {
 2536         int error;
 2537 
 2538         if (!mac_enforce_socket)
 2539                 return (0);
 2540 
 2541         MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
 2542             sockaddr);
 2543 
 2544         return (error);
 2545 }
 2546 
 2547 int
 2548 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
 2549 {
 2550         int error;
 2551 
 2552         if (!mac_enforce_socket)
 2553                 return (0);
 2554 
 2555         MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
 2556             &mbuf->m_pkthdr.label);
 2557 
 2558         return (error);
 2559 }
 2560 
 2561 int
 2562 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
 2563 {
 2564         int error;
 2565 
 2566         if (!mac_enforce_socket)
 2567                 return (0);
 2568 
 2569         MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
 2570         return (error);
 2571 }
 2572 
 2573 int
 2574 mac_check_socket_receive(struct ucred *cred, struct socket *so)
 2575 {
 2576         int error;
 2577 
 2578         if (!mac_enforce_socket)
 2579                 return (0);
 2580 
 2581         MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
 2582 
 2583         return (error);
 2584 }
 2585 
 2586 static int
 2587 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
 2588     struct label *newlabel)
 2589 {
 2590         int error;
 2591 
 2592         MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
 2593             newlabel);
 2594 
 2595         return (error);
 2596 }
 2597 
 2598 int
 2599 mac_check_socket_send(struct ucred *cred, struct socket *so)
 2600 {
 2601         int error;
 2602 
 2603         if (!mac_enforce_socket)
 2604                 return (0);
 2605 
 2606         MAC_CHECK(check_socket_send, cred, so, &so->so_label);
 2607 
 2608         return (error);
 2609 }
 2610 
 2611 int
 2612 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
 2613 {
 2614         int error;
 2615 
 2616         if (!mac_enforce_socket)
 2617                 return (0);
 2618 
 2619         MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
 2620 
 2621         return (error);
 2622 }
 2623 
 2624 int
 2625 mac_check_system_acct(struct ucred *cred, struct vnode *vp)
 2626 {
 2627         int error;
 2628 
 2629         if (vp != NULL) {
 2630                 ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
 2631         }
 2632 
 2633         if (!mac_enforce_system)
 2634                 return (0);
 2635 
 2636         MAC_CHECK(check_system_acct, cred, vp,
 2637             vp != NULL ? &vp->v_label : NULL);
 2638 
 2639         return (error);
 2640 }
 2641 
 2642 int
 2643 mac_check_system_nfsd(struct ucred *cred)
 2644 {
 2645         int error;
 2646 
 2647         if (!mac_enforce_system)
 2648                 return (0);
 2649 
 2650         MAC_CHECK(check_system_nfsd, cred);
 2651 
 2652         return (error);
 2653 }
 2654 
 2655 int
 2656 mac_check_system_reboot(struct ucred *cred, int howto)
 2657 {
 2658         int error;
 2659 
 2660         if (!mac_enforce_system)
 2661                 return (0);
 2662 
 2663         MAC_CHECK(check_system_reboot, cred, howto);
 2664 
 2665         return (error);
 2666 }
 2667 
 2668 int
 2669 mac_check_system_settime(struct ucred *cred)
 2670 {
 2671         int error;
 2672 
 2673         if (!mac_enforce_system)
 2674                 return (0);
 2675 
 2676         MAC_CHECK(check_system_settime, cred);
 2677 
 2678         return (error);
 2679 }
 2680 
 2681 int
 2682 mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
 2683 {
 2684         int error;
 2685 
 2686         ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
 2687 
 2688         if (!mac_enforce_system)
 2689                 return (0);
 2690 
 2691         MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
 2692         return (error);
 2693 }
 2694 
 2695 int
 2696 mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
 2697     void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
 2698 {
 2699         int error;
 2700 
 2701         /*
 2702          * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
 2703          * but since it's not exported from kern_sysctl.c, we can't.
 2704          */
 2705         if (!mac_enforce_system)
 2706                 return (0);
 2707 
 2708         MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
 2709             inkernel, new, newlen);
 2710 
 2711         return (error);
 2712 }
 2713 
 2714 int
 2715 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
 2716     struct ifnet *ifnet)
 2717 {
 2718         char *elements, *buffer;
 2719         struct mac mac;
 2720         int error;
 2721 
 2722         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
 2723         if (error)
 2724                 return (error);
 2725 
 2726         error = mac_check_structmac_consistent(&mac);
 2727         if (error)
 2728                 return (error);
 2729 
 2730         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 2731         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
 2732         if (error) {
 2733                 free(elements, M_MACTEMP);
 2734                 return (error);
 2735         }
 2736 
 2737         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 2738         error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
 2739             buffer, mac.m_buflen, M_WAITOK);
 2740         if (error == 0)
 2741                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 2742 
 2743         free(buffer, M_MACTEMP);
 2744         free(elements, M_MACTEMP);
 2745 
 2746         return (error);
 2747 }
 2748 
 2749 int
 2750 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
 2751     struct ifnet *ifnet)
 2752 {
 2753         struct label intlabel;
 2754         struct mac mac;
 2755         char *buffer;
 2756         int error;
 2757 
 2758         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
 2759         if (error)
 2760                 return (error);
 2761 
 2762         error = mac_check_structmac_consistent(&mac);
 2763         if (error)
 2764                 return (error);
 2765 
 2766         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 2767         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 2768         if (error) {
 2769                 free(buffer, M_MACTEMP);
 2770                 return (error);
 2771         }
 2772 
 2773         mac_init_ifnet_label(&intlabel);
 2774         error = mac_internalize_ifnet_label(&intlabel, buffer);
 2775         free(buffer, M_MACTEMP);
 2776         if (error) {
 2777                 mac_destroy_ifnet_label(&intlabel);
 2778                 return (error);
 2779         }
 2780 
 2781         /*
 2782          * XXX: Note that this is a redundant privilege check, since
 2783          * policies impose this check themselves if required by the
 2784          * policy.  Eventually, this should go away.
 2785          */
 2786         error = suser_cred(cred, 0);
 2787         if (error) {
 2788                 mac_destroy_ifnet_label(&intlabel);
 2789                 return (error);
 2790         }
 2791 
 2792         MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
 2793             &intlabel);
 2794         if (error) {
 2795                 mac_destroy_ifnet_label(&intlabel);
 2796                 return (error);
 2797         }
 2798 
 2799         MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
 2800 
 2801         mac_destroy_ifnet_label(&intlabel);
 2802         return (0);
 2803 }
 2804 
 2805 void
 2806 mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
 2807 {
 2808 
 2809         MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
 2810 }
 2811 
 2812 void
 2813 mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
 2814     struct devfs_dirent *dd, struct devfs_dirent *de)
 2815 {
 2816 
 2817         MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
 2818             &de->de_label);
 2819 }
 2820 
 2821 void
 2822 mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
 2823     struct devfs_dirent *de)
 2824 {
 2825 
 2826         MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
 2827             &de->de_label);
 2828 }
 2829 
 2830 int
 2831 mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
 2832     struct mac *mac)
 2833 {
 2834         struct label intlabel;
 2835         char *buffer;
 2836         int error;
 2837 
 2838         error = mac_check_structmac_consistent(mac);
 2839         if (error)
 2840                 return (error);
 2841 
 2842         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
 2843         error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
 2844         if (error) {
 2845                 free(buffer, M_MACTEMP);
 2846                 return (error);
 2847         }
 2848 
 2849         mac_init_socket_label(&intlabel, M_WAITOK);
 2850         error = mac_internalize_socket_label(&intlabel, buffer);
 2851         free(buffer, M_MACTEMP);
 2852         if (error) {
 2853                 mac_destroy_socket_label(&intlabel);
 2854                 return (error);
 2855         }
 2856 
 2857         mac_check_socket_relabel(cred, so, &intlabel);
 2858         if (error) {
 2859                 mac_destroy_socket_label(&intlabel);
 2860                 return (error);
 2861         }
 2862 
 2863         mac_relabel_socket(cred, so, &intlabel);
 2864 
 2865         mac_destroy_socket_label(&intlabel);
 2866         return (0);
 2867 }
 2868 
 2869 int
 2870 mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
 2871 {
 2872         int error;
 2873 
 2874         PIPE_LOCK_ASSERT(pipe, MA_OWNED);
 2875 
 2876         error = mac_check_pipe_relabel(cred, pipe, label);
 2877         if (error)
 2878                 return (error);
 2879 
 2880         mac_relabel_pipe(cred, pipe, label);
 2881 
 2882         return (0);
 2883 }
 2884 
 2885 int
 2886 mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
 2887     struct mac *mac)
 2888 {
 2889         char *buffer, *elements;
 2890         int error;
 2891 
 2892         error = mac_check_structmac_consistent(mac);
 2893         if (error)
 2894                 return (error);
 2895 
 2896         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
 2897         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
 2898         if (error) {
 2899                 free(elements, M_MACTEMP);
 2900                 return (error);
 2901         }
 2902 
 2903         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 2904         error = mac_externalize_socket_label(&so->so_label, elements,
 2905             buffer, mac->m_buflen, M_WAITOK);
 2906         if (error == 0)
 2907                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
 2908 
 2909         free(buffer, M_MACTEMP);
 2910         free(elements, M_MACTEMP);
 2911 
 2912         return (error);
 2913 }
 2914 
 2915 int
 2916 mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
 2917     struct mac *mac)
 2918 {
 2919         char *elements, *buffer;
 2920         int error;
 2921 
 2922         error = mac_check_structmac_consistent(mac);
 2923         if (error)
 2924                 return (error);
 2925 
 2926         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
 2927         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
 2928         if (error) {
 2929                 free(elements, M_MACTEMP);
 2930                 return (error);
 2931         }
 2932 
 2933         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 2934         error = mac_externalize_socket_peer_label(&so->so_peerlabel,
 2935             elements, buffer, mac->m_buflen, M_WAITOK);
 2936         if (error == 0)
 2937                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
 2938 
 2939         free(buffer, M_MACTEMP);
 2940         free(elements, M_MACTEMP);
 2941 
 2942         return (error);
 2943 }
 2944 
 2945 /*
 2946  * Implementation of VOP_SETLABEL() that relies on extended attributes
 2947  * to store label data.  Can be referenced by filesystems supporting
 2948  * extended attributes.
 2949  */
 2950 int
 2951 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
 2952 {
 2953         struct vnode *vp = ap->a_vp;
 2954         struct label *intlabel = ap->a_label;
 2955         int error;
 2956 
 2957         ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
 2958 
 2959         if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
 2960                 return (EOPNOTSUPP);
 2961 
 2962         error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
 2963         if (error)
 2964                 return (error);
 2965 
 2966         mac_relabel_vnode(ap->a_cred, vp, intlabel);
 2967 
 2968         return (0);
 2969 }
 2970 
 2971 static int
 2972 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
 2973 {
 2974         int error;
 2975 
 2976         if (vp->v_mount == NULL) {
 2977                 /* printf("vn_setlabel: null v_mount\n"); */
 2978                 if (vp->v_type != VNON)
 2979                         printf("vn_setlabel: null v_mount with non-VNON\n");
 2980                 return (EBADF);
 2981         }
 2982 
 2983         if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
 2984                 return (EOPNOTSUPP);
 2985 
 2986         /*
 2987          * Multi-phase commit.  First check the policies to confirm the
 2988          * change is OK.  Then commit via the filesystem.  Finally,
 2989          * update the actual vnode label.  Question: maybe the filesystem
 2990          * should update the vnode at the end as part of VOP_SETLABEL()?
 2991          */
 2992         error = mac_check_vnode_relabel(cred, vp, intlabel);
 2993         if (error)
 2994                 return (error);
 2995 
 2996         /*
 2997          * VADMIN provides the opportunity for the filesystem to make
 2998          * decisions about who is and is not able to modify labels
 2999          * and protections on files.  This might not be right.  We can't
 3000          * assume VOP_SETLABEL() will do it, because we might implement
 3001          * that as part of vop_stdsetlabel_ea().
 3002          */
 3003         error = VOP_ACCESS(vp, VADMIN, cred, curthread);
 3004         if (error)
 3005                 return (error);
 3006 
 3007         error = VOP_SETLABEL(vp, intlabel, cred, curthread);
 3008         if (error)
 3009                 return (error);
 3010 
 3011         return (0);
 3012 }
 3013 
 3014 int
 3015 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
 3016 {
 3017         char *elements, *buffer;
 3018         struct mac mac;
 3019         struct proc *tproc;
 3020         struct ucred *tcred;
 3021         int error;
 3022 
 3023         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3024         if (error)
 3025                 return (error);
 3026 
 3027         error = mac_check_structmac_consistent(&mac);
 3028         if (error)
 3029                 return (error);
 3030 
 3031         tproc = pfind(uap->pid);
 3032         if (tproc == NULL)
 3033                 return (ESRCH);
 3034 
 3035         tcred = NULL;                           /* Satisfy gcc. */
 3036         error = p_cansee(td, tproc);
 3037         if (error == 0)
 3038                 tcred = crhold(tproc->p_ucred);
 3039         PROC_UNLOCK(tproc);
 3040         if (error)
 3041                 return (error);
 3042 
 3043         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3044         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
 3045         if (error) {
 3046                 free(elements, M_MACTEMP);
 3047                 crfree(tcred);
 3048                 return (error);
 3049         }
 3050 
 3051         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 3052         error = mac_externalize_cred_label(&tcred->cr_label, elements,
 3053             buffer, mac.m_buflen, M_WAITOK);
 3054         if (error == 0)
 3055                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 3056 
 3057         free(buffer, M_MACTEMP);
 3058         free(elements, M_MACTEMP);
 3059         crfree(tcred);
 3060         return (error);
 3061 }
 3062 
 3063 /*
 3064  * MPSAFE
 3065  */
 3066 int
 3067 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
 3068 {
 3069         char *elements, *buffer;
 3070         struct mac mac;
 3071         int error;
 3072 
 3073         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3074         if (error)
 3075                 return (error);
 3076 
 3077         error = mac_check_structmac_consistent(&mac);
 3078         if (error)
 3079                 return (error);
 3080 
 3081         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3082         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
 3083         if (error) {
 3084                 free(elements, M_MACTEMP);
 3085                 return (error);
 3086         }
 3087 
 3088         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 3089         error = mac_externalize_cred_label(&td->td_ucred->cr_label,
 3090             elements, buffer, mac.m_buflen, M_WAITOK);
 3091         if (error == 0)
 3092                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 3093 
 3094         free(buffer, M_MACTEMP);
 3095         free(elements, M_MACTEMP);
 3096         return (error);
 3097 }
 3098 
 3099 /*
 3100  * MPSAFE
 3101  */
 3102 int
 3103 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
 3104 {
 3105         struct ucred *newcred, *oldcred;
 3106         struct label intlabel;
 3107         struct proc *p;
 3108         struct mac mac;
 3109         char *buffer;
 3110         int error;
 3111 
 3112         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3113         if (error)
 3114                 return (error);
 3115 
 3116         error = mac_check_structmac_consistent(&mac);
 3117         if (error)
 3118                 return (error);
 3119 
 3120         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3121         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 3122         if (error) {
 3123                 free(buffer, M_MACTEMP);
 3124                 return (error);
 3125         }
 3126 
 3127         mac_init_cred_label(&intlabel);
 3128         error = mac_internalize_cred_label(&intlabel, buffer);
 3129         free(buffer, M_MACTEMP);
 3130         if (error) {
 3131                 mac_destroy_cred_label(&intlabel);
 3132                 return (error);
 3133         }
 3134 
 3135         newcred = crget();
 3136 
 3137         p = td->td_proc;
 3138         PROC_LOCK(p);
 3139         oldcred = p->p_ucred;
 3140 
 3141         error = mac_check_cred_relabel(oldcred, &intlabel);
 3142         if (error) {
 3143                 PROC_UNLOCK(p);
 3144                 crfree(newcred);
 3145                 goto out;
 3146         }
 3147 
 3148         setsugid(p);
 3149         crcopy(newcred, oldcred);
 3150         mac_relabel_cred(newcred, &intlabel);
 3151         p->p_ucred = newcred;
 3152 
 3153         /*
 3154          * Grab additional reference for use while revoking mmaps, prior
 3155          * to releasing the proc lock and sharing the cred.
 3156          */
 3157         crhold(newcred);
 3158         PROC_UNLOCK(p);
 3159 
 3160         if (mac_enforce_vm) {
 3161                 mtx_lock(&Giant);
 3162                 mac_cred_mmapped_drop_perms(td, newcred);
 3163                 mtx_unlock(&Giant);
 3164         }
 3165 
 3166         crfree(newcred);        /* Free revocation reference. */
 3167         crfree(oldcred);
 3168 
 3169 out:
 3170         mac_destroy_cred_label(&intlabel);
 3171         return (error);
 3172 }
 3173 
 3174 /*
 3175  * MPSAFE
 3176  */
 3177 int
 3178 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
 3179 {
 3180         char *elements, *buffer;
 3181         struct label intlabel;
 3182         struct file *fp;
 3183         struct mac mac;
 3184         struct vnode *vp;
 3185         struct pipe *pipe;
 3186         short label_type;
 3187         int error;
 3188 
 3189         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3190         if (error)
 3191                 return (error);
 3192 
 3193         error = mac_check_structmac_consistent(&mac);
 3194         if (error)
 3195                 return (error);
 3196 
 3197         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3198         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
 3199         if (error) {
 3200                 free(elements, M_MACTEMP);
 3201                 return (error);
 3202         }
 3203 
 3204         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 3205         mtx_lock(&Giant);                               /* VFS */
 3206         error = fget(td, uap->fd, &fp);
 3207         if (error)
 3208                 goto out;
 3209 
 3210         label_type = fp->f_type;
 3211         switch (fp->f_type) {
 3212         case DTYPE_FIFO:
 3213         case DTYPE_VNODE:
 3214                 vp = (struct vnode *)fp->f_data;
 3215 
 3216                 mac_init_vnode_label(&intlabel);
 3217 
 3218                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3219                 mac_copy_vnode_label(&vp->v_label, &intlabel);
 3220                 VOP_UNLOCK(vp, 0, td);
 3221 
 3222                 break;
 3223         case DTYPE_PIPE:
 3224                 pipe = (struct pipe *)fp->f_data;
 3225 
 3226                 mac_init_pipe_label(&intlabel);
 3227 
 3228                 PIPE_LOCK(pipe);
 3229                 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
 3230                 PIPE_UNLOCK(pipe);
 3231                 break;
 3232         default:
 3233                 error = EINVAL;
 3234                 fdrop(fp, td);
 3235                 goto out;
 3236         }
 3237         fdrop(fp, td);
 3238 
 3239         switch (label_type) {
 3240         case DTYPE_FIFO:
 3241         case DTYPE_VNODE:
 3242                 if (error == 0)
 3243                         error = mac_externalize_vnode_label(&intlabel,
 3244                             elements, buffer, mac.m_buflen, M_WAITOK);
 3245                 mac_destroy_vnode_label(&intlabel);
 3246                 break;
 3247         case DTYPE_PIPE:
 3248                 error = mac_externalize_pipe_label(&intlabel, elements,
 3249                     buffer, mac.m_buflen, M_WAITOK);
 3250                 mac_destroy_pipe_label(&intlabel);
 3251                 break;
 3252         default:
 3253                 panic("__mac_get_fd: corrupted label_type");
 3254         }
 3255 
 3256         if (error == 0)
 3257                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 3258 
 3259 out:
 3260         mtx_unlock(&Giant);                             /* VFS */
 3261         free(buffer, M_MACTEMP);
 3262         free(elements, M_MACTEMP);
 3263 
 3264         return (error);
 3265 }
 3266 
 3267 /*
 3268  * MPSAFE
 3269  */
 3270 int
 3271 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
 3272 {
 3273         char *elements, *buffer;
 3274         struct nameidata nd;
 3275         struct label intlabel;
 3276         struct mac mac;
 3277         int error;
 3278 
 3279         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3280         if (error)
 3281                 return (error);
 3282 
 3283         error = mac_check_structmac_consistent(&mac);
 3284         if (error)
 3285                 return (error);
 3286 
 3287         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3288         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
 3289         if (error) {
 3290                 free(elements, M_MACTEMP);
 3291                 return (error);
 3292         }
 3293 
 3294         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 3295         mtx_lock(&Giant);                               /* VFS */
 3296         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
 3297             td);
 3298         error = namei(&nd);
 3299         if (error)
 3300                 goto out;
 3301 
 3302         mac_init_vnode_label(&intlabel);
 3303         mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
 3304         error = mac_externalize_vnode_label(&intlabel, elements, buffer,
 3305             mac.m_buflen, M_WAITOK);
 3306 
 3307         NDFREE(&nd, 0);
 3308         mac_destroy_vnode_label(&intlabel);
 3309 
 3310         if (error == 0)
 3311                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 3312 
 3313 out:
 3314         mtx_unlock(&Giant);                             /* VFS */
 3315 
 3316         free(buffer, M_MACTEMP);
 3317         free(elements, M_MACTEMP);
 3318 
 3319         return (error);
 3320 }
 3321 
 3322 /*
 3323  * MPSAFE
 3324  */
 3325 int
 3326 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
 3327 {
 3328         char *elements, *buffer;
 3329         struct nameidata nd;
 3330         struct label intlabel;
 3331         struct mac mac;
 3332         int error;
 3333 
 3334         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3335         if (error)
 3336                 return (error);
 3337 
 3338         error = mac_check_structmac_consistent(&mac);
 3339         if (error)
 3340                 return (error);
 3341 
 3342         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3343         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
 3344         if (error) {
 3345                 free(elements, M_MACTEMP);
 3346                 return (error);
 3347         }
 3348 
 3349         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 3350         mtx_lock(&Giant);                               /* VFS */
 3351         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
 3352             td);
 3353         error = namei(&nd);
 3354         if (error)
 3355                 goto out;
 3356 
 3357         mac_init_vnode_label(&intlabel);
 3358         mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
 3359         error = mac_externalize_vnode_label(&intlabel, elements, buffer,
 3360             mac.m_buflen, M_WAITOK);
 3361         NDFREE(&nd, 0);
 3362         mac_destroy_vnode_label(&intlabel);
 3363 
 3364         if (error == 0)
 3365                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
 3366 
 3367 out:
 3368         mtx_unlock(&Giant);                             /* VFS */
 3369 
 3370         free(buffer, M_MACTEMP);
 3371         free(elements, M_MACTEMP);
 3372 
 3373         return (error);
 3374 }
 3375 
 3376 /*
 3377  * MPSAFE
 3378  */
 3379 int
 3380 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
 3381 {
 3382         struct label intlabel;
 3383         struct pipe *pipe;
 3384         struct file *fp;
 3385         struct mount *mp;
 3386         struct vnode *vp;
 3387         struct mac mac;
 3388         char *buffer;
 3389         int error;
 3390 
 3391         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3392         if (error)
 3393                 return (error);
 3394 
 3395         error = mac_check_structmac_consistent(&mac);
 3396         if (error)
 3397                 return (error);
 3398 
 3399         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3400         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 3401         if (error) {
 3402                 free(buffer, M_MACTEMP);
 3403                 return (error);
 3404         }
 3405 
 3406         mtx_lock(&Giant);                               /* VFS */
 3407 
 3408         error = fget(td, uap->fd, &fp);
 3409         if (error)
 3410                 goto out;
 3411 
 3412         switch (fp->f_type) {
 3413         case DTYPE_FIFO:
 3414         case DTYPE_VNODE:
 3415                 mac_init_vnode_label(&intlabel);
 3416                 error = mac_internalize_vnode_label(&intlabel, buffer);
 3417                 if (error) {
 3418                         mac_destroy_vnode_label(&intlabel);
 3419                         break;
 3420                 }
 3421 
 3422                 vp = (struct vnode *)fp->f_data;
 3423                 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
 3424                 if (error != 0) {
 3425                         mac_destroy_vnode_label(&intlabel);
 3426                         break;
 3427                 }
 3428 
 3429                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3430                 error = vn_setlabel(vp, &intlabel, td->td_ucred);
 3431                 VOP_UNLOCK(vp, 0, td);
 3432                 vn_finished_write(mp);
 3433 
 3434                 mac_destroy_vnode_label(&intlabel);
 3435                 break;
 3436 
 3437         case DTYPE_PIPE:
 3438                 mac_init_pipe_label(&intlabel);
 3439                 error = mac_internalize_pipe_label(&intlabel, buffer);
 3440                 if (error == 0) {
 3441                         pipe = (struct pipe *)fp->f_data;
 3442                         PIPE_LOCK(pipe);
 3443                         error = mac_pipe_label_set(td->td_ucred, pipe,
 3444                             &intlabel);
 3445                         PIPE_UNLOCK(pipe);
 3446                 }
 3447 
 3448                 mac_destroy_pipe_label(&intlabel);
 3449                 break;
 3450 
 3451         default:
 3452                 error = EINVAL;
 3453         }
 3454 
 3455         fdrop(fp, td);
 3456 out:
 3457         mtx_unlock(&Giant);                             /* VFS */
 3458 
 3459         free(buffer, M_MACTEMP);
 3460 
 3461         return (error);
 3462 }
 3463 
 3464 /*
 3465  * MPSAFE
 3466  */
 3467 int
 3468 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
 3469 {
 3470         struct label intlabel;
 3471         struct nameidata nd;
 3472         struct mount *mp;
 3473         struct mac mac;
 3474         char *buffer;
 3475         int error;
 3476 
 3477         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3478         if (error)
 3479                 return (error);
 3480 
 3481         error = mac_check_structmac_consistent(&mac);
 3482         if (error)
 3483                 return (error);
 3484 
 3485         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3486         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 3487         if (error) {
 3488                 free(buffer, M_MACTEMP);
 3489                 return (error);
 3490         }
 3491 
 3492         mac_init_vnode_label(&intlabel);
 3493         error = mac_internalize_vnode_label(&intlabel, buffer);
 3494         free(buffer, M_MACTEMP);
 3495         if (error) {
 3496                 mac_destroy_vnode_label(&intlabel);
 3497                 return (error);
 3498         }
 3499 
 3500         mtx_lock(&Giant);                               /* VFS */
 3501 
 3502         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
 3503             td);
 3504         error = namei(&nd);
 3505         if (error == 0) {
 3506                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
 3507                 if (error == 0)
 3508                         error = vn_setlabel(nd.ni_vp, &intlabel,
 3509                             td->td_ucred);
 3510                 vn_finished_write(mp);
 3511         }
 3512 
 3513         NDFREE(&nd, 0);
 3514         mtx_unlock(&Giant);                             /* VFS */
 3515         mac_destroy_vnode_label(&intlabel);
 3516 
 3517         return (error);
 3518 }
 3519 
 3520 /*
 3521  * MPSAFE
 3522  */
 3523 int
 3524 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
 3525 {
 3526         struct label intlabel;
 3527         struct nameidata nd;
 3528         struct mount *mp;
 3529         struct mac mac;
 3530         char *buffer;
 3531         int error;
 3532 
 3533         error = copyin(uap->mac_p, &mac, sizeof(mac));
 3534         if (error)
 3535                 return (error);
 3536 
 3537         error = mac_check_structmac_consistent(&mac);
 3538         if (error)
 3539                 return (error);
 3540 
 3541         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 3542         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 3543         if (error) {
 3544                 free(buffer, M_MACTEMP);
 3545                 return (error);
 3546         }
 3547 
 3548         mac_init_vnode_label(&intlabel);
 3549         error = mac_internalize_vnode_label(&intlabel, buffer);
 3550         free(buffer, M_MACTEMP);
 3551         if (error) {
 3552                 mac_destroy_vnode_label(&intlabel);
 3553                 return (error);
 3554         }
 3555 
 3556         mtx_lock(&Giant);                               /* VFS */
 3557 
 3558         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
 3559             td);
 3560         error = namei(&nd);
 3561         if (error == 0) {
 3562                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
 3563                 if (error == 0)
 3564                         error = vn_setlabel(nd.ni_vp, &intlabel,
 3565                             td->td_ucred);
 3566                 vn_finished_write(mp);
 3567         }
 3568 
 3569         NDFREE(&nd, 0);
 3570         mtx_unlock(&Giant);                             /* VFS */
 3571         mac_destroy_vnode_label(&intlabel);
 3572 
 3573         return (error);
 3574 }
 3575 
 3576 /*
 3577  * MPSAFE
 3578  */
 3579 int
 3580 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
 3581 {
 3582         struct mac_policy_conf *mpc;
 3583         char target[MAC_MAX_POLICY_NAME];
 3584         int error;
 3585 
 3586         error = copyinstr(uap->policy, target, sizeof(target), NULL);
 3587         if (error)
 3588                 return (error);
 3589 
 3590         error = ENOSYS;
 3591         MAC_POLICY_LIST_BUSY();
 3592         LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
 3593                 if (strcmp(mpc->mpc_name, target) == 0 &&
 3594                     mpc->mpc_ops->mpo_syscall != NULL) {
 3595                         error = mpc->mpc_ops->mpo_syscall(td,
 3596                             uap->call, uap->arg);
 3597                         goto out;
 3598                 }
 3599         }
 3600 
 3601 out:
 3602         MAC_POLICY_LIST_UNBUSY();
 3603         return (error);
 3604 }
 3605 
 3606 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
 3607 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
 3608 
 3609 #else /* !MAC */
 3610 
 3611 int
 3612 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
 3613 {
 3614 
 3615         return (ENOSYS);
 3616 }
 3617 
 3618 int
 3619 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
 3620 {
 3621 
 3622         return (ENOSYS);
 3623 }
 3624 
 3625 int
 3626 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
 3627 {
 3628 
 3629         return (ENOSYS);
 3630 }
 3631 
 3632 int
 3633 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
 3634 {
 3635 
 3636         return (ENOSYS);
 3637 }
 3638 
 3639 int
 3640 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
 3641 {
 3642 
 3643         return (ENOSYS);
 3644 }
 3645 
 3646 int
 3647 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
 3648 {
 3649 
 3650         return (ENOSYS);
 3651 }
 3652 
 3653 int
 3654 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
 3655 {
 3656 
 3657         return (ENOSYS);
 3658 }
 3659 
 3660 int
 3661 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
 3662 {
 3663 
 3664         return (ENOSYS);
 3665 }
 3666 
 3667 int
 3668 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
 3669 {
 3670 
 3671         return (ENOSYS);
 3672 }
 3673 
 3674 int
 3675 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
 3676 {
 3677 
 3678         return (ENOSYS);
 3679 }
 3680 
 3681 #endif

Cache object: 251a65b475549b0425ceafa4190ac140


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