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-2004 Networks Associates Technology, Inc.
    5  * All rights reserved.
    6  *
    7  * This software was developed by Robert Watson and Ilmar Habibulin for the
    8  * TrustedBSD Project.
    9  *
   10  * This software was developed for the FreeBSD Project in part by Network
   11  * Associates Laboratories, the Security Research Division of Network
   12  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
   13  * as part of the DARPA CHATS research program.
   14  *
   15  * Redistribution and use in source and binary forms, with or without
   16  * modification, are permitted provided that the following conditions
   17  * are met:
   18  * 1. Redistributions of source code must retain the above copyright
   19  *    notice, this list of conditions and the following disclaimer.
   20  * 2. Redistributions in binary form must reproduce the above copyright
   21  *    notice, this list of conditions and the following disclaimer in the
   22  *    documentation and/or other materials provided with the distribution.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/5.4/sys/security/mac/mac_socket.c 130398 2004-06-13 02:50:07Z rwatson $");
   39 
   40 #include "opt_mac.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mutex.h>
   47 #include <sys/mac.h>
   48 #include <sys/sbuf.h>
   49 #include <sys/systm.h>
   50 #include <sys/mount.h>
   51 #include <sys/file.h>
   52 #include <sys/namei.h>
   53 #include <sys/protosw.h>
   54 #include <sys/socket.h>
   55 #include <sys/socketvar.h>
   56 #include <sys/sysctl.h>
   57 
   58 #include <sys/mac_policy.h>
   59 
   60 #include <net/bpfdesc.h>
   61 #include <net/if.h>
   62 #include <net/if_var.h>
   63 
   64 #include <netinet/in.h>
   65 #include <netinet/in_pcb.h>
   66 #include <netinet/ip_var.h>
   67 
   68 #include <security/mac/mac_internal.h>
   69 
   70 /*
   71  * mac_enforce_socket is used by the inet code when delivering to an inpcb
   72  * without hitting the socket layer, and has to be non-static for now.
   73  */
   74 int     mac_enforce_socket = 1;
   75 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
   76     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
   77 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
   78 
   79 #ifdef MAC_DEBUG
   80 static unsigned int nmacsockets;
   81 
   82 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
   83     &nmacsockets, 0, "number of sockets in use");
   84 #endif
   85 
   86 struct label *
   87 mac_socket_label_alloc(int flag)
   88 {
   89         struct label *label;
   90         int error;
   91 
   92         label = mac_labelzone_alloc(flag);
   93         if (label == NULL)
   94                 return (NULL);
   95 
   96         MAC_CHECK(init_socket_label, label, flag);
   97         if (error) {
   98                 MAC_PERFORM(destroy_socket_label, label);
   99                 mac_labelzone_free(label);
  100                 return (NULL);
  101         }
  102         MAC_DEBUG_COUNTER_INC(&nmacsockets);
  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         MAC_DEBUG_COUNTER_INC(&nmacsockets);
  123         return (label);
  124 }
  125 
  126 int
  127 mac_init_socket(struct socket *so, int flag)
  128 {
  129 
  130         so->so_label = mac_socket_label_alloc(flag);
  131         if (so->so_label == NULL)
  132                 return (ENOMEM);
  133         so->so_peerlabel = mac_socket_peer_label_alloc(flag);
  134         if (so->so_peerlabel == NULL) {
  135                 mac_socket_label_free(so->so_label);
  136                 so->so_label = NULL;
  137                 return (ENOMEM);
  138         }
  139         return (0);
  140 }
  141 
  142 void
  143 mac_socket_label_free(struct label *label)
  144 {
  145 
  146         MAC_PERFORM(destroy_socket_label, label);
  147         mac_labelzone_free(label);
  148         MAC_DEBUG_COUNTER_DEC(&nmacsockets);
  149 }
  150 
  151 static void
  152 mac_socket_peer_label_free(struct label *label)
  153 {
  154 
  155         MAC_PERFORM(destroy_socket_peer_label, label);
  156         mac_labelzone_free(label);
  157         MAC_DEBUG_COUNTER_DEC(&nmacsockets);
  158 }
  159 
  160 void
  161 mac_destroy_socket(struct socket *socket)
  162 {
  163 
  164         mac_socket_label_free(socket->so_label);
  165         socket->so_label = NULL;
  166         mac_socket_peer_label_free(socket->so_peerlabel);
  167         socket->so_peerlabel = NULL;
  168 }
  169 
  170 void
  171 mac_copy_socket_label(struct label *src, struct label *dest)
  172 {
  173 
  174         MAC_PERFORM(copy_socket_label, src, dest);
  175 }
  176 
  177 int
  178 mac_externalize_socket_label(struct label *label, char *elements,
  179     char *outbuf, size_t outbuflen)
  180 {
  181         int error;
  182 
  183         MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
  184 
  185         return (error);
  186 }
  187 
  188 static int
  189 mac_externalize_socket_peer_label(struct label *label, char *elements,
  190     char *outbuf, size_t outbuflen)
  191 {
  192         int error;
  193 
  194         MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
  195 
  196         return (error);
  197 }
  198 
  199 int
  200 mac_internalize_socket_label(struct label *label, char *string)
  201 {
  202         int error;
  203 
  204         MAC_INTERNALIZE(socket, label, string);
  205 
  206         return (error);
  207 }
  208 
  209 void
  210 mac_create_socket(struct ucred *cred, struct socket *socket)
  211 {
  212 
  213         MAC_PERFORM(create_socket, cred, socket, socket->so_label);
  214 }
  215 
  216 void
  217 mac_create_socket_from_socket(struct socket *oldsocket,
  218     struct socket *newsocket)
  219 {
  220 
  221         SOCK_LOCK_ASSERT(oldsocket);
  222         MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label,
  223             newsocket, newsocket->so_label);
  224 }
  225 
  226 static void
  227 mac_relabel_socket(struct ucred *cred, struct socket *socket,
  228     struct label *newlabel)
  229 {
  230 
  231         SOCK_LOCK_ASSERT(socket);
  232         MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel);
  233 }
  234 
  235 void
  236 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
  237 {
  238         struct label *label;
  239 
  240         SOCK_LOCK_ASSERT(socket);
  241 
  242         label = mac_mbuf_to_label(mbuf);
  243 
  244         MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
  245             socket->so_peerlabel);
  246 }
  247 
  248 void
  249 mac_set_socket_peer_from_socket(struct socket *oldsocket,
  250     struct socket *newsocket)
  251 {
  252 
  253         /*
  254          * XXXRW: only hold the socket lock on one at a time, as one
  255          * socket is the original, and one is the new.  However, it's
  256          * called in both directions, so we can't assert the lock
  257          * here currently.
  258          */
  259         MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
  260             oldsocket->so_label, newsocket, newsocket->so_peerlabel);
  261 }
  262 
  263 void
  264 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
  265 {
  266         struct label *label;
  267 
  268         label = mac_mbuf_to_label(mbuf);
  269 
  270         SOCK_LOCK_ASSERT(socket);
  271         MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf,
  272             label);
  273 }
  274 
  275 int
  276 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
  277     struct sockaddr *sockaddr)
  278 {
  279         int error;
  280 
  281         SOCK_LOCK_ASSERT(socket);
  282 
  283         if (!mac_enforce_socket)
  284                 return (0);
  285 
  286         MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label,
  287             sockaddr);
  288 
  289         return (error);
  290 }
  291 
  292 int
  293 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
  294     struct sockaddr *sockaddr)
  295 {
  296         int error;
  297 
  298         SOCK_LOCK_ASSERT(socket);
  299 
  300         if (!mac_enforce_socket)
  301                 return (0);
  302 
  303         MAC_CHECK(check_socket_connect, cred, socket, socket->so_label,
  304             sockaddr);
  305 
  306         return (error);
  307 }
  308 
  309 int
  310 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
  311 {
  312         struct label *label;
  313         int error;
  314 
  315         SOCK_LOCK_ASSERT(socket);
  316 
  317         if (!mac_enforce_socket)
  318                 return (0);
  319 
  320         label = mac_mbuf_to_label(mbuf);
  321 
  322         MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf,
  323             label);
  324 
  325         return (error);
  326 }
  327 
  328 int
  329 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
  330 {
  331         int error;
  332 
  333         SOCK_LOCK_ASSERT(socket);
  334 
  335         if (!mac_enforce_socket)
  336                 return (0);
  337 
  338         MAC_CHECK(check_socket_listen, cred, socket, socket->so_label);
  339         return (error);
  340 }
  341 
  342 int
  343 mac_check_socket_receive(struct ucred *cred, struct socket *so)
  344 {
  345         int error;
  346 
  347         SOCK_LOCK_ASSERT(so);
  348 
  349         if (!mac_enforce_socket)
  350                 return (0);
  351 
  352         MAC_CHECK(check_socket_receive, cred, so, so->so_label);
  353 
  354         return (error);
  355 }
  356 
  357 static int
  358 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
  359     struct label *newlabel)
  360 {
  361         int error;
  362 
  363         SOCK_LOCK_ASSERT(socket);
  364 
  365         MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label,
  366             newlabel);
  367 
  368         return (error);
  369 }
  370 
  371 int
  372 mac_check_socket_send(struct ucred *cred, struct socket *so)
  373 {
  374         int error;
  375 
  376         SOCK_LOCK_ASSERT(so);
  377 
  378         if (!mac_enforce_socket)
  379                 return (0);
  380 
  381         MAC_CHECK(check_socket_send, cred, so, so->so_label);
  382 
  383         return (error);
  384 }
  385 
  386 int
  387 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
  388 {
  389         int error;
  390 
  391         SOCK_LOCK_ASSERT(socket);
  392 
  393         if (!mac_enforce_socket)
  394                 return (0);
  395 
  396         MAC_CHECK(check_socket_visible, cred, socket, socket->so_label);
  397 
  398         return (error);
  399 }
  400 
  401 int
  402 mac_socket_label_set(struct ucred *cred, struct socket *so,
  403     struct label *label)
  404 {
  405         int error;
  406 
  407         /*
  408          * We acquire the socket lock when we perform the test and set,
  409          * but have to release it as the pcb code needs to acquire the
  410          * pcb lock, which will precede the socket lock in the lock
  411          * order.  However, this is fine, as any race will simply
  412          * result in the inpcb being refreshed twice, but still
  413          * consistently, as the inpcb code will acquire the socket lock
  414          * before refreshing, holding both locks.
  415          */
  416         SOCK_LOCK(so);
  417         error = mac_check_socket_relabel(cred, so, label);
  418         if (error) {
  419                 SOCK_UNLOCK(so);
  420                 return (error);
  421         }
  422 
  423         mac_relabel_socket(cred, so, label);
  424         SOCK_UNLOCK(so);
  425         /*
  426          * If the protocol has expressed interest in socket layer changes,
  427          * such as if it needs to propagate changes to a cached pcb
  428          * label from the socket, notify it of the label change while
  429          * holding the socket lock.
  430          */
  431         if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL)
  432                 (so->so_proto->pr_usrreqs->pru_sosetlabel)(so);
  433 
  434         return (0);
  435 }
  436 
  437 int
  438 mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
  439 {
  440         struct label *intlabel;
  441         char *buffer;
  442         int error;
  443 
  444         error = mac_check_structmac_consistent(mac);
  445         if (error)
  446                 return (error);
  447 
  448         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  449         error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
  450         if (error) {
  451                 free(buffer, M_MACTEMP);
  452                 return (error);
  453         }
  454 
  455         intlabel = mac_socket_label_alloc(M_WAITOK);
  456         error = mac_internalize_socket_label(intlabel, buffer);
  457         free(buffer, M_MACTEMP);
  458         if (error)
  459                 goto out;
  460 
  461         error = mac_socket_label_set(cred, so, intlabel);
  462 out:
  463         mac_socket_label_free(intlabel);
  464         return (error);
  465 }
  466 
  467 int
  468 mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
  469 {
  470         char *buffer, *elements;
  471         struct label *intlabel;
  472         int error;
  473 
  474         error = mac_check_structmac_consistent(mac);
  475         if (error)
  476                 return (error);
  477 
  478         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  479         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
  480         if (error) {
  481                 free(elements, M_MACTEMP);
  482                 return (error);
  483         }
  484 
  485         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  486         intlabel = mac_socket_label_alloc(M_WAITOK);
  487         SOCK_LOCK(so);
  488         mac_copy_socket_label(so->so_label, intlabel);
  489         SOCK_UNLOCK(so);
  490         error = mac_externalize_socket_label(intlabel, elements, buffer,
  491             mac->m_buflen);
  492         mac_socket_label_free(intlabel);
  493         if (error == 0)
  494                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
  495 
  496         free(buffer, M_MACTEMP);
  497         free(elements, M_MACTEMP);
  498 
  499         return (error);
  500 }
  501 
  502 int
  503 mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
  504     struct mac *mac)
  505 {
  506         char *elements, *buffer;
  507         struct label *intlabel;
  508         int error;
  509 
  510         error = mac_check_structmac_consistent(mac);
  511         if (error)
  512                 return (error);
  513 
  514         elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
  515         error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
  516         if (error) {
  517                 free(elements, M_MACTEMP);
  518                 return (error);
  519         }
  520 
  521         buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  522         intlabel = mac_socket_label_alloc(M_WAITOK);
  523         SOCK_LOCK(so);
  524         mac_copy_socket_label(so->so_peerlabel, intlabel);
  525         SOCK_UNLOCK(so);
  526         error = mac_externalize_socket_peer_label(intlabel, elements, buffer,
  527             mac->m_buflen);
  528         mac_socket_label_free(intlabel);
  529         if (error == 0)
  530                 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
  531 
  532         free(buffer, M_MACTEMP);
  533         free(elements, M_MACTEMP);
  534 
  535         return (error);
  536 }

Cache object: 0057631ea6f48750e6212c46b4d66e38


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