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

Cache object: 3651a8c01ff4f5e2573307bb74a01447


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