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_net.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-2002, 2009 Robert N. M. Watson
    3  * Copyright (c) 2001 Ilmar S. Habibulin
    4  * Copyright (c) 2001-2004 Networks Associates Technology, Inc.
    5  * Copyright (c) 2006 SPARTA, Inc.
    6  * Copyright (c) 2008 Apple Inc.
    7  * All rights reserved.
    8  *
    9  * This software was developed by Robert Watson and Ilmar Habibulin for the
   10  * TrustedBSD Project.
   11  *
   12  * This software was enhanced by SPARTA ISSO under SPAWAR contract
   13  * N66001-04-C-6019 ("SEFOS").
   14  *
   15  * This software was developed for the FreeBSD Project in part by Network
   16  * Associates Laboratories, the Security Research Division of Network
   17  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
   18  * as part of the DARPA CHATS research program.
   19  *
   20  * This software was developed at the University of Cambridge Computer
   21  * Laboratory with support from a grant from Google, Inc. 
   22  *
   23  * Redistribution and use in source and binary forms, with or without
   24  * modification, are permitted provided that the following conditions
   25  * are met:
   26  * 1. Redistributions of source code must retain the above copyright
   27  *    notice, this list of conditions and the following disclaimer.
   28  * 2. Redistributions in binary form must reproduce the above copyright
   29  *    notice, this list of conditions and the following disclaimer in the
   30  *    documentation and/or other materials provided with the distribution.
   31  *
   32  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   42  * SUCH DAMAGE.
   43  */
   44 
   45 #include <sys/cdefs.h>
   46 __FBSDID("$FreeBSD: releng/11.0/sys/security/mac/mac_net.c 258541 2013-11-25 07:38:45Z attilio $");
   47 
   48 #include "opt_mac.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/kernel.h>
   52 #include <sys/lock.h>
   53 #include <sys/malloc.h>
   54 #include <sys/mutex.h>
   55 #include <sys/mac.h>
   56 #include <sys/priv.h>
   57 #include <sys/sbuf.h>
   58 #include <sys/sdt.h>
   59 #include <sys/systm.h>
   60 #include <sys/mount.h>
   61 #include <sys/file.h>
   62 #include <sys/namei.h>
   63 #include <sys/protosw.h>
   64 #include <sys/socket.h>
   65 #include <sys/socketvar.h>
   66 #include <sys/sysctl.h>
   67 
   68 #include <net/bpfdesc.h>
   69 #include <net/if.h>
   70 #include <net/if_var.h>
   71 
   72 #include <security/mac/mac_framework.h>
   73 #include <security/mac/mac_internal.h>
   74 #include <security/mac/mac_policy.h>
   75 
   76 /*
   77  * XXXRW: struct ifnet locking is incomplete in the network code, so we use
   78  * our own global mutex for struct ifnet.  Non-ideal, but should help in the
   79  * SMP environment.
   80  */
   81 struct mtx mac_ifnet_mtx;
   82 MTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF);
   83 
   84 /*
   85  * Retrieve the label associated with an mbuf by searching for the tag.
   86  * Depending on the value of mac_labelmbufs, it's possible that a label will
   87  * not be present, in which case NULL is returned.  Policies must handle the
   88  * possibility of an mbuf not having label storage if they do not enforce
   89  * early loading.
   90  */
   91 struct label *
   92 mac_mbuf_to_label(struct mbuf *m)
   93 {
   94         struct m_tag *tag;
   95         struct label *label;
   96 
   97         if (m == NULL)
   98                 return (NULL);
   99         tag = m_tag_find(m, PACKET_TAG_MACLABEL, NULL);
  100         if (tag == NULL)
  101                 return (NULL);
  102         label = (struct label *)(tag+1);
  103         return (label);
  104 }
  105 
  106 static struct label *
  107 mac_bpfdesc_label_alloc(void)
  108 {
  109         struct label *label;
  110 
  111         label = mac_labelzone_alloc(M_WAITOK);
  112         MAC_POLICY_PERFORM(bpfdesc_init_label, label);
  113         return (label);
  114 }
  115 
  116 void
  117 mac_bpfdesc_init(struct bpf_d *d)
  118 {
  119 
  120         if (mac_labeled & MPC_OBJECT_BPFDESC)
  121                 d->bd_label = mac_bpfdesc_label_alloc();
  122         else
  123                 d->bd_label = NULL;
  124 }
  125 
  126 static struct label *
  127 mac_ifnet_label_alloc(void)
  128 {
  129         struct label *label;
  130 
  131         label = mac_labelzone_alloc(M_WAITOK);
  132         MAC_POLICY_PERFORM(ifnet_init_label, label);
  133         return (label);
  134 }
  135 
  136 void
  137 mac_ifnet_init(struct ifnet *ifp)
  138 {
  139 
  140         if (mac_labeled & MPC_OBJECT_IFNET)
  141                 ifp->if_label = mac_ifnet_label_alloc();
  142         else
  143                 ifp->if_label = NULL;
  144 }
  145 
  146 int
  147 mac_mbuf_tag_init(struct m_tag *tag, int flag)
  148 {
  149         struct label *label;
  150         int error;
  151 
  152         label = (struct label *) (tag + 1);
  153         mac_init_label(label);
  154 
  155         if (flag & M_WAITOK)
  156                 MAC_POLICY_CHECK(mbuf_init_label, label, flag);
  157         else
  158                 MAC_POLICY_CHECK_NOSLEEP(mbuf_init_label, label, flag);
  159         if (error) {
  160                 MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label);
  161                 mac_destroy_label(label);
  162         }
  163         return (error);
  164 }
  165 
  166 int
  167 mac_mbuf_init(struct mbuf *m, int flag)
  168 {
  169         struct m_tag *tag;
  170         int error;
  171 
  172         M_ASSERTPKTHDR(m);
  173 
  174         if (mac_labeled & MPC_OBJECT_MBUF) {
  175                 tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
  176                     flag);
  177                 if (tag == NULL)
  178                         return (ENOMEM);
  179                 error = mac_mbuf_tag_init(tag, flag);
  180                 if (error) {
  181                         m_tag_free(tag);
  182                         return (error);
  183                 }
  184                 m_tag_prepend(m, tag);
  185         }
  186         return (0);
  187 }
  188 
  189 static void
  190 mac_bpfdesc_label_free(struct label *label)
  191 {
  192 
  193         MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_destroy_label, label);
  194         mac_labelzone_free(label);
  195 }
  196 
  197 void
  198 mac_bpfdesc_destroy(struct bpf_d *d)
  199 {
  200 
  201         if (d->bd_label != NULL) {
  202                 mac_bpfdesc_label_free(d->bd_label);
  203                 d->bd_label = NULL;
  204         }
  205 }
  206 
  207 static void
  208 mac_ifnet_label_free(struct label *label)
  209 {
  210 
  211         MAC_POLICY_PERFORM_NOSLEEP(ifnet_destroy_label, label);
  212         mac_labelzone_free(label);
  213 }
  214 
  215 void
  216 mac_ifnet_destroy(struct ifnet *ifp)
  217 {
  218 
  219         if (ifp->if_label != NULL) {
  220                 mac_ifnet_label_free(ifp->if_label);
  221                 ifp->if_label = NULL;
  222         }
  223 }
  224 
  225 void
  226 mac_mbuf_tag_destroy(struct m_tag *tag)
  227 {
  228         struct label *label;
  229 
  230         label = (struct label *)(tag+1);
  231 
  232         MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label);
  233         mac_destroy_label(label);
  234 }
  235 
  236 /*
  237  * mac_mbuf_tag_copy is called when an mbuf header is duplicated, in which
  238  * case the labels must also be duplicated.
  239  */
  240 void
  241 mac_mbuf_tag_copy(struct m_tag *src, struct m_tag *dest)
  242 {
  243         struct label *src_label, *dest_label;
  244 
  245         src_label = (struct label *)(src+1);
  246         dest_label = (struct label *)(dest+1);
  247 
  248         /*
  249          * mac_mbuf_tag_init() is called on the target tag in m_tag_copy(),
  250          * so we don't need to call it here.
  251          */
  252         MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
  253 }
  254 
  255 void
  256 mac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to)
  257 {
  258         struct label *src_label, *dest_label;
  259 
  260         if (mac_policy_count == 0)
  261                 return;
  262 
  263         src_label = mac_mbuf_to_label(m_from);
  264         dest_label = mac_mbuf_to_label(m_to);
  265 
  266         MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
  267 }
  268 
  269 static void
  270 mac_ifnet_copy_label(struct label *src, struct label *dest)
  271 {
  272 
  273         MAC_POLICY_PERFORM_NOSLEEP(ifnet_copy_label, src, dest);
  274 }
  275 
  276 static int
  277 mac_ifnet_externalize_label(struct label *label, char *elements,
  278     char *outbuf, size_t outbuflen)
  279 {
  280         int error;
  281 
  282         MAC_POLICY_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
  283 
  284         return (error);
  285 }
  286 
  287 static int
  288 mac_ifnet_internalize_label(struct label *label, char *string)
  289 {
  290         int error;
  291 
  292         MAC_POLICY_INTERNALIZE(ifnet, label, string);
  293 
  294         return (error);
  295 }
  296 
  297 void
  298 mac_ifnet_create(struct ifnet *ifp)
  299 {
  300 
  301         if (mac_policy_count == 0)
  302                 return;
  303 
  304         MAC_IFNET_LOCK(ifp);
  305         MAC_POLICY_PERFORM_NOSLEEP(ifnet_create, ifp, ifp->if_label);
  306         MAC_IFNET_UNLOCK(ifp);
  307 }
  308 
  309 void
  310 mac_bpfdesc_create(struct ucred *cred, struct bpf_d *d)
  311 {
  312 
  313         MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create, cred, d, d->bd_label);
  314 }
  315 
  316 void
  317 mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m)
  318 {
  319         struct label *label;
  320 
  321         /* Assume reader lock is enough. */
  322         BPFD_LOCK_ASSERT(d);
  323 
  324         if (mac_policy_count == 0)
  325                 return;
  326 
  327         label = mac_mbuf_to_label(m);
  328 
  329         MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m,
  330             label);
  331 }
  332 
  333 void
  334 mac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m)
  335 {
  336         struct label *label;
  337 
  338         if (mac_policy_count == 0)
  339                 return;
  340 
  341         label = mac_mbuf_to_label(m);
  342 
  343         MAC_IFNET_LOCK(ifp);
  344         MAC_POLICY_PERFORM_NOSLEEP(ifnet_create_mbuf, ifp, ifp->if_label, m,
  345             label);
  346         MAC_IFNET_UNLOCK(ifp);
  347 }
  348 
  349 MAC_CHECK_PROBE_DEFINE2(bpfdesc_check_receive, "struct bpf_d *",
  350     "struct ifnet *");
  351 
  352 int
  353 mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp)
  354 {
  355         int error;
  356 
  357         /* Assume reader lock is enough. */
  358         BPFD_LOCK_ASSERT(d);
  359 
  360         if (mac_policy_count == 0)
  361                 return (0);
  362 
  363         MAC_IFNET_LOCK(ifp);
  364         MAC_POLICY_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp,
  365             ifp->if_label);
  366         MAC_CHECK_PROBE2(bpfdesc_check_receive, error, d, ifp);
  367         MAC_IFNET_UNLOCK(ifp);
  368 
  369         return (error);
  370 }
  371 
  372 MAC_CHECK_PROBE_DEFINE2(ifnet_check_transmit, "struct ifnet *",
  373     "struct mbuf *");
  374 
  375 int
  376 mac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m)
  377 {
  378         struct label *label;
  379         int error;
  380 
  381         M_ASSERTPKTHDR(m);
  382 
  383         if (mac_policy_count == 0)
  384                 return (0);
  385 
  386         label = mac_mbuf_to_label(m);
  387 
  388         MAC_IFNET_LOCK(ifp);
  389         MAC_POLICY_CHECK_NOSLEEP(ifnet_check_transmit, ifp, ifp->if_label, m,
  390             label);
  391         MAC_CHECK_PROBE2(ifnet_check_transmit, error, ifp, m);
  392         MAC_IFNET_UNLOCK(ifp);
  393 
  394         return (error);
  395 }
  396 
  397 int
  398 mac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr,
  399     struct ifnet *ifp)
  400 {
  401         char *elements, *buffer;
  402         struct label *intlabel;
  403         struct mac mac;
  404         int error;
  405 
  406         if (!(mac_labeled & MPC_OBJECT_IFNET))
  407                 return (EINVAL);
  408 
  409         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
  410         if (error)
  411                 return (error);
  412 
  413         error = mac_check_structmac_consistent(&mac);
  414         if (error)
  415                 return (error);
  416 
  417         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  418         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  419         if (error) {
  420                 free(elements, M_MACTEMP);
  421                 return (error);
  422         }
  423 
  424         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  425         intlabel = mac_ifnet_label_alloc();
  426         MAC_IFNET_LOCK(ifp);
  427         mac_ifnet_copy_label(ifp->if_label, intlabel);
  428         MAC_IFNET_UNLOCK(ifp);
  429         error = mac_ifnet_externalize_label(intlabel, elements, buffer,
  430             mac.m_buflen);
  431         mac_ifnet_label_free(intlabel);
  432         if (error == 0)
  433                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  434 
  435         free(buffer, M_MACTEMP);
  436         free(elements, M_MACTEMP);
  437 
  438         return (error);
  439 }
  440 
  441 int
  442 mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp)
  443 {
  444         struct label *intlabel;
  445         struct mac mac;
  446         char *buffer;
  447         int error;
  448 
  449         if (!(mac_labeled & MPC_OBJECT_IFNET))
  450                 return (EINVAL);
  451 
  452         error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
  453         if (error)
  454                 return (error);
  455 
  456         error = mac_check_structmac_consistent(&mac);
  457         if (error)
  458                 return (error);
  459 
  460         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  461         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
  462         if (error) {
  463                 free(buffer, M_MACTEMP);
  464                 return (error);
  465         }
  466 
  467         intlabel = mac_ifnet_label_alloc();
  468         error = mac_ifnet_internalize_label(intlabel, buffer);
  469         free(buffer, M_MACTEMP);
  470         if (error) {
  471                 mac_ifnet_label_free(intlabel);
  472                 return (error);
  473         }
  474 
  475         /*
  476          * XXX: Note that this is a redundant privilege check, since policies
  477          * impose this check themselves if required by the policy
  478          * Eventually, this should go away.
  479          */
  480         error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
  481         if (error) {
  482                 mac_ifnet_label_free(intlabel);
  483                 return (error);
  484         }
  485 
  486         MAC_IFNET_LOCK(ifp);
  487         MAC_POLICY_CHECK_NOSLEEP(ifnet_check_relabel, cred, ifp,
  488             ifp->if_label, intlabel);
  489         if (error) {
  490                 MAC_IFNET_UNLOCK(ifp);
  491                 mac_ifnet_label_free(intlabel);
  492                 return (error);
  493         }
  494 
  495         MAC_POLICY_PERFORM_NOSLEEP(ifnet_relabel, cred, ifp, ifp->if_label,
  496             intlabel);
  497         MAC_IFNET_UNLOCK(ifp);
  498 
  499         mac_ifnet_label_free(intlabel);
  500         return (0);
  501 }

Cache object: 97840c3c99f386479658506bd068ea68


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