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/netinet6/in6_jail.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 Poul-Henning Kamp.
    3  * Copyright (c) 2008 Bjoern A. Zeeb.
    4  * Copyright (c) 2009 James Gritton.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_ddb.h"
   33 #include "opt_inet.h"
   34 #include "opt_inet6.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/types.h>
   38 #include <sys/kernel.h>
   39 #include <sys/systm.h>
   40 #include <sys/errno.h>
   41 #include <sys/sysproto.h>
   42 #include <sys/malloc.h>
   43 #include <sys/osd.h>
   44 #include <sys/priv.h>
   45 #include <sys/proc.h>
   46 #include <sys/taskqueue.h>
   47 #include <sys/fcntl.h>
   48 #include <sys/jail.h>
   49 #include <sys/lock.h>
   50 #include <sys/mutex.h>
   51 #include <sys/racct.h>
   52 #include <sys/refcount.h>
   53 #include <sys/sx.h>
   54 #include <sys/namei.h>
   55 #include <sys/mount.h>
   56 #include <sys/queue.h>
   57 #include <sys/socket.h>
   58 #include <sys/syscallsubr.h>
   59 #include <sys/sysctl.h>
   60 #include <sys/vnode.h>
   61 
   62 #include <net/if.h>
   63 #include <net/vnet.h>
   64 
   65 #include <netinet/in.h>
   66 
   67 static void
   68 prison_bcopy_primary_ip6(const struct prison *pr, struct in6_addr *ia6)
   69 {
   70 
   71         bcopy(prison_ip_get0(pr, PR_INET6), ia6, sizeof(struct in6_addr));
   72 }
   73 
   74 int
   75 prison_qcmp_v6(const void *ip1, const void *ip2)
   76 {
   77         const struct in6_addr *ia6a, *ia6b;
   78         int i, rc;
   79 
   80         ia6a = (const struct in6_addr *)ip1;
   81         ia6b = (const struct in6_addr *)ip2;
   82 
   83         rc = 0;
   84         for (i = 0; rc == 0 && i < sizeof(struct in6_addr); i++) {
   85                 if (ia6a->s6_addr[i] > ia6b->s6_addr[i])
   86                         rc = 1;
   87                 else if (ia6a->s6_addr[i] < ia6b->s6_addr[i])
   88                         rc = -1;
   89         }
   90         return (rc);
   91 }
   92 
   93 bool
   94 prison_valid_v6(const void *ip)
   95 {
   96         const struct in6_addr *ia = ip;
   97 
   98         return (!IN6_IS_ADDR_UNSPECIFIED(ia));
   99 }
  100 
  101 /*
  102  * Pass back primary IPv6 address for this jail.
  103  *
  104  * If not restricted return success but do not alter the address.  Caller has
  105  * to make sure to initialize it correctly (e.g. IN6ADDR_ANY_INIT).
  106  *
  107  * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
  108  */
  109 int
  110 prison_get_ip6(struct ucred *cred, struct in6_addr *ia6)
  111 {
  112         struct prison *pr;
  113 
  114         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  115         KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
  116 
  117         pr = cred->cr_prison;
  118         if (!(pr->pr_flags & PR_IP6))
  119                 return (0);
  120         mtx_lock(&pr->pr_mtx);
  121         if (!(pr->pr_flags & PR_IP6)) {
  122                 mtx_unlock(&pr->pr_mtx);
  123                 return (0);
  124         }
  125         if (pr->pr_addrs[PR_INET6] == NULL) {
  126                 mtx_unlock(&pr->pr_mtx);
  127                 return (EAFNOSUPPORT);
  128         }
  129 
  130         prison_bcopy_primary_ip6(pr, ia6);
  131         mtx_unlock(&pr->pr_mtx);
  132         return (0);
  133 }
  134 
  135 /*
  136  * Return 1 if we should do proper source address selection or are not jailed.
  137  * We will return 0 if we should bypass source address selection in favour
  138  * of the primary jail IPv6 address. Only in this case *ia will be updated and
  139  * returned in NBO.
  140  * Return EAFNOSUPPORT, in case this jail does not allow IPv6.
  141  */
  142 int
  143 prison_saddrsel_ip6(struct ucred *cred, struct in6_addr *ia6)
  144 {
  145         struct prison *pr;
  146         struct in6_addr lia6;
  147         int error;
  148 
  149         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  150         KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
  151 
  152         if (!jailed(cred))
  153                 return (1);
  154 
  155         pr = cred->cr_prison;
  156         if (pr->pr_flags & PR_IP6_SADDRSEL)
  157                 return (1);
  158 
  159         lia6 = in6addr_any;
  160         error = prison_get_ip6(cred, &lia6);
  161         if (error)
  162                 return (error);
  163         if (IN6_IS_ADDR_UNSPECIFIED(&lia6))
  164                 return (1);
  165 
  166         bcopy(&lia6, ia6, sizeof(struct in6_addr));
  167         return (0);
  168 }
  169 
  170 /*
  171  * Return true if pr1 and pr2 have the same IPv6 address restrictions.
  172  */
  173 int
  174 prison_equal_ip6(struct prison *pr1, struct prison *pr2)
  175 {
  176 
  177         if (pr1 == pr2)
  178                 return (1);
  179 
  180         while (pr1 != &prison0 &&
  181 #ifdef VIMAGE
  182                !(pr1->pr_flags & PR_VNET) &&
  183 #endif
  184                !(pr1->pr_flags & PR_IP6_USER))
  185                 pr1 = pr1->pr_parent;
  186         while (pr2 != &prison0 &&
  187 #ifdef VIMAGE
  188                !(pr2->pr_flags & PR_VNET) &&
  189 #endif
  190                !(pr2->pr_flags & PR_IP6_USER))
  191                 pr2 = pr2->pr_parent;
  192         return (pr1 == pr2);
  193 }
  194 
  195 /*
  196  * Make sure our (source) address is set to something meaningful to this jail.
  197  *
  198  * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0)
  199  * when needed while binding.
  200  *
  201  * Returns 0 if jail doesn't restrict IPv6 or if address belongs to jail,
  202  * EADDRNOTAVAIL if the address doesn't belong, or EAFNOSUPPORT if the jail
  203  * doesn't allow IPv6.
  204  */
  205 int
  206 prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only)
  207 {
  208         struct prison *pr;
  209         int error;
  210 
  211         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  212         KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
  213 
  214         pr = cred->cr_prison;
  215         if (!(pr->pr_flags & PR_IP6))
  216                 return (0);
  217         mtx_lock(&pr->pr_mtx);
  218         if (!(pr->pr_flags & PR_IP6)) {
  219                 mtx_unlock(&pr->pr_mtx);
  220                 return (0);
  221         }
  222         if (pr->pr_addrs[PR_INET6] == NULL) {
  223                 mtx_unlock(&pr->pr_mtx);
  224                 return (EAFNOSUPPORT);
  225         }
  226 
  227         if (IN6_IS_ADDR_UNSPECIFIED(ia6)) {
  228                 /*
  229                  * In case there is only 1 IPv6 address, and v6only is true,
  230                  * then bind directly.
  231                  */
  232                 if (v6only != 0 && prison_ip_cnt(pr, PR_INET6) == 1)
  233                         prison_bcopy_primary_ip6(pr, ia6);
  234                 mtx_unlock(&pr->pr_mtx);
  235                 return (0);
  236         }
  237 
  238         error = prison_check_ip6_locked(pr, ia6);
  239         if (error == EADDRNOTAVAIL && IN6_IS_ADDR_LOOPBACK(ia6)) {
  240                 prison_bcopy_primary_ip6(pr, ia6);
  241                 error = 0;
  242         }
  243 
  244         mtx_unlock(&pr->pr_mtx);
  245         return (error);
  246 }
  247 
  248 /*
  249  * Rewrite destination address in case we will connect to loopback address.
  250  *
  251  * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
  252  */
  253 int
  254 prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6)
  255 {
  256         struct prison *pr;
  257 
  258         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  259         KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
  260 
  261         pr = cred->cr_prison;
  262         if (!(pr->pr_flags & PR_IP6))
  263                 return (0);
  264         mtx_lock(&pr->pr_mtx);
  265         if (!(pr->pr_flags & PR_IP6)) {
  266                 mtx_unlock(&pr->pr_mtx);
  267                 return (0);
  268         }
  269         if (pr->pr_addrs[PR_INET6] == NULL) {
  270                 mtx_unlock(&pr->pr_mtx);
  271                 return (EAFNOSUPPORT);
  272         }
  273 
  274         if (IN6_IS_ADDR_LOOPBACK(ia6) &&
  275             prison_check_ip6_locked(pr, ia6) == EADDRNOTAVAIL) {
  276                 prison_bcopy_primary_ip6(pr, ia6);
  277                 mtx_unlock(&pr->pr_mtx);
  278                 return (0);
  279         }
  280 
  281         /*
  282          * Return success because nothing had to be changed.
  283          */
  284         mtx_unlock(&pr->pr_mtx);
  285         return (0);
  286 }
  287 
  288 /*
  289  * Check if given address belongs to the jail referenced by cred/prison.
  290  *
  291  * Returns 0 if address belongs to jail,
  292  * EADDRNOTAVAIL if the address doesn't belong to the jail.
  293  */
  294 int
  295 prison_check_ip6_locked(const struct prison *pr, const struct in6_addr *ia6)
  296 {
  297 
  298         if (!(pr->pr_flags & PR_IP6))
  299                 return (0);
  300 
  301         return (prison_ip_check(pr, PR_INET6, ia6));
  302 }
  303 
  304 int
  305 prison_check_ip6(const struct ucred *cred, const struct in6_addr *ia6)
  306 {
  307         struct prison *pr;
  308         int error;
  309 
  310         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  311         KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
  312 
  313         pr = cred->cr_prison;
  314         if (!(pr->pr_flags & PR_IP6))
  315                 return (0);
  316         mtx_lock(&pr->pr_mtx);
  317         if (!(pr->pr_flags & PR_IP6)) {
  318                 mtx_unlock(&pr->pr_mtx);
  319                 return (0);
  320         }
  321         if (pr->pr_addrs[PR_INET6] == NULL) {
  322                 mtx_unlock(&pr->pr_mtx);
  323                 return (EAFNOSUPPORT);
  324         }
  325 
  326         error = prison_check_ip6_locked(pr, ia6);
  327         mtx_unlock(&pr->pr_mtx);
  328         return (error);
  329 }

Cache object: 602da8332d7f0d6a35d516ffe29945b0


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