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-2012 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 <security/mac_internal.h>
   86 
   87 #if CONFIG_MACF_SOCKET
   88 struct label *
   89 mac_socket_label_alloc(int flag)
   90 {
   91         struct label *label;
   92         int error;
   93 
   94         label = mac_labelzone_alloc(flag);
   95         if (label == NULL)
   96                 return (NULL);
   97 
   98         MAC_CHECK(socket_label_init, label, flag);
   99         if (error) {
  100                 MAC_PERFORM(socket_label_destroy, label);
  101                 mac_labelzone_free(label);
  102                 return (NULL);
  103         }
  104 
  105         return (label);
  106 }
  107 
  108 static struct label *
  109 mac_socket_peer_label_alloc(int flag)
  110 {
  111         struct label *label;
  112         int error;
  113 
  114         label = mac_labelzone_alloc(flag);
  115         if (label == NULL)
  116                 return (NULL);
  117 
  118         MAC_CHECK(socketpeer_label_init, label, flag);
  119         if (error) {
  120                 MAC_PERFORM(socketpeer_label_destroy, label);
  121                 mac_labelzone_free(label);
  122                 return (NULL);
  123         }
  124 
  125         return (label);
  126 }
  127 
  128 int
  129 mac_socket_label_init(struct socket *so, int flag)
  130 {
  131 
  132         so->so_label = mac_socket_label_alloc(flag);
  133         if (so->so_label == NULL)
  134                 return (ENOMEM);
  135         so->so_peerlabel = mac_socket_peer_label_alloc(flag);
  136         if (so->so_peerlabel == NULL) {
  137                 mac_socket_label_free(so->so_label);
  138                 so->so_label = NULL;
  139                 return (ENOMEM);
  140         }
  141         return (0);
  142 }
  143 
  144 void
  145 mac_socket_label_free(struct label *label)
  146 {
  147 
  148         MAC_PERFORM(socket_label_destroy, label);
  149         mac_labelzone_free(label);
  150 }
  151 
  152 static void
  153 mac_socket_peer_label_free(struct label *label)
  154 {
  155 
  156         MAC_PERFORM(socketpeer_label_destroy, label);
  157         mac_labelzone_free(label);
  158 }
  159 
  160 void
  161 mac_socket_label_destroy(struct socket *so)
  162 {
  163 
  164         if (so->so_label != NULL) {
  165                 mac_socket_label_free(so->so_label);
  166                 so->so_label = NULL;
  167         }
  168         if (so->so_peerlabel != NULL) {
  169                 mac_socket_peer_label_free(so->so_peerlabel);
  170                 so->so_peerlabel = NULL;
  171         }
  172 }
  173 
  174 void
  175 mac_socket_label_copy(struct label *src, struct label *dest)
  176 {
  177 
  178         MAC_PERFORM(socket_label_copy, src, dest);
  179 }
  180 
  181 int
  182 mac_socket_label_externalize(struct label *label, char *elements,
  183     char *outbuf, size_t outbuflen)
  184 {
  185         int error;
  186 
  187         error = MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
  188 
  189         return (error);
  190 }
  191 
  192 static int
  193 mac_socketpeer_label_externalize(struct label *label, char *elements,
  194     char *outbuf, size_t outbuflen)
  195 {
  196         int error;
  197 
  198         error = MAC_EXTERNALIZE(socketpeer, label, elements, outbuf, outbuflen);
  199 
  200         return (error);
  201 }
  202 
  203 int
  204 mac_socket_label_internalize(struct label *label, char *string)
  205 {
  206         int error;
  207 
  208         error = MAC_INTERNALIZE(socket, label, string);
  209 
  210         return (error);
  211 }
  212 
  213 void
  214 mac_socket_label_associate(struct ucred *cred, struct socket *so)
  215 {
  216         if (!mac_socket_enforce)
  217                 return;
  218 
  219         MAC_PERFORM(socket_label_associate, cred, 
  220                     (socket_t)so, so->so_label);
  221 }
  222 
  223 void
  224 mac_socket_label_associate_accept(struct socket *oldsocket,
  225     struct socket *newsocket)
  226 {
  227         if (!mac_socket_enforce)
  228                 return;
  229 
  230         MAC_PERFORM(socket_label_associate_accept, 
  231                     (socket_t)oldsocket, oldsocket->so_label,
  232                     (socket_t)newsocket, newsocket->so_label);
  233 }
  234 
  235 #if CONFIG_MACF_SOCKET && CONFIG_MACF_NET
  236 void
  237 mac_socketpeer_label_associate_mbuf(struct mbuf *mbuf, struct socket *so)
  238 {
  239         struct label *label;
  240 
  241         if (!mac_socket_enforce && !mac_net_enforce)
  242                 return;
  243 
  244         label = mac_mbuf_to_label(mbuf);
  245 
  246         /* Policy must deal with NULL label (unlabeled mbufs) */
  247         MAC_PERFORM(socketpeer_label_associate_mbuf, mbuf, label,
  248                     (socket_t)so, so->so_peerlabel);
  249 }
  250 #else
  251 void
  252 mac_socketpeer_label_associate_mbuf(__unused struct mbuf *mbuf, 
  253         __unused struct socket *so)
  254 {
  255         return;
  256 }
  257 #endif
  258 
  259 void
  260 mac_socketpeer_label_associate_socket(struct socket *oldsocket,
  261     struct socket *newsocket)
  262 {
  263         if (!mac_socket_enforce)
  264                 return;
  265 
  266         MAC_PERFORM(socketpeer_label_associate_socket,
  267                     (socket_t)oldsocket, oldsocket->so_label,
  268                     (socket_t)newsocket, newsocket->so_peerlabel);
  269 }
  270 
  271 int
  272 mac_socket_check_kqfilter(kauth_cred_t cred, struct knote *kn,
  273                           struct socket *so)
  274 {
  275         int error;
  276 
  277         if (!mac_socket_enforce)
  278                 return 0;
  279 
  280         MAC_CHECK(socket_check_kqfilter, cred, kn, 
  281                   (socket_t)so, so->so_label);
  282         return (error);
  283 }
  284 
  285 static int
  286 mac_socket_check_label_update(kauth_cred_t cred, struct socket *so,
  287     struct label *newlabel)
  288 {
  289         int error;
  290 
  291         if (!mac_socket_enforce)
  292                 return 0;
  293 
  294         MAC_CHECK(socket_check_label_update, cred,
  295                   (socket_t)so, so->so_label,
  296                   newlabel);
  297         return (error);
  298 }
  299 
  300 int
  301 mac_socket_check_select(kauth_cred_t cred, struct socket *so, int which)
  302 {
  303         int error;
  304 
  305         if (!mac_socket_enforce)
  306                 return 0;
  307 
  308         MAC_CHECK(socket_check_select, cred,
  309                   (socket_t)so, so->so_label, which);
  310         return (error);
  311 }
  312 
  313 int
  314 mac_socket_check_stat(kauth_cred_t cred, struct socket *so)
  315 {
  316         int error;
  317 
  318         if (!mac_socket_enforce)
  319                 return 0;
  320 
  321         MAC_CHECK(socket_check_stat, cred,
  322                   (socket_t)so, so->so_label);
  323         return (error);
  324 }
  325 
  326 
  327 int
  328 mac_socket_label_update(kauth_cred_t cred, struct socket *so, struct label *label)
  329 {
  330         int error;
  331 #if 0
  332         if (!mac_socket_enforce)
  333                 return;
  334 #endif
  335         error = mac_socket_check_label_update(cred, so, label);
  336         if (error)
  337                 return (error);
  338 
  339         MAC_PERFORM(socket_label_update, cred,
  340                     (socket_t)so, so->so_label, label);
  341 
  342 #if CONFIG_MACF_NET
  343         /*
  344          * If the protocol has expressed interest in socket layer changes,
  345          * such as if it needs to propagate changes to a cached pcb
  346          * label from the socket, notify it of the label change while
  347          * holding the socket lock.
  348          * XXXMAC - are there cases when we should not do this?
  349          */
  350         mac_inpcb_label_update(so);
  351 #endif
  352         return (0);
  353 }
  354 
  355 int
  356 mac_setsockopt_label(kauth_cred_t cred, struct socket *so, struct mac *mac)
  357 {
  358         struct label *intlabel;
  359         char *buffer;
  360         int error;
  361         size_t len;
  362 
  363         error = mac_check_structmac_consistent(mac);
  364         if (error)
  365                 return (error);
  366 
  367         MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
  368         error = copyinstr(CAST_USER_ADDR_T(mac->m_string), buffer,
  369                 mac->m_buflen, &len);
  370         if (error) {
  371                 FREE(buffer, M_MACTEMP);
  372                 return (error);
  373         }
  374 
  375         intlabel = mac_socket_label_alloc(MAC_WAITOK);
  376         error = mac_socket_label_internalize(intlabel, buffer);
  377         FREE(buffer, M_MACTEMP);
  378         if (error)
  379                 goto out;
  380 
  381         error = mac_socket_label_update(cred, so, intlabel);
  382 out:
  383         mac_socket_label_free(intlabel);
  384         return (error);
  385 }
  386 
  387 int
  388 mac_socket_label_get(__unused kauth_cred_t cred, struct socket *so,
  389     struct mac *mac)
  390 {
  391         char *buffer, *elements;
  392         struct label *intlabel;
  393         int error;
  394         size_t len;
  395 
  396         error = mac_check_structmac_consistent(mac);
  397         if (error)
  398                 return (error);
  399 
  400         MALLOC(elements, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
  401         error = copyinstr(CAST_USER_ADDR_T(mac->m_string), elements,
  402                 mac->m_buflen, &len);
  403         if (error) {
  404                 FREE(elements, M_MACTEMP);
  405                 return (error);
  406         }
  407 
  408         MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  409         intlabel = mac_socket_label_alloc(MAC_WAITOK);
  410         mac_socket_label_copy(so->so_label, intlabel);
  411         error = mac_socket_label_externalize(intlabel, elements, buffer,
  412             mac->m_buflen);
  413         mac_socket_label_free(intlabel);
  414         if (error == 0)
  415                 error = copyout(buffer, CAST_USER_ADDR_T(mac->m_string),
  416                         strlen(buffer)+1);
  417 
  418         FREE(buffer, M_MACTEMP);
  419         FREE(elements, M_MACTEMP);
  420 
  421         return (error);
  422 }
  423 
  424 int
  425 mac_socketpeer_label_get(__unused kauth_cred_t cred, struct socket *so,
  426     struct mac *mac)
  427 {
  428         char *elements, *buffer;
  429         struct label *intlabel;
  430         int error;
  431         size_t len;
  432 
  433         error = mac_check_structmac_consistent(mac);
  434         if (error)
  435                 return (error);
  436 
  437         MALLOC(elements, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
  438         error = copyinstr(CAST_USER_ADDR_T(mac->m_string), elements,
  439                 mac->m_buflen, &len);
  440         if (error) {
  441                 FREE(elements, M_MACTEMP);
  442                 return (error);
  443         }
  444 
  445         MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  446         intlabel = mac_socket_label_alloc(MAC_WAITOK);
  447         mac_socket_label_copy(so->so_peerlabel, intlabel);
  448         error = mac_socketpeer_label_externalize(intlabel, elements, buffer,
  449             mac->m_buflen);
  450         mac_socket_label_free(intlabel);
  451         if (error == 0)
  452                 error = copyout(buffer, CAST_USER_ADDR_T(mac->m_string),
  453                                 strlen(buffer)+1);
  454 
  455         FREE(buffer, M_MACTEMP);
  456         FREE(elements, M_MACTEMP);
  457 
  458         return (error);
  459 }
  460 #endif /* MAC_SOCKET */
  461 
  462 int
  463 mac_socket_check_accept(kauth_cred_t cred, struct socket *so)
  464 {
  465         int error;
  466 
  467         if (!mac_socket_enforce)
  468                 return 0;
  469 
  470         MAC_CHECK(socket_check_accept, cred,
  471                   (socket_t)so, so->so_label);
  472         return (error);
  473 }
  474 
  475 int
  476 mac_socket_check_accepted(kauth_cred_t cred, struct socket *so)
  477 {
  478         struct sockaddr *sockaddr;
  479         int error;
  480 
  481         if (!mac_socket_enforce)
  482                 return 0;
  483 
  484         if (sock_getaddr((socket_t)so, &sockaddr, 1) != 0) {
  485                 error = ECONNABORTED;
  486         } else {
  487                 MAC_CHECK(socket_check_accepted, cred,
  488                           (socket_t)so, so->so_label, sockaddr);
  489                 sock_freeaddr(sockaddr);
  490         }
  491         return (error);
  492 }
  493 
  494 int
  495 mac_socket_check_bind(kauth_cred_t ucred, struct socket *so,
  496     struct sockaddr *sockaddr)
  497 {
  498         int error;
  499 
  500         if (!mac_socket_enforce)
  501                 return 0;
  502 
  503         MAC_CHECK(socket_check_bind, ucred,
  504                   (socket_t)so, so->so_label, sockaddr);
  505         return (error);
  506 }
  507 
  508 int
  509 mac_socket_check_connect(kauth_cred_t cred, struct socket *so,
  510     struct sockaddr *sockaddr)
  511 {
  512         int error;
  513 
  514         if (!mac_socket_enforce)
  515                 return 0;
  516 
  517         MAC_CHECK(socket_check_connect, cred,
  518                   (socket_t)so, so->so_label,
  519                   sockaddr);
  520         return (error);
  521 }
  522 
  523 int
  524 mac_socket_check_create(kauth_cred_t cred, int domain, int type, int protocol)
  525 {
  526         int error;
  527 
  528         if (!mac_socket_enforce)
  529                 return 0;
  530 
  531         MAC_CHECK(socket_check_create, cred, domain, type, protocol);
  532         return (error);
  533 }
  534 
  535 #if CONFIG_MACF_SOCKET && CONFIG_MACF_NET
  536 int
  537 mac_socket_check_deliver(struct socket *so, struct mbuf *mbuf)
  538 {
  539         struct label *label;
  540         int error;
  541 
  542         if (!mac_socket_enforce)
  543                 return 0;
  544 
  545         label = mac_mbuf_to_label(mbuf);
  546 
  547         /* Policy must deal with NULL label (unlabeled mbufs) */
  548         MAC_CHECK(socket_check_deliver,
  549                   (socket_t)so, so->so_label, mbuf, label);
  550         return (error);
  551 }
  552 #else
  553 int
  554 mac_socket_check_deliver(__unused struct socket *so, __unused struct mbuf *mbuf)
  555 {
  556         return (0);
  557 }
  558 #endif
  559 
  560 int
  561 mac_socket_check_listen(kauth_cred_t cred, struct socket *so)
  562 {
  563         int error;
  564 
  565         if (!mac_socket_enforce)
  566                 return 0;
  567 
  568         MAC_CHECK(socket_check_listen, cred,
  569                   (socket_t)so, so->so_label);
  570         return (error);
  571 }
  572 
  573 int
  574 mac_socket_check_receive(kauth_cred_t cred, struct socket *so)
  575 {
  576         int error;
  577 
  578         if (!mac_socket_enforce)
  579                 return 0;
  580 
  581         MAC_CHECK(socket_check_receive, cred,
  582                   (socket_t)so, so->so_label);
  583         return (error);
  584 }
  585 
  586 int
  587 mac_socket_check_received(kauth_cred_t cred, struct socket *so, struct sockaddr *saddr)
  588 {
  589         int error;
  590 
  591         if (!mac_socket_enforce)
  592                 return 0;
  593         
  594         MAC_CHECK(socket_check_received, cred,
  595                   so, so->so_label, saddr);
  596         return (error);
  597 }
  598 
  599 int
  600 mac_socket_check_send(kauth_cred_t cred, struct socket *so,
  601                       struct sockaddr *sockaddr)
  602 {
  603         int error;
  604 
  605         if (!mac_socket_enforce)
  606                 return 0;
  607 
  608         MAC_CHECK(socket_check_send, cred,
  609                   (socket_t)so, so->so_label, sockaddr);
  610         return (error);
  611 }
  612 
  613 int
  614 mac_socket_check_setsockopt(kauth_cred_t cred, struct socket *so,
  615                             struct sockopt *sopt)
  616 {
  617         int error;
  618 
  619         if (!mac_socket_enforce)
  620                 return (0);
  621 
  622         MAC_CHECK(socket_check_setsockopt, cred,
  623                   (socket_t)so, so->so_label, sopt);
  624         return (error);
  625 }
  626 
  627 int mac_socket_check_getsockopt(kauth_cred_t cred, struct socket *so,
  628                                 struct sockopt *sopt)
  629 {
  630         int error;
  631 
  632         if (!mac_socket_enforce)
  633                 return (0);
  634 
  635         MAC_CHECK(socket_check_getsockopt, cred,
  636                   (socket_t)so, so->so_label, sopt);
  637         return (error);
  638 }

Cache object: cd01c2e02047bd1540d1b4a9539e8d8b


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