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/kern/kern_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  * ----------------------------------------------------------------------------
    3  * "THE BEER-WARE LICENSE" (Revision 42):
    4  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
    5  * can do whatever you want with this stuff. If we meet some day, and you think
    6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
    7  * ----------------------------------------------------------------------------
    8  *
    9  */
   10 /*-
   11  * Copyright (c) 2006 Victor Balada Diaz <victor@bsdes.net>
   12  * All rights reserved.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 
   36 
   37 /*
   38  * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $
   39  * $DragonFly: src/sys/kern/kern_jail.c,v 1.19 2008/05/17 18:20:33 dillon Exp $
   40  */
   41 
   42 #include "opt_inet6.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/types.h>
   46 #include <sys/kernel.h>
   47 #include <sys/systm.h>
   48 #include <sys/errno.h>
   49 #include <sys/sysproto.h>
   50 #include <sys/malloc.h>
   51 #include <sys/nlookup.h>
   52 #include <sys/namecache.h>
   53 #include <sys/proc.h>
   54 #include <sys/priv.h>
   55 #include <sys/jail.h>
   56 #include <sys/socket.h>
   57 #include <sys/sysctl.h>
   58 #include <sys/kern_syscall.h>
   59 #include <net/if.h>
   60 #include <netinet/in.h>
   61 #include <netinet6/in6_var.h>
   62 
   63 #include <sys/mplock2.h>
   64 
   65 static struct prison    *prison_find(int);
   66 static void             prison_ipcache_init(struct prison *);
   67 
   68 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
   69 
   70 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
   71     "Jail rules");
   72 
   73 int     jail_set_hostname_allowed = 1;
   74 SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
   75     &jail_set_hostname_allowed, 0,
   76     "Processes in jail can set their hostnames");
   77 
   78 int     jail_socket_unixiproute_only = 1;
   79 SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
   80     &jail_socket_unixiproute_only, 0,
   81     "Processes in jail are limited to creating UNIX/IPv[46]/route sockets only");
   82 
   83 int     jail_sysvipc_allowed = 0;
   84 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
   85     &jail_sysvipc_allowed, 0,
   86     "Processes in jail can use System V IPC primitives");
   87 
   88 int    jail_chflags_allowed = 0;
   89 SYSCTL_INT(_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,
   90     &jail_chflags_allowed, 0,
   91     "Process in jail can set chflags(1)");
   92 
   93 int    jail_allow_raw_sockets = 0;
   94 SYSCTL_INT(_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,
   95     &jail_allow_raw_sockets, 0,
   96     "Process in jail can create raw sockets");
   97 
   98 int     lastprid = 0;
   99 int     prisoncount = 0;
  100 
  101 LIST_HEAD(prisonlist, prison);
  102 struct  prisonlist allprison = LIST_HEAD_INITIALIZER(&allprison);
  103 
  104 static int
  105 kern_jail_attach(int jid)
  106 {
  107         struct proc *p = curthread->td_proc;
  108         struct prison *pr;
  109         int error;
  110 
  111         pr = prison_find(jid);
  112         if (pr == NULL)
  113                 return(EINVAL);
  114 
  115         error = kern_chroot(&pr->pr_root);
  116         if (error)
  117                 return(error);
  118 
  119         prison_hold(pr);
  120         lwkt_gettoken(&p->p_token);
  121         cratom(&p->p_ucred);
  122         p->p_ucred->cr_prison = pr;
  123         p->p_flags |= P_JAILED;
  124         lwkt_reltoken(&p->p_token);
  125 
  126         return(0);
  127 }
  128 
  129 static int
  130 assign_prison_id(struct prison *pr)
  131 {
  132         int tryprid;
  133         struct prison *tpr;
  134 
  135         tryprid = lastprid + 1;
  136         if (tryprid == JAIL_MAX)
  137                 tryprid = 1;
  138 next:
  139         LIST_FOREACH(tpr, &allprison, pr_list) {
  140                 if (tpr->pr_id != tryprid)
  141                         continue;
  142                 tryprid++;
  143                 if (tryprid == JAIL_MAX) {
  144                         return (ERANGE);
  145                 }
  146                 goto next;
  147         }
  148         pr->pr_id = lastprid = tryprid;
  149 
  150         return (0);
  151 }
  152 
  153 static int
  154 kern_jail(struct prison *pr, struct jail *j)
  155 {
  156         int error;
  157         struct nlookupdata nd;
  158 
  159         error = nlookup_init(&nd, j->path, UIO_USERSPACE, NLC_FOLLOW);
  160         if (error) {
  161                 nlookup_done(&nd);
  162                 return (error);
  163         }
  164         error = nlookup(&nd);
  165         if (error) {
  166                 nlookup_done(&nd);
  167                 return (error);
  168         }
  169         cache_copy(&nd.nl_nch, &pr->pr_root);
  170 
  171         varsymset_init(&pr->pr_varsymset, NULL);
  172         prison_ipcache_init(pr);
  173 
  174         error = assign_prison_id(pr);
  175         if (error) {
  176                 varsymset_clean(&pr->pr_varsymset);
  177                 nlookup_done(&nd);
  178                 return (error);
  179         }
  180                 
  181         LIST_INSERT_HEAD(&allprison, pr, pr_list);
  182         ++prisoncount;
  183 
  184         error = kern_jail_attach(pr->pr_id);
  185         if (error) {
  186                 LIST_REMOVE(pr, pr_list);
  187                 --prisoncount;
  188                 varsymset_clean(&pr->pr_varsymset);
  189         }
  190         nlookup_done(&nd);
  191         return (error);
  192 }
  193 
  194 /*
  195  * jail()
  196  *
  197  * jail_args(syscallarg(struct jail *) jail)
  198  *
  199  * MPALMOSTSAFE
  200  */
  201 int
  202 sys_jail(struct jail_args *uap)
  203 {
  204         struct thread *td = curthread;
  205         struct prison *pr;
  206         struct jail_ip_storage *jip;
  207         struct jail j;
  208         int error;
  209         uint32_t jversion;
  210 
  211         uap->sysmsg_result = -1;
  212 
  213         error = priv_check(td, PRIV_JAIL_CREATE);
  214         if (error)
  215                 return (error);
  216 
  217         error = copyin(uap->jail, &jversion, sizeof(jversion));
  218         if (error)
  219                 return (error);
  220 
  221         pr = kmalloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
  222         SLIST_INIT(&pr->pr_ips);
  223         get_mplock();
  224 
  225         switch (jversion) {
  226         case 0:
  227                 /* Single IPv4 jails. */
  228                 {
  229                 struct jail_v0 jv0;
  230                 struct sockaddr_in ip4addr;
  231 
  232                 error = copyin(uap->jail, &jv0, sizeof(jv0));
  233                 if (error)
  234                         goto out;
  235 
  236                 j.path = jv0.path;
  237                 j.hostname = jv0.hostname; 
  238 
  239                 jip = kmalloc(sizeof(*jip),  M_PRISON, M_WAITOK | M_ZERO);
  240                 ip4addr.sin_family = AF_INET;
  241                 ip4addr.sin_addr.s_addr = htonl(jv0.ip_number);
  242                 memcpy(&jip->ip, &ip4addr, sizeof(ip4addr));
  243                 SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
  244                 break;
  245                 }
  246 
  247         case 1:
  248                 /*
  249                  * DragonFly multi noIP/IPv4/IPv6 jails
  250                  *
  251                  * NOTE: This version is unsupported by FreeBSD
  252                  * (which uses version 2 instead).
  253                  */
  254 
  255                 error = copyin(uap->jail, &j, sizeof(j));
  256                 if (error)
  257                         goto out;
  258 
  259                 for (int i = 0; i < j.n_ips; i++) {
  260                         jip = kmalloc(sizeof(*jip), M_PRISON,
  261                                       M_WAITOK | M_ZERO);
  262                         SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
  263                         error = copyin(&j.ips[i], &jip->ip,
  264                                         sizeof(struct sockaddr_storage));
  265                         if (error)
  266                                 goto out;
  267                 }
  268                 break;
  269         default:
  270                 error = EINVAL;
  271                 goto out;
  272         }
  273 
  274         error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
  275         if (error)
  276                 goto out;
  277 
  278         error = kern_jail(pr, &j);
  279         if (error)
  280                 goto out;
  281 
  282         uap->sysmsg_result = pr->pr_id;
  283         rel_mplock();
  284         return (0);
  285 
  286 out:
  287         /* Delete all ips */
  288         while (!SLIST_EMPTY(&pr->pr_ips)) {
  289                 jip = SLIST_FIRST(&pr->pr_ips);
  290                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
  291                 kfree(jip, M_PRISON);
  292         }
  293         rel_mplock();
  294         kfree(pr, M_PRISON);
  295         return (error);
  296 }
  297 
  298 /*
  299  * int jail_attach(int jid);
  300  *
  301  * MPALMOSTSAFE
  302  */
  303 int
  304 sys_jail_attach(struct jail_attach_args *uap)
  305 {
  306         struct thread *td = curthread;
  307         int error;
  308 
  309         error = priv_check(td, PRIV_JAIL_ATTACH);
  310         if (error)
  311                 return(error);
  312         get_mplock();
  313         error = kern_jail_attach(uap->jid);
  314         rel_mplock();
  315         return (error);
  316 }
  317 
  318 static void
  319 prison_ipcache_init(struct prison *pr)
  320 {
  321         struct jail_ip_storage *jis;
  322         struct sockaddr_in *ip4;
  323         struct sockaddr_in6 *ip6;
  324 
  325         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
  326                 switch (jis->ip.ss_family) {
  327                 case AF_INET:
  328                         ip4 = (struct sockaddr_in *)&jis->ip;
  329                         if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) ==
  330                             IN_LOOPBACKNET) {
  331                                 /* loopback address */
  332                                 if (pr->local_ip4 == NULL)
  333                                         pr->local_ip4 = ip4;
  334                         } else {
  335                                 /* public address */
  336                                 if (pr->nonlocal_ip4 == NULL)
  337                                         pr->nonlocal_ip4 = ip4;
  338                         }
  339                         break;
  340 
  341                 case AF_INET6:
  342                         ip6 = (struct sockaddr_in6 *)&jis->ip;
  343                         if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) {
  344                                 /* loopback address */
  345                                 if (pr->local_ip6 == NULL)
  346                                         pr->local_ip6 = ip6;
  347                         } else {
  348                                 /* public address */
  349                                 if (pr->nonlocal_ip6 == NULL)
  350                                         pr->nonlocal_ip6 = ip6;
  351                         }
  352                         break;
  353                 }
  354         }
  355 }
  356 
  357 /* 
  358  * Changes INADDR_LOOPBACK for a valid jail address.
  359  * ip is in network byte order.
  360  * Returns 1 if the ip is among jail valid ips.
  361  * Returns 0 if is not among jail valid ips or
  362  * if couldn't replace INADDR_LOOPBACK for a valid
  363  * IP.
  364  */
  365 int
  366 prison_replace_wildcards(struct thread *td, struct sockaddr *ip)
  367 {
  368         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
  369         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
  370         struct prison *pr;
  371 
  372         if (td->td_proc == NULL || td->td_ucred == NULL)
  373                 return (1);
  374         if ((pr = td->td_ucred->cr_prison) == NULL)
  375                 return (1);
  376 
  377         if ((ip->sa_family == AF_INET &&
  378             ip4->sin_addr.s_addr == htonl(INADDR_ANY)) ||
  379             (ip->sa_family == AF_INET6 &&
  380             IN6_IS_ADDR_UNSPECIFIED(&ip6->sin6_addr)))
  381                 return (1);
  382         if ((ip->sa_family == AF_INET &&
  383             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
  384             (ip->sa_family == AF_INET6 &&
  385             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
  386                 if (!prison_get_local(pr, ip->sa_family, ip) &&
  387                     !prison_get_nonlocal(pr, ip->sa_family, ip))
  388                         return(0);
  389                 else
  390                         return(1);
  391         }
  392         if (jailed_ip(pr, ip))
  393                 return(1);
  394         return(0);
  395 }
  396 
  397 int
  398 prison_remote_ip(struct thread *td, struct sockaddr *ip)
  399 {
  400         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
  401         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
  402         struct prison *pr;
  403 
  404         if (td == NULL || td->td_proc == NULL || td->td_ucred == NULL)
  405                 return(1);
  406         if ((pr = td->td_ucred->cr_prison) == NULL)
  407                 return(1);
  408         if ((ip->sa_family == AF_INET &&
  409             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
  410             (ip->sa_family == AF_INET6 &&
  411             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
  412                 if (!prison_get_local(pr, ip->sa_family, ip) &&
  413                     !prison_get_nonlocal(pr, ip->sa_family, ip))
  414                         return(0);
  415                 else
  416                         return(1);
  417         }
  418         return(1);
  419 }
  420 
  421 /*
  422  * Prison get non loopback ip:
  423  * - af is the address family of the ip we want (AF_INET|AF_INET6).
  424  * - If ip != NULL, put the first IP address that is not a loopback address
  425  *   into *ip.
  426  *
  427  * ip is in network by order and we don't touch it unless we find a valid ip.
  428  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
  429  * or NULL.  This struct may not be modified.
  430  */
  431 struct sockaddr *
  432 prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip)
  433 {
  434         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
  435         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
  436 
  437         /* Check if it is cached */
  438         switch(af) {
  439         case AF_INET:
  440                 if (ip4 != NULL && pr->nonlocal_ip4 != NULL)
  441                         ip4->sin_addr.s_addr = pr->nonlocal_ip4->sin_addr.s_addr;
  442                 return (struct sockaddr *)pr->nonlocal_ip4;
  443 
  444         case AF_INET6:
  445                 if (ip6 != NULL && pr->nonlocal_ip6 != NULL)
  446                         ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr;
  447                 return (struct sockaddr *)pr->nonlocal_ip6;
  448         }
  449 
  450         /* NOTREACHED */
  451         return NULL;
  452 }
  453 
  454 /*
  455  * Prison get loopback ip.
  456  * - af is the address family of the ip we want (AF_INET|AF_INET6).
  457  * - If ip != NULL, put the first IP address that is not a loopback address
  458  *   into *ip.
  459  *
  460  * ip is in network by order and we don't touch it unless we find a valid ip.
  461  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
  462  * or NULL.  This struct may not be modified.
  463  */
  464 struct sockaddr *
  465 prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip)
  466 {
  467         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
  468         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
  469 
  470         /* Check if it is cached */
  471         switch(af) {
  472         case AF_INET:
  473                 if (ip4 != NULL && pr->local_ip4 != NULL)
  474                         ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr;
  475                 return (struct sockaddr *)pr->local_ip4;
  476 
  477         case AF_INET6:
  478                 if (ip6 != NULL && pr->local_ip6 != NULL)
  479                         ip6->sin6_addr = pr->local_ip6->sin6_addr;
  480                 return (struct sockaddr *)pr->local_ip6;
  481         }
  482 
  483         /* NOTREACHED */
  484         return NULL;
  485 }
  486 
  487 /* Check if the IP is among ours, if it is return 1, else 0 */
  488 int
  489 jailed_ip(struct prison *pr, struct sockaddr *ip)
  490 {
  491         struct jail_ip_storage *jis;
  492         struct sockaddr_in *jip4, *ip4;
  493         struct sockaddr_in6 *jip6, *ip6;
  494 
  495         if (pr == NULL)
  496                 return(0);
  497         ip4 = (struct sockaddr_in *)ip;
  498         ip6 = (struct sockaddr_in6 *)ip;
  499         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
  500                 switch (ip->sa_family) {
  501                 case AF_INET:
  502                         jip4 = (struct sockaddr_in *) &jis->ip;
  503                         if (jip4->sin_family == AF_INET &&
  504                             ip4->sin_addr.s_addr == jip4->sin_addr.s_addr)
  505                                 return(1);
  506                         break;
  507                 case AF_INET6:
  508                         jip6 = (struct sockaddr_in6 *) &jis->ip;
  509                         if (jip6->sin6_family == AF_INET6 &&
  510                             IN6_ARE_ADDR_EQUAL(&ip6->sin6_addr,
  511                                                &jip6->sin6_addr))
  512                                 return(1);
  513                         break;
  514                 }
  515         }
  516         /* Ip not in list */
  517         return(0);
  518 }
  519 
  520 int
  521 prison_if(struct ucred *cred, struct sockaddr *sa)
  522 {
  523         struct prison *pr;
  524         struct sockaddr_in *sai = (struct sockaddr_in*) sa;
  525 
  526         pr = cred->cr_prison;
  527 
  528         if (((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
  529             && jail_socket_unixiproute_only)
  530                 return(1);
  531         else if ((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
  532                 return(0);
  533         else if (jailed_ip(pr, sa))
  534                 return(0);
  535         return(1);
  536 }
  537 
  538 /*
  539  * Returns a prison instance, or NULL on failure.
  540  */
  541 static struct prison *
  542 prison_find(int prid)
  543 {
  544         struct prison *pr;
  545 
  546         LIST_FOREACH(pr, &allprison, pr_list) {
  547                 if (pr->pr_id == prid)
  548                         break;
  549         }
  550         return(pr);
  551 }
  552 
  553 static int
  554 sysctl_jail_list(SYSCTL_HANDLER_ARGS)
  555 {
  556         struct thread *td = curthread;
  557         struct jail_ip_storage *jip;
  558 #ifdef INET6
  559         struct sockaddr_in6 *jsin6;
  560 #endif
  561         struct sockaddr_in *jsin;
  562         struct lwp *lp;
  563         struct prison *pr;
  564         unsigned int jlssize, jlsused;
  565         int count, error;
  566         char *jls; /* Jail list */
  567         char *oip; /* Output ip */
  568         char *fullpath, *freepath;
  569 
  570         jlsused = 0;
  571 
  572         if (jailed(td->td_ucred))
  573                 return (0);
  574         lp = td->td_lwp;
  575 retry:
  576         count = prisoncount;
  577 
  578         if (count == 0)
  579                 return(0);
  580 
  581         jlssize = (count * 1024);
  582         jls = kmalloc(jlssize + 1, M_TEMP, M_WAITOK | M_ZERO);
  583         if (count < prisoncount) {
  584                 kfree(jls, M_TEMP);
  585                 goto retry;
  586         }
  587         count = prisoncount;
  588 
  589         LIST_FOREACH(pr, &allprison, pr_list) {
  590                 error = cache_fullpath(lp->lwp_proc, &pr->pr_root, NULL,
  591                                         &fullpath, &freepath, 0);
  592                 if (error)
  593                         continue;
  594                 if (jlsused && jlsused < jlssize)
  595                         jls[jlsused++] = '\n';
  596                 count = ksnprintf(jls + jlsused, (jlssize - jlsused),
  597                                  "%d %s %s", 
  598                                  pr->pr_id, pr->pr_host, fullpath);
  599                 kfree(freepath, M_TEMP);                
  600                 if (count < 0)
  601                         goto end;
  602                 jlsused += count;
  603 
  604                 /* Copy the IPS */
  605                 SLIST_FOREACH(jip, &pr->pr_ips, entries) {
  606                         jsin = (struct sockaddr_in *)&jip->ip;
  607 
  608                         switch(jsin->sin_family) {
  609                         case AF_INET:
  610                                 oip = inet_ntoa(jsin->sin_addr);
  611                                 break;
  612 #ifdef INET6
  613                         case AF_INET6:
  614                                 jsin6 = (struct sockaddr_in6 *)&jip->ip;
  615                                 oip = ip6_sprintf(&jsin6->sin6_addr);
  616                                 break;
  617 #endif
  618                         default:
  619                                 oip = "?family?";
  620                                 break;
  621                         }
  622 
  623                         if ((jlssize - jlsused) < (strlen(oip) + 1)) {
  624                                 error = ERANGE;
  625                                 goto end;
  626                         }
  627                         count = ksnprintf(jls + jlsused, (jlssize - jlsused),
  628                                           " %s", oip);
  629                         if (count < 0)
  630                                 goto end;
  631                         jlsused += count;
  632                 }
  633         }
  634 
  635         /* 
  636          * The format is:
  637          * pr_id <SPC> hostname1 <SPC> PATH1 <SPC> IP1 <SPC> IP2\npr_id...
  638          */
  639         error = SYSCTL_OUT(req, jls, jlsused);
  640 end:
  641         kfree(jls, M_TEMP);
  642         return(error);
  643 }
  644 
  645 SYSCTL_OID(_jail, OID_AUTO, list, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
  646            sysctl_jail_list, "A", "List of active jails");
  647 
  648 /*
  649  * MPSAFE
  650  */
  651 void
  652 prison_hold(struct prison *pr)
  653 {
  654         atomic_add_int(&pr->pr_ref, 1);
  655 }
  656 
  657 /*
  658  * MPALMOSTSAFE
  659  */
  660 void
  661 prison_free(struct prison *pr)
  662 {
  663         struct jail_ip_storage *jls;
  664 
  665         KKASSERT(pr->pr_ref > 0);
  666         if (atomic_fetchadd_int(&pr->pr_ref, -1) != 1)
  667                 return;
  668 
  669         /*
  670          * The MP lock is needed on the last ref to adjust
  671          * the list.
  672          */
  673         get_mplock();
  674         if (pr->pr_ref) {
  675                 rel_mplock();
  676                 return;
  677         }
  678         LIST_REMOVE(pr, pr_list);
  679         --prisoncount;
  680         rel_mplock();
  681 
  682         /*
  683          * Clean up
  684          */
  685         while (!SLIST_EMPTY(&pr->pr_ips)) {
  686                 jls = SLIST_FIRST(&pr->pr_ips);
  687                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
  688                 kfree(jls, M_PRISON);
  689         }
  690 
  691         if (pr->pr_linux != NULL)
  692                 kfree(pr->pr_linux, M_PRISON);
  693         varsymset_clean(&pr->pr_varsymset);
  694         cache_drop(&pr->pr_root);
  695         kfree(pr, M_PRISON);
  696 }
  697 
  698 /*
  699  * Check if permisson for a specific privilege is granted within jail.
  700  *
  701  * MPSAFE
  702  */
  703 int
  704 prison_priv_check(struct ucred *cred, int priv)
  705 {
  706         if (!jailed(cred))
  707                 return (0);
  708 
  709         switch (priv) {
  710         case PRIV_CRED_SETUID:
  711         case PRIV_CRED_SETEUID:
  712         case PRIV_CRED_SETGID:
  713         case PRIV_CRED_SETEGID:
  714         case PRIV_CRED_SETGROUPS:
  715         case PRIV_CRED_SETREUID:
  716         case PRIV_CRED_SETREGID:
  717         case PRIV_CRED_SETRESUID:
  718         case PRIV_CRED_SETRESGID:
  719 
  720         case PRIV_VFS_SYSFLAGS:
  721         case PRIV_VFS_CHOWN:
  722         case PRIV_VFS_CHMOD:
  723         case PRIV_VFS_CHROOT:
  724         case PRIV_VFS_LINK:
  725         case PRIV_VFS_CHFLAGS_DEV:
  726         case PRIV_VFS_REVOKE:
  727         case PRIV_VFS_MKNOD_BAD:
  728         case PRIV_VFS_MKNOD_WHT:
  729         case PRIV_VFS_MKNOD_DIR:
  730         case PRIV_VFS_SETATTR:
  731         case PRIV_VFS_SETGID:
  732 
  733         case PRIV_PROC_SETRLIMIT:
  734         case PRIV_PROC_SETLOGIN:
  735 
  736         case PRIV_SYSCTL_WRITEJAIL:
  737 
  738         case PRIV_VARSYM_SYS:
  739 
  740         case PRIV_SETHOSTNAME:
  741 
  742         case PRIV_PROC_TRESPASS:
  743 
  744                 return (0);
  745 
  746         case PRIV_UFS_QUOTAON:
  747         case PRIV_UFS_QUOTAOFF:
  748         case PRIV_VFS_SETQUOTA:
  749         case PRIV_UFS_SETUSE:
  750         case PRIV_VFS_GETQUOTA:
  751                 return (0);
  752 
  753 
  754         case PRIV_DEBUG_UNPRIV:
  755                 return (0);
  756 
  757 
  758                 /*
  759                  * Allow jailed root to bind reserved ports.
  760                  */
  761         case PRIV_NETINET_RESERVEDPORT:
  762                 return (0);
  763 
  764 
  765                 /*
  766                  * Conditionally allow creating raw sockets in jail.
  767                  */
  768         case PRIV_NETINET_RAW:
  769                 if (jail_allow_raw_sockets)
  770                         return (0);
  771                 else
  772                         return (EPERM);
  773 
  774         case PRIV_HAMMER_IOCTL:
  775                 return (0);
  776 
  777         default:
  778 
  779                 return (EPERM);
  780         }
  781 }

Cache object: b78c60c7e4431d072c2ccf9f3292ae83


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