kern_jail.c revision 191671
1139804Simp/*- 2185435Sbz * Copyright (c) 1999 Poul-Henning Kamp. 3185435Sbz * Copyright (c) 2008 Bjoern A. Zeeb. 4185435Sbz * All rights reserved. 5190466Sjamie * 6185404Sbz * Redistribution and use in source and binary forms, with or without 7185404Sbz * modification, are permitted provided that the following conditions 8185404Sbz * are met: 9185404Sbz * 1. Redistributions of source code must retain the above copyright 10185404Sbz * notice, this list of conditions and the following disclaimer. 11185404Sbz * 2. Redistributions in binary form must reproduce the above copyright 12185404Sbz * notice, this list of conditions and the following disclaimer in the 13185404Sbz * documentation and/or other materials provided with the distribution. 14185404Sbz * 15185404Sbz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16185404Sbz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17185404Sbz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18185404Sbz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19185404Sbz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20185404Sbz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21185404Sbz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22185404Sbz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23185404Sbz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24185404Sbz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25185404Sbz * SUCH DAMAGE. 2646197Sphk */ 2746155Sphk 28116182Sobrien#include <sys/cdefs.h> 29116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_jail.c 191671 2009-04-29 18:41:08Z jamie $"); 30116182Sobrien 31185435Sbz#include "opt_ddb.h" 32185435Sbz#include "opt_inet.h" 33185435Sbz#include "opt_inet6.h" 34131177Spjd#include "opt_mac.h" 35131177Spjd 3646155Sphk#include <sys/param.h> 3746155Sphk#include <sys/types.h> 3846155Sphk#include <sys/kernel.h> 3946155Sphk#include <sys/systm.h> 4046155Sphk#include <sys/errno.h> 4146155Sphk#include <sys/sysproto.h> 4246155Sphk#include <sys/malloc.h> 43164032Srwatson#include <sys/priv.h> 4446155Sphk#include <sys/proc.h> 45124882Srwatson#include <sys/taskqueue.h> 46177785Skib#include <sys/fcntl.h> 4746155Sphk#include <sys/jail.h> 4887275Srwatson#include <sys/lock.h> 4987275Srwatson#include <sys/mutex.h> 50168401Spjd#include <sys/sx.h> 51113275Smike#include <sys/namei.h> 52147185Spjd#include <sys/mount.h> 53113275Smike#include <sys/queue.h> 5446155Sphk#include <sys/socket.h> 55113275Smike#include <sys/syscallsubr.h> 5657163Srwatson#include <sys/sysctl.h> 57113275Smike#include <sys/vnode.h> 58181803Sbz#include <sys/vimage.h> 59185029Spjd#include <sys/osd.h> 6046155Sphk#include <net/if.h> 6146155Sphk#include <netinet/in.h> 62185435Sbz#ifdef DDB 63185435Sbz#include <ddb/ddb.h> 64185435Sbz#ifdef INET6 65185435Sbz#include <netinet6/in6_var.h> 66185435Sbz#endif /* INET6 */ 67185435Sbz#endif /* DDB */ 6846155Sphk 69163606Srwatson#include <security/mac/mac_framework.h> 70163606Srwatson 7146155SphkMALLOC_DEFINE(M_PRISON, "prison", "Prison structures"); 7246155Sphk 7389414SarrSYSCTL_NODE(_security, OID_AUTO, jail, CTLFLAG_RW, 0, 7457163Srwatson "Jail rules"); 7557163Srwatson 7657163Srwatsonint jail_set_hostname_allowed = 1; 7789414SarrSYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, 7857163Srwatson &jail_set_hostname_allowed, 0, 7957163Srwatson "Processes in jail can set their hostnames"); 8057163Srwatson 8161235Srwatsonint jail_socket_unixiproute_only = 1; 8289414SarrSYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, 8361235Srwatson &jail_socket_unixiproute_only, 0, 84185435Sbz "Processes in jail are limited to creating UNIX/IP/route sockets only"); 8561235Srwatson 8668024Srwatsonint jail_sysvipc_allowed = 0; 8789414SarrSYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, 8868024Srwatson &jail_sysvipc_allowed, 0, 8968024Srwatson "Processes in jail can use System V IPC primitives"); 9068024Srwatson 91147185Spjdstatic int jail_enforce_statfs = 2; 92147185SpjdSYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW, 93147185Spjd &jail_enforce_statfs, 0, 94147185Spjd "Processes in jail cannot see all mounted file systems"); 95125804Srwatson 96128664Sbmilekicint jail_allow_raw_sockets = 0; 97128664SbmilekicSYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, 98128664Sbmilekic &jail_allow_raw_sockets, 0, 99128664Sbmilekic "Prison root can create raw sockets"); 100128664Sbmilekic 101141543Scpercivaint jail_chflags_allowed = 0; 102141543ScpercivaSYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW, 103141543Scperciva &jail_chflags_allowed, 0, 104141543Scperciva "Processes in jail can alter system file flags"); 105141543Scperciva 106168396Spjdint jail_mount_allowed = 0; 107168396SpjdSYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW, 108168396Spjd &jail_mount_allowed, 0, 109168396Spjd "Processes in jail can mount/unmount jail-friendly file systems"); 110168396Spjd 111185435Sbzint jail_max_af_ips = 255; 112185435SbzSYSCTL_INT(_security_jail, OID_AUTO, jail_max_af_ips, CTLFLAG_RW, 113185435Sbz &jail_max_af_ips, 0, 114185435Sbz "Number of IP addresses a jail may have at most per address family"); 115185435Sbz 116179881Sdelphij/* allprison, lastprid, and prisoncount are protected by allprison_lock. */ 117179881Sdelphijstruct prisonlist allprison; 118168401Spjdstruct sx allprison_lock; 119179881Sdelphijint lastprid = 0; 120113275Smikeint prisoncount = 0; 121113275Smike 122190466Sjamiestatic void init_prison(void *); 123190466Sjamiestatic void prison_complete(void *context, int pending); 124185435Sbz#ifdef INET 125190466Sjamiestatic int _prison_check_ip4(struct prison *pr, struct in_addr *ia); 126185435Sbz#endif 127185435Sbz#ifdef INET6 128190466Sjamiestatic int _prison_check_ip6(struct prison *pr, struct in6_addr *ia6); 129185435Sbz#endif 130191671Sjamiestatic int sysctl_jail_list(SYSCTL_HANDLER_ARGS); 131113275Smike 132113275Smikestatic void 133113275Smikeinit_prison(void *data __unused) 134113275Smike{ 135113275Smike 136179881Sdelphij sx_init(&allprison_lock, "allprison"); 137179881Sdelphij LIST_INIT(&allprison); 138113275Smike} 139113275Smike 140113275SmikeSYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL); 141113275Smike 142185435Sbz#ifdef INET 143185435Sbzstatic int 144185435Sbzqcmp_v4(const void *ip1, const void *ip2) 145185435Sbz{ 146185435Sbz in_addr_t iaa, iab; 147185435Sbz 148185435Sbz /* 149185435Sbz * We need to compare in HBO here to get the list sorted as expected 150185435Sbz * by the result of the code. Sorting NBO addresses gives you 151185435Sbz * interesting results. If you do not understand, do not try. 152185435Sbz */ 153185435Sbz iaa = ntohl(((const struct in_addr *)ip1)->s_addr); 154185435Sbz iab = ntohl(((const struct in_addr *)ip2)->s_addr); 155185435Sbz 156185435Sbz /* 157185435Sbz * Do not simply return the difference of the two numbers, the int is 158185435Sbz * not wide enough. 159185435Sbz */ 160185435Sbz if (iaa > iab) 161185435Sbz return (1); 162185435Sbz else if (iaa < iab) 163185435Sbz return (-1); 164185435Sbz else 165185435Sbz return (0); 166185435Sbz} 167185435Sbz#endif 168185435Sbz 169185435Sbz#ifdef INET6 170185435Sbzstatic int 171185435Sbzqcmp_v6(const void *ip1, const void *ip2) 172185435Sbz{ 173185435Sbz const struct in6_addr *ia6a, *ia6b; 174185435Sbz int i, rc; 175185435Sbz 176185435Sbz ia6a = (const struct in6_addr *)ip1; 177185435Sbz ia6b = (const struct in6_addr *)ip2; 178185435Sbz 179185435Sbz rc = 0; 180190466Sjamie for (i = 0; rc == 0 && i < sizeof(struct in6_addr); i++) { 181185435Sbz if (ia6a->s6_addr[i] > ia6b->s6_addr[i]) 182185435Sbz rc = 1; 183185435Sbz else if (ia6a->s6_addr[i] < ia6b->s6_addr[i]) 184185435Sbz rc = -1; 185185435Sbz } 186185435Sbz return (rc); 187185435Sbz} 188185435Sbz#endif 189185435Sbz 190185435Sbz#if defined(INET) || defined(INET6) 191185435Sbzstatic int 192185435Sbzprison_check_conflicting_ips(struct prison *p) 193185435Sbz{ 194185435Sbz struct prison *pr; 195185435Sbz int i; 196185435Sbz 197185435Sbz sx_assert(&allprison_lock, SX_LOCKED); 198185435Sbz 199185435Sbz if (p->pr_ip4s == 0 && p->pr_ip6s == 0) 200185435Sbz return (0); 201185435Sbz 202185435Sbz LIST_FOREACH(pr, &allprison, pr_list) { 203185435Sbz /* 204185435Sbz * Skip 'dying' prisons to avoid problems when 205185435Sbz * restarting multi-IP jails. 206185435Sbz */ 207185435Sbz if (pr->pr_state == PRISON_STATE_DYING) 208185435Sbz continue; 209185435Sbz 210185435Sbz /* 211185435Sbz * We permit conflicting IPs if there is no 212185435Sbz * more than 1 IP on eeach jail. 213185435Sbz * In case there is one duplicate on a jail with 214185435Sbz * more than one IP stop checking and return error. 215185435Sbz */ 216185435Sbz#ifdef INET 217185435Sbz if ((p->pr_ip4s >= 1 && pr->pr_ip4s > 1) || 218185435Sbz (p->pr_ip4s > 1 && pr->pr_ip4s >= 1)) { 219185435Sbz for (i = 0; i < p->pr_ip4s; i++) { 220188144Sjamie if (_prison_check_ip4(pr, &p->pr_ip4[i]) == 0) 221185435Sbz return (EINVAL); 222185435Sbz } 223185435Sbz } 224185435Sbz#endif 225185435Sbz#ifdef INET6 226185435Sbz if ((p->pr_ip6s >= 1 && pr->pr_ip6s > 1) || 227185435Sbz (p->pr_ip6s > 1 && pr->pr_ip6s >= 1)) { 228185435Sbz for (i = 0; i < p->pr_ip6s; i++) { 229188144Sjamie if (_prison_check_ip6(pr, &p->pr_ip6[i]) == 0) 230185435Sbz return (EINVAL); 231185435Sbz } 232185435Sbz } 233185435Sbz#endif 234185435Sbz } 235185435Sbz 236185435Sbz return (0); 237185435Sbz} 238185435Sbz 239185435Sbzstatic int 240185435Sbzjail_copyin_ips(struct jail *j) 241185435Sbz{ 242185435Sbz#ifdef INET 243190466Sjamie struct in_addr *ip4; 244185435Sbz#endif 245185435Sbz#ifdef INET6 246185435Sbz struct in6_addr *ip6; 247185435Sbz#endif 248185435Sbz int error, i; 249185435Sbz 250185435Sbz /* 251185435Sbz * Copy in addresses, check for duplicate addresses and do some 252185435Sbz * simple 0 and broadcast checks. If users give other bogus addresses 253185435Sbz * it is their problem. 254185435Sbz * 255185435Sbz * IP addresses are all sorted but ip[0] to preserve the primary IP 256185435Sbz * address as given from userland. This special IP is used for 257185435Sbz * unbound outgoing connections as well for "loopback" traffic. 258185435Sbz */ 259185435Sbz#ifdef INET 260185435Sbz ip4 = NULL; 261185435Sbz#endif 262185435Sbz#ifdef INET6 263185435Sbz ip6 = NULL; 264185435Sbz#endif 265185435Sbz#ifdef INET 266185435Sbz if (j->ip4s > 0) { 267185435Sbz ip4 = (struct in_addr *)malloc(j->ip4s * sizeof(struct in_addr), 268185435Sbz M_PRISON, M_WAITOK | M_ZERO); 269185435Sbz error = copyin(j->ip4, ip4, j->ip4s * sizeof(struct in_addr)); 270185435Sbz if (error) 271185435Sbz goto e_free_ip; 272185435Sbz /* Sort all but the first IPv4 address. */ 273185435Sbz if (j->ip4s > 1) 274185435Sbz qsort((ip4 + 1), j->ip4s - 1, 275185435Sbz sizeof(struct in_addr), qcmp_v4); 276185435Sbz 277185435Sbz /* 278185435Sbz * We do not have to care about byte order for these checks 279185435Sbz * so we will do them in NBO. 280185435Sbz */ 281185435Sbz for (i=0; i<j->ip4s; i++) { 282185435Sbz if (ip4[i].s_addr == htonl(INADDR_ANY) || 283185435Sbz ip4[i].s_addr == htonl(INADDR_BROADCAST)) { 284185435Sbz error = EINVAL; 285185435Sbz goto e_free_ip; 286185435Sbz } 287185435Sbz if ((i+1) < j->ip4s && 288185435Sbz (ip4[0].s_addr == ip4[i+1].s_addr || 289185435Sbz ip4[i].s_addr == ip4[i+1].s_addr)) { 290185435Sbz error = EINVAL; 291185435Sbz goto e_free_ip; 292185435Sbz } 293185435Sbz } 294185435Sbz 295185435Sbz j->ip4 = ip4; 296186606Spho } else 297186606Spho j->ip4 = NULL; 298185435Sbz#endif 299185435Sbz#ifdef INET6 300185435Sbz if (j->ip6s > 0) { 301185435Sbz ip6 = (struct in6_addr *)malloc(j->ip6s * sizeof(struct in6_addr), 302185435Sbz M_PRISON, M_WAITOK | M_ZERO); 303185435Sbz error = copyin(j->ip6, ip6, j->ip6s * sizeof(struct in6_addr)); 304185435Sbz if (error) 305185435Sbz goto e_free_ip; 306185435Sbz /* Sort all but the first IPv6 address. */ 307185435Sbz if (j->ip6s > 1) 308185435Sbz qsort((ip6 + 1), j->ip6s - 1, 309185435Sbz sizeof(struct in6_addr), qcmp_v6); 310185435Sbz for (i=0; i<j->ip6s; i++) { 311185435Sbz if (IN6_IS_ADDR_UNSPECIFIED(&ip6[i])) { 312185435Sbz error = EINVAL; 313185435Sbz goto e_free_ip; 314185435Sbz } 315185435Sbz if ((i+1) < j->ip6s && 316185435Sbz (IN6_ARE_ADDR_EQUAL(&ip6[0], &ip6[i+1]) || 317185435Sbz IN6_ARE_ADDR_EQUAL(&ip6[i], &ip6[i+1]))) { 318185435Sbz error = EINVAL; 319185435Sbz goto e_free_ip; 320185435Sbz } 321185435Sbz } 322185435Sbz 323185435Sbz j->ip6 = ip6; 324186606Spho } else 325186606Spho j->ip6 = NULL; 326185435Sbz#endif 327185435Sbz return (0); 328185435Sbz 329185435Sbze_free_ip: 330185435Sbz#ifdef INET6 331185435Sbz free(ip6, M_PRISON); 332185435Sbz#endif 333185435Sbz#ifdef INET 334185435Sbz free(ip4, M_PRISON); 335185435Sbz#endif 336185435Sbz return (error); 337185435Sbz} 338185435Sbz#endif /* INET || INET6 */ 339185435Sbz 340185435Sbzstatic int 341185435Sbzjail_handle_ips(struct jail *j) 342185435Sbz{ 343185435Sbz#if defined(INET) || defined(INET6) 344185435Sbz int error; 345185435Sbz#endif 346185435Sbz 347185435Sbz /* 348185435Sbz * Finish conversion for older versions, copyin and setup IPs. 349185435Sbz */ 350185435Sbz switch (j->version) { 351190466Sjamie case 0: 352185435Sbz { 353185435Sbz#ifdef INET 354185435Sbz /* FreeBSD single IPv4 jails. */ 355185435Sbz struct in_addr *ip4; 356185435Sbz 357185435Sbz if (j->ip4s == INADDR_ANY || j->ip4s == INADDR_BROADCAST) 358185435Sbz return (EINVAL); 359185435Sbz ip4 = (struct in_addr *)malloc(sizeof(struct in_addr), 360185435Sbz M_PRISON, M_WAITOK | M_ZERO); 361185435Sbz 362185435Sbz /* 363185435Sbz * Jail version 0 still used HBO for the IPv4 address. 364185435Sbz */ 365185435Sbz ip4->s_addr = htonl(j->ip4s); 366185435Sbz j->ip4s = 1; 367185435Sbz j->ip4 = ip4; 368185435Sbz break; 369185435Sbz#else 370185435Sbz return (EINVAL); 371185435Sbz#endif 372185435Sbz } 373185435Sbz 374185435Sbz case 1: 375185435Sbz /* 376185435Sbz * Version 1 was used by multi-IPv4 jail implementations 377185435Sbz * that never made it into the official kernel. 378185435Sbz * We should never hit this here; jail() should catch it. 379185435Sbz */ 380185435Sbz return (EINVAL); 381185435Sbz 382185435Sbz case 2: /* JAIL_API_VERSION */ 383185435Sbz /* FreeBSD multi-IPv4/IPv6,noIP jails. */ 384185435Sbz#if defined(INET) || defined(INET6) 385185435Sbz#ifdef INET 386185435Sbz if (j->ip4s > jail_max_af_ips) 387185435Sbz return (EINVAL); 388185435Sbz#else 389185435Sbz if (j->ip4s != 0) 390185435Sbz return (EINVAL); 391185435Sbz#endif 392185435Sbz#ifdef INET6 393185435Sbz if (j->ip6s > jail_max_af_ips) 394185435Sbz return (EINVAL); 395185435Sbz#else 396185435Sbz if (j->ip6s != 0) 397185435Sbz return (EINVAL); 398185435Sbz#endif 399185435Sbz error = jail_copyin_ips(j); 400185435Sbz if (error) 401185435Sbz return (error); 402185435Sbz#endif 403185435Sbz break; 404185435Sbz 405185435Sbz default: 406185435Sbz /* Sci-Fi jails are not supported, sorry. */ 407185435Sbz return (EINVAL); 408185435Sbz } 409185435Sbz 410185435Sbz return (0); 411185435Sbz} 412185435Sbz 413185435Sbz 41482710Sdillon/* 415114168Smike * struct jail_args { 416114168Smike * struct jail *jail; 417114168Smike * }; 41882710Sdillon */ 41946155Sphkint 420114168Smikejail(struct thread *td, struct jail_args *uap) 42146155Sphk{ 422185435Sbz uint32_t version; 423185435Sbz int error; 424185435Sbz struct jail j; 425185435Sbz 426185435Sbz error = copyin(uap->jail, &version, sizeof(uint32_t)); 427185435Sbz if (error) 428185435Sbz return (error); 429185435Sbz 430185435Sbz switch (version) { 431185435Sbz case 0: 432185435Sbz /* FreeBSD single IPv4 jails. */ 433185435Sbz { 434185435Sbz struct jail_v0 j0; 435185435Sbz 436185435Sbz bzero(&j, sizeof(struct jail)); 437185435Sbz error = copyin(uap->jail, &j0, sizeof(struct jail_v0)); 438185435Sbz if (error) 439185435Sbz return (error); 440185435Sbz j.version = j0.version; 441185435Sbz j.path = j0.path; 442185435Sbz j.hostname = j0.hostname; 443185435Sbz j.ip4s = j0.ip_number; 444185435Sbz break; 445185435Sbz } 446185435Sbz 447185435Sbz case 1: 448185435Sbz /* 449185435Sbz * Version 1 was used by multi-IPv4 jail implementations 450185435Sbz * that never made it into the official kernel. 451185435Sbz */ 452185435Sbz return (EINVAL); 453185435Sbz 454185435Sbz case 2: /* JAIL_API_VERSION */ 455185435Sbz /* FreeBSD multi-IPv4/IPv6,noIP jails. */ 456185435Sbz error = copyin(uap->jail, &j, sizeof(struct jail)); 457185435Sbz if (error) 458185435Sbz return (error); 459185435Sbz break; 460185435Sbz 461185435Sbz default: 462185435Sbz /* Sci-Fi jails are not supported, sorry. */ 463185435Sbz return (EINVAL); 464185435Sbz } 465185435Sbz return (kern_jail(td, &j)); 466185435Sbz} 467185435Sbz 468185435Sbzint 469185435Sbzkern_jail(struct thread *td, struct jail *j) 470185435Sbz{ 471113275Smike struct nameidata nd; 472179881Sdelphij struct prison *pr, *tpr; 473113275Smike struct jail_attach_args jaa; 474179881Sdelphij int vfslocked, error, tryprid; 47546155Sphk 476185435Sbz KASSERT(j != NULL, ("%s: j is NULL", __func__)); 477185435Sbz 478185435Sbz /* Handle addresses - convert old structs, copyin, check IPs. */ 479185435Sbz error = jail_handle_ips(j); 48046155Sphk if (error) 48184828Sjhb return (error); 48284828Sjhb 483185435Sbz /* Allocate struct prison and fill it with life. */ 484184205Sdes pr = malloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); 48593818Sjhb mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF); 486113275Smike pr->pr_ref = 1; 487185435Sbz error = copyinstr(j->path, &pr->pr_path, sizeof(pr->pr_path), NULL); 488113275Smike if (error) 489113275Smike goto e_killmtx; 490150652Scsjp NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE, 491150652Scsjp pr->pr_path, td); 492113275Smike error = namei(&nd); 493150652Scsjp if (error) 494113275Smike goto e_killmtx; 495150652Scsjp vfslocked = NDHASGIANT(&nd); 496113275Smike pr->pr_root = nd.ni_vp; 497175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 498113275Smike NDFREE(&nd, NDF_ONLY_PNBUF); 499150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 500185435Sbz error = copyinstr(j->hostname, &pr->pr_host, sizeof(pr->pr_host), NULL); 50184828Sjhb if (error) 502113275Smike goto e_dropvnref; 503185435Sbz if (j->jailname != NULL) { 504185435Sbz error = copyinstr(j->jailname, &pr->pr_name, 505185435Sbz sizeof(pr->pr_name), NULL); 506185435Sbz if (error) 507185435Sbz goto e_dropvnref; 508185435Sbz } 509185435Sbz if (j->ip4s > 0) { 510185435Sbz pr->pr_ip4 = j->ip4; 511185435Sbz pr->pr_ip4s = j->ip4s; 512185435Sbz } 513185435Sbz#ifdef INET6 514185435Sbz if (j->ip6s > 0) { 515185435Sbz pr->pr_ip6 = j->ip6; 516185435Sbz pr->pr_ip6s = j->ip6s; 517185435Sbz } 518185435Sbz#endif 519113275Smike pr->pr_linux = NULL; 520113275Smike pr->pr_securelevel = securelevel; 521185029Spjd bzero(&pr->pr_osd, sizeof(pr->pr_osd)); 522113275Smike 523185435Sbz /* 524185435Sbz * Pre-set prison state to ALIVE upon cration. This is needed so we 525185435Sbz * can later attach the process to it, etc (avoiding another extra 526185435Sbz * state for ther process of creation, complicating things). 527185435Sbz */ 528185435Sbz pr->pr_state = PRISON_STATE_ALIVE; 529185435Sbz 530185435Sbz /* Allocate a dedicated cpuset for each jail. */ 531185435Sbz error = cpuset_create_root(td, &pr->pr_cpuset); 532185435Sbz if (error) 533185435Sbz goto e_dropvnref; 534185435Sbz 535185435Sbz sx_xlock(&allprison_lock); 536185435Sbz /* Make sure we cannot run into problems with ambiguous bind()ings. */ 537185441Sbz#if defined(INET) || defined(INET6) 538185435Sbz error = prison_check_conflicting_ips(pr); 539185435Sbz if (error) { 540185435Sbz sx_xunlock(&allprison_lock); 541185435Sbz goto e_dropcpuset; 542185435Sbz } 543185441Sbz#endif 544185435Sbz 545179881Sdelphij /* Determine next pr_id and add prison to allprison list. */ 546179881Sdelphij tryprid = lastprid + 1; 547179881Sdelphij if (tryprid == JAIL_MAX) 548179881Sdelphij tryprid = 1; 549179881Sdelphijnext: 550179881Sdelphij LIST_FOREACH(tpr, &allprison, pr_list) { 551179881Sdelphij if (tpr->pr_id == tryprid) { 552179881Sdelphij tryprid++; 553179881Sdelphij if (tryprid == JAIL_MAX) { 554179881Sdelphij sx_xunlock(&allprison_lock); 555179881Sdelphij error = EAGAIN; 556185435Sbz goto e_dropcpuset; 557179881Sdelphij } 558179881Sdelphij goto next; 559179881Sdelphij } 560179881Sdelphij } 561179881Sdelphij pr->pr_id = jaa.jid = lastprid = tryprid; 562113275Smike LIST_INSERT_HEAD(&allprison, pr, pr_list); 563113275Smike prisoncount++; 564185029Spjd sx_xunlock(&allprison_lock); 565113275Smike 566113275Smike error = jail_attach(td, &jaa); 567113275Smike if (error) 568113275Smike goto e_dropprref; 569113275Smike mtx_lock(&pr->pr_mtx); 570113275Smike pr->pr_ref--; 571113275Smike mtx_unlock(&pr->pr_mtx); 572113275Smike td->td_retval[0] = jaa.jid; 573113275Smike return (0); 574113275Smikee_dropprref: 575168401Spjd sx_xlock(&allprison_lock); 576113275Smike LIST_REMOVE(pr, pr_list); 577113275Smike prisoncount--; 578185029Spjd sx_xunlock(&allprison_lock); 579185435Sbze_dropcpuset: 580185435Sbz cpuset_rel(pr->pr_cpuset); 581113275Smikee_dropvnref: 582150652Scsjp vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 583113275Smike vrele(pr->pr_root); 584150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 585113275Smikee_killmtx: 586113275Smike mtx_destroy(&pr->pr_mtx); 587184205Sdes free(pr, M_PRISON); 588185435Sbz#ifdef INET6 589185435Sbz free(j->ip6, M_PRISON); 590185435Sbz#endif 591185435Sbz#ifdef INET 592185435Sbz free(j->ip4, M_PRISON); 593185435Sbz#endif 594113275Smike return (error); 595113275Smike} 596113275Smike 597190466Sjamie 598113275Smike/* 599114168Smike * struct jail_attach_args { 600114168Smike * int jid; 601114168Smike * }; 602113275Smike */ 603113275Smikeint 604114168Smikejail_attach(struct thread *td, struct jail_attach_args *uap) 605113275Smike{ 606113275Smike struct proc *p; 607113275Smike struct ucred *newcred, *oldcred; 608113275Smike struct prison *pr; 609150652Scsjp int vfslocked, error; 610167309Spjd 611126023Snectar /* 612126023Snectar * XXX: Note that there is a slight race here if two threads 613126023Snectar * in the same privileged process attempt to attach to two 614126023Snectar * different jails at the same time. It is important for 615126023Snectar * user processes not to do this, or they might end up with 616126023Snectar * a process root from one prison, but attached to the jail 617126023Snectar * of another. 618126023Snectar */ 619164032Srwatson error = priv_check(td, PRIV_JAIL_ATTACH); 620126023Snectar if (error) 621126023Snectar return (error); 622126023Snectar 623113275Smike p = td->td_proc; 624168401Spjd sx_slock(&allprison_lock); 625113275Smike pr = prison_find(uap->jid); 626113275Smike if (pr == NULL) { 627168401Spjd sx_sunlock(&allprison_lock); 628113275Smike return (EINVAL); 629113275Smike } 630185435Sbz 631185435Sbz /* 632185435Sbz * Do not allow a process to attach to a prison that is not 633185435Sbz * considered to be "ALIVE". 634185435Sbz */ 635185435Sbz if (pr->pr_state != PRISON_STATE_ALIVE) { 636185435Sbz mtx_unlock(&pr->pr_mtx); 637185435Sbz sx_sunlock(&allprison_lock); 638185435Sbz return (EINVAL); 639185435Sbz } 640113275Smike pr->pr_ref++; 641113275Smike mtx_unlock(&pr->pr_mtx); 642168401Spjd sx_sunlock(&allprison_lock); 643113275Smike 644185435Sbz /* 645185435Sbz * Reparent the newly attached process to this jail. 646185435Sbz */ 647185435Sbz error = cpuset_setproc_update_set(p, pr->pr_cpuset); 648185435Sbz if (error) 649185435Sbz goto e_unref; 650185435Sbz 651150652Scsjp vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 652175202Sattilio vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY); 653113275Smike if ((error = change_dir(pr->pr_root, td)) != 0) 654113275Smike goto e_unlock; 655113275Smike#ifdef MAC 656172930Srwatson if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root))) 657113275Smike goto e_unlock; 658113275Smike#endif 659175294Sattilio VOP_UNLOCK(pr->pr_root, 0); 660113275Smike change_root(pr->pr_root, td); 661150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 662113275Smike 66384828Sjhb newcred = crget(); 66484828Sjhb PROC_LOCK(p); 66584828Sjhb oldcred = p->p_ucred; 666113275Smike setsugid(p); 66784828Sjhb crcopy(newcred, oldcred); 668113630Sjhb newcred->cr_prison = pr; 66984828Sjhb p->p_ucred = newcred; 670185435Sbz prison_proc_hold(pr); 67184828Sjhb PROC_UNLOCK(p); 67284828Sjhb crfree(oldcred); 67346155Sphk return (0); 674113275Smikee_unlock: 675175294Sattilio VOP_UNLOCK(pr->pr_root, 0); 676150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 677185435Sbze_unref: 678113275Smike mtx_lock(&pr->pr_mtx); 679113275Smike pr->pr_ref--; 680113275Smike mtx_unlock(&pr->pr_mtx); 68146155Sphk return (error); 68246155Sphk} 68346155Sphk 684113275Smike/* 685113275Smike * Returns a locked prison instance, or NULL on failure. 686113275Smike */ 687168399Spjdstruct prison * 688113275Smikeprison_find(int prid) 689113275Smike{ 690113275Smike struct prison *pr; 691113275Smike 692168401Spjd sx_assert(&allprison_lock, SX_LOCKED); 693113275Smike LIST_FOREACH(pr, &allprison, pr_list) { 694113275Smike if (pr->pr_id == prid) { 695113275Smike mtx_lock(&pr->pr_mtx); 696168489Spjd if (pr->pr_ref == 0) { 697168489Spjd mtx_unlock(&pr->pr_mtx); 698168489Spjd break; 699168489Spjd } 700113275Smike return (pr); 701113275Smike } 702113275Smike } 703113275Smike return (NULL); 704113275Smike} 705113275Smike 70672786Srwatsonvoid 707185029Spjdprison_free_locked(struct prison *pr) 70872786Srwatson{ 70972786Srwatson 710185029Spjd mtx_assert(&pr->pr_mtx, MA_OWNED); 71172786Srwatson pr->pr_ref--; 71272786Srwatson if (pr->pr_ref == 0) { 713168483Spjd mtx_unlock(&pr->pr_mtx); 714124882Srwatson TASK_INIT(&pr->pr_task, 0, prison_complete, pr); 715144660Sjeff taskqueue_enqueue(taskqueue_thread, &pr->pr_task); 71687275Srwatson return; 71772786Srwatson } 71887275Srwatson mtx_unlock(&pr->pr_mtx); 71972786Srwatson} 72072786Srwatson 721185029Spjdvoid 722185029Spjdprison_free(struct prison *pr) 723185029Spjd{ 724185029Spjd 725185029Spjd mtx_lock(&pr->pr_mtx); 726185029Spjd prison_free_locked(pr); 727185029Spjd} 728185029Spjd 729124882Srwatsonstatic void 730124882Srwatsonprison_complete(void *context, int pending) 731124882Srwatson{ 732124882Srwatson struct prison *pr; 733150652Scsjp int vfslocked; 734124882Srwatson 735124882Srwatson pr = (struct prison *)context; 736124882Srwatson 737168489Spjd sx_xlock(&allprison_lock); 738168489Spjd LIST_REMOVE(pr, pr_list); 739168489Spjd prisoncount--; 740185029Spjd sx_xunlock(&allprison_lock); 741168489Spjd 742185435Sbz cpuset_rel(pr->pr_cpuset); 743185435Sbz 744185029Spjd /* Free all OSD associated to this jail. */ 745185029Spjd osd_jail_exit(pr); 746185029Spjd 747150652Scsjp vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 748124882Srwatson vrele(pr->pr_root); 749150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 750124882Srwatson 751124882Srwatson mtx_destroy(&pr->pr_mtx); 752185435Sbz free(pr->pr_linux, M_PRISON); 753185435Sbz#ifdef INET6 754185435Sbz free(pr->pr_ip6, M_PRISON); 755185435Sbz#endif 756185435Sbz#ifdef INET 757185435Sbz free(pr->pr_ip4, M_PRISON); 758185435Sbz#endif 759184205Sdes free(pr, M_PRISON); 760124882Srwatson} 761124882Srwatson 76272786Srwatsonvoid 763185029Spjdprison_hold_locked(struct prison *pr) 76472786Srwatson{ 76572786Srwatson 766185029Spjd mtx_assert(&pr->pr_mtx, MA_OWNED); 767168489Spjd KASSERT(pr->pr_ref > 0, 768191671Sjamie ("Trying to hold dead prison (jid=%d).", pr->pr_id)); 76972786Srwatson pr->pr_ref++; 770185029Spjd} 771185029Spjd 772185029Spjdvoid 773185029Spjdprison_hold(struct prison *pr) 774185029Spjd{ 775185029Spjd 776185029Spjd mtx_lock(&pr->pr_mtx); 777185029Spjd prison_hold_locked(pr); 77887275Srwatson mtx_unlock(&pr->pr_mtx); 77972786Srwatson} 78072786Srwatson 781185435Sbzvoid 782185435Sbzprison_proc_hold(struct prison *pr) 78387275Srwatson{ 78487275Srwatson 785185435Sbz mtx_lock(&pr->pr_mtx); 786185435Sbz KASSERT(pr->pr_state == PRISON_STATE_ALIVE, 787191671Sjamie ("Cannot add a process to a non-alive prison (jid=%d).", 788191671Sjamie pr->pr_id)); 789185435Sbz pr->pr_nprocs++; 790185435Sbz mtx_unlock(&pr->pr_mtx); 79187275Srwatson} 79287275Srwatson 793185435Sbzvoid 794185435Sbzprison_proc_free(struct prison *pr) 795185435Sbz{ 796185435Sbz 797185435Sbz mtx_lock(&pr->pr_mtx); 798185435Sbz KASSERT(pr->pr_state == PRISON_STATE_ALIVE && pr->pr_nprocs > 0, 799191671Sjamie ("Trying to kill a process in a dead prison (jid=%d).", pr->pr_id)); 800185435Sbz pr->pr_nprocs--; 801185435Sbz if (pr->pr_nprocs == 0) 802185435Sbz pr->pr_state = PRISON_STATE_DYING; 803185435Sbz mtx_unlock(&pr->pr_mtx); 804185435Sbz} 805185435Sbz 806185435Sbz 807185435Sbz#ifdef INET 808185435Sbz/* 809185435Sbz * Pass back primary IPv4 address of this jail. 810185435Sbz * 811185435Sbz * If not jailed return success but do not alter the address. Caller has to 812190466Sjamie * make sure to initialize it correctly (e.g. INADDR_ANY). 813185435Sbz * 814188144Sjamie * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4. 815188144Sjamie * Address returned in NBO. 816185435Sbz */ 81746155Sphkint 818187684Sbzprison_get_ip4(struct ucred *cred, struct in_addr *ia) 81946155Sphk{ 82046155Sphk 821185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 822185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 823185435Sbz 82472786Srwatson if (!jailed(cred)) 82546155Sphk return (0); 826185435Sbz if (cred->cr_prison->pr_ip4 == NULL) 827188144Sjamie return (EAFNOSUPPORT); 828185435Sbz 829185435Sbz ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 830185435Sbz return (0); 831185435Sbz} 832185435Sbz 833185435Sbz/* 834185435Sbz * Make sure our (source) address is set to something meaningful to this 835185435Sbz * jail. 836185435Sbz * 837188144Sjamie * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if 838188144Sjamie * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv4. 839188144Sjamie * Address passed in in NBO and returned in NBO. 840185435Sbz */ 841185435Sbzint 842185435Sbzprison_local_ip4(struct ucred *cred, struct in_addr *ia) 843185435Sbz{ 844185435Sbz struct in_addr ia0; 845185435Sbz 846185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 847185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 848185435Sbz 849185435Sbz if (!jailed(cred)) 85046155Sphk return (0); 851185435Sbz if (cred->cr_prison->pr_ip4 == NULL) 852188144Sjamie return (EAFNOSUPPORT); 853185435Sbz 854185435Sbz ia0.s_addr = ntohl(ia->s_addr); 855185435Sbz if (ia0.s_addr == INADDR_LOOPBACK) { 856185435Sbz ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 857185435Sbz return (0); 85846155Sphk } 859185435Sbz 860188144Sjamie if (ia0.s_addr == INADDR_ANY) { 861188144Sjamie /* 862188144Sjamie * In case there is only 1 IPv4 address, bind directly. 863188144Sjamie */ 864188144Sjamie if (cred->cr_prison->pr_ip4s == 1) 865188144Sjamie ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 866185435Sbz return (0); 867185435Sbz } 868185435Sbz 869188144Sjamie return (_prison_check_ip4(cred->cr_prison, ia)); 870185435Sbz} 871185435Sbz 872185435Sbz/* 873185435Sbz * Rewrite destination address in case we will connect to loopback address. 874185435Sbz * 875188144Sjamie * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4. 876188144Sjamie * Address passed in in NBO and returned in NBO. 877185435Sbz */ 878185435Sbzint 879185435Sbzprison_remote_ip4(struct ucred *cred, struct in_addr *ia) 880185435Sbz{ 881185435Sbz 882185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 883185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 884185435Sbz 885185435Sbz if (!jailed(cred)) 886185435Sbz return (0); 887185435Sbz if (cred->cr_prison->pr_ip4 == NULL) 888188144Sjamie return (EAFNOSUPPORT); 889188144Sjamie 890185435Sbz if (ntohl(ia->s_addr) == INADDR_LOOPBACK) { 891185435Sbz ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 892185435Sbz return (0); 893185435Sbz } 894185435Sbz 895185435Sbz /* 896185435Sbz * Return success because nothing had to be changed. 897185435Sbz */ 898185435Sbz return (0); 899185435Sbz} 900185435Sbz 901185435Sbz/* 902188144Sjamie * Check if given address belongs to the jail referenced by cred/prison. 903185435Sbz * 904188144Sjamie * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if 905188144Sjamie * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv4. 906188144Sjamie * Address passed in in NBO. 907185435Sbz */ 908185435Sbzstatic int 909185435Sbz_prison_check_ip4(struct prison *pr, struct in_addr *ia) 910185435Sbz{ 911185435Sbz int i, a, z, d; 912185435Sbz 913185435Sbz /* 914185435Sbz * Check the primary IP. 915185435Sbz */ 916185435Sbz if (pr->pr_ip4[0].s_addr == ia->s_addr) 917188144Sjamie return (0); 918185435Sbz 919185435Sbz /* 920185435Sbz * All the other IPs are sorted so we can do a binary search. 921185435Sbz */ 922185435Sbz a = 0; 923185435Sbz z = pr->pr_ip4s - 2; 924185435Sbz while (a <= z) { 925185435Sbz i = (a + z) / 2; 926185435Sbz d = qcmp_v4(&pr->pr_ip4[i+1], ia); 927185435Sbz if (d > 0) 928185435Sbz z = i - 1; 929185435Sbz else if (d < 0) 930185435Sbz a = i + 1; 93181114Srwatson else 932188144Sjamie return (0); 933185435Sbz } 934188144Sjamie 935188144Sjamie return (EADDRNOTAVAIL); 936185435Sbz} 937185435Sbz 938185435Sbzint 939185435Sbzprison_check_ip4(struct ucred *cred, struct in_addr *ia) 940185435Sbz{ 941185435Sbz 942185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 943185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 944185435Sbz 945185435Sbz if (!jailed(cred)) 946188144Sjamie return (0); 947188144Sjamie if (cred->cr_prison->pr_ip4 == NULL) 948188144Sjamie return (EAFNOSUPPORT); 949185435Sbz 950185435Sbz return (_prison_check_ip4(cred->cr_prison, ia)); 951185435Sbz} 952185435Sbz#endif 953185435Sbz 954185435Sbz#ifdef INET6 955185435Sbz/* 956185435Sbz * Pass back primary IPv6 address for this jail. 957185435Sbz * 958185435Sbz * If not jailed return success but do not alter the address. Caller has to 959190466Sjamie * make sure to initialize it correctly (e.g. IN6ADDR_ANY_INIT). 960185435Sbz * 961188144Sjamie * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6. 962185435Sbz */ 963185435Sbzint 964187684Sbzprison_get_ip6(struct ucred *cred, struct in6_addr *ia6) 965185435Sbz{ 966185435Sbz 967185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 968185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 969185435Sbz 970185435Sbz if (!jailed(cred)) 97181114Srwatson return (0); 972185435Sbz if (cred->cr_prison->pr_ip6 == NULL) 973188144Sjamie return (EAFNOSUPPORT); 974188144Sjamie 975185435Sbz bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr)); 976185435Sbz return (0); 977185435Sbz} 978185435Sbz 979185435Sbz/* 980185435Sbz * Make sure our (source) address is set to something meaningful to this jail. 981185435Sbz * 982185435Sbz * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0) 983185435Sbz * when needed while binding. 984185435Sbz * 985188144Sjamie * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if 986188144Sjamie * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv6. 987185435Sbz */ 988185435Sbzint 989185435Sbzprison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only) 990185435Sbz{ 991185435Sbz 992185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 993185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 994185435Sbz 995185435Sbz if (!jailed(cred)) 996185435Sbz return (0); 997185435Sbz if (cred->cr_prison->pr_ip6 == NULL) 998188144Sjamie return (EAFNOSUPPORT); 999188144Sjamie 1000185435Sbz if (IN6_IS_ADDR_LOOPBACK(ia6)) { 1001185435Sbz bcopy(&cred->cr_prison->pr_ip6[0], ia6, 1002185435Sbz sizeof(struct in6_addr)); 1003185435Sbz return (0); 100481114Srwatson } 1005185435Sbz 1006188144Sjamie if (IN6_IS_ADDR_UNSPECIFIED(ia6)) { 1007188144Sjamie /* 1008188144Sjamie * In case there is only 1 IPv6 address, and v6only is true, 1009188144Sjamie * then bind directly. 1010188144Sjamie */ 1011188144Sjamie if (v6only != 0 && cred->cr_prison->pr_ip6s == 1) 1012188144Sjamie bcopy(&cred->cr_prison->pr_ip6[0], ia6, 1013188144Sjamie sizeof(struct in6_addr)); 1014185435Sbz return (0); 1015185435Sbz } 1016188144Sjamie 1017188144Sjamie return (_prison_check_ip6(cred->cr_prison, ia6)); 1018185435Sbz} 1019185435Sbz 1020185435Sbz/* 1021185435Sbz * Rewrite destination address in case we will connect to loopback address. 1022185435Sbz * 1023188144Sjamie * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6. 1024185435Sbz */ 1025185435Sbzint 1026185435Sbzprison_remote_ip6(struct ucred *cred, struct in6_addr *ia6) 1027185435Sbz{ 1028185435Sbz 1029185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1030185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 1031185435Sbz 1032185435Sbz if (!jailed(cred)) 1033185435Sbz return (0); 1034185435Sbz if (cred->cr_prison->pr_ip6 == NULL) 1035188144Sjamie return (EAFNOSUPPORT); 1036188144Sjamie 1037185435Sbz if (IN6_IS_ADDR_LOOPBACK(ia6)) { 1038185435Sbz bcopy(&cred->cr_prison->pr_ip6[0], ia6, 1039185435Sbz sizeof(struct in6_addr)); 1040185435Sbz return (0); 1041185435Sbz } 1042185435Sbz 1043185435Sbz /* 1044185435Sbz * Return success because nothing had to be changed. 1045185435Sbz */ 104646155Sphk return (0); 104746155Sphk} 104846155Sphk 1049185435Sbz/* 1050188144Sjamie * Check if given address belongs to the jail referenced by cred/prison. 1051185435Sbz * 1052188144Sjamie * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if 1053188144Sjamie * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv6. 1054185435Sbz */ 1055185435Sbzstatic int 1056185435Sbz_prison_check_ip6(struct prison *pr, struct in6_addr *ia6) 105746155Sphk{ 1058185435Sbz int i, a, z, d; 105946155Sphk 1060185435Sbz /* 1061185435Sbz * Check the primary IP. 1062185435Sbz */ 1063185435Sbz if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6)) 1064188144Sjamie return (0); 1065185435Sbz 1066185435Sbz /* 1067185435Sbz * All the other IPs are sorted so we can do a binary search. 1068185435Sbz */ 1069185435Sbz a = 0; 1070185435Sbz z = pr->pr_ip6s - 2; 1071185435Sbz while (a <= z) { 1072185435Sbz i = (a + z) / 2; 1073185435Sbz d = qcmp_v6(&pr->pr_ip6[i+1], ia6); 1074185435Sbz if (d > 0) 1075185435Sbz z = i - 1; 1076185435Sbz else if (d < 0) 1077185435Sbz a = i + 1; 107846155Sphk else 1079188144Sjamie return (0); 108046155Sphk } 1081188144Sjamie 1082188144Sjamie return (EADDRNOTAVAIL); 108346155Sphk} 108446155Sphk 108546155Sphkint 1086185435Sbzprison_check_ip6(struct ucred *cred, struct in6_addr *ia6) 1087185435Sbz{ 1088185435Sbz 1089185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1090185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 1091185435Sbz 1092185435Sbz if (!jailed(cred)) 1093188144Sjamie return (0); 1094188144Sjamie if (cred->cr_prison->pr_ip6 == NULL) 1095188144Sjamie return (EAFNOSUPPORT); 1096185435Sbz 1097185435Sbz return (_prison_check_ip6(cred->cr_prison, ia6)); 1098185435Sbz} 1099185435Sbz#endif 1100185435Sbz 1101185435Sbz/* 1102188146Sjamie * Check if a jail supports the given address family. 1103188146Sjamie * 1104188146Sjamie * Returns 0 if not jailed or the address family is supported, EAFNOSUPPORT 1105188146Sjamie * if not. 1106188146Sjamie */ 1107188146Sjamieint 1108188146Sjamieprison_check_af(struct ucred *cred, int af) 1109188146Sjamie{ 1110188146Sjamie int error; 1111188146Sjamie 1112188146Sjamie KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1113188146Sjamie 1114188146Sjamie 1115188146Sjamie if (!jailed(cred)) 1116188146Sjamie return (0); 1117188146Sjamie 1118188146Sjamie error = 0; 1119188146Sjamie switch (af) 1120188146Sjamie { 1121188146Sjamie#ifdef INET 1122188146Sjamie case AF_INET: 1123188146Sjamie if (cred->cr_prison->pr_ip4 == NULL) 1124188146Sjamie error = EAFNOSUPPORT; 1125188146Sjamie break; 1126188146Sjamie#endif 1127188146Sjamie#ifdef INET6 1128188146Sjamie case AF_INET6: 1129188146Sjamie if (cred->cr_prison->pr_ip6 == NULL) 1130188146Sjamie error = EAFNOSUPPORT; 1131188146Sjamie break; 1132188146Sjamie#endif 1133188146Sjamie case AF_LOCAL: 1134188146Sjamie case AF_ROUTE: 1135188146Sjamie break; 1136188146Sjamie default: 1137188146Sjamie if (jail_socket_unixiproute_only) 1138188146Sjamie error = EAFNOSUPPORT; 1139188146Sjamie } 1140188146Sjamie return (error); 1141188146Sjamie} 1142188146Sjamie 1143188146Sjamie/* 1144185435Sbz * Check if given address belongs to the jail referenced by cred (wrapper to 1145185435Sbz * prison_check_ip[46]). 1146185435Sbz * 1147188144Sjamie * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if 1148188144Sjamie * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow 1149188144Sjamie * the address family. IPv4 Address passed in in NBO. 1150185435Sbz */ 1151185435Sbzint 115272786Srwatsonprison_if(struct ucred *cred, struct sockaddr *sa) 115346155Sphk{ 1154185435Sbz#ifdef INET 1155114168Smike struct sockaddr_in *sai; 1156185435Sbz#endif 1157185435Sbz#ifdef INET6 1158185435Sbz struct sockaddr_in6 *sai6; 1159185435Sbz#endif 1160188144Sjamie int error; 116146155Sphk 1162185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1163185435Sbz KASSERT(sa != NULL, ("%s: sa is NULL", __func__)); 1164185435Sbz 1165188144Sjamie error = 0; 1166188144Sjamie switch (sa->sa_family) 1167185435Sbz { 1168185435Sbz#ifdef INET 1169185435Sbz case AF_INET: 1170185435Sbz sai = (struct sockaddr_in *)sa; 1171188144Sjamie error = prison_check_ip4(cred, &sai->sin_addr); 1172185435Sbz break; 1173185435Sbz#endif 1174185435Sbz#ifdef INET6 1175185435Sbz case AF_INET6: 1176185435Sbz sai6 = (struct sockaddr_in6 *)sa; 1177188144Sjamie error = prison_check_ip6(cred, &sai6->sin6_addr); 1178185435Sbz break; 1179185435Sbz#endif 1180185435Sbz default: 1181188144Sjamie if (jailed(cred) && jail_socket_unixiproute_only) 1182188144Sjamie error = EAFNOSUPPORT; 1183185435Sbz } 1184188144Sjamie return (error); 118546155Sphk} 118672786Srwatson 118772786Srwatson/* 118872786Srwatson * Return 0 if jails permit p1 to frob p2, otherwise ESRCH. 118972786Srwatson */ 119072786Srwatsonint 1191114168Smikeprison_check(struct ucred *cred1, struct ucred *cred2) 119272786Srwatson{ 119372786Srwatson 119472786Srwatson if (jailed(cred1)) { 119572786Srwatson if (!jailed(cred2)) 119672786Srwatson return (ESRCH); 119772786Srwatson if (cred2->cr_prison != cred1->cr_prison) 119872786Srwatson return (ESRCH); 119972786Srwatson } 120072786Srwatson 120172786Srwatson return (0); 120272786Srwatson} 120372786Srwatson 120472786Srwatson/* 120572786Srwatson * Return 1 if the passed credential is in a jail, otherwise 0. 120672786Srwatson */ 120772786Srwatsonint 1208114168Smikejailed(struct ucred *cred) 120972786Srwatson{ 121072786Srwatson 121172786Srwatson return (cred->cr_prison != NULL); 121272786Srwatson} 121391384Srobert 121491384Srobert/* 121591384Srobert * Return the correct hostname for the passed credential. 121691384Srobert */ 121791391Srobertvoid 1218114168Smikegetcredhostname(struct ucred *cred, char *buf, size_t size) 121991384Srobert{ 1220183550Szec INIT_VPROCG(cred->cr_vimage->v_procg); 122191384Srobert 122291391Srobert if (jailed(cred)) { 122391391Srobert mtx_lock(&cred->cr_prison->pr_mtx); 1224105354Srobert strlcpy(buf, cred->cr_prison->pr_host, size); 122591391Srobert mtx_unlock(&cred->cr_prison->pr_mtx); 1226180291Srwatson } else { 1227180291Srwatson mtx_lock(&hostname_mtx); 1228181803Sbz strlcpy(buf, V_hostname, size); 1229180291Srwatson mtx_unlock(&hostname_mtx); 1230180291Srwatson } 123191384Srobert} 1232113275Smike 1233125804Srwatson/* 1234147185Spjd * Determine whether the subject represented by cred can "see" 1235147185Spjd * status of a mount point. 1236147185Spjd * Returns: 0 for permitted, ENOENT otherwise. 1237147185Spjd * XXX: This function should be called cr_canseemount() and should be 1238147185Spjd * placed in kern_prot.c. 1239125804Srwatson */ 1240125804Srwatsonint 1241147185Spjdprison_canseemount(struct ucred *cred, struct mount *mp) 1242125804Srwatson{ 1243147185Spjd struct prison *pr; 1244147185Spjd struct statfs *sp; 1245147185Spjd size_t len; 1246125804Srwatson 1247147185Spjd if (!jailed(cred) || jail_enforce_statfs == 0) 1248147185Spjd return (0); 1249147185Spjd pr = cred->cr_prison; 1250147185Spjd if (pr->pr_root->v_mount == mp) 1251147185Spjd return (0); 1252147185Spjd if (jail_enforce_statfs == 2) 1253147185Spjd return (ENOENT); 1254147185Spjd /* 1255147185Spjd * If jail's chroot directory is set to "/" we should be able to see 1256147185Spjd * all mount-points from inside a jail. 1257147185Spjd * This is ugly check, but this is the only situation when jail's 1258147185Spjd * directory ends with '/'. 1259147185Spjd */ 1260147185Spjd if (strcmp(pr->pr_path, "/") == 0) 1261147185Spjd return (0); 1262147185Spjd len = strlen(pr->pr_path); 1263147185Spjd sp = &mp->mnt_stat; 1264147185Spjd if (strncmp(pr->pr_path, sp->f_mntonname, len) != 0) 1265147185Spjd return (ENOENT); 1266147185Spjd /* 1267147185Spjd * Be sure that we don't have situation where jail's root directory 1268147185Spjd * is "/some/path" and mount point is "/some/pathpath". 1269147185Spjd */ 1270147185Spjd if (sp->f_mntonname[len] != '\0' && sp->f_mntonname[len] != '/') 1271147185Spjd return (ENOENT); 1272147185Spjd return (0); 1273147185Spjd} 1274147185Spjd 1275147185Spjdvoid 1276147185Spjdprison_enforce_statfs(struct ucred *cred, struct mount *mp, struct statfs *sp) 1277147185Spjd{ 1278147185Spjd char jpath[MAXPATHLEN]; 1279147185Spjd struct prison *pr; 1280147185Spjd size_t len; 1281147185Spjd 1282147185Spjd if (!jailed(cred) || jail_enforce_statfs == 0) 1283147185Spjd return; 1284147185Spjd pr = cred->cr_prison; 1285147185Spjd if (prison_canseemount(cred, mp) != 0) { 1286147185Spjd bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1287147185Spjd strlcpy(sp->f_mntonname, "[restricted]", 1288147185Spjd sizeof(sp->f_mntonname)); 1289147185Spjd return; 1290125804Srwatson } 1291147185Spjd if (pr->pr_root->v_mount == mp) { 1292147185Spjd /* 1293147185Spjd * Clear current buffer data, so we are sure nothing from 1294147185Spjd * the valid path left there. 1295147185Spjd */ 1296147185Spjd bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1297147185Spjd *sp->f_mntonname = '/'; 1298147185Spjd return; 1299147185Spjd } 1300147185Spjd /* 1301147185Spjd * If jail's chroot directory is set to "/" we should be able to see 1302147185Spjd * all mount-points from inside a jail. 1303147185Spjd */ 1304147185Spjd if (strcmp(pr->pr_path, "/") == 0) 1305147185Spjd return; 1306147185Spjd len = strlen(pr->pr_path); 1307147185Spjd strlcpy(jpath, sp->f_mntonname + len, sizeof(jpath)); 1308147185Spjd /* 1309147185Spjd * Clear current buffer data, so we are sure nothing from 1310147185Spjd * the valid path left there. 1311147185Spjd */ 1312147185Spjd bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1313147185Spjd if (*jpath == '\0') { 1314147185Spjd /* Should never happen. */ 1315147185Spjd *sp->f_mntonname = '/'; 1316147185Spjd } else { 1317147185Spjd strlcpy(sp->f_mntonname, jpath, sizeof(sp->f_mntonname)); 1318147185Spjd } 1319125804Srwatson} 1320125804Srwatson 1321164032Srwatson/* 1322164032Srwatson * Check with permission for a specific privilege is granted within jail. We 1323164032Srwatson * have a specific list of accepted privileges; the rest are denied. 1324164032Srwatson */ 1325164032Srwatsonint 1326164032Srwatsonprison_priv_check(struct ucred *cred, int priv) 1327164032Srwatson{ 1328164032Srwatson 1329164032Srwatson if (!jailed(cred)) 1330164032Srwatson return (0); 1331164032Srwatson 1332164032Srwatson switch (priv) { 1333164032Srwatson 1334164032Srwatson /* 1335164032Srwatson * Allow ktrace privileges for root in jail. 1336164032Srwatson */ 1337164032Srwatson case PRIV_KTRACE: 1338164032Srwatson 1339166827Srwatson#if 0 1340164032Srwatson /* 1341164032Srwatson * Allow jailed processes to configure audit identity and 1342164032Srwatson * submit audit records (login, etc). In the future we may 1343164032Srwatson * want to further refine the relationship between audit and 1344164032Srwatson * jail. 1345164032Srwatson */ 1346164032Srwatson case PRIV_AUDIT_GETAUDIT: 1347164032Srwatson case PRIV_AUDIT_SETAUDIT: 1348164032Srwatson case PRIV_AUDIT_SUBMIT: 1349166827Srwatson#endif 1350164032Srwatson 1351164032Srwatson /* 1352164032Srwatson * Allow jailed processes to manipulate process UNIX 1353164032Srwatson * credentials in any way they see fit. 1354164032Srwatson */ 1355164032Srwatson case PRIV_CRED_SETUID: 1356164032Srwatson case PRIV_CRED_SETEUID: 1357164032Srwatson case PRIV_CRED_SETGID: 1358164032Srwatson case PRIV_CRED_SETEGID: 1359164032Srwatson case PRIV_CRED_SETGROUPS: 1360164032Srwatson case PRIV_CRED_SETREUID: 1361164032Srwatson case PRIV_CRED_SETREGID: 1362164032Srwatson case PRIV_CRED_SETRESUID: 1363164032Srwatson case PRIV_CRED_SETRESGID: 1364164032Srwatson 1365164032Srwatson /* 1366164032Srwatson * Jail implements visibility constraints already, so allow 1367164032Srwatson * jailed root to override uid/gid-based constraints. 1368164032Srwatson */ 1369164032Srwatson case PRIV_SEEOTHERGIDS: 1370164032Srwatson case PRIV_SEEOTHERUIDS: 1371164032Srwatson 1372164032Srwatson /* 1373164032Srwatson * Jail implements inter-process debugging limits already, so 1374164032Srwatson * allow jailed root various debugging privileges. 1375164032Srwatson */ 1376164032Srwatson case PRIV_DEBUG_DIFFCRED: 1377164032Srwatson case PRIV_DEBUG_SUGID: 1378164032Srwatson case PRIV_DEBUG_UNPRIV: 1379164032Srwatson 1380164032Srwatson /* 1381164032Srwatson * Allow jail to set various resource limits and login 1382164032Srwatson * properties, and for now, exceed process resource limits. 1383164032Srwatson */ 1384164032Srwatson case PRIV_PROC_LIMIT: 1385164032Srwatson case PRIV_PROC_SETLOGIN: 1386164032Srwatson case PRIV_PROC_SETRLIMIT: 1387164032Srwatson 1388164032Srwatson /* 1389164032Srwatson * System V and POSIX IPC privileges are granted in jail. 1390164032Srwatson */ 1391164032Srwatson case PRIV_IPC_READ: 1392164032Srwatson case PRIV_IPC_WRITE: 1393164032Srwatson case PRIV_IPC_ADMIN: 1394164032Srwatson case PRIV_IPC_MSGSIZE: 1395164032Srwatson case PRIV_MQ_ADMIN: 1396164032Srwatson 1397164032Srwatson /* 1398164032Srwatson * Jail implements its own inter-process limits, so allow 1399164032Srwatson * root processes in jail to change scheduling on other 1400164032Srwatson * processes in the same jail. Likewise for signalling. 1401164032Srwatson */ 1402164032Srwatson case PRIV_SCHED_DIFFCRED: 1403185435Sbz case PRIV_SCHED_CPUSET: 1404164032Srwatson case PRIV_SIGNAL_DIFFCRED: 1405164032Srwatson case PRIV_SIGNAL_SUGID: 1406164032Srwatson 1407164032Srwatson /* 1408164032Srwatson * Allow jailed processes to write to sysctls marked as jail 1409164032Srwatson * writable. 1410164032Srwatson */ 1411164032Srwatson case PRIV_SYSCTL_WRITEJAIL: 1412164032Srwatson 1413164032Srwatson /* 1414164032Srwatson * Allow root in jail to manage a variety of quota 1415166831Srwatson * properties. These should likely be conditional on a 1416166831Srwatson * configuration option. 1417164032Srwatson */ 1418166832Srwatson case PRIV_VFS_GETQUOTA: 1419166832Srwatson case PRIV_VFS_SETQUOTA: 1420164032Srwatson 1421164032Srwatson /* 1422164032Srwatson * Since Jail relies on chroot() to implement file system 1423164032Srwatson * protections, grant many VFS privileges to root in jail. 1424164032Srwatson * Be careful to exclude mount-related and NFS-related 1425164032Srwatson * privileges. 1426164032Srwatson */ 1427164032Srwatson case PRIV_VFS_READ: 1428164032Srwatson case PRIV_VFS_WRITE: 1429164032Srwatson case PRIV_VFS_ADMIN: 1430164032Srwatson case PRIV_VFS_EXEC: 1431164032Srwatson case PRIV_VFS_LOOKUP: 1432164032Srwatson case PRIV_VFS_BLOCKRESERVE: /* XXXRW: Slightly surprising. */ 1433164032Srwatson case PRIV_VFS_CHFLAGS_DEV: 1434164032Srwatson case PRIV_VFS_CHOWN: 1435164032Srwatson case PRIV_VFS_CHROOT: 1436167152Spjd case PRIV_VFS_RETAINSUGID: 1437164032Srwatson case PRIV_VFS_FCHROOT: 1438164032Srwatson case PRIV_VFS_LINK: 1439164032Srwatson case PRIV_VFS_SETGID: 1440172860Srwatson case PRIV_VFS_STAT: 1441164032Srwatson case PRIV_VFS_STICKYFILE: 1442164032Srwatson return (0); 1443164032Srwatson 1444164032Srwatson /* 1445164032Srwatson * Depending on the global setting, allow privilege of 1446164032Srwatson * setting system flags. 1447164032Srwatson */ 1448164032Srwatson case PRIV_VFS_SYSFLAGS: 1449164032Srwatson if (jail_chflags_allowed) 1450164032Srwatson return (0); 1451164032Srwatson else 1452164032Srwatson return (EPERM); 1453164032Srwatson 1454164032Srwatson /* 1455168396Spjd * Depending on the global setting, allow privilege of 1456168396Spjd * mounting/unmounting file systems. 1457168396Spjd */ 1458168396Spjd case PRIV_VFS_MOUNT: 1459168396Spjd case PRIV_VFS_UNMOUNT: 1460168396Spjd case PRIV_VFS_MOUNT_NONUSER: 1461168699Spjd case PRIV_VFS_MOUNT_OWNER: 1462168396Spjd if (jail_mount_allowed) 1463168396Spjd return (0); 1464168396Spjd else 1465168396Spjd return (EPERM); 1466168396Spjd 1467168396Spjd /* 1468168591Srwatson * Allow jailed root to bind reserved ports and reuse in-use 1469168591Srwatson * ports. 1470164032Srwatson */ 1471164032Srwatson case PRIV_NETINET_RESERVEDPORT: 1472168591Srwatson case PRIV_NETINET_REUSEPORT: 1473164032Srwatson return (0); 1474164032Srwatson 1475164032Srwatson /* 1476175630Sbz * Allow jailed root to set certian IPv4/6 (option) headers. 1477175630Sbz */ 1478175630Sbz case PRIV_NETINET_SETHDROPTS: 1479175630Sbz return (0); 1480175630Sbz 1481175630Sbz /* 1482164032Srwatson * Conditionally allow creating raw sockets in jail. 1483164032Srwatson */ 1484164032Srwatson case PRIV_NETINET_RAW: 1485164032Srwatson if (jail_allow_raw_sockets) 1486164032Srwatson return (0); 1487164032Srwatson else 1488164032Srwatson return (EPERM); 1489164032Srwatson 1490164032Srwatson /* 1491164032Srwatson * Since jail implements its own visibility limits on netstat 1492164032Srwatson * sysctls, allow getcred. This allows identd to work in 1493164032Srwatson * jail. 1494164032Srwatson */ 1495164032Srwatson case PRIV_NETINET_GETCRED: 1496164032Srwatson return (0); 1497164032Srwatson 1498164032Srwatson default: 1499164032Srwatson /* 1500164032Srwatson * In all remaining cases, deny the privilege request. This 1501164032Srwatson * includes almost all network privileges, many system 1502164032Srwatson * configuration privileges. 1503164032Srwatson */ 1504164032Srwatson return (EPERM); 1505164032Srwatson } 1506164032Srwatson} 1507164032Srwatson 1508113275Smikestatic int 1509113275Smikesysctl_jail_list(SYSCTL_HANDLER_ARGS) 1510113275Smike{ 1511113275Smike struct xprison *xp, *sxp; 1512113275Smike struct prison *pr; 1513185435Sbz char *p; 1514185435Sbz size_t len; 1515113275Smike int count, error; 1516113275Smike 1517127020Spjd if (jailed(req->td->td_ucred)) 1518125806Srwatson return (0); 1519113275Smike 1520168401Spjd sx_slock(&allprison_lock); 1521168401Spjd if ((count = prisoncount) == 0) { 1522168401Spjd sx_sunlock(&allprison_lock); 1523113275Smike return (0); 1524168401Spjd } 1525113275Smike 1526185435Sbz len = sizeof(*xp) * count; 1527185435Sbz LIST_FOREACH(pr, &allprison, pr_list) { 1528185435Sbz#ifdef INET 1529185435Sbz len += pr->pr_ip4s * sizeof(struct in_addr); 1530185435Sbz#endif 1531185435Sbz#ifdef INET6 1532185435Sbz len += pr->pr_ip6s * sizeof(struct in6_addr); 1533185435Sbz#endif 1534185435Sbz } 1535167309Spjd 1536185435Sbz sxp = xp = malloc(len, M_TEMP, M_WAITOK | M_ZERO); 1537185435Sbz 1538113275Smike LIST_FOREACH(pr, &allprison, pr_list) { 1539113275Smike xp->pr_version = XPRISON_VERSION; 1540113275Smike xp->pr_id = pr->pr_id; 1541185435Sbz xp->pr_state = pr->pr_state; 1542185435Sbz xp->pr_cpusetid = pr->pr_cpuset->cs_id; 1543113275Smike strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path)); 1544168487Spjd mtx_lock(&pr->pr_mtx); 1545113275Smike strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host)); 1546185435Sbz strlcpy(xp->pr_name, pr->pr_name, sizeof(xp->pr_name)); 1547113275Smike mtx_unlock(&pr->pr_mtx); 1548185435Sbz#ifdef INET 1549185435Sbz xp->pr_ip4s = pr->pr_ip4s; 1550185435Sbz#endif 1551185435Sbz#ifdef INET6 1552185435Sbz xp->pr_ip6s = pr->pr_ip6s; 1553185435Sbz#endif 1554185435Sbz p = (char *)(xp + 1); 1555185435Sbz#ifdef INET 1556185435Sbz if (pr->pr_ip4s > 0) { 1557185435Sbz bcopy(pr->pr_ip4, (struct in_addr *)p, 1558185435Sbz pr->pr_ip4s * sizeof(struct in_addr)); 1559185435Sbz p += (pr->pr_ip4s * sizeof(struct in_addr)); 1560185435Sbz } 1561185435Sbz#endif 1562185435Sbz#ifdef INET6 1563185435Sbz if (pr->pr_ip6s > 0) { 1564185435Sbz bcopy(pr->pr_ip6, (struct in6_addr *)p, 1565185435Sbz pr->pr_ip6s * sizeof(struct in6_addr)); 1566185435Sbz p += (pr->pr_ip6s * sizeof(struct in6_addr)); 1567185435Sbz } 1568185435Sbz#endif 1569185435Sbz xp = (struct xprison *)p; 1570113275Smike } 1571168401Spjd sx_sunlock(&allprison_lock); 1572113275Smike 1573185435Sbz error = SYSCTL_OUT(req, sxp, len); 1574113275Smike free(sxp, M_TEMP); 1575167354Spjd return (error); 1576113275Smike} 1577113275Smike 1578187864SedSYSCTL_OID(_security_jail, OID_AUTO, list, 1579187864Sed CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, 1580187864Sed sysctl_jail_list, "S", "List of active jails"); 1581126004Spjd 1582126004Spjdstatic int 1583126004Spjdsysctl_jail_jailed(SYSCTL_HANDLER_ARGS) 1584126004Spjd{ 1585126004Spjd int error, injail; 1586126004Spjd 1587126004Spjd injail = jailed(req->td->td_ucred); 1588126004Spjd error = SYSCTL_OUT(req, &injail, sizeof(injail)); 1589126004Spjd 1590126004Spjd return (error); 1591126004Spjd} 1592187864SedSYSCTL_PROC(_security_jail, OID_AUTO, jailed, 1593187864Sed CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, 1594187864Sed sysctl_jail_jailed, "I", "Process in jail?"); 1595185435Sbz 1596185435Sbz#ifdef DDB 1597185435SbzDB_SHOW_COMMAND(jails, db_show_jails) 1598185435Sbz{ 1599185435Sbz struct prison *pr; 1600185435Sbz#ifdef INET 1601185435Sbz struct in_addr ia; 1602185435Sbz#endif 1603185435Sbz#ifdef INET6 1604185435Sbz char ip6buf[INET6_ADDRSTRLEN]; 1605185435Sbz#endif 1606185435Sbz const char *state; 1607185435Sbz#if defined(INET) || defined(INET6) 1608185435Sbz int i; 1609185435Sbz#endif 1610185435Sbz 1611185435Sbz db_printf( 1612185435Sbz " JID pr_ref pr_nprocs pr_ip4s pr_ip6s\n"); 1613185435Sbz db_printf( 1614185435Sbz " Hostname Path\n"); 1615185435Sbz db_printf( 1616185435Sbz " Name State\n"); 1617185435Sbz db_printf( 1618185435Sbz " Cpusetid\n"); 1619185435Sbz db_printf( 1620185435Sbz " IP Address(es)\n"); 1621185435Sbz LIST_FOREACH(pr, &allprison, pr_list) { 1622185435Sbz db_printf("%6d %6d %9d %7d %7d\n", 1623185435Sbz pr->pr_id, pr->pr_ref, pr->pr_nprocs, 1624185435Sbz pr->pr_ip4s, pr->pr_ip6s); 1625185435Sbz db_printf("%6s %-29.29s %.74s\n", 1626185435Sbz "", pr->pr_host, pr->pr_path); 1627185899Sbz if (pr->pr_state < 0 || pr->pr_state >= (int)((sizeof( 1628185435Sbz prison_states) / sizeof(struct prison_state)))) 1629185435Sbz state = "(bogus)"; 1630185435Sbz else 1631185435Sbz state = prison_states[pr->pr_state].state_name; 1632185435Sbz db_printf("%6s %-29.29s %.74s\n", 1633185899Sbz "", (pr->pr_name[0] != '\0') ? pr->pr_name : "", state); 1634185435Sbz db_printf("%6s %-6d\n", 1635185435Sbz "", pr->pr_cpuset->cs_id); 1636185435Sbz#ifdef INET 1637185435Sbz for (i=0; i < pr->pr_ip4s; i++) { 1638185435Sbz ia.s_addr = pr->pr_ip4[i].s_addr; 1639185435Sbz db_printf("%6s %s\n", "", inet_ntoa(ia)); 1640185435Sbz } 1641185435Sbz#endif 1642185435Sbz#ifdef INET6 1643185435Sbz for (i=0; i < pr->pr_ip6s; i++) 1644185435Sbz db_printf("%6s %s\n", 1645185435Sbz "", ip6_sprintf(ip6buf, &pr->pr_ip6[i])); 1646185435Sbz#endif /* INET6 */ 1647185435Sbz if (db_pager_quit) 1648185435Sbz break; 1649185435Sbz } 1650185435Sbz} 1651185435Sbz#endif /* DDB */ 1652