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_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) 2007 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*-
   29  * Copyright (c) 1999-2002 Robert N. M. Watson
   30  * Copyright (c) 2001 Ilmar S. Habibulin
   31  * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
   32  * Copyright (c) 2005 SPARTA, Inc.
   33  * All rights reserved.
   34  *
   35  * This software was developed by Robert Watson and Ilmar Habibulin for the
   36  * TrustedBSD Project.
   37  *
   38  * This software was developed for the FreeBSD Project in part by McAfee
   39  * Research, the Technology Research Division of Network Associates, Inc.
   40  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
   41  * DARPA CHATS research program.
   42  * 
   43  * This software was enhanced by SPARTA ISSO under SPAWAR contract
   44  * N66001-04-C-6019 ("SEFOS").
   45  *
   46  * Redistribution and use in source and binary forms, with or without
   47  * modification, are permitted provided that the following conditions
   48  * are met:
   49  * 1. Redistributions of source code must retain the above copyright
   50  *    notice, this list of conditions and the following disclaimer.
   51  * 2. Redistributions in binary form must reproduce the above copyright
   52  *    notice, this list of conditions and the following disclaimer in the
   53  *    documentation and/or other materials provided with the distribution.
   54  *
   55  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   56  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   58  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   59  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   60  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   61  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   63  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   64  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   65  * SUCH DAMAGE.
   66  */
   67 
   68 #include <sys/cdefs.h>
   69 
   70 #include <sys/param.h>
   71 #include <sys/kernel.h>
   72 #include <sys/lock.h>
   73 #include <sys/malloc.h>
   74 #include <sys/sbuf.h>
   75 #include <sys/systm.h>
   76 #include <sys/mount.h>
   77 #include <sys/file.h>
   78 #include <sys/namei.h>
   79 #include <sys/protosw.h>
   80 #include <sys/socket.h>
   81 #include <sys/socketvar.h>
   82 #include <sys/sysctl.h>
   83 #include <sys/kpi_socket.h>
   84 
   85 #include <net/if.h>
   86 #include <net/if_var.h>
   87 
   88 #include <netinet/in.h>
   89 #include <netinet/ip_var.h>
   90 
   91 #include <security/mac_internal.h>
   92 
   93 #if CONFIG_MACF_SOCKET
   94 struct label *
   95 mac_socket_label_alloc(int flag)
   96 {
   97         struct label *label;
   98         int error;
   99 
  100         label = mac_labelzone_alloc(flag);
  101         if (label == NULL)
  102                 return (NULL);
  103 
  104         MAC_CHECK(socket_label_init, label, flag);
  105         if (error) {
  106                 MAC_PERFORM(socket_label_destroy, label);
  107                 mac_labelzone_free(label);
  108                 return (NULL);
  109         }
  110 
  111         return (label);
  112 }
  113 
  114 static struct label *
  115 mac_socket_peer_label_alloc(int flag)
  116 {
  117         struct label *label;
  118         int error;
  119 
  120         label = mac_labelzone_alloc(flag);
  121         if (label == NULL)
  122                 return (NULL);
  123 
  124         MAC_CHECK(socketpeer_label_init, label, flag);
  125         if (error) {
  126                 MAC_PERFORM(socketpeer_label_destroy, label);
  127                 mac_labelzone_free(label);
  128                 return (NULL);
  129         }
  130 
  131         return (label);
  132 }
  133 
  134 int
  135 mac_socket_label_init(struct socket *so, int flag)
  136 {
  137 
  138         so->so_label = mac_socket_label_alloc(flag);
  139         if (so->so_label == NULL)
  140                 return (ENOMEM);
  141         so->so_peerlabel = mac_socket_peer_label_alloc(flag);
  142         if (so->so_peerlabel == NULL) {
  143                 mac_socket_label_free(so->so_label);
  144                 so->so_label = NULL;
  145                 return (ENOMEM);
  146         }
  147         return (0);
  148 }
  149 
  150 void
  151 mac_socket_label_free(struct label *label)
  152 {
  153 
  154         MAC_PERFORM(socket_label_destroy, label);
  155         mac_labelzone_free(label);
  156 }
  157 
  158 static void
  159 mac_socket_peer_label_free(struct label *label)
  160 {
  161 
  162         MAC_PERFORM(socketpeer_label_destroy, label);
  163         mac_labelzone_free(label);
  164 }
  165 
  166 void
  167 mac_socket_label_destroy(struct socket *so)
  168 {
  169 
  170         if (so->so_label != NULL) {
  171                 mac_socket_label_free(so->so_label);
  172                 so->so_label = NULL;
  173         }
  174         if (so->so_peerlabel != NULL) {
  175                 mac_socket_peer_label_free(so->so_peerlabel);
  176                 so->so_peerlabel = NULL;
  177         }
  178 }
  179 
  180 void
  181 mac_socket_label_copy(struct label *src, struct label *dest)
  182 {
  183 
  184         MAC_PERFORM(socket_label_copy, src, dest);
  185 }
  186 
  187 int
  188 mac_socket_label_externalize(struct label *label, char *elements,
  189     char *outbuf, size_t outbuflen)
  190 {
  191         int error;
  192 
  193         error = MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
  194 
  195         return (error);
  196 }
  197 
  198 static int
  199 mac_socketpeer_label_externalize(struct label *label, char *elements,
  200     char *outbuf, size_t outbuflen)
  201 {
  202         int error;
  203 
  204         error = MAC_EXTERNALIZE(socketpeer, label, elements, outbuf, outbuflen);
  205 
  206         return (error);
  207 }
  208 
  209 int
  210 mac_socket_label_internalize(struct label *label, char *string)
  211 {
  212         int error;
  213 
  214         error = MAC_INTERNALIZE(socket, label, string);
  215 
  216         return (error);
  217 }
  218 
  219 void
  220 mac_socket_label_associate(struct ucred *cred, struct socket *so)
  221 {
  222         if (!mac_socket_enforce)
  223                 return;
  224 
  225         MAC_PERFORM(socket_label_associate, cred, 
  226                     (socket_t)so, so->so_label);
  227 }
  228 
  229 void
  230 mac_socket_label_associate_accept(struct socket *oldsocket,
  231     struct socket *newsocket)
  232 {
  233         if (!mac_socket_enforce)
  234                 return;
  235 
  236         MAC_PERFORM(socket_label_associate_accept, 
  237                     (socket_t)oldsocket, oldsocket->so_label,
  238                     (socket_t)newsocket, newsocket->so_label);
  239 }
  240 
  241 #if CONFIG_MACF_SOCKET && CONFIG_MACF_NET
  242 void
  243 mac_socketpeer_label_associate_mbuf(struct mbuf *mbuf, struct socket *so)
  244 {
  245         struct label *label;
  246 
  247         if (!mac_socket_enforce && !mac_net_enforce)
  248                 return;
  249 
  250         label = mac_mbuf_to_label(mbuf);
  251 
  252         /* Policy must deal with NULL label (unlabeled mbufs) */
  253         MAC_PERFORM(socketpeer_label_associate_mbuf, mbuf, label,
  254                     (socket_t)so, so->so_peerlabel);
  255 }
  256 #else
  257 void
  258 mac_socketpeer_label_associate_mbuf(__unused struct mbuf *mbuf, 
  259         __unused struct socket *so)
  260 {
  261         return;
  262 }
  263 #endif
  264 
  265 void
  266 mac_socketpeer_label_associate_socket(struct socket *oldsocket,
  267     struct socket *newsocket)
  268 {
  269         if (!mac_socket_enforce)
  270                 return;
  271 
  272         MAC_PERFORM(socketpeer_label_associate_socket,
  273                     (socket_t)oldsocket, oldsocket->so_label,
  274                     (socket_t)newsocket, newsocket->so_peerlabel);
  275 }
  276 
  277 int
  278 mac_socket_check_kqfilter(kauth_cred_t cred, struct knote *kn,
  279                           struct socket *so)
  280 {
  281         int error;
  282 
  283         if (!mac_socket_enforce)
  284                 return 0;
  285 
  286         MAC_CHECK(socket_check_kqfilter, cred, kn, 
  287                   (socket_t)so, so->so_label);
  288         return (error);
  289 }
  290 
  291 static int
  292 mac_socket_check_label_update(kauth_cred_t cred, struct socket *so,
  293     struct label *newlabel)
  294 {
  295         int error;
  296 
  297         if (!mac_socket_enforce)
  298                 return 0;
  299 
  300         MAC_CHECK(socket_check_label_update, cred,
  301                   (socket_t)so, so->so_label,
  302                   newlabel);
  303         return (error);
  304 }
  305 
  306 int
  307 mac_socket_check_select(kauth_cred_t cred, struct socket *so, int which)
  308 {
  309         int error;
  310 
  311         if (!mac_socket_enforce)
  312                 return 0;
  313 
  314         MAC_CHECK(socket_check_select, cred,
  315                   (socket_t)so, so->so_label, which);
  316         return (error);
  317 }
  318 
  319 int
  320 mac_socket_check_stat(kauth_cred_t cred, struct socket *so)
  321 {
  322         int error;
  323 
  324         if (!mac_socket_enforce)
  325                 return 0;
  326 
  327         MAC_CHECK(socket_check_stat, cred,
  328                   (socket_t)so, so->so_label);
  329         return (error);
  330 }
  331 
  332 
  333 int
  334 mac_socket_label_update(kauth_cred_t cred, struct socket *so, struct label *label)
  335 {
  336         int error;
  337 #if 0
  338         if (!mac_socket_enforce)
  339                 return;
  340 #endif
  341         error = mac_socket_check_label_update(cred, so, label);
  342         if (error)
  343                 return (error);
  344 
  345         MAC_PERFORM(socket_label_update, cred,
  346                     (socket_t)so, so->so_label, label);
  347 
  348 #if CONFIG_MACF_NET
  349         /*
  350          * If the protocol has expressed interest in socket layer changes,
  351          * such as if it needs to propagate changes to a cached pcb
  352          * label from the socket, notify it of the label change while
  353          * holding the socket lock.
  354          * XXXMAC - are there cases when we should not do this?
  355          */
  356         mac_inpcb_label_update(so);
  357 #endif
  358         return (0);
  359 }
  360 
  361 int
  362 mac_setsockopt_label(kauth_cred_t cred, struct socket *so, struct mac *mac)
  363 {
  364         struct label *intlabel;
  365         char *buffer;
  366         int error;
  367         size_t len;
  368 
  369         error = mac_check_structmac_consistent(mac);
  370         if (error)
  371                 return (error);
  372 
  373         MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
  374         error = copyinstr(CAST_USER_ADDR_T(mac->m_string), buffer,
  375                 mac->m_buflen, &len);
  376         if (error) {
  377                 FREE(buffer, M_MACTEMP);
  378                 return (error);
  379         }
  380 
  381         intlabel = mac_socket_label_alloc(MAC_WAITOK);
  382         error = mac_socket_label_internalize(intlabel, buffer);
  383         FREE(buffer, M_MACTEMP);
  384         if (error)
  385                 goto out;
  386 
  387         error = mac_socket_label_update(cred, so, intlabel);
  388 out:
  389         mac_socket_label_free(intlabel);
  390         return (error);
  391 }
  392 
  393 int
  394 mac_socket_label_get(__unused kauth_cred_t cred, struct socket *so,
  395     struct mac *mac)
  396 {
  397         char *buffer, *elements;
  398         struct label *intlabel;
  399         int error;
  400         size_t len;
  401 
  402         error = mac_check_structmac_consistent(mac);
  403         if (error)
  404                 return (error);
  405 
  406         MALLOC(elements, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
  407         error = copyinstr(CAST_USER_ADDR_T(mac->m_string), elements,
  408                 mac->m_buflen, &len);
  409         if (error) {
  410                 FREE(elements, M_MACTEMP);
  411                 return (error);
  412         }
  413 
  414         MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  415         intlabel = mac_socket_label_alloc(MAC_WAITOK);
  416         mac_socket_label_copy(so->so_label, intlabel);
  417         error = mac_socket_label_externalize(intlabel, elements, buffer,
  418             mac->m_buflen);
  419         mac_socket_label_free(intlabel);
  420         if (error == 0)
  421                 error = copyout(buffer, CAST_USER_ADDR_T(mac->m_string),
  422                         strlen(buffer)+1);
  423 
  424         FREE(buffer, M_MACTEMP);
  425         FREE(elements, M_MACTEMP);
  426 
  427         return (error);
  428 }
  429 
  430 int
  431 mac_socketpeer_label_get(__unused kauth_cred_t cred, struct socket *so,
  432     struct mac *mac)
  433 {
  434         char *elements, *buffer;
  435         struct label *intlabel;
  436         int error;
  437         size_t len;
  438 
  439         error = mac_check_structmac_consistent(mac);
  440         if (error)
  441                 return (error);
  442 
  443         MALLOC(elements, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
  444         error = copyinstr(CAST_USER_ADDR_T(mac->m_string), elements,
  445                 mac->m_buflen, &len);
  446         if (error) {
  447                 FREE(elements, M_MACTEMP);
  448                 return (error);
  449         }
  450 
  451         MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  452         intlabel = mac_socket_label_alloc(MAC_WAITOK);
  453         mac_socket_label_copy(so->so_peerlabel, intlabel);
  454         error = mac_socketpeer_label_externalize(intlabel, elements, buffer,
  455             mac->m_buflen);
  456         mac_socket_label_free(intlabel);
  457         if (error == 0)
  458                 error = copyout(buffer, CAST_USER_ADDR_T(mac->m_string),
  459                                 strlen(buffer)+1);
  460 
  461         FREE(buffer, M_MACTEMP);
  462         FREE(elements, M_MACTEMP);
  463 
  464         return (error);
  465 }
  466 #endif /* MAC_SOCKET */
  467 
  468 int
  469 mac_socket_check_accept(kauth_cred_t cred, struct socket *so)
  470 {
  471         int error;
  472 
  473         if (!mac_socket_enforce)
  474                 return 0;
  475 
  476         MAC_CHECK(socket_check_accept, cred,
  477                   (socket_t)so, so->so_label);
  478         return (error);
  479 }
  480 
  481 int
  482 mac_socket_check_accepted(kauth_cred_t cred, struct socket *so)
  483 {
  484         struct sockaddr *sockaddr;
  485         int error;
  486 
  487         if (!mac_socket_enforce)
  488                 return 0;
  489 
  490         if (sock_getaddr((socket_t)so, &sockaddr, 1) != 0) {
  491                 error = ECONNABORTED;
  492         } else {
  493                 MAC_CHECK(socket_check_accepted, cred,
  494                           (socket_t)so, so->so_label, sockaddr);
  495                 sock_freeaddr(sockaddr);
  496         }
  497         return (error);
  498 }
  499 
  500 int
  501 mac_socket_check_bind(kauth_cred_t ucred, struct socket *so,
  502     struct sockaddr *sockaddr)
  503 {
  504         int error;
  505 
  506         if (!mac_socket_enforce)
  507                 return 0;
  508 
  509         MAC_CHECK(socket_check_bind, ucred,
  510                   (socket_t)so, so->so_label, sockaddr);
  511         return (error);
  512 }
  513 
  514 int
  515 mac_socket_check_connect(kauth_cred_t cred, struct socket *so,
  516     struct sockaddr *sockaddr)
  517 {
  518         int error;
  519 
  520         if (!mac_socket_enforce)
  521                 return 0;
  522 
  523         MAC_CHECK(socket_check_connect, cred,
  524                   (socket_t)so, so->so_label,
  525                   sockaddr);
  526         return (error);
  527 }
  528 
  529 int
  530 mac_socket_check_create(kauth_cred_t cred, int domain, int type, int protocol)
  531 {
  532         int error;
  533 
  534         if (!mac_socket_enforce)
  535                 return 0;
  536 
  537         MAC_CHECK(socket_check_create, cred, domain, type, protocol);
  538         return (error);
  539 }
  540 
  541 #if CONFIG_MACF_SOCKET && CONFIG_MACF_NET
  542 int
  543 mac_socket_check_deliver(struct socket *so, struct mbuf *mbuf)
  544 {
  545         struct label *label;
  546         int error;
  547 
  548         if (!mac_socket_enforce)
  549                 return 0;
  550 
  551         label = mac_mbuf_to_label(mbuf);
  552 
  553         /* Policy must deal with NULL label (unlabeled mbufs) */
  554         MAC_CHECK(socket_check_deliver,
  555                   (socket_t)so, so->so_label, mbuf, label);
  556         return (error);
  557 }
  558 #else
  559 int
  560 mac_socket_check_deliver(__unused struct socket *so, __unused struct mbuf *mbuf)
  561 {
  562         return (0);
  563 }
  564 #endif
  565 
  566 int
  567 mac_socket_check_listen(kauth_cred_t cred, struct socket *so)
  568 {
  569         int error;
  570 
  571         if (!mac_socket_enforce)
  572                 return 0;
  573 
  574         MAC_CHECK(socket_check_listen, cred,
  575                   (socket_t)so, so->so_label);
  576         return (error);
  577 }
  578 
  579 int
  580 mac_socket_check_receive(kauth_cred_t cred, struct socket *so)
  581 {
  582         int error;
  583 
  584         if (!mac_socket_enforce)
  585                 return 0;
  586 
  587         MAC_CHECK(socket_check_receive, cred,
  588                   (socket_t)so, so->so_label);
  589         return (error);
  590 }
  591 
  592 int
  593 mac_socket_check_received(kauth_cred_t cred, struct socket *so, struct sockaddr *saddr)
  594 {
  595         int error;
  596 
  597         if (!mac_socket_enforce)
  598                 return 0;
  599         
  600         MAC_CHECK(socket_check_received, cred,
  601                   so, so->so_label, saddr);
  602         return (error);
  603 }
  604 
  605 int
  606 mac_socket_check_send(kauth_cred_t cred, struct socket *so,
  607                       struct sockaddr *sockaddr)
  608 {
  609         int error;
  610 
  611         if (!mac_socket_enforce)
  612                 return 0;
  613 
  614         MAC_CHECK(socket_check_send, cred,
  615                   (socket_t)so, so->so_label, sockaddr);
  616         return (error);
  617 }
  618 
  619 int
  620 mac_socket_check_setsockopt(kauth_cred_t cred, struct socket *so,
  621                             struct sockopt *sopt)
  622 {
  623         int error;
  624 
  625         if (!mac_socket_enforce)
  626                 return (0);
  627 
  628         MAC_CHECK(socket_check_setsockopt, cred,
  629                   (socket_t)so, so->so_label, sopt);
  630         return (error);
  631 }
  632 
  633 int mac_socket_check_getsockopt(kauth_cred_t cred, struct socket *so,
  634                                 struct sockopt *sopt)
  635 {
  636         int error;
  637 
  638         if (!mac_socket_enforce)
  639                 return (0);
  640 
  641         MAC_CHECK(socket_check_getsockopt, cred,
  642                   (socket_t)so, so->so_label, sopt);
  643         return (error);
  644 }

Cache object: d4b173f635a45b6864d245c32aa26101


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