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/netinet/in_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 in_addr_t
   68 prison_primary_ip4(const struct prison *pr)
   69 {
   70 
   71         return (((const struct in_addr *)prison_ip_get0(pr, PR_INET))->s_addr);
   72 }
   73 
   74 int
   75 prison_qcmp_v4(const void *ip1, const void *ip2)
   76 {
   77         in_addr_t iaa, iab;
   78 
   79         /*
   80          * We need to compare in HBO here to get the list sorted as expected
   81          * by the result of the code.  Sorting NBO addresses gives you
   82          * interesting results.  If you do not understand, do not try.
   83          */
   84         iaa = ntohl(((const struct in_addr *)ip1)->s_addr);
   85         iab = ntohl(((const struct in_addr *)ip2)->s_addr);
   86 
   87         /*
   88          * Do not simply return the difference of the two numbers, the int is
   89          * not wide enough.
   90          */
   91         if (iaa > iab)
   92                 return (1);
   93         else if (iaa < iab)
   94                 return (-1);
   95         else
   96                 return (0);
   97 }
   98 
   99 bool
  100 prison_valid_v4(const void *ip)
  101 {
  102         in_addr_t ia = ((const struct in_addr *)ip)->s_addr;
  103 
  104         /*
  105          * We do not have to care about byte order for these
  106          * checks so we will do them in NBO.
  107          */
  108         return (ia != INADDR_ANY && ia != INADDR_BROADCAST);
  109 }
  110 
  111 /*
  112  * Pass back primary IPv4 address of this jail.
  113  *
  114  * If not restricted return success but do not alter the address.  Caller has
  115  * to make sure to initialize it correctly (e.g. INADDR_ANY).
  116  *
  117  * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4.
  118  * Address returned in NBO.
  119  */
  120 int
  121 prison_get_ip4(struct ucred *cred, struct in_addr *ia)
  122 {
  123         struct prison *pr;
  124 
  125         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  126         KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
  127 
  128         pr = cred->cr_prison;
  129         if (!(pr->pr_flags & PR_IP4))
  130                 return (0);
  131         mtx_lock(&pr->pr_mtx);
  132         if (!(pr->pr_flags & PR_IP4)) {
  133                 mtx_unlock(&pr->pr_mtx);
  134                 return (0);
  135         }
  136         if (pr->pr_addrs[PR_INET] == NULL) {
  137                 mtx_unlock(&pr->pr_mtx);
  138                 return (EAFNOSUPPORT);
  139         }
  140 
  141         ia->s_addr = prison_primary_ip4(pr);
  142         mtx_unlock(&pr->pr_mtx);
  143         return (0);
  144 }
  145 
  146 /*
  147  * Return 1 if we should do proper source address selection or are not jailed.
  148  * We will return 0 if we should bypass source address selection in favour
  149  * of the primary jail IPv4 address. Only in this case *ia will be updated and
  150  * returned in NBO.
  151  * Return EAFNOSUPPORT, in case this jail does not allow IPv4.
  152  */
  153 int
  154 prison_saddrsel_ip4(struct ucred *cred, struct in_addr *ia)
  155 {
  156         struct prison *pr;
  157         struct in_addr lia;
  158         int error;
  159 
  160         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  161         KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
  162 
  163         if (!jailed(cred))
  164                 return (1);
  165 
  166         pr = cred->cr_prison;
  167         if (pr->pr_flags & PR_IP4_SADDRSEL)
  168                 return (1);
  169 
  170         lia.s_addr = INADDR_ANY;
  171         error = prison_get_ip4(cred, &lia);
  172         if (error)
  173                 return (error);
  174         if (lia.s_addr == INADDR_ANY)
  175                 return (1);
  176 
  177         ia->s_addr = lia.s_addr;
  178         return (0);
  179 }
  180 
  181 /*
  182  * Return true if pr1 and pr2 have the same IPv4 address restrictions.
  183  */
  184 int
  185 prison_equal_ip4(struct prison *pr1, struct prison *pr2)
  186 {
  187 
  188         if (pr1 == pr2)
  189                 return (1);
  190 
  191         /*
  192          * No need to lock since the PR_IP4_USER flag can't be altered for
  193          * existing prisons.
  194          */
  195         while (pr1 != &prison0 &&
  196 #ifdef VIMAGE
  197                !(pr1->pr_flags & PR_VNET) &&
  198 #endif
  199                !(pr1->pr_flags & PR_IP4_USER))
  200                 pr1 = pr1->pr_parent;
  201         while (pr2 != &prison0 &&
  202 #ifdef VIMAGE
  203                !(pr2->pr_flags & PR_VNET) &&
  204 #endif
  205                !(pr2->pr_flags & PR_IP4_USER))
  206                 pr2 = pr2->pr_parent;
  207         return (pr1 == pr2);
  208 }
  209 
  210 /*
  211  * Make sure our (source) address is set to something meaningful to this
  212  * jail.
  213  *
  214  * Returns 0 if jail doesn't restrict IPv4 or if address belongs to jail,
  215  * EADDRNOTAVAIL if the address doesn't belong, or EAFNOSUPPORT if the jail
  216  * doesn't allow IPv4.  Address passed in in NBO and returned in NBO.
  217  */
  218 int
  219 prison_local_ip4(struct ucred *cred, struct in_addr *ia)
  220 {
  221         struct prison *pr;
  222         struct in_addr ia0;
  223         int error;
  224 
  225         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  226         KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
  227 
  228         pr = cred->cr_prison;
  229         if (!(pr->pr_flags & PR_IP4))
  230                 return (0);
  231         mtx_lock(&pr->pr_mtx);
  232         if (!(pr->pr_flags & PR_IP4)) {
  233                 mtx_unlock(&pr->pr_mtx);
  234                 return (0);
  235         }
  236         if (pr->pr_addrs[PR_INET] == NULL) {
  237                 mtx_unlock(&pr->pr_mtx);
  238                 return (EAFNOSUPPORT);
  239         }
  240 
  241         ia0.s_addr = ntohl(ia->s_addr);
  242 
  243         if (ia0.s_addr == INADDR_ANY) {
  244                 /*
  245                  * In case there is only 1 IPv4 address, bind directly.
  246                  */
  247                 if (prison_ip_cnt(pr, PR_INET) == 1)
  248                         ia->s_addr = prison_primary_ip4(pr);
  249                 mtx_unlock(&pr->pr_mtx);
  250                 return (0);
  251         }
  252 
  253         error = prison_check_ip4_locked(pr, ia);
  254         if (error == EADDRNOTAVAIL && ia0.s_addr == INADDR_LOOPBACK) {
  255                 ia->s_addr = prison_primary_ip4(pr);
  256                 error = 0;
  257         }
  258 
  259         mtx_unlock(&pr->pr_mtx);
  260         return (error);
  261 }
  262 
  263 /*
  264  * Rewrite destination address in case we will connect to loopback address.
  265  *
  266  * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4.
  267  * Address passed in in NBO and returned in NBO.
  268  */
  269 int
  270 prison_remote_ip4(struct ucred *cred, struct in_addr *ia)
  271 {
  272         struct prison *pr;
  273 
  274         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  275         KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
  276 
  277         pr = cred->cr_prison;
  278         if (!(pr->pr_flags & PR_IP4))
  279                 return (0);
  280         mtx_lock(&pr->pr_mtx);
  281         if (!(pr->pr_flags & PR_IP4)) {
  282                 mtx_unlock(&pr->pr_mtx);
  283                 return (0);
  284         }
  285         if (pr->pr_addrs[PR_INET] == NULL) {
  286                 mtx_unlock(&pr->pr_mtx);
  287                 return (EAFNOSUPPORT);
  288         }
  289 
  290         if (ntohl(ia->s_addr) == INADDR_LOOPBACK &&
  291             prison_check_ip4_locked(pr, ia) == EADDRNOTAVAIL) {
  292                 ia->s_addr = prison_primary_ip4(pr);
  293                 mtx_unlock(&pr->pr_mtx);
  294                 return (0);
  295         }
  296 
  297         /*
  298          * Return success because nothing had to be changed.
  299          */
  300         mtx_unlock(&pr->pr_mtx);
  301         return (0);
  302 }
  303 
  304 /*
  305  * Check if given address belongs to the jail referenced by cred/prison.
  306  *
  307  * Returns 0 if address belongs to jail,
  308  * EADDRNOTAVAIL if the address doesn't belong to the jail.
  309  */
  310 int
  311 prison_check_ip4_locked(const struct prison *pr, const struct in_addr *ia)
  312 {
  313 
  314         if (!(pr->pr_flags & PR_IP4))
  315                 return (0);
  316 
  317         return (prison_ip_check(pr, PR_INET, ia));
  318 }
  319 
  320 int
  321 prison_check_ip4(const struct ucred *cred, const struct in_addr *ia)
  322 {
  323         struct prison *pr;
  324         int error;
  325 
  326         KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
  327         KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
  328 
  329         pr = cred->cr_prison;
  330         if (!(pr->pr_flags & PR_IP4))
  331                 return (0);
  332         mtx_lock(&pr->pr_mtx);
  333         if (!(pr->pr_flags & PR_IP4)) {
  334                 mtx_unlock(&pr->pr_mtx);
  335                 return (0);
  336         }
  337         if (pr->pr_addrs[PR_INET] == NULL) {
  338                 mtx_unlock(&pr->pr_mtx);
  339                 return (EAFNOSUPPORT);
  340         }
  341 
  342         error = prison_check_ip4_locked(pr, ia);
  343         mtx_unlock(&pr->pr_mtx);
  344         return (error);
  345 }

Cache object: fbc63e5f1f8b8df9dff9e962993fc47c


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