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 <sys/mac_policy.h>
   63 
   64 #include <net/bpfdesc.h>
   65 #include <net/if.h>
   66 #include <net/if_var.h>
   67 
   68 #include <netinet/in.h>
   69 #include <netinet/in_pcb.h>
   70 #include <netinet/ip_var.h>
   71 
   72 #include <security/mac/mac_internal.h>
   73 
   74 /*
   75  * mac_enforce_socket is used by the inet code when delivering to an inpcb
   76  * without hitting the socket layer, and has to be non-static for now.
   77  */
   78 int     mac_enforce_socket = 1;
   79 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
   80     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
   81 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
   82 
   83 #ifdef MAC_DEBUG
   84 static unsigned int nmacsockets;
   85 
   86 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
   87     &nmacsockets, 0, "number of sockets in use");
   88 #endif
   89 
   90 struct label *
   91 mac_socket_label_alloc(int flag)
   92 {
   93         struct label *label;
   94         int error;
   95 
   96         label = mac_labelzone_alloc(flag);
   97         if (label == NULL)
   98                 return (NULL);
   99 
  100         MAC_CHECK(init_socket_label, label, flag);
  101         if (error) {
  102                 MAC_PERFORM(destroy_socket_label, label);
  103                 mac_labelzone_free(label);
  104                 return (NULL);
  105         }
  106         MAC_DEBUG_COUNTER_INC(&nmacsockets);
  107         return (label);
  108 }
  109 
  110 static struct label *
  111 mac_socket_peer_label_alloc(int flag)
  112 {
  113         struct label *label;
  114         int error;
  115 
  116         label = mac_labelzone_alloc(flag);
  117         if (label == NULL)
  118                 return (NULL);
  119 
  120         MAC_CHECK(init_socket_peer_label, label, flag);
  121         if (error) {
  122                 MAC_PERFORM(destroy_socket_peer_label, label);
  123                 mac_labelzone_free(label);
  124                 return (NULL);
  125         }
  126         MAC_DEBUG_COUNTER_INC(&nmacsockets);
  127         return (label);
  128 }
  129 
  130 int
  131 mac_init_socket(struct socket *so, int flag)
  132 {
  133 
  134         so->so_label = mac_socket_label_alloc(flag);
  135         if (so->so_label == NULL)
  136                 return (ENOMEM);
  137         so->so_peerlabel = mac_socket_peer_label_alloc(flag);
  138         if (so->so_peerlabel == NULL) {
  139                 mac_socket_label_free(so->so_label);
  140                 so->so_label = NULL;
  141                 return (ENOMEM);
  142         }
  143         return (0);
  144 }
  145 
  146 void
  147 mac_socket_label_free(struct label *label)
  148 {
  149 
  150         MAC_PERFORM(destroy_socket_label, label);
  151         mac_labelzone_free(label);
  152         MAC_DEBUG_COUNTER_DEC(&nmacsockets);
  153 }
  154 
  155 static void
  156 mac_socket_peer_label_free(struct label *label)
  157 {
  158 
  159         MAC_PERFORM(destroy_socket_peer_label, label);
  160         mac_labelzone_free(label);
  161         MAC_DEBUG_COUNTER_DEC(&nmacsockets);
  162 }
  163 
  164 void
  165 mac_destroy_socket(struct socket *socket)
  166 {
  167 
  168         mac_socket_label_free(socket->so_label);
  169         socket->so_label = NULL;
  170         mac_socket_peer_label_free(socket->so_peerlabel);
  171         socket->so_peerlabel = NULL;
  172 }
  173 
  174 void
  175 mac_copy_socket_label(struct label *src, struct label *dest)
  176 {
  177 
  178         MAC_PERFORM(copy_socket_label, src, dest);
  179 }
  180 
  181 int
  182 mac_externalize_socket_label(struct label *label, char *elements,
  183     char *outbuf, size_t outbuflen)
  184 {
  185         int error;
  186 
  187         MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
  188 
  189         return (error);
  190 }
  191 
  192 static int
  193 mac_externalize_socket_peer_label(struct label *label, char *elements,
  194     char *outbuf, size_t outbuflen)
  195 {
  196         int error;
  197 
  198         MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
  199 
  200         return (error);
  201 }
  202 
  203 int
  204 mac_internalize_socket_label(struct label *label, char *string)
  205 {
  206         int error;
  207 
  208         MAC_INTERNALIZE(socket, label, string);
  209 
  210         return (error);
  211 }
  212 
  213 void
  214 mac_create_socket(struct ucred *cred, struct socket *socket)
  215 {
  216 
  217         MAC_PERFORM(create_socket, cred, socket, socket->so_label);
  218 }
  219 
  220 void
  221 mac_create_socket_from_socket(struct socket *oldsocket,
  222     struct socket *newsocket)
  223 {
  224 
  225         SOCK_LOCK_ASSERT(oldsocket);
  226         MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label,
  227             newsocket, newsocket->so_label);
  228 }
  229 
  230 static void
  231 mac_relabel_socket(struct ucred *cred, struct socket *socket,
  232     struct label *newlabel)
  233 {
  234 
  235         SOCK_LOCK_ASSERT(socket);
  236         MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel);
  237 }
  238 
  239 void
  240 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
  241 {
  242         struct label *label;
  243 
  244         SOCK_LOCK_ASSERT(socket);
  245 
  246         label = mac_mbuf_to_label(mbuf);
  247 
  248         MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
  249             socket->so_peerlabel);
  250 }
  251 
  252 void
  253 mac_set_socket_peer_from_socket(struct socket *oldsocket,
  254     struct socket *newsocket)
  255 {
  256 
  257         /*
  258          * XXXRW: only hold the socket lock on one at a time, as one
  259          * socket is the original, and one is the new.  However, it's
  260          * called in both directions, so we can't assert the lock
  261          * here currently.
  262          */
  263         MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
  264             oldsocket->so_label, newsocket, newsocket->so_peerlabel);
  265 }
  266 
  267 void
  268 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
  269 {
  270         struct label *label;
  271 
  272         label = mac_mbuf_to_label(mbuf);
  273 
  274         SOCK_LOCK_ASSERT(socket);
  275         MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf,
  276             label);
  277 }
  278 
  279 int
  280 mac_check_socket_accept(struct ucred *cred, struct socket *socket)
  281 {
  282         int error;
  283 
  284         SOCK_LOCK_ASSERT(socket);
  285 
  286         if (!mac_enforce_socket)
  287                 return (0);
  288 
  289         MAC_CHECK(check_socket_accept, cred, socket, socket->so_label);
  290 
  291         return (error);
  292 }
  293 
  294 int
  295 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
  296     struct sockaddr *sockaddr)
  297 {
  298         int error;
  299 
  300         SOCK_LOCK_ASSERT(socket);
  301 
  302         if (!mac_enforce_socket)
  303                 return (0);
  304 
  305         MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label,
  306             sockaddr);
  307 
  308         return (error);
  309 }
  310 
  311 int
  312 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
  313     struct sockaddr *sockaddr)
  314 {
  315         int error;
  316 
  317         SOCK_LOCK_ASSERT(socket);
  318 
  319         if (!mac_enforce_socket)
  320                 return (0);
  321 
  322         MAC_CHECK(check_socket_connect, cred, socket, socket->so_label,
  323             sockaddr);
  324 
  325         return (error);
  326 }
  327 
  328 int
  329 mac_check_socket_create(struct ucred *cred, int domain, int type,
  330     int protocol)
  331 {
  332         int error;
  333 
  334         if (!mac_enforce_socket)
  335                 return (0);
  336 
  337         MAC_CHECK(check_socket_create, cred, domain, type, protocol);
  338 
  339         return (error);
  340 }
  341 
  342 int
  343 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
  344 {
  345         struct label *label;
  346         int error;
  347 
  348         SOCK_LOCK_ASSERT(socket);
  349 
  350         if (!mac_enforce_socket)
  351                 return (0);
  352 
  353         label = mac_mbuf_to_label(mbuf);
  354 
  355         MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf,
  356             label);
  357 
  358         return (error);
  359 }
  360 
  361 int
  362 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
  363 {
  364         int error;
  365 
  366         SOCK_LOCK_ASSERT(socket);
  367 
  368         if (!mac_enforce_socket)
  369                 return (0);
  370 
  371         MAC_CHECK(check_socket_listen, cred, socket, socket->so_label);
  372         return (error);
  373 }
  374 
  375 int
  376 mac_check_socket_poll(struct ucred *cred, struct socket *so)
  377 {
  378         int error;
  379 
  380         SOCK_LOCK_ASSERT(so);
  381 
  382         if (!mac_enforce_socket)
  383                 return (0);
  384 
  385         MAC_CHECK(check_socket_poll, cred, so, so->so_label);
  386         return (error);
  387 }
  388 
  389 int
  390 mac_check_socket_receive(struct ucred *cred, struct socket *so)
  391 {
  392         int error;
  393 
  394         SOCK_LOCK_ASSERT(so);
  395 
  396         if (!mac_enforce_socket)
  397                 return (0);
  398 
  399         MAC_CHECK(check_socket_receive, cred, so, so->so_label);
  400 
  401         return (error);
  402 }
  403 
  404 static int
  405 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
  406     struct label *newlabel)
  407 {
  408         int error;
  409 
  410         SOCK_LOCK_ASSERT(socket);
  411 
  412         MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label,
  413             newlabel);
  414 
  415         return (error);
  416 }
  417 
  418 int
  419 mac_check_socket_send(struct ucred *cred, struct socket *so)
  420 {
  421         int error;
  422 
  423         SOCK_LOCK_ASSERT(so);
  424 
  425         if (!mac_enforce_socket)
  426                 return (0);
  427 
  428         MAC_CHECK(check_socket_send, cred, so, so->so_label);
  429 
  430         return (error);
  431 }
  432 
  433 int
  434 mac_check_socket_stat(struct ucred *cred, struct socket *so)
  435 {
  436         int error;
  437 
  438         SOCK_LOCK_ASSERT(so);
  439 
  440         if (!mac_enforce_socket)
  441                 return (0);
  442 
  443         MAC_CHECK(check_socket_stat, cred, so, so->so_label);
  444 
  445         return (error);
  446 }
  447 
  448 int
  449 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
  450 {
  451         int error;
  452 
  453         SOCK_LOCK_ASSERT(socket);
  454 
  455         if (!mac_enforce_socket)
  456                 return (0);
  457 
  458         MAC_CHECK(check_socket_visible, cred, socket, socket->so_label);
  459 
  460         return (error);
  461 }
  462 
  463 int
  464 mac_socket_label_set(struct ucred *cred, struct socket *so,
  465     struct label *label)
  466 {
  467         int error;
  468 
  469         /*
  470          * We acquire the socket lock when we perform the test and set,
  471          * but have to release it as the pcb code needs to acquire the
  472          * pcb lock, which will precede the socket lock in the lock
  473          * order.  However, this is fine, as any race will simply
  474          * result in the inpcb being refreshed twice, but still
  475          * consistently, as the inpcb code will acquire the socket lock
  476          * before refreshing, holding both locks.
  477          */
  478         SOCK_LOCK(so);
  479         error = mac_check_socket_relabel(cred, so, label);
  480         if (error) {
  481                 SOCK_UNLOCK(so);
  482                 return (error);
  483         }
  484 
  485         mac_relabel_socket(cred, so, label);
  486         SOCK_UNLOCK(so);
  487         /*
  488          * If the protocol has expressed interest in socket layer changes,
  489          * such as if it needs to propagate changes to a cached pcb
  490          * label from the socket, notify it of the label change while
  491          * holding the socket lock.
  492          */
  493         if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL)
  494                 (so->so_proto->pr_usrreqs->pru_sosetlabel)(so);
  495 
  496         return (0);
  497 }
  498 
  499 int
  500 mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
  501 {
  502         struct label *intlabel;
  503         char *buffer;
  504         int error;
  505 
  506         error = mac_check_structmac_consistent(mac);
  507         if (error)
  508                 return (error);
  509 
  510         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  511         error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
  512         if (error) {
  513                 free(buffer, M_MACTEMP);
  514                 return (error);
  515         }
  516 
  517         intlabel = mac_socket_label_alloc(M_WAITOK);
  518         error = mac_internalize_socket_label(intlabel, buffer);
  519         free(buffer, M_MACTEMP);
  520         if (error)
  521                 goto out;
  522 
  523         error = mac_socket_label_set(cred, so, intlabel);
  524 out:
  525         mac_socket_label_free(intlabel);
  526         return (error);
  527 }
  528 
  529 int
  530 mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
  531 {
  532         char *buffer, *elements;
  533         struct label *intlabel;
  534         int error;
  535 
  536         error = mac_check_structmac_consistent(mac);
  537         if (error)
  538                 return (error);
  539 
  540         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  541         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
  542         if (error) {
  543                 free(elements, M_MACTEMP);
  544                 return (error);
  545         }
  546 
  547         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  548         intlabel = mac_socket_label_alloc(M_WAITOK);
  549         SOCK_LOCK(so);
  550         mac_copy_socket_label(so->so_label, intlabel);
  551         SOCK_UNLOCK(so);
  552         error = mac_externalize_socket_label(intlabel, elements, buffer,
  553             mac->m_buflen);
  554         mac_socket_label_free(intlabel);
  555         if (error == 0)
  556                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
  557 
  558         free(buffer, M_MACTEMP);
  559         free(elements, M_MACTEMP);
  560 
  561         return (error);
  562 }
  563 
  564 int
  565 mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
  566     struct mac *mac)
  567 {
  568         char *elements, *buffer;
  569         struct label *intlabel;
  570         int error;
  571 
  572         error = mac_check_structmac_consistent(mac);
  573         if (error)
  574                 return (error);
  575 
  576         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  577         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
  578         if (error) {
  579                 free(elements, M_MACTEMP);
  580                 return (error);
  581         }
  582 
  583         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  584         intlabel = mac_socket_label_alloc(M_WAITOK);
  585         SOCK_LOCK(so);
  586         mac_copy_socket_label(so->so_peerlabel, intlabel);
  587         SOCK_UNLOCK(so);
  588         error = mac_externalize_socket_peer_label(intlabel, elements, buffer,
  589             mac->m_buflen);
  590         mac_socket_label_free(intlabel);
  591         if (error == 0)
  592                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
  593 
  594         free(buffer, M_MACTEMP);
  595         free(elements, M_MACTEMP);
  596 
  597         return (error);
  598 }

Cache object: ae19f66e7750b731acb05c89411693fd


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