[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/security/mac_mls/mac_mls.c

Version: -  FREEBSD  -  FREEBSD8  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

    1 /*-
    2  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
    3  * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
    4  * All rights reserved.
    5  *
    6  * This software was developed by Robert Watson for the TrustedBSD Project.
    7  *
    8  * This software was developed for the FreeBSD Project in part by Network
    9  * Associates Laboratories, the Security Research Division of Network
   10  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
   11  * as part of the DARPA CHATS research program.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * $FreeBSD: src/sys/security/mac_mls/mac_mls.c,v 1.47.2.2 2003/06/02 18:59:29 rwatson Exp $
   35  */
   36 
   37 /*
   38  * Developed by the TrustedBSD Project.
   39  * MLS fixed label mandatory confidentiality policy.
   40  */
   41 
   42 #include <sys/types.h>
   43 #include <sys/param.h>
   44 #include <sys/acl.h>
   45 #include <sys/conf.h>
   46 #include <sys/extattr.h>
   47 #include <sys/kernel.h>
   48 #include <sys/mac.h>
   49 #include <sys/malloc.h>
   50 #include <sys/mount.h>
   51 #include <sys/proc.h>
   52 #include <sys/sbuf.h>
   53 #include <sys/systm.h>
   54 #include <sys/sysproto.h>
   55 #include <sys/sysent.h>
   56 #include <sys/systm.h>
   57 #include <sys/vnode.h>
   58 #include <sys/file.h>
   59 #include <sys/socket.h>
   60 #include <sys/socketvar.h>
   61 #include <sys/pipe.h>
   62 #include <sys/sysctl.h>
   63 
   64 #include <fs/devfs/devfs.h>
   65 
   66 #include <net/bpfdesc.h>
   67 #include <net/if.h>
   68 #include <net/if_types.h>
   69 #include <net/if_var.h>
   70 
   71 #include <netinet/in.h>
   72 #include <netinet/ip_var.h>
   73 
   74 #include <vm/vm.h>
   75 
   76 #include <sys/mac_policy.h>
   77 
   78 #include <security/mac_mls/mac_mls.h>
   79 
   80 SYSCTL_DECL(_security_mac);
   81 
   82 SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
   83     "TrustedBSD mac_mls policy controls");
   84 
   85 static int      mac_mls_label_size = sizeof(struct mac_mls);
   86 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
   87     &mac_mls_label_size, 0, "Size of struct mac_mls");
   88 
   89 static int      mac_mls_enabled = 1;
   90 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
   91     &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
   92 TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
   93 
   94 static int      destroyed_not_inited;
   95 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
   96     &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
   97 
   98 static int      ptys_equal = 0;
   99 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
  100     &ptys_equal, 0, "Label pty devices as mls/equal on create");
  101 TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
  102 
  103 static int      revocation_enabled = 0;
  104 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
  105     &revocation_enabled, 0, "Revoke access to objects on relabel");
  106 TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
  107 
  108 static int      max_compartments = MAC_MLS_MAX_COMPARTMENTS;
  109 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
  110     &max_compartments, 0, "Maximum compartments the policy supports");
  111 
  112 static int      mac_mls_slot;
  113 #define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
  114 
  115 MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
  116 
  117 static __inline int
  118 mls_bit_set_empty(u_char *set) {
  119         int i;
  120 
  121         for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
  122                 if (set[i] != 0)
  123                         return (0);
  124         return (1);
  125 }
  126 
  127 static struct mac_mls *
  128 mls_alloc(int flag)
  129 {
  130         struct mac_mls *mac_mls;
  131 
  132         mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | flag);
  133 
  134         return (mac_mls);
  135 }
  136 
  137 static void
  138 mls_free(struct mac_mls *mac_mls)
  139 {
  140 
  141         if (mac_mls != NULL)
  142                 free(mac_mls, M_MACMLS);
  143         else
  144                 atomic_add_int(&destroyed_not_inited, 1);
  145 }
  146 
  147 static int
  148 mls_atmostflags(struct mac_mls *mac_mls, int flags)
  149 {
  150 
  151         if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags)
  152                 return (EINVAL);
  153         return (0);
  154 }
  155 
  156 static int
  157 mac_mls_dominate_element(struct mac_mls_element *a,
  158     struct mac_mls_element *b)
  159 {
  160         int bit;
  161 
  162         switch (a->mme_type) {
  163         case MAC_MLS_TYPE_EQUAL:
  164         case MAC_MLS_TYPE_HIGH:
  165                 return (1);
  166 
  167         case MAC_MLS_TYPE_LOW:
  168                 switch (b->mme_type) {
  169                 case MAC_MLS_TYPE_LEVEL:
  170                 case MAC_MLS_TYPE_HIGH:
  171                         return (0);
  172 
  173                 case MAC_MLS_TYPE_EQUAL:
  174                 case MAC_MLS_TYPE_LOW:
  175                         return (1);
  176 
  177                 default:
  178                         panic("mac_mls_dominate_element: b->mme_type invalid");
  179                 }
  180 
  181         case MAC_MLS_TYPE_LEVEL:
  182                 switch (b->mme_type) {
  183                 case MAC_MLS_TYPE_EQUAL:
  184                 case MAC_MLS_TYPE_LOW:
  185                         return (1);
  186 
  187                 case MAC_MLS_TYPE_HIGH:
  188                         return (0);
  189 
  190                 case MAC_MLS_TYPE_LEVEL:
  191                         for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
  192                                 if (!MAC_MLS_BIT_TEST(bit,
  193                                     a->mme_compartments) &&
  194                                     MAC_MLS_BIT_TEST(bit, b->mme_compartments))
  195                                         return (0);
  196                         return (a->mme_level >= b->mme_level);
  197 
  198                 default:
  199                         panic("mac_mls_dominate_element: b->mme_type invalid");
  200                 }
  201 
  202         default:
  203                 panic("mac_mls_dominate_element: a->mme_type invalid");
  204         }
  205 
  206         return (0);
  207 }
  208 
  209 static int
  210 mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
  211 {
  212 
  213         return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
  214             &rangea->mm_rangehigh) &&
  215             mac_mls_dominate_element(&rangea->mm_rangelow,
  216             &rangeb->mm_rangelow));
  217 }
  218 
  219 static int
  220 mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range)
  221 {
  222 
  223         KASSERT((single->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
  224             ("mac_mls_single_in_range: a not single"));
  225         KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
  226             ("mac_mls_single_in_range: b not range"));
  227 
  228         return (mac_mls_dominate_element(&range->mm_rangehigh,
  229             &single->mm_single) &&
  230             mac_mls_dominate_element(&single->mm_single,
  231             &range->mm_rangelow));
  232 
  233         return (1);
  234 }
  235 
  236 static int
  237 mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b)
  238 {
  239         KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
  240             ("mac_mls_dominate_single: a not single"));
  241         KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
  242             ("mac_mls_dominate_single: b not single"));
  243 
  244         return (mac_mls_dominate_element(&a->mm_single, &b->mm_single));
  245 }
  246 
  247 static int
  248 mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
  249 {
  250 
  251         if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
  252             b->mme_type == MAC_MLS_TYPE_EQUAL)
  253                 return (1);
  254 
  255         return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
  256 }
  257 
  258 static int
  259 mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b)
  260 {
  261 
  262         KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
  263             ("mac_mls_equal_single: a not single"));
  264         KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
  265             ("mac_mls_equal_single: b not single"));
  266 
  267         return (mac_mls_equal_element(&a->mm_single, &b->mm_single));
  268 }
  269 
  270 static int
  271 mac_mls_contains_equal(struct mac_mls *mac_mls)
  272 {
  273 
  274         if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE)
  275                 if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
  276                         return (1);
  277 
  278         if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
  279                 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
  280                         return (1);
  281                 if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
  282                         return (1);
  283         }
  284 
  285         return (0);
  286 }
  287 
  288 static int
  289 mac_mls_subject_equal_ok(struct mac_mls *mac_mls)
  290 {
  291 
  292         KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
  293             ("mac_mls_subject_equal_ok: subject doesn't have both labels"));
  294 
  295         /* If the single is EQUAL, it's ok. */
  296         if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
  297                 return (0);
  298 
  299         /* If either range endpoint is EQUAL, it's ok. */
  300         if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
  301             mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
  302                 return (0);
  303 
  304         /* If the range is low-high, it's ok. */
  305         if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
  306             mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
  307                 return (0);
  308 
  309         /* It's not ok. */
  310         return (EPERM);
  311 }
  312 
  313 static int
  314 mac_mls_valid(struct mac_mls *mac_mls)
  315 {
  316 
  317         if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
  318                 switch (mac_mls->mm_single.mme_type) {
  319                 case MAC_MLS_TYPE_LEVEL:
  320                         break;
  321 
  322                 case MAC_MLS_TYPE_EQUAL:
  323                 case MAC_MLS_TYPE_HIGH:
  324                 case MAC_MLS_TYPE_LOW:
  325                         if (mac_mls->mm_single.mme_level != 0 ||
  326                             !MAC_MLS_BIT_SET_EMPTY(
  327                             mac_mls->mm_single.mme_compartments))
  328                                 return (EINVAL);
  329                         break;
  330 
  331                 default:
  332                         return (EINVAL);
  333                 }
  334         } else {
  335                 if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF)
  336                         return (EINVAL);
  337         }
  338 
  339         if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
  340                 switch (mac_mls->mm_rangelow.mme_type) {
  341                 case MAC_MLS_TYPE_LEVEL:
  342                         break;
  343 
  344                 case MAC_MLS_TYPE_EQUAL:
  345                 case MAC_MLS_TYPE_HIGH:
  346                 case MAC_MLS_TYPE_LOW:
  347                         if (mac_mls->mm_rangelow.mme_level != 0 ||
  348                             !MAC_MLS_BIT_SET_EMPTY(
  349                             mac_mls->mm_rangelow.mme_compartments))
  350                                 return (EINVAL);
  351                         break;
  352 
  353                 default:
  354                         return (EINVAL);
  355                 }
  356 
  357                 switch (mac_mls->mm_rangehigh.mme_type) {
  358                 case MAC_MLS_TYPE_LEVEL:
  359                         break;
  360 
  361                 case MAC_MLS_TYPE_EQUAL:
  362                 case MAC_MLS_TYPE_HIGH:
  363                 case MAC_MLS_TYPE_LOW:
  364                         if (mac_mls->mm_rangehigh.mme_level != 0 ||
  365                             !MAC_MLS_BIT_SET_EMPTY(
  366                             mac_mls->mm_rangehigh.mme_compartments))
  367                                 return (EINVAL);
  368                         break;
  369 
  370                 default:
  371                         return (EINVAL);
  372                 }
  373                 if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
  374                     &mac_mls->mm_rangelow))
  375                         return (EINVAL);
  376         } else {
  377                 if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
  378                     mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
  379                         return (EINVAL);
  380         }
  381 
  382         return (0);
  383 }
  384 
  385 static void
  386 mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
  387     u_short levellow, u_char *compartmentslow, u_short typehigh,
  388     u_short levelhigh, u_char *compartmentshigh)
  389 {
  390 
  391         mac_mls->mm_rangelow.mme_type = typelow;
  392         mac_mls->mm_rangelow.mme_level = levellow;
  393         if (compartmentslow != NULL)
  394                 memcpy(mac_mls->mm_rangelow.mme_compartments,
  395                     compartmentslow,
  396                     sizeof(mac_mls->mm_rangelow.mme_compartments));
  397         mac_mls->mm_rangehigh.mme_type = typehigh;
  398         mac_mls->mm_rangehigh.mme_level = levelhigh;
  399         if (compartmentshigh != NULL)
  400                 memcpy(mac_mls->mm_rangehigh.mme_compartments,
  401                     compartmentshigh,
  402                     sizeof(mac_mls->mm_rangehigh.mme_compartments));
  403         mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
  404 }
  405 
  406 static void
  407 mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level,
  408     u_char *compartments)
  409 {
  410 
  411         mac_mls->mm_single.mme_type = type;
  412         mac_mls->mm_single.mme_level = level;
  413         if (compartments != NULL)
  414                 memcpy(mac_mls->mm_single.mme_compartments, compartments,
  415                     sizeof(mac_mls->mm_single.mme_compartments));
  416         mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
  417 }
  418 
  419 static void
  420 mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
  421 {
  422 
  423         KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
  424             ("mac_mls_copy_range: labelfrom not range"));
  425 
  426         labelto->mm_rangelow = labelfrom->mm_rangelow;
  427         labelto->mm_rangehigh = labelfrom->mm_rangehigh;
  428         labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
  429 }
  430 
  431 static void
  432 mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto)
  433 {
  434 
  435         KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
  436             ("mac_mls_copy_single: labelfrom not single"));
  437 
  438         labelto->mm_single = labelfrom->mm_single;
  439         labelto->mm_flags |= MAC_MLS_FLAG_SINGLE;
  440 }
  441 
  442 static void
  443 mac_mls_copy(struct mac_mls *source, struct mac_mls *dest)
  444 {
  445 
  446         if (source->mm_flags & MAC_MLS_FLAG_SINGLE)
  447                 mac_mls_copy_single(source, dest);
  448         if (source->mm_flags & MAC_MLS_FLAG_RANGE)
  449                 mac_mls_copy_range(source, dest);
  450 }
  451 
  452 /*
  453  * Policy module operations.
  454  */
  455 static void
  456 mac_mls_destroy(struct mac_policy_conf *conf)
  457 {
  458 
  459 }
  460 
  461 static void
  462 mac_mls_init(struct mac_policy_conf *conf)
  463 {
  464 
  465 }
  466 
  467 /*
  468  * Label operations.
  469  */
  470 static void
  471 mac_mls_init_label(struct label *label)
  472 {
  473 
  474         SLOT(label) = mls_alloc(M_WAITOK);
  475 }
  476 
  477 static int
  478 mac_mls_init_label_waitcheck(struct label *label, int flag)
  479 {
  480 
  481         SLOT(label) = mls_alloc(flag);
  482         if (SLOT(label) == NULL)
  483                 return (ENOMEM);
  484 
  485         return (0);
  486 }
  487 
  488 static void
  489 mac_mls_destroy_label(struct label *label)
  490 {
  491 
  492         mls_free(SLOT(label));
  493         SLOT(label) = NULL;
  494 }
  495 
  496 /*
  497  * mac_mls_element_to_string() accepts an sbuf and MLS element.  It
  498  * converts the MLS element to a string and stores the result in the
  499  * sbuf; if there isn't space in the sbuf, -1 is returned.
  500  */
  501 static int
  502 mac_mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
  503 {
  504         int i, first;
  505 
  506         switch (element->mme_type) {
  507         case MAC_MLS_TYPE_HIGH:
  508                 return (sbuf_printf(sb, "high"));
  509 
  510         case MAC_MLS_TYPE_LOW:
  511                 return (sbuf_printf(sb, "low"));
  512 
  513         case MAC_MLS_TYPE_EQUAL:
  514                 return (sbuf_printf(sb, "equal"));
  515 
  516         case MAC_MLS_TYPE_LEVEL:
  517                 if (sbuf_printf(sb, "%d", element->mme_level) == -1)
  518                         return (-1);
  519 
  520                 first = 1;
  521                 for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
  522                         if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
  523                                 if (first) {
  524                                         if (sbuf_putc(sb, ':') == -1)
  525                                                 return (-1);
  526                                         if (sbuf_printf(sb, "%d", i) == -1)
  527                                                 return (-1);
  528                                         first = 0;
  529                                 } else {
  530                                         if (sbuf_printf(sb, "+%d", i) == -1)
  531                                                 return (-1);
  532                                 }
  533                         }
  534                 }
  535                 return (0);
  536 
  537         default:
  538                 panic("mac_mls_element_to_string: invalid type (%d)",
  539                     element->mme_type);
  540         }
  541 }
  542 
  543 /*
  544  * mac_mls_to_string() converts an MLS label to a string, placing the
  545  * results in the passed string buffer.  It returns 0 on success,
  546  * or EINVAL if there isn't room in the buffer.  The size of the
  547  * string appended, leaving out the nul termination, is returned to
  548  * the caller via *caller_len.  Eventually, we should expose the
  549  * sbuf to the caller rather than using C strings at this layer.
  550  */
  551 static int
  552 mac_mls_to_string(char *string, size_t size, size_t *caller_len,
  553     struct mac_mls *mac_mls)
  554 {
  555         struct sbuf sb;
  556 
  557         sbuf_new(&sb, string, size, SBUF_FIXEDLEN);
  558 
  559         if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
  560                 if (mac_mls_element_to_string(&sb, &mac_mls->mm_single)
  561                     == -1)
  562                         return (EINVAL);
  563         }
  564 
  565         if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
  566                 if (sbuf_putc(&sb, '(') == -1)
  567                         return (EINVAL);
  568 
  569                 if (mac_mls_element_to_string(&sb, &mac_mls->mm_rangelow)
  570                     == -1)
  571                         return (EINVAL);
  572 
  573                 if (sbuf_putc(&sb, '-') == -1)
  574                         return (EINVAL);
  575 
  576                 if (mac_mls_element_to_string(&sb, &mac_mls->mm_rangehigh)
  577                     == -1)
  578                         return (EINVAL);
  579 
  580                 if (sbuf_putc(&sb, ')') == -1)
  581                         return (EINVAL);
  582         }
  583 
  584         sbuf_finish(&sb);
  585         *caller_len = strlen(string);
  586         return (0);
  587 }
  588 
  589 static int
  590 mac_mls_externalize_label(struct label *label, char *element_name,
  591     char *element_data, size_t size, size_t *len, int *claimed)
  592 {
  593         struct mac_mls *mac_mls;
  594         int error;
  595 
  596         if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
  597                 return (0);
  598 
  599         (*claimed)++;
  600 
  601         mac_mls = SLOT(label);
  602 
  603         error = mac_mls_to_string(element_data, size, len, mac_mls);
  604         if (error)
  605                 return (error);
  606 
  607         return (0);
  608 }
  609 
  610 static int
  611 mac_mls_parse_element(struct mac_mls_element *element, char *string)
  612 {
  613         char *compartment, *end, *level;
  614         int value;
  615 
  616         if (strcmp(string, "high") == 0 ||
  617             strcmp(string, "hi") == 0) {
  618                 element->mme_type = MAC_MLS_TYPE_HIGH;
  619                 element->mme_level = MAC_MLS_TYPE_UNDEF;
  620         } else if (strcmp(string, "low") == 0 ||
  621             strcmp(string, "lo") == 0) {
  622                 element->mme_type = MAC_MLS_TYPE_LOW;
  623                 element->mme_level = MAC_MLS_TYPE_UNDEF;
  624         } else if (strcmp(string, "equal") == 0 ||
  625             strcmp(string, "eq") == 0) {
  626                 element->mme_type = MAC_MLS_TYPE_EQUAL;
  627                 element->mme_level = MAC_MLS_TYPE_UNDEF;
  628         } else {
  629                 element->mme_type = MAC_MLS_TYPE_LEVEL;
  630 
  631                 /*
  632                  * Numeric level piece of the element.
  633                  */
  634                 level = strsep(&string, ":");
  635                 value = strtol(level, &end, 10);
  636                 if (end == level || *end != '\0')
  637                         return (EINVAL);
  638                 if (value < 0 || value > 65535)
  639                         return (EINVAL);
  640                 element->mme_level = value;
  641 
  642                 /*
  643                  * Optional compartment piece of the element.  If none
  644                  * are included, we assume that the label has no
  645                  * compartments.
  646                  */
  647                 if (string == NULL)
  648                         return (0);
  649                 if (*string == '\0')
  650                         return (0);
  651 
  652                 while ((compartment = strsep(&string, "+")) != NULL) {
  653                         value = strtol(compartment, &end, 10);
  654                         if (compartment == end || *end != '\0')
  655                                 return (EINVAL);
  656                         if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
  657                                 return (EINVAL);
  658                         MAC_MLS_BIT_SET(value, element->mme_compartments);
  659                 }
  660         }
  661 
  662         return (0);
  663 }
  664 
  665 /*
  666  * Note: destructively consumes the string, make a local copy before
  667  * calling if that's a problem.
  668  */
  669 static int
  670 mac_mls_parse(struct mac_mls *mac_mls, char *string)
  671 {
  672         char *rangehigh, *rangelow, *single;
  673         int error;
  674 
  675         single = strsep(&string, "(");
  676         if (*single == '\0')
  677                 single = NULL;
  678 
  679         if (string != NULL) {
  680                 rangelow = strsep(&string, "-");
  681                 if (string == NULL)
  682                         return (EINVAL);
  683                 rangehigh = strsep(&string, ")");
  684                 if (string == NULL)
  685                         return (EINVAL);
  686                 if (*string != '\0')
  687                         return (EINVAL);
  688         } else {
  689                 rangelow = NULL;
  690                 rangehigh = NULL;
  691         }
  692 
  693         KASSERT((rangelow != NULL && rangehigh != NULL) ||
  694             (rangelow == NULL && rangehigh == NULL),
  695             ("mac_mls_parse: range mismatch"));
  696 
  697         bzero(mac_mls, sizeof(*mac_mls));
  698         if (single != NULL) {
  699                 error = mac_mls_parse_element(&mac_mls->mm_single, single);
  700                 if (error)
  701                         return (error);
  702                 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
  703         }
  704 
  705         if (rangelow != NULL) {
  706                 error = mac_mls_parse_element(&mac_mls->mm_rangelow,
  707                     rangelow);
  708                 if (error)
  709                         return (error);
  710                 error = mac_mls_parse_element(&mac_mls->mm_rangehigh,
  711                     rangehigh);
  712                 if (error)
  713                         return (error);
  714                 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
  715         }
  716 
  717         error = mac_mls_valid(mac_mls);
  718         if (error)
  719                 return (error);
  720 
  721         return (0);
  722 }
  723 
  724 static int
  725 mac_mls_internalize_label(struct label *label, char *element_name,
  726     char *element_data, int *claimed)
  727 {
  728         struct mac_mls *mac_mls, mac_mls_temp;
  729         int error;
  730 
  731         if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
  732                 return (0);
  733 
  734         (*claimed)++;
  735 
  736         error = mac_mls_parse(&mac_mls_temp, element_data);
  737         if (error)
  738                 return (error);
  739 
  740         mac_mls = SLOT(label);
  741         *mac_mls = mac_mls_temp;
  742 
  743         return (0);
  744 }
  745 
  746 static void
  747 mac_mls_copy_label(struct label *src, struct label *dest)
  748 {
  749 
  750         *SLOT(dest) = *SLOT(src);
  751 }
  752 
  753 /*
  754  * Labeling event operations: file system objects, and things that look
  755  * a lot like file system objects.
  756  */
  757 static void
  758 mac_mls_create_devfs_device(struct mount *mp, dev_t dev,
  759     struct devfs_dirent *devfs_dirent, struct label *label)
  760 {
  761         struct mac_mls *mac_mls;
  762         int mls_type;
  763 
  764         mac_mls = SLOT(label);
  765         if (strcmp(dev->si_name, "null") == 0 ||
  766             strcmp(dev->si_name, "zero") == 0 ||
  767             strcmp(dev->si_name, "random") == 0 ||
  768             strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
  769                 mls_type = MAC_MLS_TYPE_EQUAL;
  770         else if (strcmp(dev->si_name, "kmem") == 0 ||
  771             strcmp(dev->si_name, "mem") == 0)
  772                 mls_type = MAC_MLS_TYPE_HIGH;
  773         else if (ptys_equal &&
  774             (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
  775             strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
  776                 mls_type = MAC_MLS_TYPE_EQUAL;
  777         else
  778                 mls_type = MAC_MLS_TYPE_LOW;
  779         mac_mls_set_single(mac_mls, mls_type, 0, NULL);
  780 }
  781 
  782 static void
  783 mac_mls_create_devfs_directory(struct mount *mp, char *dirname,
  784     int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
  785 {
  786         struct mac_mls *mac_mls;
  787 
  788         mac_mls = SLOT(label);
  789         mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
  790 }
  791 
  792 static void
  793 mac_mls_create_devfs_symlink(struct ucred *cred, struct mount *mp,
  794     struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
  795     struct label *delabel)
  796 {
  797         struct mac_mls *source, *dest;
  798 
  799         source = SLOT(&cred->cr_label);
  800         dest = SLOT(delabel);
  801 
  802         mac_mls_copy_single(source, dest);
  803 }
  804 
  805 static void
  806 mac_mls_create_mount(struct ucred *cred, struct mount *mp,
  807     struct label *mntlabel, struct label *fslabel)
  808 {
  809         struct mac_mls *source, *dest;
  810 
  811         source = SLOT(&cred->cr_label);
  812         dest = SLOT(mntlabel);
  813         mac_mls_copy_single(source, dest);
  814         dest = SLOT(fslabel);
  815         mac_mls_copy_single(source, dest);
  816 }
  817 
  818 static void
  819 mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
  820     struct label *mntlabel, struct label *fslabel)
  821 {
  822         struct mac_mls *mac_mls;
  823 
  824         /* Always mount root as high integrity. */
  825         mac_mls = SLOT(fslabel);
  826         mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
  827         mac_mls = SLOT(mntlabel);
  828         mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
  829 }
  830 
  831 static void
  832 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
  833     struct label *vnodelabel, struct label *label)
  834 {
  835         struct mac_mls *source, *dest;
  836 
  837         source = SLOT(label);
  838         dest = SLOT(vnodelabel);
  839 
  840         mac_mls_copy(source, dest);
  841 }
  842 
  843 static void
  844 mac_mls_update_devfsdirent(struct mount *mp,
  845     struct devfs_dirent *devfs_dirent, struct label *direntlabel,
  846     struct vnode *vp, struct label *vnodelabel)
  847 {
  848         struct mac_mls *source, *dest;
  849 
  850         source = SLOT(vnodelabel);
  851         dest = SLOT(direntlabel);
  852 
  853         mac_mls_copy_single(source, dest);
  854 }
  855 
  856 static void
  857 mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
  858     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
  859     struct label *vlabel)
  860 {
  861         struct mac_mls *source, *dest;
  862 
  863         source = SLOT(delabel);
  864         dest = SLOT(vlabel);
  865 
  866         mac_mls_copy_single(source, dest);
  867 }
  868 
  869 static int
  870 mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
  871     struct vnode *vp, struct label *vlabel)
  872 {
  873         struct mac_mls temp, *source, *dest;
  874         int buflen, error;
  875 
  876         source = SLOT(fslabel);
  877         dest = SLOT(vlabel);
  878 
  879         buflen = sizeof(temp);
  880         bzero(&temp, buflen);
  881 
  882         error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
  883             MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
  884         if (error == ENOATTR || error == EOPNOTSUPP) {
  885                 /* Fall back to the fslabel. */
  886                 mac_mls_copy_single(source, dest);
  887                 return (0);
  888         } else if (error)
  889                 return (error);
  890 
  891         if (buflen != sizeof(temp)) {
  892                 printf("mac_mls_associate_vnode_extattr: bad size %d\n",
  893                     buflen);
  894                 return (EPERM);
  895         }
  896         if (mac_mls_valid(&temp) != 0) {
  897                 printf("mac_mls_associate_vnode_extattr: invalid\n");
  898                 return (EPERM);
  899         }
  900         if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) {
  901                 printf("mac_mls_associated_vnode_extattr: not single\n");
  902                 return (EPERM);
  903         }
  904 
  905         mac_mls_copy_single(&temp, dest);
  906         return (0);
  907 }
  908 
  909 static void
  910 mac_mls_associate_vnode_singlelabel(struct mount *mp,
  911     struct label *fslabel, struct vnode *vp, struct label *vlabel)
  912 {
  913         struct mac_mls *source, *dest;
  914 
  915         source = SLOT(fslabel);
  916         dest = SLOT(vlabel);
  917 
  918         mac_mls_copy_single(source, dest);
  919 }
  920 
  921 static int
  922 mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp,
  923     struct label *fslabel, struct vnode *dvp, struct label *dlabel,
  924     struct vnode *vp, struct label *vlabel, struct componentname *cnp)
  925 {
  926         struct mac_mls *source, *dest, temp;
  927         size_t buflen;
  928         int error;
  929 
  930         buflen = sizeof(temp);
  931         bzero(&temp, buflen);
  932 
  933         source = SLOT(&cred->cr_label);
  934         dest = SLOT(vlabel);
  935         mac_mls_copy_single(source, &temp);
  936 
  937         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
  938             MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
  939         if (error == 0)
  940                 mac_mls_copy_single(source, dest);
  941         return (error);
  942 }
  943 
  944 static int
  945 mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
  946     struct label *vlabel, struct label *intlabel)
  947 {
  948         struct mac_mls *source, temp;
  949         size_t buflen;
  950         int error;
  951 
  952         buflen = sizeof(temp);
  953         bzero(&temp, buflen);
  954 
  955         source = SLOT(intlabel);
  956         if ((source->mm_flags & MAC_MLS_FLAG_SINGLE) == 0)
  957                 return (0);
  958 
  959         mac_mls_copy_single(source, &temp);
  960 
  961         error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
  962             MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
  963         return (error);
  964 }
  965 
  966 /*
  967  * Labeling event operations: IPC object.
  968  */
  969 static void
  970 mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
  971     struct mbuf *m, struct label *mbuflabel)
  972 {
  973         struct mac_mls *source, *dest;
  974 
  975         source = SLOT(socketlabel);
  976         dest = SLOT(mbuflabel);
  977 
  978         mac_mls_copy_single(source, dest);
  979 }
  980 
  981 static void
  982 mac_mls_create_socket(struct ucred *cred, struct socket *socket,
  983     struct label *socketlabel)
  984 {
  985         struct mac_mls *source, *dest;
  986 
  987         source = SLOT(&cred->cr_label);
  988         dest = SLOT(socketlabel);
  989 
  990         mac_mls_copy_single(source, dest);
  991 }
  992 
  993 static void
  994 mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
  995     struct label *pipelabel)
  996 {
  997         struct mac_mls *source, *dest;
  998 
  999         source = SLOT(&cred->cr_label);
 1000         dest = SLOT(pipelabel);
 1001 
 1002         mac_mls_copy_single(source, dest);
 1003 }
 1004 
 1005 static void
 1006 mac_mls_create_socket_from_socket(struct socket *oldsocket,
 1007     struct label *oldsocketlabel, struct socket *newsocket,
 1008     struct label *newsocketlabel)
 1009 {
 1010         struct mac_mls *source, *dest;
 1011 
 1012         source = SLOT(oldsocketlabel);
 1013         dest = SLOT(newsocketlabel);
 1014 
 1015         mac_mls_copy_single(source, dest);
 1016 }
 1017 
 1018 static void
 1019 mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
 1020     struct label *socketlabel, struct label *newlabel)
 1021 {
 1022         struct mac_mls *source, *dest;
 1023 
 1024         source = SLOT(newlabel);
 1025         dest = SLOT(socketlabel);
 1026 
 1027         mac_mls_copy(source, dest);
 1028 }
 1029 
 1030 static void
 1031 mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
 1032     struct label *pipelabel, struct label *newlabel)
 1033 {
 1034         struct mac_mls *source, *dest;
 1035 
 1036         source = SLOT(newlabel);
 1037         dest = SLOT(pipelabel);
 1038 
 1039         mac_mls_copy(source, dest);
 1040 }
 1041 
 1042 static void
 1043 mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
 1044     struct socket *socket, struct label *socketpeerlabel)
 1045 {
 1046         struct mac_mls *source, *dest;
 1047 
 1048         source = SLOT(mbuflabel);
 1049         dest = SLOT(socketpeerlabel);
 1050 
 1051         mac_mls_copy_single(source, dest);
 1052 }
 1053 
 1054 /*
 1055  * Labeling event operations: network objects.
 1056  */
 1057 static void
 1058 mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
 1059     struct label *oldsocketlabel, struct socket *newsocket,
 1060     struct label *newsocketpeerlabel)
 1061 {
 1062         struct mac_mls *source, *dest;
 1063 
 1064         source = SLOT(oldsocketlabel);
 1065         dest = SLOT(newsocketpeerlabel);
 1066 
 1067         mac_mls_copy_single(source, dest);
 1068 }
 1069 
 1070 static void
 1071 mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
 1072     struct label *bpflabel)
 1073 {
 1074         struct mac_mls *source, *dest;
 1075 
 1076         source = SLOT(&cred->cr_label);
 1077         dest = SLOT(bpflabel);
 1078 
 1079         mac_mls_copy_single(source, dest);
 1080 }
 1081 
 1082 static void
 1083 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
 1084 {
 1085         struct mac_mls *dest;
 1086         int type;
 1087 
 1088         dest = SLOT(ifnetlabel);
 1089 
 1090         if (ifnet->if_type == IFT_LOOP)
 1091                 type = MAC_MLS_TYPE_EQUAL;
 1092         else
 1093                 type = MAC_MLS_TYPE_LOW;
 1094 
 1095         mac_mls_set_single(dest, type, 0, NULL);
 1096         mac_mls_set_range(dest, type, 0, NULL, type, 0, NULL);
 1097 }
 1098 
 1099 static void
 1100 mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
 1101     struct ipq *ipq, struct label *ipqlabel)
 1102 {
 1103         struct mac_mls *source, *dest;
 1104 
 1105         source = SLOT(fragmentlabel);
 1106         dest = SLOT(ipqlabel);
 1107 
 1108         mac_mls_copy_single(source, dest);
 1109 }
 1110 
 1111 static void
 1112 mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
 1113     struct mbuf *datagram, struct label *datagramlabel)
 1114 {
 1115         struct mac_mls *source, *dest;
 1116 
 1117         source = SLOT(ipqlabel);
 1118         dest = SLOT(datagramlabel);
 1119 
 1120         /* Just use the head, since we require them all to match. */
 1121         mac_mls_copy_single(source, dest);
 1122 }
 1123 
 1124 static void
 1125 mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
 1126     struct mbuf *fragment, struct label *fragmentlabel)
 1127 {
 1128         struct mac_mls *source, *dest;
 1129 
 1130         source = SLOT(datagramlabel);
 1131         dest = SLOT(fragmentlabel);
 1132 
 1133         mac_mls_copy_single(source, dest);
 1134 }
 1135 
 1136 static void
 1137 mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
 1138     struct label *oldmbuflabel, struct mbuf *newmbuf,
 1139     struct label *newmbuflabel)
 1140 {
 1141         struct mac_mls *source, *dest;
 1142 
 1143         source = SLOT(oldmbuflabel);
 1144         dest = SLOT(newmbuflabel);
 1145 
 1146         /*
 1147          * Because the source mbuf may not yet have been "created",
 1148          * just initialized, we do a conditional copy.  Since we don't
 1149          * allow mbufs to have ranges, do a KASSERT to make sure that
 1150          * doesn't happen.
 1151          */
 1152         KASSERT((source->mm_flags & MAC_MLS_FLAG_RANGE) == 0,
 1153             ("mac_mls_create_mbuf_from_mbuf: source mbuf has range"));
 1154         mac_mls_copy(source, dest);
 1155 }
 1156 
 1157 static void
 1158 mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
 1159     struct mbuf *mbuf, struct label *mbuflabel)
 1160 {
 1161         struct mac_mls *dest;
 1162 
 1163         dest = SLOT(mbuflabel);
 1164 
 1165         mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
 1166 }
 1167 
 1168 static void
 1169 mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
 1170     struct mbuf *mbuf, struct label *mbuflabel)
 1171 {
 1172         struct mac_mls *source, *dest;
 1173 
 1174         source = SLOT(bpflabel);
 1175         dest = SLOT(mbuflabel);
 1176 
 1177         mac_mls_copy_single(source, dest);
 1178 }
 1179 
 1180 static void
 1181 mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
 1182     struct mbuf *m, struct label *mbuflabel)
 1183 {
 1184         struct mac_mls *source, *dest;
 1185 
 1186         source = SLOT(ifnetlabel);
 1187         dest = SLOT(mbuflabel);
 1188 
 1189         mac_mls_copy_single(source, dest);
 1190 }
 1191 
 1192 static void
 1193 mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
 1194     struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
 1195     struct mbuf *newmbuf, struct label *newmbuflabel)
 1196 {
 1197         struct mac_mls *source, *dest;
 1198 
 1199         source = SLOT(oldmbuflabel);
 1200         dest = SLOT(newmbuflabel);
 1201 
 1202         mac_mls_copy_single(source, dest);
 1203 }
 1204 
 1205 static void
 1206 mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
 1207     struct mbuf *newmbuf, struct label *newmbuflabel)
 1208 {
 1209         struct mac_mls *source, *dest;
 1210 
 1211         source = SLOT(oldmbuflabel);
 1212         dest = SLOT(newmbuflabel);
 1213 
 1214         mac_mls_copy_single(source, dest);
 1215 }
 1216 
 1217 static int
 1218 mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
 1219     struct ipq *ipq, struct label *ipqlabel)
 1220 {
 1221         struct mac_mls *a, *b;
 1222 
 1223         a = SLOT(ipqlabel);
 1224         b = SLOT(fragmentlabel);
 1225 
 1226         return (mac_mls_equal_single(a, b));
 1227 }
 1228 
 1229 static void
 1230 mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
 1231     struct label *ifnetlabel, struct label *newlabel)
 1232 {
 1233         struct mac_mls *source, *dest;
 1234 
 1235         source = SLOT(newlabel);
 1236         dest = SLOT(ifnetlabel);
 1237 
 1238         mac_mls_copy(source, dest);
 1239 }
 1240 
 1241 static void
 1242 mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
 1243     struct ipq *ipq, struct label *ipqlabel)
 1244 {
 1245 
 1246         /* NOOP: we only accept matching labels, so no need to update */
 1247 }
 1248 
 1249 /*
 1250  * Labeling event operations: processes.
 1251  */
 1252 static void
 1253 mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
 1254 {
 1255         struct mac_mls *source, *dest;
 1256 
 1257         source = SLOT(&cred_parent->cr_label);
 1258         dest = SLOT(&cred_child->cr_label);
 1259 
 1260         mac_mls_copy_single(source, dest);
 1261         mac_mls_copy_range(source, dest);
 1262 }
 1263 
 1264 static void
 1265 mac_mls_create_proc0(struct ucred *cred)
 1266 {
 1267         struct mac_mls *dest;
 1268 
 1269         dest = SLOT(&cred->cr_label);
 1270 
 1271         mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
 1272         mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
 1273             0, NULL);
 1274 }
 1275 
 1276 static void
 1277 mac_mls_create_proc1(struct ucred *cred)
 1278 {
 1279         struct mac_mls *dest;
 1280 
 1281         dest = SLOT(&cred->cr_label);
 1282 
 1283         mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0, NULL);
 1284         mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
 1285             0, NULL);
 1286 }
 1287 
 1288 static void
 1289 mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
 1290 {
 1291         struct mac_mls *source, *dest;
 1292 
 1293         source = SLOT(newlabel);
 1294         dest = SLOT(&cred->cr_label);
 1295 
 1296         mac_mls_copy(source, dest);
 1297 }
 1298 
 1299 /*
 1300  * Access control checks.
 1301  */
 1302 static int
 1303 mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
 1304      struct ifnet *ifnet, struct label *ifnetlabel)
 1305 {
 1306         struct mac_mls *a, *b;
 1307 
 1308         if (!mac_mls_enabled)
 1309                 return (0);
 1310 
 1311         a = SLOT(bpflabel);
 1312         b = SLOT(ifnetlabel);
 1313 
 1314         if (mac_mls_equal_single(a, b))
 1315                 return (0);
 1316         return (EACCES);
 1317 }
 1318 
 1319 static int
 1320 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
 1321 {
 1322         struct mac_mls *subj, *new;
 1323         int error;
 1324 
 1325         subj = SLOT(&cred->cr_label);
 1326         new = SLOT(newlabel);
 1327 
 1328         /*
 1329          * If there is an MLS label update for the credential, it may be
 1330          * an update of single, range, or both.
 1331          */
 1332         error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
 1333         if (error)
 1334                 return (error);
 1335 
 1336         /*
 1337          * If the MLS label is to be changed, authorize as appropriate.
 1338          */
 1339         if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
 1340                 /*
 1341                  * If the change request modifies both the MLS label single
 1342                  * and range, check that the new single will be in the
 1343                  * new range.
 1344                  */
 1345                 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
 1346                     MAC_MLS_FLAGS_BOTH &&
 1347                     !mac_mls_single_in_range(new, new))
 1348                         return (EINVAL);
 1349 
 1350                 /*
 1351                  * To change the MLS single label on a credential, the
 1352                  * new single label must be in the current range.
 1353                  */
 1354                 if (new->mm_flags & MAC_MLS_FLAG_SINGLE &&
 1355                     !mac_mls_single_in_range(new, subj))
 1356                         return (EPERM);
 1357 
 1358                 /*
 1359                  * To change the MLS range label on a credential, the
 1360                  * new range must be in the current range.
 1361                  */
 1362                 if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
 1363                     !mac_mls_range_in_range(new, subj))
 1364                         return (EPERM);
 1365 
 1366                 /*
 1367                  * To have EQUAL in any component of the new credential
 1368                  * MLS label, the subject must already have EQUAL in
 1369                  * their label.
 1370                  */
 1371                 if (mac_mls_contains_equal(new)) {
 1372                         error = mac_mls_subject_equal_ok(subj);
 1373                         if (error)
 1374                                 return (error);
 1375                 }
 1376         }
 1377 
 1378         return (0);
 1379 }
 1380 
 1381 static int
 1382 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
 1383 {
 1384         struct mac_mls *subj, *obj;
 1385 
 1386         if (!mac_mls_enabled)
 1387                 return (0);
 1388 
 1389         subj = SLOT(&u1->cr_label);
 1390         obj = SLOT(&u2->cr_label);
 1391 
 1392         /* XXX: range */
 1393         if (!mac_mls_dominate_single(subj, obj))
 1394                 return (ESRCH);
 1395 
 1396         return (0);
 1397 }
 1398 
 1399 static int
 1400 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
 1401     struct label *ifnetlabel, struct label *newlabel)
 1402 {
 1403         struct mac_mls *subj, *new;
 1404         int error;
 1405 
 1406         subj = SLOT(&cred->cr_label);
 1407         new = SLOT(newlabel);
 1408 
 1409         /*
 1410          * If there is an MLS label update for the interface, it may
 1411          * be an update of single, range, or both.
 1412          */
 1413         error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
 1414         if (error)
 1415                 return (error);
 1416 
 1417         /*
 1418          * If the MLS label is to be changed, authorize as appropriate.
 1419          */
 1420         if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
 1421                 /*
 1422                  * Rely on traditional superuser status for the MLS
 1423                  * interface relabel requirements.  XXX: This will go
 1424                  * away.
 1425                  */
 1426                 error = suser_cred(cred, 0);
 1427                 if (error)
 1428                         return (EPERM);
 1429 
 1430                 /*
 1431                  * XXXMAC: Additional consistency tests regarding the single
 1432                  * and the range of the new label might be performed here.
 1433                  */
 1434         }
 1435 
 1436         return (0);
 1437 }
 1438 
 1439 static int
 1440 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
 1441     struct mbuf *m, struct label *mbuflabel)
 1442 {
 1443         struct mac_mls *p, *i;
 1444 
 1445         if (!mac_mls_enabled)
 1446                 return (0);
 1447 
 1448         p = SLOT(mbuflabel);
 1449         i = SLOT(ifnetlabel);
 1450 
 1451         return (mac_mls_single_in_range(p, i) ? 0 : EACCES);
 1452 }
 1453 
 1454 static int
 1455 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
 1456     struct label *mntlabel)
 1457 {
 1458         struct mac_mls *subj, *obj;
 1459 
 1460         if (!mac_mls_enabled)
 1461                 return (0);
 1462 
 1463         subj = SLOT(&cred->cr_label);
 1464         obj = SLOT(mntlabel);
 1465 
 1466         if (!mac_mls_dominate_single(subj, obj))
 1467                 return (EACCES);
 1468 
 1469         return (0);
 1470 }
 1471 
 1472 static int
 1473 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
 1474     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
 1475 {
 1476 
 1477         if(!mac_mls_enabled)
 1478                 return (0);
 1479 
 1480         /* XXX: This will be implemented soon... */
 1481 
 1482         return (0);
 1483 }
 1484 
 1485 static int
 1486 mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
 1487     struct label *pipelabel)
 1488 {
 1489         struct mac_mls *subj, *obj;
 1490 
 1491         if (!mac_mls_enabled)
 1492                 return (0);
 1493 
 1494         subj = SLOT(&cred->cr_label);
 1495         obj = SLOT((pipelabel));
 1496 
 1497         if (!mac_mls_dominate_single(subj, obj))
 1498                 return (EACCES);
 1499 
 1500         return (0);
 1501 }
 1502 
 1503 static int
 1504 mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
 1505     struct label *pipelabel)
 1506 {
 1507         struct mac_mls *subj, *obj;
 1508 
 1509         if (!mac_mls_enabled)
 1510                 return (0);
 1511 
 1512         subj = SLOT(&cred->cr_label);
 1513         obj = SLOT((pipelabel));
 1514 
 1515         if (!mac_mls_dominate_single(subj, obj))
 1516                 return (EACCES);
 1517 
 1518         return (0);
 1519 }
 1520 
 1521 static int
 1522 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
 1523     struct label *pipelabel, struct label *newlabel)
 1524 {
 1525         struct mac_mls *subj, *obj, *new;
 1526         int error;
 1527 
 1528         new = SLOT(newlabel);
 1529         subj = SLOT(&cred->cr_label);
 1530         obj = SLOT(pipelabel);
 1531 
 1532         /*
 1533          * If there is an MLS label update for a pipe, it must be a
 1534          * single update.
 1535          */
 1536         error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
 1537         if (error)
 1538                 return (error);
 1539 
 1540         /*
 1541          * To perform a relabel of a pipe (MLS label or not), MLS must
 1542          * authorize the relabel.
 1543          */
 1544         if (!mac_mls_single_in_range(obj, subj))
 1545                 return (EPERM);
 1546 
 1547         /*
 1548          * If the MLS label is to be changed, authorize as appropriate.
 1549          */
 1550         if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
 1551                 /*
 1552                  * To change the MLS label on a pipe, the new pipe label
 1553                  * must be in the subject range.
 1554                  */
 1555                 if (!mac_mls_single_in_range(new, subj))
 1556                         return (EPERM);
 1557 
 1558                 /*
 1559                  * To change the MLS label on a pipe to be EQUAL, the
 1560                  * subject must have appropriate privilege.
 1561                  */
 1562                 if (mac_mls_contains_equal(new)) {
 1563                         error = mac_mls_subject_equal_ok(subj);
 1564                         if (error)
 1565                                 return (error);
 1566                 }
 1567         }
 1568 
 1569         return (0);
 1570 }
 1571 
 1572 static int
 1573 mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
 1574     struct label *pipelabel)
 1575 {
 1576         struct mac_mls *subj, *obj;
 1577 
 1578         if (!mac_mls_enabled)
 1579                 return (0);
 1580 
 1581         subj = SLOT(&cred->cr_label);
 1582         obj = SLOT((pipelabel));
 1583 
 1584         if (!mac_mls_dominate_single(subj, obj))
 1585                 return (EACCES);
 1586 
 1587         return (0);
 1588 }
 1589 
 1590 static int
 1591 mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
 1592     struct label *pipelabel)
 1593 {
 1594         struct mac_mls *subj, *obj;
 1595 
 1596         if (!mac_mls_enabled)
 1597                 return (0);
 1598 
 1599         subj = SLOT(&cred->cr_label);
 1600         obj = SLOT((pipelabel));
 1601 
 1602         if (!mac_mls_dominate_single(obj, subj))
 1603                 return (EACCES);
 1604 
 1605         return (0);
 1606 }
 1607 
 1608 static int
 1609 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
 1610 {
 1611         struct mac_mls *subj, *obj;
 1612 
 1613         if (!mac_mls_enabled)
 1614                 return (0);
 1615 
 1616         subj = SLOT(&cred->cr_label);
 1617         obj = SLOT(&proc->p_ucred->cr_label);
 1618 
 1619         /* XXX: range checks */
 1620         if (!mac_mls_dominate_single(subj, obj))
 1621                 return (ESRCH);
 1622         if (!mac_mls_dominate_single(obj, subj))
 1623                 return (EACCES);
 1624 
 1625         return (0);
 1626 }
 1627 
 1628 static int
 1629 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
 1630 {
 1631         struct mac_mls *subj, *obj;
 1632 
 1633         if (!mac_mls_enabled)
 1634                 return (0);
 1635 
 1636         subj = SLOT(&cred->cr_label);
 1637         obj = SLOT(&proc->p_ucred->cr_label);
 1638 
 1639         /* XXX: range checks */
 1640         if (!mac_mls_dominate_single(subj, obj))
 1641                 return (ESRCH);
 1642         if (!mac_mls_dominate_single(obj, subj))
 1643                 return (EACCES);
 1644 
 1645         return (0);
 1646 }
 1647 
 1648 static int
 1649 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
 1650 {
 1651         struct mac_mls *subj, *obj;
 1652 
 1653         if (!mac_mls_enabled)
 1654                 return (0);
 1655 
 1656         subj = SLOT(&cred->cr_label);
 1657         obj = SLOT(&proc->p_ucred->cr_label);
 1658 
 1659         /* XXX: range checks */
 1660         if (!mac_mls_dominate_single(subj, obj))
 1661                 return (ESRCH);
 1662         if (!mac_mls_dominate_single(obj, subj))
 1663                 return (EACCES);
 1664 
 1665         return (0);
 1666 }
 1667 
 1668 static int
 1669 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
 1670     struct mbuf *m, struct label *mbuflabel)
 1671 {
 1672         struct mac_mls *p, *s;
 1673 
 1674         if (!mac_mls_enabled)
 1675                 return (0);
 1676 
 1677         p = SLOT(mbuflabel);
 1678         s = SLOT(socketlabel);
 1679 
 1680         return (mac_mls_equal_single(p, s) ? 0 : EACCES);
 1681 }
 1682 
 1683 static int
 1684 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
 1685     struct label *socketlabel, struct label *newlabel)
 1686 {
 1687         struct mac_mls *subj, *obj, *new;
 1688         int error;
 1689 
 1690         new = SLOT(newlabel);
 1691         subj = SLOT(&cred->cr_label);
 1692         obj = SLOT(socketlabel);
 1693 
 1694         /*
 1695          * If there is an MLS label update for the socket, it may be
 1696          * an update of single.
 1697          */
 1698         error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
 1699         if (error)
 1700                 return (error);
 1701 
 1702         /*
 1703          * To relabel a socket, the old socket single must be in the subject
 1704          * range.
 1705          */
 1706         if (!mac_mls_single_in_range(obj, subj))
 1707                 return (EPERM);
 1708 
 1709         /*
 1710          * If the MLS label is to be changed, authorize as appropriate.
 1711          */
 1712         if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
 1713                 /*
 1714                  * To relabel a socket, the new socket single must be in
 1715                  * the subject range.
 1716                  */
 1717                 if (!mac_mls_single_in_range(new, subj))
 1718                         return (EPERM);
 1719 
 1720                 /*
 1721                  * To change the MLS label on the socket to contain EQUAL,
 1722                  * the subject must have appropriate privilege.
 1723                  */
 1724                 if (mac_mls_contains_equal(new)) {
 1725                         error = mac_mls_subject_equal_ok(subj);
 1726                         if (error)
 1727                                 return (error);
 1728                 }
 1729         }
 1730 
 1731         return (0);
 1732 }
 1733 
 1734 static int
 1735 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
 1736     struct label *socketlabel)
 1737 {
 1738         struct mac_mls *subj, *obj;
 1739 
 1740         if (!mac_mls_enabled)
 1741                 return (0);
 1742 
 1743         subj = SLOT(&cred->cr_label);
 1744         obj = SLOT(socketlabel);
 1745 
 1746         if (!mac_mls_dominate_single(subj, obj))
 1747                 return (ENOENT);
 1748 
 1749         return (0);
 1750 }
 1751 
 1752 static int
 1753 mac_mls_check_system_swapon(struct ucred *cred, struct vnode *vp,
 1754     struct label *label)
 1755 {
 1756         struct mac_mls *subj, *obj;
 1757 
 1758         if (!mac_mls_enabled)
 1759                 return (0);
 1760 
 1761         subj = SLOT(&cred->cr_label);
 1762         obj = SLOT(label);
 1763 
 1764         if (!mac_mls_dominate_single(obj, subj) ||
 1765             !mac_mls_dominate_single(subj, obj))
 1766                 return (EACCES);
 1767 
 1768         return (0);
 1769 }
 1770 
 1771 static int
 1772 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
 1773     struct label *dlabel)
 1774 {
 1775         struct mac_mls *subj, *obj;
 1776 
 1777         if (!mac_mls_enabled)
 1778                 return (0);
 1779 
 1780         subj = SLOT(&cred->cr_label);
 1781         obj = SLOT(dlabel);
 1782 
 1783         if (!mac_mls_dominate_single(subj, obj))
 1784                 return (EACCES);
 1785 
 1786         return (0);
 1787 }
 1788 
 1789 static int
 1790 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
 1791     struct label *dlabel)
 1792 {
 1793         struct mac_mls *subj, *obj;
 1794 
 1795         if (!mac_mls_enabled)
 1796                 return (0);
 1797 
 1798         subj = SLOT(&cred->cr_label);
 1799         obj = SLOT(dlabel);
 1800 
 1801         if (!mac_mls_dominate_single(subj, obj))
 1802                 return (EACCES);
 1803 
 1804         return (0);
 1805 }
 1806 
 1807 static int
 1808 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
 1809     struct label *dlabel, struct componentname *cnp, struct vattr *vap)
 1810 {
 1811         struct mac_mls *subj, *obj;
 1812 
 1813         if (!mac_mls_enabled)
 1814                 return (0);
 1815 
 1816         subj = SLOT(&cred->cr_label);
 1817         obj = SLOT(dlabel);
 1818 
 1819         if (!mac_mls_dominate_single(obj, subj))
 1820                 return (EACCES);
 1821 
 1822         return (0);
 1823 }
 1824 
 1825 static int
 1826 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
 1827     struct label *dlabel, struct vnode *vp, struct label *label,
 1828     struct componentname *cnp)
 1829 {
 1830         struct mac_mls *subj, *obj;
 1831 
 1832         if (!mac_mls_enabled)
 1833                 return (0);
 1834 
 1835         subj = SLOT(&cred->cr_label);
 1836         obj = SLOT(dlabel);
 1837 
 1838         if (!mac_mls_dominate_single(obj, subj))
 1839                 return (EACCES);
 1840 
 1841         obj = SLOT(label);
 1842 
 1843         if (!mac_mls_dominate_single(obj, subj))
 1844                 return (EACCES);
 1845 
 1846         return (0);
 1847 }
 1848 
 1849 static int
 1850 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
 1851     struct label *label, acl_type_t type)
 1852 {
 1853         struct mac_mls *subj, *obj;
 1854 
 1855         if (!mac_mls_enabled)
 1856                 return (0);
 1857 
 1858         subj = SLOT(&cred->cr_label);
 1859         obj = SLOT(label);
 1860 
 1861         if (!mac_mls_dominate_single(obj, subj))
 1862                 return (EACCES);
 1863 
 1864         return (0);
 1865 }
 1866 
 1867 static int
 1868 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
 1869     struct label *label, struct image_params *imgp,
 1870     struct label *execlabel)
 1871 {
 1872         struct mac_mls *subj, *obj, *exec;
 1873         int error;
 1874 
 1875         if (execlabel != NULL) {
 1876                 /*
 1877                  * We currently don't permit labels to be changed at
 1878                  * exec-time as part of MLS, so disallow non-NULL
 1879                  * MLS label elements in the execlabel.
 1880                  */
 1881                 exec = SLOT(execlabel);
 1882                 error = mls_atmostflags(exec, 0);
 1883                 if (error)
 1884                         return (error);
 1885         }
 1886 
 1887         if (!mac_mls_enabled)
 1888                 return (0);
 1889 
 1890         subj = SLOT(&cred->cr_label);
 1891         obj = SLOT(label);
 1892 
 1893         if (!mac_mls_dominate_single(subj, obj))
 1894                 return (EACCES);
 1895 
 1896         return (0);
 1897 }
 1898 
 1899 static int
 1900 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
 1901     struct label *label, acl_type_t type)
 1902 {
 1903         struct mac_mls *subj, *obj;
 1904 
 1905         if (!mac_mls_enabled)
 1906                 return (0);
 1907 
 1908         subj = SLOT(&cred->cr_label);
 1909         obj = SLOT(label);
 1910 
 1911         if (!mac_mls_dominate_single(subj, obj))
 1912                 return (EACCES);
 1913 
 1914         return (0);
 1915 }
 1916 
 1917 static int
 1918 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
 1919     struct label *label, int attrnamespace, const char *name, struct uio *uio)
 1920 {
 1921         struct mac_mls *subj, *obj;
 1922 
 1923         if (!mac_mls_enabled)
 1924                 return (0);
 1925 
 1926         subj = SLOT(&cred->cr_label);
 1927         obj = SLOT(label);
 1928 
 1929         if (!mac_mls_dominate_single(subj, obj))
 1930                 return (EACCES);
 1931 
 1932         return (0);
 1933 }
 1934 
 1935 static int
 1936 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
 1937     struct label *dlabel, struct vnode *vp, struct label *label,
 1938     struct componentname *cnp)
 1939 {
 1940         struct mac_mls *subj, *obj;
 1941 
 1942         if (!mac_mls_enabled)
 1943                 return (0);
 1944 
 1945         subj = SLOT(&cred->cr_label);
 1946         obj = SLOT(dlabel);
 1947 
 1948         if (!mac_mls_dominate_single(obj, subj))
 1949                 return (EACCES);
 1950 
 1951         obj = SLOT(dlabel);
 1952         if (!mac_mls_dominate_single(obj, subj))
 1953                 return (EACCES);
 1954 
 1955         return (0);
 1956 }
 1957 
 1958 static int
 1959 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
 1960     struct label *dlabel, struct componentname *cnp)
 1961 {
 1962         struct mac_mls *subj, *obj;
 1963 
 1964         if (!mac_mls_enabled)
 1965                 return (0);
 1966 
 1967         subj = SLOT(&cred->cr_label);
 1968         obj = SLOT(dlabel);
 1969 
 1970         if (!mac_mls_dominate_single(subj, obj))
 1971                 return (EACCES);
 1972 
 1973         return (0);
 1974 }
 1975 
 1976 static int
 1977 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
 1978     struct label *label, int prot)
 1979 {
 1980         struct mac_mls *subj, *obj;
 1981 
 1982         /*
 1983          * Rely on the use of open()-time protections to handle
 1984          * non-revocation cases.
 1985          */
 1986         if (!mac_mls_enabled || !revocation_enabled)
 1987                 return (0);
 1988 
 1989         subj = SLOT(&cred->cr_label);
 1990         obj = SLOT(label);
 1991 
 1992         if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
 1993                 if (!mac_mls_dominate_single(subj, obj))
 1994                         return (EACCES);
 1995         }
 1996         if (prot & VM_PROT_WRITE) {
 1997                 if (!mac_mls_dominate_single(obj, subj))
 1998                         return (EACCES);
 1999         }
 2000 
 2001         return (0);
 2002 }
 2003 
 2004 static int
 2005 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
 2006     struct label *vnodelabel, int acc_mode)
 2007 {
 2008         struct mac_mls *subj, *obj;
 2009 
 2010         if (!mac_mls_enabled)
 2011                 return (0);
 2012 
 2013         subj = SLOT(&cred->cr_label);
 2014         obj = SLOT(vnodelabel);
 2015 
 2016         /* XXX privilege override for admin? */
 2017         if (acc_mode & (VREAD | VEXEC | VSTAT)) {
 2018                 if (!mac_mls_dominate_single(subj, obj))
 2019                         return (EACCES);
 2020         }
 2021         if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
 2022                 if (!mac_mls_dominate_single(obj, subj))
 2023                         return (EACCES);
 2024         }
 2025 
 2026         return (0);
 2027 }
 2028 
 2029 static int
 2030 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
 2031     struct vnode *vp, struct label *label)
 2032 {
 2033         struct mac_mls *subj, *obj;
 2034 
 2035         if (!mac_mls_enabled || !revocation_enabled)
 2036                 return (0);
 2037 
 2038         subj = SLOT(&active_cred->cr_label);
 2039         obj = SLOT(label);
 2040 
 2041         if (!mac_mls_dominate_single(subj, obj))
 2042                 return (EACCES);
 2043 
 2044         return (0);
 2045 }
 2046 
 2047 static int
 2048 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
 2049     struct vnode *vp, struct label *label)
 2050 {
 2051         struct mac_mls *subj, *obj;
 2052 
 2053         if (!mac_mls_enabled || !revocation_enabled)
 2054                 return (0);
 2055 
 2056         subj = SLOT(&active_cred->cr_label);
 2057         obj = SLOT(label);
 2058 
 2059         if (!mac_mls_dominate_single(subj, obj))
 2060                 return (EACCES);
 2061 
 2062         return (0);
 2063 }
 2064 
 2065 static int
 2066 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
 2067     struct label *dlabel)
 2068 {
 2069         struct mac_mls *subj, *obj;
 2070 
 2071         if (!mac_mls_enabled)
 2072                 return (0);
 2073 
 2074         subj = SLOT(&cred->cr_label);
 2075         obj = SLOT(dlabel);
 2076 
 2077         if (!mac_mls_dominate_single(subj, obj))
 2078                 return (EACCES);
 2079 
 2080         return (0);
 2081 }
 2082 
 2083 static int
 2084 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
 2085     struct label *vnodelabel)
 2086 {
 2087         struct mac_mls *subj, *obj;
 2088 
 2089         if (!mac_mls_enabled)
 2090                 return (0);
 2091 
 2092         subj = SLOT(&cred->cr_label);
 2093         obj = SLOT(vnodelabel);
 2094 
 2095         if (!mac_mls_dominate_single(subj, obj))
 2096                 return (EACCES);
 2097 
 2098         return (0);
 2099 }
 2100 
 2101 static int
 2102 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
 2103     struct label *vnodelabel, struct label *newlabel)
 2104 {
 2105         struct mac_mls *old, *new, *subj;
 2106         int error;
 2107 
 2108         old = SLOT(vnodelabel);
 2109         new = SLOT(newlabel);
 2110         subj = SLOT(&cred->cr_label);
 2111 
 2112         /*
 2113          * If there is an MLS label update for the vnode, it must be a
 2114          * single label.
 2115          */
 2116         error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
 2117         if (error)
 2118                 return (error);
 2119 
 2120         /*
 2121          * To perform a relabel of the vnode (MLS label or not), MLS must
 2122          * authorize the relabel.
 2123          */
 2124         if (!mac_mls_single_in_range(old, subj))
 2125                 return (EPERM);
 2126 
 2127         /*
 2128          * If the MLS label is to be changed, authorize as appropriate.
 2129          */
 2130         if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
 2131                 /*
 2132                  * To change the MLS label on a vnode, the new vnode label
 2133                  * must be in the subject range.
 2134                  */
 2135                 if (!mac_mls_single_in_range(new, subj))
 2136                         return (EPERM);
 2137 
 2138                 /*
 2139                  * To change the MLS label on the vnode to be EQUAL,
 2140                  * the subject must have appropriate privilege.
 2141                  */
 2142                 if (mac_mls_contains_equal(new)) {
 2143                         error = mac_mls_subject_equal_ok(subj);
 2144                         if (error)
 2145                                 return (error);
 2146                 }
 2147         }
 2148 
 2149         return (0);
 2150 }
 2151 
 2152 
 2153 static int
 2154 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
 2155     struct label *dlabel, struct vnode *vp, struct label *label,
 2156     struct componentname *cnp)
 2157 {
 2158         struct mac_mls *subj, *obj;
 2159 
 2160         if (!mac_mls_enabled)
 2161                 return (0);
 2162 
 2163         subj = SLOT(&cred->cr_label);
 2164         obj = SLOT(dlabel);
 2165 
 2166         if (!mac_mls_dominate_single(obj, subj))
 2167                 return (EACCES);
 2168 
 2169         obj = SLOT(label);
 2170 
 2171         if (!mac_mls_dominate_single(obj, subj))
 2172                 return (EACCES);
 2173 
 2174         return (0);
 2175 }
 2176 
 2177 static int
 2178 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
 2179     struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
 2180     struct componentname *cnp)
 2181 {
 2182         struct mac_mls *subj, *obj;
 2183 
 2184         if (!mac_mls_enabled)
 2185                 return (0);
 2186 
 2187         subj = SLOT(&cred->cr_label);
 2188         obj = SLOT(dlabel);
 2189 
 2190         if (!mac_mls_dominate_single(obj, subj))
 2191                 return (EACCES);
 2192 
 2193         if (vp != NULL) {
 2194                 obj = SLOT(label);
 2195 
 2196                 if (!mac_mls_dominate_single(obj, subj))
 2197                         return (EACCES);
 2198         }
 2199 
 2200         return (0);
 2201 }
 2202 
 2203 static int
 2204 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
 2205     struct label *label)
 2206 {
 2207         struct mac_mls *subj, *obj;
 2208 
 2209         if (!mac_mls_enabled)
 2210                 return (0);
 2211 
 2212         subj = SLOT(&cred->cr_label);
 2213         obj = SLOT(label);
 2214 
 2215         if (!mac_mls_dominate_single(obj, subj))
 2216                 return (EACCES);
 2217 
 2218         return (0);
 2219 }
 2220 
 2221 static int
 2222 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
 2223     struct label *label, acl_type_t type, struct acl *acl)
 2224 {
 2225         struct mac_mls *subj, *obj;
 2226 
 2227         if (!mac_mls_enabled)
 2228                 return (0);
 2229 
 2230         subj = SLOT(&cred->cr_label);
 2231         obj = SLOT(label);
 2232 
 2233         if (!mac_mls_dominate_single(obj, subj))
 2234                 return (EACCES);
 2235 
 2236         return (0);
 2237 }
 2238 
 2239 static int
 2240 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
 2241     struct label *vnodelabel, int attrnamespace, const char *name,
 2242     struct uio *uio)
 2243 {
 2244         struct mac_mls *subj, *obj;
 2245 
 2246         if (!mac_mls_enabled)
 2247                 return (0);
 2248 
 2249         subj = SLOT(&cred->cr_label);
 2250         obj = SLOT(vnodelabel);
 2251 
 2252         if (!mac_mls_dominate_single(obj, subj))
 2253                 return (EACCES);
 2254 
 2255         /* XXX: protect the MAC EA in a special way? */
 2256 
 2257         return (0);
 2258 }
 2259 
 2260 static int
 2261 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
 2262     struct label *vnodelabel, u_long flags)
 2263 {
 2264         struct mac_mls *subj, *obj;
 2265 
 2266         if (!mac_mls_enabled)
 2267                 return (0);
 2268 
 2269         subj = SLOT(&cred->cr_label);
 2270         obj = SLOT(vnodelabel);
 2271 
 2272         if (!mac_mls_dominate_single(obj, subj))
 2273                 return (EACCES);
 2274 
 2275         return (0);
 2276 }
 2277 
 2278 static int
 2279 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
 2280     struct label *vnodelabel, mode_t mode)
 2281 {
 2282         struct mac_mls *subj, *obj;
 2283 
 2284         if (!mac_mls_enabled)
 2285                 return (0);
 2286 
 2287         subj = SLOT(&cred->cr_label);
 2288         obj = SLOT(vnodelabel);
 2289 
 2290         if (!mac_mls_dominate_single(obj, subj))
 2291                 return (EACCES);
 2292 
 2293         return (0);
 2294 }
 2295 
 2296 static int
 2297 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
 2298     struct label *vnodelabel, uid_t uid, gid_t gid)
 2299 {
 2300         struct mac_mls *subj, *obj;
 2301 
 2302         if (!mac_mls_enabled)
 2303                 return (0);
 2304 
 2305         subj = SLOT(&cred->cr_label);
 2306         obj = SLOT(vnodelabel);
 2307 
 2308         if (!mac_mls_dominate_single(obj, subj))
 2309                 return (EACCES);
 2310 
 2311         return (0);
 2312 }
 2313 
 2314 static int
 2315 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
 2316     struct label *vnodelabel, struct timespec atime, struct timespec mtime)
 2317 {
 2318         struct mac_mls *subj, *obj;
 2319 
 2320         if (!mac_mls_enabled)
 2321                 return (0);
 2322 
 2323         subj = SLOT(&cred->cr_label);
 2324         obj = SLOT(vnodelabel);
 2325 
 2326         if (!mac_mls_dominate_single(obj, subj))
 2327                 return (EACCES);
 2328 
 2329         return (0);
 2330 }
 2331 
 2332 static int
 2333 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
 2334     struct vnode *vp, struct label *vnodelabel)
 2335 {
 2336         struct mac_mls *subj, *obj;
 2337 
 2338         if (!mac_mls_enabled)
 2339                 return (0);
 2340 
 2341         subj = SLOT(&active_cred->cr_label);
 2342         obj = SLOT(vnodelabel);
 2343 
 2344         if (!mac_mls_dominate_single(subj, obj))
 2345                 return (EACCES);
 2346 
 2347         return (0);
 2348 }
 2349 
 2350 static int
 2351 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
 2352     struct vnode *vp, struct label *label)
 2353 {
 2354         struct mac_mls *subj, *obj;
 2355 
 2356         if (!mac_mls_enabled || !revocation_enabled)
 2357                 return (0);
 2358 
 2359         subj = SLOT(&active_cred->cr_label);
 2360         obj = SLOT(label);
 2361 
 2362         if (!mac_mls_dominate_single(obj, subj))
 2363                 return (EACCES);
 2364 
 2365         return (0);
 2366 }
 2367 
 2368 static struct mac_policy_ops mac_mls_ops =
 2369 {
 2370         .mpo_destroy = mac_mls_destroy,
 2371         .mpo_init = mac_mls_init,
 2372         .mpo_init_bpfdesc_label = mac_mls_init_label,
 2373         .mpo_init_cred_label = mac_mls_init_label,
 2374         .mpo_init_devfsdirent_label = mac_mls_init_label,
 2375         .mpo_init_ifnet_label = mac_mls_init_label,
 2376         .mpo_init_ipq_label = mac_mls_init_label_waitcheck,
 2377         .mpo_init_mbuf_label = mac_mls_init_label_waitcheck,
 2378         .mpo_init_mount_label = mac_mls_init_label,
 2379         .mpo_init_mount_fs_label = mac_mls_init_label,
 2380         .mpo_init_pipe_label = mac_mls_init_label,
 2381         .mpo_init_socket_label = mac_mls_init_label_waitcheck,
 2382         .mpo_init_socket_peer_label = mac_mls_init_label_waitcheck,
 2383         .mpo_init_vnode_label = mac_mls_init_label,
 2384         .mpo_destroy_bpfdesc_label = mac_mls_destroy_label,
 2385         .mpo_destroy_cred_label = mac_mls_destroy_label,
 2386         .mpo_destroy_devfsdirent_label = mac_mls_destroy_label,
 2387         .mpo_destroy_ifnet_label = mac_mls_destroy_label,
 2388         .mpo_destroy_ipq_label = mac_mls_destroy_label,
 2389         .mpo_destroy_mbuf_label = mac_mls_destroy_label,
 2390         .mpo_destroy_mount_label = mac_mls_destroy_label,
 2391         .mpo_destroy_mount_fs_label = mac_mls_destroy_label,
 2392         .mpo_destroy_pipe_label = mac_mls_destroy_label,
 2393         .mpo_destroy_socket_label = mac_mls_destroy_label,
 2394         .mpo_destroy_socket_peer_label = mac_mls_destroy_label,
 2395         .mpo_destroy_vnode_label = mac_mls_destroy_label,
 2396         .mpo_copy_mbuf_label = mac_mls_copy_label,
 2397         .mpo_copy_pipe_label = mac_mls_copy_label,
 2398         .mpo_copy_vnode_label = mac_mls_copy_label,
 2399         .mpo_externalize_cred_label = mac_mls_externalize_label,
 2400         .mpo_externalize_ifnet_label = mac_mls_externalize_label,
 2401         .mpo_externalize_pipe_label = mac_mls_externalize_label,
 2402         .mpo_externalize_socket_label = mac_mls_externalize_label,
 2403         .mpo_externalize_socket_peer_label = mac_mls_externalize_label,
 2404         .mpo_externalize_vnode_label = mac_mls_externalize_label,
 2405         .mpo_internalize_cred_label = mac_mls_internalize_label,
 2406         .mpo_internalize_ifnet_label = mac_mls_internalize_label,
 2407         .mpo_internalize_pipe_label = mac_mls_internalize_label,
 2408         .mpo_internalize_socket_label = mac_mls_internalize_label,
 2409         .mpo_internalize_vnode_label = mac_mls_internalize_label,
 2410         .mpo_create_devfs_device = mac_mls_create_devfs_device,
 2411         .mpo_create_devfs_directory = mac_mls_create_devfs_directory,
 2412         .mpo_create_devfs_symlink = mac_mls_create_devfs_symlink,
 2413         .mpo_create_mount = mac_mls_create_mount,
 2414         .mpo_create_root_mount = mac_mls_create_root_mount,
 2415         .mpo_relabel_vnode = mac_mls_relabel_vnode,
 2416         .mpo_update_devfsdirent = mac_mls_update_devfsdirent,
 2417         .mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs,
 2418         .mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr,
 2419         .mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel,
 2420         .mpo_create_vnode_extattr = mac_mls_create_vnode_extattr,
 2421         .mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr,
 2422         .mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket,
 2423         .mpo_create_pipe = mac_mls_create_pipe,
 2424         .mpo_create_socket = mac_mls_create_socket,
 2425         .mpo_create_socket_from_socket = mac_mls_create_socket_from_socket,
 2426         .mpo_relabel_pipe = mac_mls_relabel_pipe,
 2427         .mpo_relabel_socket = mac_mls_relabel_socket,
 2428         .mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf,
 2429         .mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket,
 2430         .mpo_create_bpfdesc = mac_mls_create_bpfdesc,
 2431         .mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq,
 2432         .mpo_create_fragment = mac_mls_create_fragment,
 2433         .mpo_create_ifnet = mac_mls_create_ifnet,
 2434         .mpo_create_ipq = mac_mls_create_ipq,
 2435         .mpo_create_mbuf_from_mbuf = mac_mls_create_mbuf_from_mbuf,
 2436         .mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer,
 2437         .mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc,
 2438         .mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet,
 2439         .mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap,
 2440         .mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer,
 2441         .mpo_fragment_match = mac_mls_fragment_match,
 2442         .mpo_relabel_ifnet = mac_mls_relabel_ifnet,
 2443         .mpo_update_ipq = mac_mls_update_ipq,
 2444         .mpo_create_cred = mac_mls_create_cred,
 2445         .mpo_create_proc0 = mac_mls_create_proc0,
 2446         .mpo_create_proc1 = mac_mls_create_proc1,
 2447         .mpo_relabel_cred = mac_mls_relabel_cred,
 2448         .mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive,
 2449         .mpo_check_cred_relabel = mac_mls_check_cred_relabel,
 2450         .mpo_check_cred_visible = mac_mls_check_cred_visible,
 2451         .mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel,
 2452         .mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit,
 2453         .mpo_check_mount_stat = mac_mls_check_mount_stat,
 2454         .mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl,
 2455         .mpo_check_pipe_poll = mac_mls_check_pipe_poll,
 2456         .mpo_check_pipe_read = mac_mls_check_pipe_read,
 2457         .mpo_check_pipe_relabel = mac_mls_check_pipe_relabel,
 2458         .mpo_check_pipe_stat = mac_mls_check_pipe_stat,
 2459         .mpo_check_pipe_write = mac_mls_check_pipe_write,
 2460         .mpo_check_proc_debug = mac_mls_check_proc_debug,
 2461         .mpo_check_proc_sched = mac_mls_check_proc_sched,
 2462         .mpo_check_proc_signal = mac_mls_check_proc_signal,
 2463         .mpo_check_socket_deliver = mac_mls_check_socket_deliver,
 2464         .mpo_check_socket_relabel = mac_mls_check_socket_relabel,
 2465         .mpo_check_socket_visible = mac_mls_check_socket_visible,
 2466         .mpo_check_system_swapon = mac_mls_check_system_swapon,
 2467         .mpo_check_vnode_access = mac_mls_check_vnode_open,
 2468         .mpo_check_vnode_chdir = mac_mls_check_vnode_chdir,
 2469         .mpo_check_vnode_chroot = mac_mls_check_vnode_chroot,
 2470         .mpo_check_vnode_create = mac_mls_check_vnode_create,
 2471         .mpo_check_vnode_delete = mac_mls_check_vnode_delete,
 2472         .mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl,
 2473         .mpo_check_vnode_exec = mac_mls_check_vnode_exec,
 2474         .mpo_check_vnode_getacl = mac_mls_check_vnode_getacl,
 2475         .mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr,
 2476         .mpo_check_vnode_link = mac_mls_check_vnode_link,
 2477         .mpo_check_vnode_lookup = mac_mls_check_vnode_lookup,
 2478         .mpo_check_vnode_mmap = mac_mls_check_vnode_mmap,
 2479         .mpo_check_vnode_mprotect = mac_mls_check_vnode_mmap,
 2480         .mpo_check_vnode_open = mac_mls_check_vnode_open,
 2481         .mpo_check_vnode_poll = mac_mls_check_vnode_poll,
 2482         .mpo_check_vnode_read = mac_mls_check_vnode_read,
 2483         .mpo_check_vnode_readdir = mac_mls_check_vnode_readdir,
 2484         .mpo_check_vnode_readlink = mac_mls_check_vnode_readlink,
 2485         .mpo_check_vnode_relabel = mac_mls_check_vnode_relabel,
 2486         .mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from,
 2487         .mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to,
 2488         .mpo_check_vnode_revoke = mac_mls_check_vnode_revoke,
 2489         .mpo_check_vnode_setacl = mac_mls_check_vnode_setacl,
 2490         .mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr,
 2491         .mpo_check_vnode_setflags = mac_mls_check_vnode_setflags,
 2492         .mpo_check_vnode_setmode = mac_mls_check_vnode_setmode,
 2493         .mpo_check_vnode_setowner = mac_mls_check_vnode_setowner,
 2494         .mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes,
 2495         .mpo_check_vnode_stat = mac_mls_check_vnode_stat,
 2496         .mpo_check_vnode_write = mac_mls_check_vnode_write,
 2497 };
 2498 
 2499 MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
 2500     MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot);

Cache object: 1295fbd522a6283ba8ddaa3a1d1074af


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