The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

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

Cache object: d8de5bb7219ef8588c54ed65a80b26d7


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