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/mac_internal.h

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-2002, 2006 Robert N. M. Watson
    3  * Copyright (c) 2001 Ilmar S. Habibulin
    4  * Copyright (c) 2001-2004 Networks Associates Technology, Inc.
    5  * Copyright (c) 2006 nCircle Network Security, Inc.
    6  * All rights reserved.
    7  *
    8  * This software was developed by Robert Watson and Ilmar Habibulin for the
    9  * TrustedBSD Project.
   10  *
   11  * This software was developed for the FreeBSD Project in part by Network
   12  * Associates Laboratories, the Security Research Division of Network
   13  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
   14  * as part of the DARPA CHATS research program.
   15  *
   16  * This software was developed by Robert N. M. Watson for the TrustedBSD
   17  * Project under contract to nCircle Network Security, Inc.
   18  *
   19  * Redistribution and use in source and binary forms, with or without
   20  * modification, are permitted provided that the following conditions
   21  * are met:
   22  * 1. Redistributions of source code must retain the above copyright
   23  *    notice, this list of conditions and the following disclaimer.
   24  * 2. Redistributions in binary form must reproduce the above copyright
   25  *    notice, this list of conditions and the following disclaimer in the
   26  *    documentation and/or other materials provided with the distribution.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  * $FreeBSD$
   41  */
   42 
   43 #ifndef _SECURITY_MAC_MAC_INTERNAL_H_
   44 #define _SECURITY_MAC_MAC_INTERNAL_H_
   45 
   46 #ifndef _KERNEL
   47 #error "no user-serviceable parts inside"
   48 #endif
   49 
   50 /*
   51  * MAC Framework sysctl namespace.
   52  */
   53 #ifdef SYSCTL_DECL
   54 SYSCTL_DECL(_security_mac);
   55 #endif /* SYSCTL_DECL */
   56 
   57 /*
   58  * MAC Framework global types and typedefs.
   59  */
   60 LIST_HEAD(mac_policy_list_head, mac_policy_conf);
   61 #ifdef MALLOC_DECLARE
   62 MALLOC_DECLARE(M_MACTEMP);
   63 #endif
   64 
   65 /*
   66  * MAC labels -- in-kernel storage format.
   67  *
   68  * In general, struct label pointers are embedded in kernel data structures
   69  * representing objects that may be labeled (and protected).  Struct label is
   70  * opaque to both kernel services that invoke the MAC Framework and MAC
   71  * policy modules.  In particular, we do not wish to encode the layout of the
   72  * label structure into any ABIs.  Historically, the slot array contained
   73  * unions of {long, void} but now contains uintptr_t.
   74  */
   75 #define MAC_MAX_SLOTS   4
   76 #define MAC_FLAG_INITIALIZED    0x0000001       /* Is initialized for use. */
   77 struct label {
   78         int             l_flags;
   79         intptr_t        l_perpolicy[MAC_MAX_SLOTS];
   80 };
   81 
   82 /*
   83  * MAC Framework global variables.
   84  */
   85 extern struct mac_policy_list_head      mac_policy_list;
   86 extern struct mac_policy_list_head      mac_static_policy_list;
   87 #ifndef MAC_ALWAYS_LABEL_MBUF
   88 extern int                              mac_labelmbufs;
   89 #endif
   90 
   91 /*
   92  * MAC Framework infrastructure functions.
   93  */
   94 int     mac_error_select(int error1, int error2);
   95 
   96 void    mac_policy_grab_exclusive(void);
   97 void    mac_policy_assert_exclusive(void);
   98 void    mac_policy_release_exclusive(void);
   99 void    mac_policy_list_busy(void);
  100 int     mac_policy_list_conditional_busy(void);
  101 void    mac_policy_list_unbusy(void);
  102 
  103 struct label    *mac_labelzone_alloc(int flags);
  104 void             mac_labelzone_free(struct label *label);
  105 void             mac_labelzone_init(void);
  106 
  107 void    mac_init_label(struct label *label);
  108 void    mac_destroy_label(struct label *label);
  109 int     mac_check_structmac_consistent(struct mac *mac);
  110 int     mac_allocate_slot(void);
  111 
  112 /*
  113  * MAC Framework per-object type functions.  It's not yet clear how the
  114  * namespaces, etc, should work for these, so for now, sort by object type.
  115  */
  116 struct label    *mac_pipe_label_alloc(void);
  117 void             mac_pipe_label_free(struct label *label);
  118 struct label    *mac_socket_label_alloc(int flag);
  119 void             mac_socket_label_free(struct label *label);
  120 
  121 int     mac_check_cred_relabel(struct ucred *cred, struct label *newlabel);
  122 int     mac_externalize_cred_label(struct label *label, char *elements,
  123             char *outbuf, size_t outbuflen);
  124 int     mac_internalize_cred_label(struct label *label, char *string);
  125 void    mac_relabel_cred(struct ucred *cred, struct label *newlabel);
  126 
  127 struct label    *mac_mbuf_to_label(struct mbuf *m);
  128 
  129 void    mac_copy_pipe_label(struct label *src, struct label *dest);
  130 int     mac_externalize_pipe_label(struct label *label, char *elements,
  131             char *outbuf, size_t outbuflen);
  132 int     mac_internalize_pipe_label(struct label *label, char *string);
  133 
  134 int     mac_socket_label_set(struct ucred *cred, struct socket *so,
  135             struct label *label);
  136 void    mac_copy_socket_label(struct label *src, struct label *dest);
  137 int     mac_externalize_socket_label(struct label *label, char *elements,
  138             char *outbuf, size_t outbuflen);
  139 int     mac_internalize_socket_label(struct label *label, char *string);
  140 
  141 int     mac_externalize_vnode_label(struct label *label, char *elements,
  142             char *outbuf, size_t outbuflen);
  143 int     mac_internalize_vnode_label(struct label *label, char *string);
  144 void    mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
  145             int *prot);
  146 int     vn_setlabel(struct vnode *vp, struct label *intlabel,
  147             struct ucred *cred);
  148 
  149 /*
  150  * MAC_CHECK performs the designated check by walking the policy module list
  151  * and checking with each as to how it feels about the request.  Note that it
  152  * returns its value via 'error' in the scope of the caller.
  153  */
  154 #define MAC_CHECK(check, args...) do {                                  \
  155         struct mac_policy_conf *mpc;                                    \
  156         int entrycount;                                                 \
  157                                                                         \
  158         error = 0;                                                      \
  159         LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {          \
  160                 if (mpc->mpc_ops->mpo_ ## check != NULL)                \
  161                         error = mac_error_select(                       \
  162                             mpc->mpc_ops->mpo_ ## check (args),         \
  163                             error);                                     \
  164         }                                                               \
  165         if ((entrycount = mac_policy_list_conditional_busy()) != 0) {   \
  166                 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {         \
  167                         if (mpc->mpc_ops->mpo_ ## check != NULL)        \
  168                                 error = mac_error_select(               \
  169                                     mpc->mpc_ops->mpo_ ## check (args), \
  170                                     error);                             \
  171                 }                                                       \
  172                 mac_policy_list_unbusy();                               \
  173         }                                                               \
  174 } while (0)
  175 
  176 /*
  177  * MAC_GRANT performs the designated check by walking the policy module list
  178  * and checking with each as to how it feels about the request.  Unlike
  179  * MAC_CHECK, it grants if any policies return '', and otherwise returns
  180  * EPERM.  Note that it returns its value via 'error' in the scope of the
  181  * caller.
  182  */
  183 #define MAC_GRANT(check, args...) do {                                  \
  184         struct mac_policy_conf *mpc;                                    \
  185         int entrycount;                                                 \
  186                                                                         \
  187         error = EPERM;                                                  \
  188         LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {          \
  189                 if (mpc->mpc_ops->mpo_ ## check != NULL) {              \
  190                         if (mpc->mpc_ops->mpo_ ## check(args) == 0)     \
  191                                 error = 0;                              \
  192                 }                                                       \
  193         }                                                               \
  194         if ((entrycount = mac_policy_list_conditional_busy()) != 0) {   \
  195                 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {         \
  196                         if (mpc->mpc_ops->mpo_ ## check != NULL) {      \
  197                                 if (mpc->mpc_ops->mpo_ ## check (args)  \
  198                                     == 0)                               \
  199                                         error = 0;                      \
  200                         }                                               \
  201                 }                                                       \
  202                 mac_policy_list_unbusy();                               \
  203         }                                                               \
  204 } while (0)
  205 
  206 /*
  207  * MAC_BOOLEAN performs the designated boolean composition by walking the
  208  * module list, invoking each instance of the operation, and combining the
  209  * results using the passed C operator.  Note that it returns its value via
  210  * 'result' in the scope of the caller, which should be initialized by the
  211  * caller in a meaningful way to get a meaningful result.
  212  */
  213 #define MAC_BOOLEAN(operation, composition, args...) do {               \
  214         struct mac_policy_conf *mpc;                                    \
  215         int entrycount;                                                 \
  216                                                                         \
  217         LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {          \
  218                 if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
  219                         result = result composition                     \
  220                             mpc->mpc_ops->mpo_ ## operation (args);     \
  221         }                                                               \
  222         if ((entrycount = mac_policy_list_conditional_busy()) != 0) {   \
  223                 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {         \
  224                         if (mpc->mpc_ops->mpo_ ## operation != NULL)    \
  225                                 result = result composition             \
  226                                     mpc->mpc_ops->mpo_ ## operation     \
  227                                     (args);                             \
  228                 }                                                       \
  229                 mac_policy_list_unbusy();                               \
  230         }                                                               \
  231 } while (0)
  232 
  233 /*
  234  * MAC_EXTERNALIZE queries each policy to see if it can generate an
  235  * externalized version of a label element by name.  Policies declare whether
  236  * they have matched a particular element name, parsed from the string by
  237  * MAC_EXTERNALIZE, and an error is returned if any element is matched by no
  238  * policy.
  239  */
  240 #define MAC_EXTERNALIZE(type, label, elementlist, outbuf,               \
  241     outbuflen) do {                                                     \
  242         int claimed, first, ignorenotfound, savedlen;                   \
  243         char *element_name, *element_temp;                              \
  244         struct sbuf sb;                                                 \
  245                                                                         \
  246         error = 0;                                                      \
  247         first = 1;                                                      \
  248         sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN);                \
  249         element_temp = elementlist;                                     \
  250         while ((element_name = strsep(&element_temp, ",")) != NULL) {   \
  251                 if (element_name[0] == '?') {                           \
  252                         element_name++;                                 \
  253                         ignorenotfound = 1;                             \
  254                  } else                                                 \
  255                         ignorenotfound = 0;                             \
  256                 savedlen = sbuf_len(&sb);                               \
  257                 if (first)                                              \
  258                         error = sbuf_printf(&sb, "%s/", element_name);  \
  259                 else                                                    \
  260                         error = sbuf_printf(&sb, ",%s/", element_name); \
  261                 if (error == -1) {                                      \
  262                         error = EINVAL; /* XXX: E2BIG? */               \
  263                         break;                                          \
  264                 }                                                       \
  265                 claimed = 0;                                            \
  266                 MAC_CHECK(externalize_ ## type ## _label, label,        \
  267                     element_name, &sb, &claimed);                       \
  268                 if (error)                                              \
  269                         break;                                          \
  270                 if (claimed == 0 && ignorenotfound) {                   \
  271                         /* Revert last label name. */                   \
  272                         sbuf_setpos(&sb, savedlen);                     \
  273                 } else if (claimed != 1) {                              \
  274                         error = EINVAL; /* XXX: ENOLABEL? */            \
  275                         break;                                          \
  276                 } else {                                                \
  277                         first = 0;                                      \
  278                 }                                                       \
  279         }                                                               \
  280         sbuf_finish(&sb);                                               \
  281 } while (0)
  282 
  283 /*
  284  * MAC_INTERNALIZE presents parsed element names and data to each policy to
  285  * see if any is willing to claim it and internalize the label data.  If no
  286  * policies match, an error is returned.
  287  */
  288 #define MAC_INTERNALIZE(type, label, instring) do {                     \
  289         char *element, *element_name, *element_data;                    \
  290         int claimed;                                                    \
  291                                                                         \
  292         error = 0;                                                      \
  293         element = instring;                                             \
  294         while ((element_name = strsep(&element, ",")) != NULL) {        \
  295                 element_data = element_name;                            \
  296                 element_name = strsep(&element_data, "/");              \
  297                 if (element_data == NULL) {                             \
  298                         error = EINVAL;                                 \
  299                         break;                                          \
  300                 }                                                       \
  301                 claimed = 0;                                            \
  302                 MAC_CHECK(internalize_ ## type ## _label, label,        \
  303                     element_name, element_data, &claimed);              \
  304                 if (error)                                              \
  305                         break;                                          \
  306                 if (claimed != 1) {                                     \
  307                         /* XXXMAC: Another error here? */               \
  308                         error = EINVAL;                                 \
  309                         break;                                          \
  310                 }                                                       \
  311         }                                                               \
  312 } while (0)
  313 
  314 /*
  315  * MAC_PERFORM performs the designated operation by walking the policy module
  316  * list and invoking that operation for each policy.
  317  */
  318 #define MAC_PERFORM(operation, args...) do {                            \
  319         struct mac_policy_conf *mpc;                                    \
  320         int entrycount;                                                 \
  321                                                                         \
  322         LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {          \
  323                 if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
  324                         mpc->mpc_ops->mpo_ ## operation (args);         \
  325         }                                                               \
  326         if ((entrycount = mac_policy_list_conditional_busy()) != 0) {   \
  327                 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {         \
  328                         if (mpc->mpc_ops->mpo_ ## operation != NULL)    \
  329                                 mpc->mpc_ops->mpo_ ## operation (args); \
  330                 }                                                       \
  331                 mac_policy_list_unbusy();                               \
  332         }                                                               \
  333 } while (0)
  334 
  335 #endif /* !_SECURITY_MAC_MAC_INTERNAL_H_ */

Cache object: 09220cd988888f1d5214af94e922650b


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