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_socket.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 Robert N. M. Watson
    3  * Copyright (c) 2001 Ilmar S. Habibulin
    4  * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
    5  * Copyright (c) 2005 SPARTA, 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 McAfee
   12  * Research, the Technology Research Division of Network Associates, Inc.
   13  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
   14  * DARPA CHATS research program.
   15  *
   16  * This software was enhanced by SPARTA ISSO under SPAWAR contract
   17  * N66001-04-C-6019 ("SEFOS").
   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 
   41 #include <sys/cdefs.h>
   42 __FBSDID("$FreeBSD$");
   43 
   44 #include "opt_mac.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/kernel.h>
   48 #include <sys/lock.h>
   49 #include <sys/malloc.h>
   50 #include <sys/mutex.h>
   51 #include <sys/mac.h>
   52 #include <sys/sbuf.h>
   53 #include <sys/systm.h>
   54 #include <sys/mount.h>
   55 #include <sys/file.h>
   56 #include <sys/namei.h>
   57 #include <sys/protosw.h>
   58 #include <sys/socket.h>
   59 #include <sys/socketvar.h>
   60 #include <sys/sysctl.h>
   61 
   62 #include <net/bpfdesc.h>
   63 #include <net/if.h>
   64 #include <net/if_var.h>
   65 
   66 #include <netinet/in.h>
   67 #include <netinet/in_pcb.h>
   68 #include <netinet/ip_var.h>
   69 
   70 #include <security/mac/mac_framework.h>
   71 #include <security/mac/mac_internal.h>
   72 #include <security/mac/mac_policy.h>
   73 
   74 /*
   75  * Currently, sockets hold two labels: the label of the socket itself, and a
   76  * peer label, which may be used by policies to hold a copy of the label of
   77  * any remote endpoint.
   78  *
   79  * Possibly, this peer label should be maintained at the protocol layer
   80  * (inpcb, unpcb, etc), as this would allow protocol-aware code to maintain
   81  * the label consistently.  For example, it might be copied live from a
   82  * remote socket for UNIX domain sockets rather than keeping a local copy on
   83  * this endpoint, but be cached and updated based on packets received for
   84  * TCP/IP.
   85  */
   86 
   87 struct label *
   88 mac_socket_label_alloc(int flag)
   89 {
   90         struct label *label;
   91         int error;
   92 
   93         label = mac_labelzone_alloc(flag);
   94         if (label == NULL)
   95                 return (NULL);
   96 
   97         MAC_CHECK(init_socket_label, label, flag);
   98         if (error) {
   99                 MAC_PERFORM(destroy_socket_label, label);
  100                 mac_labelzone_free(label);
  101                 return (NULL);
  102         }
  103         return (label);
  104 }
  105 
  106 static struct label *
  107 mac_socket_peer_label_alloc(int flag)
  108 {
  109         struct label *label;
  110         int error;
  111 
  112         label = mac_labelzone_alloc(flag);
  113         if (label == NULL)
  114                 return (NULL);
  115 
  116         MAC_CHECK(init_socket_peer_label, label, flag);
  117         if (error) {
  118                 MAC_PERFORM(destroy_socket_peer_label, label);
  119                 mac_labelzone_free(label);
  120                 return (NULL);
  121         }
  122         return (label);
  123 }
  124 
  125 int
  126 mac_init_socket(struct socket *so, int flag)
  127 {
  128 
  129         so->so_label = mac_socket_label_alloc(flag);
  130         if (so->so_label == NULL)
  131                 return (ENOMEM);
  132         so->so_peerlabel = mac_socket_peer_label_alloc(flag);
  133         if (so->so_peerlabel == NULL) {
  134                 mac_socket_label_free(so->so_label);
  135                 so->so_label = NULL;
  136                 return (ENOMEM);
  137         }
  138         return (0);
  139 }
  140 
  141 void
  142 mac_socket_label_free(struct label *label)
  143 {
  144 
  145         MAC_PERFORM(destroy_socket_label, label);
  146         mac_labelzone_free(label);
  147 }
  148 
  149 static void
  150 mac_socket_peer_label_free(struct label *label)
  151 {
  152 
  153         MAC_PERFORM(destroy_socket_peer_label, label);
  154         mac_labelzone_free(label);
  155 }
  156 
  157 void
  158 mac_destroy_socket(struct socket *so)
  159 {
  160 
  161         mac_socket_label_free(so->so_label);
  162         so->so_label = NULL;
  163         mac_socket_peer_label_free(so->so_peerlabel);
  164         so->so_peerlabel = NULL;
  165 }
  166 
  167 void
  168 mac_copy_socket_label(struct label *src, struct label *dest)
  169 {
  170 
  171         MAC_PERFORM(copy_socket_label, src, dest);
  172 }
  173 
  174 int
  175 mac_externalize_socket_label(struct label *label, char *elements,
  176     char *outbuf, size_t outbuflen)
  177 {
  178         int error;
  179 
  180         MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
  181 
  182         return (error);
  183 }
  184 
  185 static int
  186 mac_externalize_socket_peer_label(struct label *label, char *elements,
  187     char *outbuf, size_t outbuflen)
  188 {
  189         int error;
  190 
  191         MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
  192 
  193         return (error);
  194 }
  195 
  196 int
  197 mac_internalize_socket_label(struct label *label, char *string)
  198 {
  199         int error;
  200 
  201         MAC_INTERNALIZE(socket, label, string);
  202 
  203         return (error);
  204 }
  205 
  206 void
  207 mac_create_socket(struct ucred *cred, struct socket *so)
  208 {
  209 
  210         MAC_PERFORM(create_socket, cred, so, so->so_label);
  211 }
  212 
  213 void
  214 mac_create_socket_from_socket(struct socket *oldso, struct socket *newso)
  215 {
  216 
  217         SOCK_LOCK_ASSERT(oldso);
  218 
  219         MAC_PERFORM(create_socket_from_socket, oldso, oldso->so_label, newso,
  220             newso->so_label);
  221 }
  222 
  223 static void
  224 mac_relabel_socket(struct ucred *cred, struct socket *so,
  225     struct label *newlabel)
  226 {
  227 
  228         SOCK_LOCK_ASSERT(so);
  229 
  230         MAC_PERFORM(relabel_socket, cred, so, so->so_label, newlabel);
  231 }
  232 
  233 void
  234 mac_set_socket_peer_from_mbuf(struct mbuf *m, struct socket *so)
  235 {
  236         struct label *label;
  237 
  238         SOCK_LOCK_ASSERT(so);
  239 
  240         label = mac_mbuf_to_label(m);
  241 
  242         MAC_PERFORM(set_socket_peer_from_mbuf, m, label, so,
  243             so->so_peerlabel);
  244 }
  245 
  246 void
  247 mac_set_socket_peer_from_socket(struct socket *oldso, struct socket *newso)
  248 {
  249 
  250         /*
  251          * XXXRW: only hold the socket lock on one at a time, as one socket
  252          * is the original, and one is the new.  However, it's called in both
  253          * directions, so we can't assert the lock here currently.
  254          */
  255         MAC_PERFORM(set_socket_peer_from_socket, oldso, oldso->so_label,
  256             newso, newso->so_peerlabel);
  257 }
  258 
  259 void
  260 mac_create_mbuf_from_socket(struct socket *so, struct mbuf *m)
  261 {
  262         struct label *label;
  263 
  264         SOCK_LOCK_ASSERT(so);
  265 
  266         label = mac_mbuf_to_label(m);
  267 
  268         MAC_PERFORM(create_mbuf_from_socket, so, so->so_label, m, label);
  269 }
  270 
  271 int
  272 mac_check_socket_accept(struct ucred *cred, struct socket *so)
  273 {
  274         int error;
  275 
  276         SOCK_LOCK_ASSERT(so);
  277 
  278         MAC_CHECK(check_socket_accept, cred, so, so->so_label);
  279 
  280         return (error);
  281 }
  282 
  283 int
  284 mac_check_socket_bind(struct ucred *ucred, struct socket *so,
  285     struct sockaddr *sa)
  286 {
  287         int error;
  288 
  289         SOCK_LOCK_ASSERT(so);
  290 
  291         MAC_CHECK(check_socket_bind, ucred, so, so->so_label, sa);
  292 
  293         return (error);
  294 }
  295 
  296 int
  297 mac_check_socket_connect(struct ucred *cred, struct socket *so,
  298     struct sockaddr *sa)
  299 {
  300         int error;
  301 
  302         SOCK_LOCK_ASSERT(so);
  303 
  304         MAC_CHECK(check_socket_connect, cred, so, so->so_label, sa);
  305 
  306         return (error);
  307 }
  308 
  309 int
  310 mac_check_socket_create(struct ucred *cred, int domain, int type, int proto)
  311 {
  312         int error;
  313 
  314         MAC_CHECK(check_socket_create, cred, domain, type, proto);
  315 
  316         return (error);
  317 }
  318 
  319 int
  320 mac_check_socket_deliver(struct socket *so, struct mbuf *m)
  321 {
  322         struct label *label;
  323         int error;
  324 
  325         SOCK_LOCK_ASSERT(so);
  326 
  327         label = mac_mbuf_to_label(m);
  328 
  329         MAC_CHECK(check_socket_deliver, so, so->so_label, m, label);
  330 
  331         return (error);
  332 }
  333 
  334 int
  335 mac_check_socket_listen(struct ucred *cred, struct socket *so)
  336 {
  337         int error;
  338 
  339         SOCK_LOCK_ASSERT(so);
  340 
  341         MAC_CHECK(check_socket_listen, cred, so, so->so_label);
  342 
  343         return (error);
  344 }
  345 
  346 int
  347 mac_check_socket_poll(struct ucred *cred, struct socket *so)
  348 {
  349         int error;
  350 
  351         SOCK_LOCK_ASSERT(so);
  352 
  353         MAC_CHECK(check_socket_poll, cred, so, so->so_label);
  354 
  355         return (error);
  356 }
  357 
  358 int
  359 mac_check_socket_receive(struct ucred *cred, struct socket *so)
  360 {
  361         int error;
  362 
  363         SOCK_LOCK_ASSERT(so);
  364 
  365         MAC_CHECK(check_socket_receive, cred, so, so->so_label);
  366 
  367         return (error);
  368 }
  369 
  370 static int
  371 mac_check_socket_relabel(struct ucred *cred, struct socket *so,
  372     struct label *newlabel)
  373 {
  374         int error;
  375 
  376         SOCK_LOCK_ASSERT(so);
  377 
  378         MAC_CHECK(check_socket_relabel, cred, so, so->so_label, newlabel);
  379 
  380         return (error);
  381 }
  382 
  383 int
  384 mac_check_socket_send(struct ucred *cred, struct socket *so)
  385 {
  386         int error;
  387 
  388         SOCK_LOCK_ASSERT(so);
  389 
  390         MAC_CHECK(check_socket_send, cred, so, so->so_label);
  391 
  392         return (error);
  393 }
  394 
  395 int
  396 mac_check_socket_stat(struct ucred *cred, struct socket *so)
  397 {
  398         int error;
  399 
  400         SOCK_LOCK_ASSERT(so);
  401 
  402         MAC_CHECK(check_socket_stat, cred, so, so->so_label);
  403 
  404         return (error);
  405 }
  406 
  407 int
  408 mac_check_socket_visible(struct ucred *cred, struct socket *so)
  409 {
  410         int error;
  411 
  412         SOCK_LOCK_ASSERT(so);
  413 
  414         MAC_CHECK(check_socket_visible, cred, so, so->so_label);
  415 
  416         return (error);
  417 }
  418 
  419 int
  420 mac_socket_label_set(struct ucred *cred, struct socket *so,
  421     struct label *label)
  422 {
  423         int error;
  424 
  425         /*
  426          * We acquire the socket lock when we perform the test and set, but
  427          * have to release it as the pcb code needs to acquire the pcb lock,
  428          * which will precede the socket lock in the lock order.  However,
  429          * this is fine, as any race will simply result in the inpcb being
  430          * refreshed twice, but still consistently, as the inpcb code will
  431          * acquire the socket lock before refreshing, holding both locks.
  432          */
  433         SOCK_LOCK(so);
  434         error = mac_check_socket_relabel(cred, so, label);
  435         if (error) {
  436                 SOCK_UNLOCK(so);
  437                 return (error);
  438         }
  439 
  440         mac_relabel_socket(cred, so, label);
  441         SOCK_UNLOCK(so);
  442 
  443         /*
  444          * If the protocol has expressed interest in socket layer changes,
  445          * such as if it needs to propagate changes to a cached pcb label
  446          * from the socket, notify it of the label change while holding the
  447          * socket lock.
  448          */
  449         if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL)
  450                 (so->so_proto->pr_usrreqs->pru_sosetlabel)(so);
  451 
  452         return (0);
  453 }
  454 
  455 int
  456 mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
  457 {
  458         struct label *intlabel;
  459         char *buffer;
  460         int error;
  461 
  462         error = mac_check_structmac_consistent(mac);
  463         if (error)
  464                 return (error);
  465 
  466         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  467         error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
  468         if (error) {
  469                 free(buffer, M_MACTEMP);
  470                 return (error);
  471         }
  472 
  473         intlabel = mac_socket_label_alloc(M_WAITOK);
  474         error = mac_internalize_socket_label(intlabel, buffer);
  475         free(buffer, M_MACTEMP);
  476         if (error)
  477                 goto out;
  478 
  479         error = mac_socket_label_set(cred, so, intlabel);
  480 out:
  481         mac_socket_label_free(intlabel);
  482         return (error);
  483 }
  484 
  485 int
  486 mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
  487 {
  488         char *buffer, *elements;
  489         struct label *intlabel;
  490         int error;
  491 
  492         error = mac_check_structmac_consistent(mac);
  493         if (error)
  494                 return (error);
  495 
  496         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  497         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
  498         if (error) {
  499                 free(elements, M_MACTEMP);
  500                 return (error);
  501         }
  502 
  503         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  504         intlabel = mac_socket_label_alloc(M_WAITOK);
  505         SOCK_LOCK(so);
  506         mac_copy_socket_label(so->so_label, intlabel);
  507         SOCK_UNLOCK(so);
  508         error = mac_externalize_socket_label(intlabel, elements, buffer,
  509             mac->m_buflen);
  510         mac_socket_label_free(intlabel);
  511         if (error == 0)
  512                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
  513 
  514         free(buffer, M_MACTEMP);
  515         free(elements, M_MACTEMP);
  516 
  517         return (error);
  518 }
  519 
  520 int
  521 mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
  522     struct mac *mac)
  523 {
  524         char *elements, *buffer;
  525         struct label *intlabel;
  526         int error;
  527 
  528         error = mac_check_structmac_consistent(mac);
  529         if (error)
  530                 return (error);
  531 
  532         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  533         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
  534         if (error) {
  535                 free(elements, M_MACTEMP);
  536                 return (error);
  537         }
  538 
  539         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  540         intlabel = mac_socket_label_alloc(M_WAITOK);
  541         SOCK_LOCK(so);
  542         mac_copy_socket_label(so->so_peerlabel, intlabel);
  543         SOCK_UNLOCK(so);
  544         error = mac_externalize_socket_peer_label(intlabel, elements, buffer,
  545             mac->m_buflen);
  546         mac_socket_label_free(intlabel);
  547         if (error == 0)
  548                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
  549 
  550         free(buffer, M_MACTEMP);
  551         free(elements, M_MACTEMP);
  552 
  553         return (error);
  554 }

Cache object: d03c4ec6acb9ea4debb3f0a02565ea3e


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