kern_jail.c revision 185435
1139804Simp/*- 2185435Sbz * Copyright (c) 1999 Poul-Henning Kamp. 3185435Sbz * Copyright (c) 2008 Bjoern A. Zeeb. 4185435Sbz * All rights reserved. 5185404Sbz * 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 185435 2008-11-29 14:32:14Z bz $"); 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 122113275Smikestatic void init_prison(void *); 123124882Srwatsonstatic void prison_complete(void *context, int pending); 124113275Smikestatic int sysctl_jail_list(SYSCTL_HANDLER_ARGS); 125185435Sbz#ifdef INET 126185435Sbzstatic int _prison_check_ip4(struct prison *, struct in_addr *); 127185435Sbz#endif 128185435Sbz#ifdef INET6 129185435Sbzstatic int _prison_check_ip6(struct prison *, struct in6_addr *); 130185435Sbz#endif 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; 180185435Sbz 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++) { 220185435Sbz if (_prison_check_ip4(pr, &p->pr_ip4[i])) 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++) { 229185435Sbz if (_prison_check_ip6(pr, &p->pr_ip6[i])) 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 243185435Sbz 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; 296185435Sbz } 297185435Sbz#endif 298185435Sbz#ifdef INET6 299185435Sbz if (j->ip6s > 0) { 300185435Sbz ip6 = (struct in6_addr *)malloc(j->ip6s * sizeof(struct in6_addr), 301185435Sbz M_PRISON, M_WAITOK | M_ZERO); 302185435Sbz error = copyin(j->ip6, ip6, j->ip6s * sizeof(struct in6_addr)); 303185435Sbz if (error) 304185435Sbz goto e_free_ip; 305185435Sbz /* Sort all but the first IPv6 address. */ 306185435Sbz if (j->ip6s > 1) 307185435Sbz qsort((ip6 + 1), j->ip6s - 1, 308185435Sbz sizeof(struct in6_addr), qcmp_v6); 309185435Sbz for (i=0; i<j->ip6s; i++) { 310185435Sbz if (IN6_IS_ADDR_UNSPECIFIED(&ip6[i])) { 311185435Sbz error = EINVAL; 312185435Sbz goto e_free_ip; 313185435Sbz } 314185435Sbz if ((i+1) < j->ip6s && 315185435Sbz (IN6_ARE_ADDR_EQUAL(&ip6[0], &ip6[i+1]) || 316185435Sbz IN6_ARE_ADDR_EQUAL(&ip6[i], &ip6[i+1]))) { 317185435Sbz error = EINVAL; 318185435Sbz goto e_free_ip; 319185435Sbz } 320185435Sbz } 321185435Sbz 322185435Sbz j->ip6 = ip6; 323185435Sbz } 324185435Sbz#endif 325185435Sbz return (0); 326185435Sbz 327185435Sbze_free_ip: 328185435Sbz#ifdef INET6 329185435Sbz free(ip6, M_PRISON); 330185435Sbz#endif 331185435Sbz#ifdef INET 332185435Sbz free(ip4, M_PRISON); 333185435Sbz#endif 334185435Sbz return (error); 335185435Sbz} 336185435Sbz#endif /* INET || INET6 */ 337185435Sbz 338185435Sbzstatic int 339185435Sbzjail_handle_ips(struct jail *j) 340185435Sbz{ 341185435Sbz#if defined(INET) || defined(INET6) 342185435Sbz int error; 343185435Sbz#endif 344185435Sbz 345185435Sbz /* 346185435Sbz * Finish conversion for older versions, copyin and setup IPs. 347185435Sbz */ 348185435Sbz switch (j->version) { 349185435Sbz case 0: 350185435Sbz { 351185435Sbz#ifdef INET 352185435Sbz /* FreeBSD single IPv4 jails. */ 353185435Sbz struct in_addr *ip4; 354185435Sbz 355185435Sbz if (j->ip4s == INADDR_ANY || j->ip4s == INADDR_BROADCAST) 356185435Sbz return (EINVAL); 357185435Sbz ip4 = (struct in_addr *)malloc(sizeof(struct in_addr), 358185435Sbz M_PRISON, M_WAITOK | M_ZERO); 359185435Sbz 360185435Sbz /* 361185435Sbz * Jail version 0 still used HBO for the IPv4 address. 362185435Sbz */ 363185435Sbz ip4->s_addr = htonl(j->ip4s); 364185435Sbz j->ip4s = 1; 365185435Sbz j->ip4 = ip4; 366185435Sbz break; 367185435Sbz#else 368185435Sbz return (EINVAL); 369185435Sbz#endif 370185435Sbz } 371185435Sbz 372185435Sbz case 1: 373185435Sbz /* 374185435Sbz * Version 1 was used by multi-IPv4 jail implementations 375185435Sbz * that never made it into the official kernel. 376185435Sbz * We should never hit this here; jail() should catch it. 377185435Sbz */ 378185435Sbz return (EINVAL); 379185435Sbz 380185435Sbz case 2: /* JAIL_API_VERSION */ 381185435Sbz /* FreeBSD multi-IPv4/IPv6,noIP jails. */ 382185435Sbz#if defined(INET) || defined(INET6) 383185435Sbz#ifdef INET 384185435Sbz if (j->ip4s > jail_max_af_ips) 385185435Sbz return (EINVAL); 386185435Sbz#else 387185435Sbz if (j->ip4s != 0) 388185435Sbz return (EINVAL); 389185435Sbz#endif 390185435Sbz#ifdef INET6 391185435Sbz if (j->ip6s > jail_max_af_ips) 392185435Sbz return (EINVAL); 393185435Sbz#else 394185435Sbz if (j->ip6s != 0) 395185435Sbz return (EINVAL); 396185435Sbz#endif 397185435Sbz error = jail_copyin_ips(j); 398185435Sbz if (error) 399185435Sbz return (error); 400185435Sbz#endif 401185435Sbz break; 402185435Sbz 403185435Sbz default: 404185435Sbz /* Sci-Fi jails are not supported, sorry. */ 405185435Sbz return (EINVAL); 406185435Sbz } 407185435Sbz 408185435Sbz return (0); 409185435Sbz} 410185435Sbz 411185435Sbz 41282710Sdillon/* 413114168Smike * struct jail_args { 414114168Smike * struct jail *jail; 415114168Smike * }; 41682710Sdillon */ 41746155Sphkint 418114168Smikejail(struct thread *td, struct jail_args *uap) 41946155Sphk{ 420185435Sbz uint32_t version; 421185435Sbz int error; 422185435Sbz struct jail j; 423185435Sbz 424185435Sbz error = copyin(uap->jail, &version, sizeof(uint32_t)); 425185435Sbz if (error) 426185435Sbz return (error); 427185435Sbz 428185435Sbz switch (version) { 429185435Sbz case 0: 430185435Sbz /* FreeBSD single IPv4 jails. */ 431185435Sbz { 432185435Sbz struct jail_v0 j0; 433185435Sbz 434185435Sbz bzero(&j, sizeof(struct jail)); 435185435Sbz error = copyin(uap->jail, &j0, sizeof(struct jail_v0)); 436185435Sbz if (error) 437185435Sbz return (error); 438185435Sbz j.version = j0.version; 439185435Sbz j.path = j0.path; 440185435Sbz j.hostname = j0.hostname; 441185435Sbz j.ip4s = j0.ip_number; 442185435Sbz break; 443185435Sbz } 444185435Sbz 445185435Sbz case 1: 446185435Sbz /* 447185435Sbz * Version 1 was used by multi-IPv4 jail implementations 448185435Sbz * that never made it into the official kernel. 449185435Sbz */ 450185435Sbz return (EINVAL); 451185435Sbz 452185435Sbz case 2: /* JAIL_API_VERSION */ 453185435Sbz /* FreeBSD multi-IPv4/IPv6,noIP jails. */ 454185435Sbz error = copyin(uap->jail, &j, sizeof(struct jail)); 455185435Sbz if (error) 456185435Sbz return (error); 457185435Sbz break; 458185435Sbz 459185435Sbz default: 460185435Sbz /* Sci-Fi jails are not supported, sorry. */ 461185435Sbz return (EINVAL); 462185435Sbz } 463185435Sbz return (kern_jail(td, &j)); 464185435Sbz} 465185435Sbz 466185435Sbzint 467185435Sbzkern_jail(struct thread *td, struct jail *j) 468185435Sbz{ 469113275Smike struct nameidata nd; 470179881Sdelphij struct prison *pr, *tpr; 471113275Smike struct jail_attach_args jaa; 472179881Sdelphij int vfslocked, error, tryprid; 47346155Sphk 474185435Sbz KASSERT(j != NULL, ("%s: j is NULL", __func__)); 475185435Sbz 476185435Sbz /* Handle addresses - convert old structs, copyin, check IPs. */ 477185435Sbz error = jail_handle_ips(j); 47846155Sphk if (error) 47984828Sjhb return (error); 48084828Sjhb 481185435Sbz /* Allocate struct prison and fill it with life. */ 482184205Sdes pr = malloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); 48393818Sjhb mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF); 484113275Smike pr->pr_ref = 1; 485185435Sbz error = copyinstr(j->path, &pr->pr_path, sizeof(pr->pr_path), NULL); 486113275Smike if (error) 487113275Smike goto e_killmtx; 488150652Scsjp NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE, 489150652Scsjp pr->pr_path, td); 490113275Smike error = namei(&nd); 491150652Scsjp if (error) 492113275Smike goto e_killmtx; 493150652Scsjp vfslocked = NDHASGIANT(&nd); 494113275Smike pr->pr_root = nd.ni_vp; 495175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 496113275Smike NDFREE(&nd, NDF_ONLY_PNBUF); 497150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 498185435Sbz error = copyinstr(j->hostname, &pr->pr_host, sizeof(pr->pr_host), NULL); 49984828Sjhb if (error) 500113275Smike goto e_dropvnref; 501185435Sbz if (j->jailname != NULL) { 502185435Sbz error = copyinstr(j->jailname, &pr->pr_name, 503185435Sbz sizeof(pr->pr_name), NULL); 504185435Sbz if (error) 505185435Sbz goto e_dropvnref; 506185435Sbz } 507185435Sbz if (j->ip4s > 0) { 508185435Sbz pr->pr_ip4 = j->ip4; 509185435Sbz pr->pr_ip4s = j->ip4s; 510185435Sbz } 511185435Sbz#ifdef INET6 512185435Sbz if (j->ip6s > 0) { 513185435Sbz pr->pr_ip6 = j->ip6; 514185435Sbz pr->pr_ip6s = j->ip6s; 515185435Sbz } 516185435Sbz#endif 517113275Smike pr->pr_linux = NULL; 518113275Smike pr->pr_securelevel = securelevel; 519185029Spjd bzero(&pr->pr_osd, sizeof(pr->pr_osd)); 520113275Smike 521185435Sbz /* 522185435Sbz * Pre-set prison state to ALIVE upon cration. This is needed so we 523185435Sbz * can later attach the process to it, etc (avoiding another extra 524185435Sbz * state for ther process of creation, complicating things). 525185435Sbz */ 526185435Sbz pr->pr_state = PRISON_STATE_ALIVE; 527185435Sbz 528185435Sbz /* Allocate a dedicated cpuset for each jail. */ 529185435Sbz error = cpuset_create_root(td, &pr->pr_cpuset); 530185435Sbz if (error) 531185435Sbz goto e_dropvnref; 532185435Sbz 533185435Sbz sx_xlock(&allprison_lock); 534185435Sbz /* Make sure we cannot run into problems with ambiguous bind()ings. */ 535185435Sbz error = prison_check_conflicting_ips(pr); 536185435Sbz if (error) { 537185435Sbz sx_xunlock(&allprison_lock); 538185435Sbz goto e_dropcpuset; 539185435Sbz } 540185435Sbz 541179881Sdelphij /* Determine next pr_id and add prison to allprison list. */ 542179881Sdelphij tryprid = lastprid + 1; 543179881Sdelphij if (tryprid == JAIL_MAX) 544179881Sdelphij tryprid = 1; 545179881Sdelphijnext: 546179881Sdelphij LIST_FOREACH(tpr, &allprison, pr_list) { 547179881Sdelphij if (tpr->pr_id == tryprid) { 548179881Sdelphij tryprid++; 549179881Sdelphij if (tryprid == JAIL_MAX) { 550179881Sdelphij sx_xunlock(&allprison_lock); 551179881Sdelphij error = EAGAIN; 552185435Sbz goto e_dropcpuset; 553179881Sdelphij } 554179881Sdelphij goto next; 555179881Sdelphij } 556179881Sdelphij } 557179881Sdelphij pr->pr_id = jaa.jid = lastprid = tryprid; 558113275Smike LIST_INSERT_HEAD(&allprison, pr, pr_list); 559113275Smike prisoncount++; 560185029Spjd sx_xunlock(&allprison_lock); 561113275Smike 562113275Smike error = jail_attach(td, &jaa); 563113275Smike if (error) 564113275Smike goto e_dropprref; 565113275Smike mtx_lock(&pr->pr_mtx); 566113275Smike pr->pr_ref--; 567113275Smike mtx_unlock(&pr->pr_mtx); 568113275Smike td->td_retval[0] = jaa.jid; 569113275Smike return (0); 570113275Smikee_dropprref: 571168401Spjd sx_xlock(&allprison_lock); 572113275Smike LIST_REMOVE(pr, pr_list); 573113275Smike prisoncount--; 574185029Spjd sx_xunlock(&allprison_lock); 575185435Sbze_dropcpuset: 576185435Sbz cpuset_rel(pr->pr_cpuset); 577113275Smikee_dropvnref: 578150652Scsjp vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 579113275Smike vrele(pr->pr_root); 580150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 581113275Smikee_killmtx: 582113275Smike mtx_destroy(&pr->pr_mtx); 583184205Sdes free(pr, M_PRISON); 584185435Sbz#ifdef INET6 585185435Sbz free(j->ip6, M_PRISON); 586185435Sbz#endif 587185435Sbz#ifdef INET 588185435Sbz free(j->ip4, M_PRISON); 589185435Sbz#endif 590113275Smike return (error); 591113275Smike} 592113275Smike 593113275Smike/* 594114168Smike * struct jail_attach_args { 595114168Smike * int jid; 596114168Smike * }; 597113275Smike */ 598113275Smikeint 599114168Smikejail_attach(struct thread *td, struct jail_attach_args *uap) 600113275Smike{ 601113275Smike struct proc *p; 602113275Smike struct ucred *newcred, *oldcred; 603113275Smike struct prison *pr; 604150652Scsjp int vfslocked, error; 605167309Spjd 606126023Snectar /* 607126023Snectar * XXX: Note that there is a slight race here if two threads 608126023Snectar * in the same privileged process attempt to attach to two 609126023Snectar * different jails at the same time. It is important for 610126023Snectar * user processes not to do this, or they might end up with 611126023Snectar * a process root from one prison, but attached to the jail 612126023Snectar * of another. 613126023Snectar */ 614164032Srwatson error = priv_check(td, PRIV_JAIL_ATTACH); 615126023Snectar if (error) 616126023Snectar return (error); 617126023Snectar 618113275Smike p = td->td_proc; 619168401Spjd sx_slock(&allprison_lock); 620113275Smike pr = prison_find(uap->jid); 621113275Smike if (pr == NULL) { 622168401Spjd sx_sunlock(&allprison_lock); 623113275Smike return (EINVAL); 624113275Smike } 625185435Sbz 626185435Sbz /* 627185435Sbz * Do not allow a process to attach to a prison that is not 628185435Sbz * considered to be "ALIVE". 629185435Sbz */ 630185435Sbz if (pr->pr_state != PRISON_STATE_ALIVE) { 631185435Sbz mtx_unlock(&pr->pr_mtx); 632185435Sbz sx_sunlock(&allprison_lock); 633185435Sbz return (EINVAL); 634185435Sbz } 635113275Smike pr->pr_ref++; 636113275Smike mtx_unlock(&pr->pr_mtx); 637168401Spjd sx_sunlock(&allprison_lock); 638113275Smike 639185435Sbz /* 640185435Sbz * Reparent the newly attached process to this jail. 641185435Sbz */ 642185435Sbz error = cpuset_setproc_update_set(p, pr->pr_cpuset); 643185435Sbz if (error) 644185435Sbz goto e_unref; 645185435Sbz 646150652Scsjp vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 647175202Sattilio vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY); 648113275Smike if ((error = change_dir(pr->pr_root, td)) != 0) 649113275Smike goto e_unlock; 650113275Smike#ifdef MAC 651172930Srwatson if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root))) 652113275Smike goto e_unlock; 653113275Smike#endif 654175294Sattilio VOP_UNLOCK(pr->pr_root, 0); 655113275Smike change_root(pr->pr_root, td); 656150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 657113275Smike 65884828Sjhb newcred = crget(); 65984828Sjhb PROC_LOCK(p); 66084828Sjhb oldcred = p->p_ucred; 661113275Smike setsugid(p); 66284828Sjhb crcopy(newcred, oldcred); 663113630Sjhb newcred->cr_prison = pr; 66484828Sjhb p->p_ucred = newcred; 665185435Sbz prison_proc_hold(pr); 66684828Sjhb PROC_UNLOCK(p); 66784828Sjhb crfree(oldcred); 66846155Sphk return (0); 669113275Smikee_unlock: 670175294Sattilio VOP_UNLOCK(pr->pr_root, 0); 671150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 672185435Sbze_unref: 673113275Smike mtx_lock(&pr->pr_mtx); 674113275Smike pr->pr_ref--; 675113275Smike mtx_unlock(&pr->pr_mtx); 67646155Sphk return (error); 67746155Sphk} 67846155Sphk 679113275Smike/* 680113275Smike * Returns a locked prison instance, or NULL on failure. 681113275Smike */ 682168399Spjdstruct prison * 683113275Smikeprison_find(int prid) 684113275Smike{ 685113275Smike struct prison *pr; 686113275Smike 687168401Spjd sx_assert(&allprison_lock, SX_LOCKED); 688113275Smike LIST_FOREACH(pr, &allprison, pr_list) { 689113275Smike if (pr->pr_id == prid) { 690113275Smike mtx_lock(&pr->pr_mtx); 691168489Spjd if (pr->pr_ref == 0) { 692168489Spjd mtx_unlock(&pr->pr_mtx); 693168489Spjd break; 694168489Spjd } 695113275Smike return (pr); 696113275Smike } 697113275Smike } 698113275Smike return (NULL); 699113275Smike} 700113275Smike 70172786Srwatsonvoid 702185029Spjdprison_free_locked(struct prison *pr) 70372786Srwatson{ 70472786Srwatson 705185029Spjd mtx_assert(&pr->pr_mtx, MA_OWNED); 70672786Srwatson pr->pr_ref--; 70772786Srwatson if (pr->pr_ref == 0) { 708168483Spjd mtx_unlock(&pr->pr_mtx); 709124882Srwatson TASK_INIT(&pr->pr_task, 0, prison_complete, pr); 710144660Sjeff taskqueue_enqueue(taskqueue_thread, &pr->pr_task); 71187275Srwatson return; 71272786Srwatson } 71387275Srwatson mtx_unlock(&pr->pr_mtx); 71472786Srwatson} 71572786Srwatson 716185029Spjdvoid 717185029Spjdprison_free(struct prison *pr) 718185029Spjd{ 719185029Spjd 720185029Spjd mtx_lock(&pr->pr_mtx); 721185029Spjd prison_free_locked(pr); 722185029Spjd} 723185029Spjd 724124882Srwatsonstatic void 725124882Srwatsonprison_complete(void *context, int pending) 726124882Srwatson{ 727124882Srwatson struct prison *pr; 728150652Scsjp int vfslocked; 729124882Srwatson 730124882Srwatson pr = (struct prison *)context; 731124882Srwatson 732168489Spjd sx_xlock(&allprison_lock); 733168489Spjd LIST_REMOVE(pr, pr_list); 734168489Spjd prisoncount--; 735185029Spjd sx_xunlock(&allprison_lock); 736168489Spjd 737185435Sbz cpuset_rel(pr->pr_cpuset); 738185435Sbz 739185029Spjd /* Free all OSD associated to this jail. */ 740185029Spjd osd_jail_exit(pr); 741185029Spjd 742150652Scsjp vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 743124882Srwatson vrele(pr->pr_root); 744150652Scsjp VFS_UNLOCK_GIANT(vfslocked); 745124882Srwatson 746124882Srwatson mtx_destroy(&pr->pr_mtx); 747185435Sbz free(pr->pr_linux, M_PRISON); 748185435Sbz#ifdef INET6 749185435Sbz free(pr->pr_ip6, M_PRISON); 750185435Sbz#endif 751185435Sbz#ifdef INET 752185435Sbz free(pr->pr_ip4, M_PRISON); 753185435Sbz#endif 754184205Sdes free(pr, M_PRISON); 755124882Srwatson} 756124882Srwatson 75772786Srwatsonvoid 758185029Spjdprison_hold_locked(struct prison *pr) 75972786Srwatson{ 76072786Srwatson 761185029Spjd mtx_assert(&pr->pr_mtx, MA_OWNED); 762168489Spjd KASSERT(pr->pr_ref > 0, 763168489Spjd ("Trying to hold dead prison (id=%d).", pr->pr_id)); 76472786Srwatson pr->pr_ref++; 765185029Spjd} 766185029Spjd 767185029Spjdvoid 768185029Spjdprison_hold(struct prison *pr) 769185029Spjd{ 770185029Spjd 771185029Spjd mtx_lock(&pr->pr_mtx); 772185029Spjd prison_hold_locked(pr); 77387275Srwatson mtx_unlock(&pr->pr_mtx); 77472786Srwatson} 77572786Srwatson 776185435Sbzvoid 777185435Sbzprison_proc_hold(struct prison *pr) 77887275Srwatson{ 77987275Srwatson 780185435Sbz mtx_lock(&pr->pr_mtx); 781185435Sbz KASSERT(pr->pr_state == PRISON_STATE_ALIVE, 782185435Sbz ("Cannot add a process to a non-alive prison (id=%d).", pr->pr_id)); 783185435Sbz pr->pr_nprocs++; 784185435Sbz mtx_unlock(&pr->pr_mtx); 78587275Srwatson} 78687275Srwatson 787185435Sbzvoid 788185435Sbzprison_proc_free(struct prison *pr) 789185435Sbz{ 790185435Sbz 791185435Sbz mtx_lock(&pr->pr_mtx); 792185435Sbz KASSERT(pr->pr_state == PRISON_STATE_ALIVE && pr->pr_nprocs > 0, 793185435Sbz ("Trying to kill a process in a dead prison (id=%d).", pr->pr_id)); 794185435Sbz pr->pr_nprocs--; 795185435Sbz if (pr->pr_nprocs == 0) 796185435Sbz pr->pr_state = PRISON_STATE_DYING; 797185435Sbz mtx_unlock(&pr->pr_mtx); 798185435Sbz} 799185435Sbz 800185435Sbz 801185435Sbz#ifdef INET 802185435Sbz/* 803185435Sbz * Pass back primary IPv4 address of this jail. 804185435Sbz * 805185435Sbz * If not jailed return success but do not alter the address. Caller has to 806185435Sbz * make sure to intialize it correctly (INADDR_ANY). 807185435Sbz * 808185435Sbz * Returns 0 on success, 1 on error. Address returned in NBO. 809185435Sbz */ 81046155Sphkint 811185435Sbzprison_getip4(struct ucred *cred, struct in_addr *ia) 81246155Sphk{ 81346155Sphk 814185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 815185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 816185435Sbz 81772786Srwatson if (!jailed(cred)) 818185435Sbz /* Do not change address passed in. */ 81946155Sphk return (0); 820185435Sbz 821185435Sbz if (cred->cr_prison->pr_ip4 == NULL) 822185435Sbz return (1); 823185435Sbz 824185435Sbz ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 825185435Sbz return (0); 826185435Sbz} 827185435Sbz 828185435Sbz/* 829185435Sbz * Make sure our (source) address is set to something meaningful to this 830185435Sbz * jail. 831185435Sbz * 832185435Sbz * Returns 0 on success, 1 on error. Address passed in in NBO and returned 833185435Sbz * in NBO. 834185435Sbz */ 835185435Sbzint 836185435Sbzprison_local_ip4(struct ucred *cred, struct in_addr *ia) 837185435Sbz{ 838185435Sbz struct in_addr ia0; 839185435Sbz 840185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 841185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 842185435Sbz 843185435Sbz if (!jailed(cred)) 84446155Sphk return (0); 845185435Sbz if (cred->cr_prison->pr_ip4 == NULL) 846185435Sbz return (1); 847185435Sbz 848185435Sbz ia0.s_addr = ntohl(ia->s_addr); 849185435Sbz if (ia0.s_addr == INADDR_LOOPBACK) { 850185435Sbz ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 851185435Sbz return (0); 85246155Sphk } 853185435Sbz 854185435Sbz /* 855185435Sbz * In case there is only 1 IPv4 address, bind directly. 856185435Sbz */ 857185435Sbz if (ia0.s_addr == INADDR_ANY && cred->cr_prison->pr_ip4s == 1) { 858185435Sbz ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 859185435Sbz return (0); 860185435Sbz } 861185435Sbz 862185435Sbz if (ia0.s_addr == INADDR_ANY || prison_check_ip4(cred, ia)) 863185435Sbz return (0); 864185435Sbz 865185435Sbz return (1); 866185435Sbz} 867185435Sbz 868185435Sbz/* 869185435Sbz * Rewrite destination address in case we will connect to loopback address. 870185435Sbz * 871185435Sbz * Returns 0 on success, 1 on error. Address passed in in NBO and returned 872185435Sbz * in NBO. 873185435Sbz */ 874185435Sbzint 875185435Sbzprison_remote_ip4(struct ucred *cred, struct in_addr *ia) 876185435Sbz{ 877185435Sbz 878185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 879185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 880185435Sbz 881185435Sbz if (!jailed(cred)) 882185435Sbz return (0); 883185435Sbz if (cred->cr_prison->pr_ip4 == NULL) 884185435Sbz return (1); 885185435Sbz if (ntohl(ia->s_addr) == INADDR_LOOPBACK) { 886185435Sbz ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; 887185435Sbz return (0); 888185435Sbz } 889185435Sbz 890185435Sbz /* 891185435Sbz * Return success because nothing had to be changed. 892185435Sbz */ 893185435Sbz return (0); 894185435Sbz} 895185435Sbz 896185435Sbz/* 897185435Sbz * Check if given address belongs to the jail referenced by cred. 898185435Sbz * 899185435Sbz * Returns 1 if address belongs to jail, 0 if not. Address passed in in NBO. 900185435Sbz */ 901185435Sbzstatic int 902185435Sbz_prison_check_ip4(struct prison *pr, struct in_addr *ia) 903185435Sbz{ 904185435Sbz int i, a, z, d; 905185435Sbz 906185435Sbz if (pr->pr_ip4 == NULL) 907185435Sbz return (0); 908185435Sbz 909185435Sbz /* 910185435Sbz * Check the primary IP. 911185435Sbz */ 912185435Sbz if (pr->pr_ip4[0].s_addr == ia->s_addr) 913185435Sbz return (1); 914185435Sbz 915185435Sbz /* 916185435Sbz * All the other IPs are sorted so we can do a binary search. 917185435Sbz */ 918185435Sbz a = 0; 919185435Sbz z = pr->pr_ip4s - 2; 920185435Sbz while (a <= z) { 921185435Sbz i = (a + z) / 2; 922185435Sbz d = qcmp_v4(&pr->pr_ip4[i+1], ia); 923185435Sbz if (d > 0) 924185435Sbz z = i - 1; 925185435Sbz else if (d < 0) 926185435Sbz a = i + 1; 92781114Srwatson else 928185435Sbz return (1); 929185435Sbz } 930185435Sbz return (0); 931185435Sbz} 932185435Sbz 933185435Sbzint 934185435Sbzprison_check_ip4(struct ucred *cred, struct in_addr *ia) 935185435Sbz{ 936185435Sbz 937185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 938185435Sbz KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); 939185435Sbz 940185435Sbz if (!jailed(cred)) 941185435Sbz return (1); 942185435Sbz 943185435Sbz return (_prison_check_ip4(cred->cr_prison, ia)); 944185435Sbz} 945185435Sbz#endif 946185435Sbz 947185435Sbz#ifdef INET6 948185435Sbz/* 949185435Sbz * Pass back primary IPv6 address for this jail. 950185435Sbz * 951185435Sbz * If not jailed return success but do not alter the address. Caller has to 952185435Sbz * make sure to intialize it correctly (IN6ADDR_ANY_INIT). 953185435Sbz * 954185435Sbz * Returns 0 on success, 1 on error. 955185435Sbz */ 956185435Sbzint 957185435Sbzprison_getip6(struct ucred *cred, struct in6_addr *ia6) 958185435Sbz{ 959185435Sbz 960185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 961185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 962185435Sbz 963185435Sbz if (!jailed(cred)) 96481114Srwatson return (0); 965185435Sbz if (cred->cr_prison->pr_ip6 == NULL) 966185435Sbz return (1); 967185435Sbz bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr)); 968185435Sbz return (0); 969185435Sbz} 970185435Sbz 971185435Sbz/* 972185435Sbz * Make sure our (source) address is set to something meaningful to this jail. 973185435Sbz * 974185435Sbz * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0) 975185435Sbz * when needed while binding. 976185435Sbz * 977185435Sbz * Returns 0 on success, 1 on error. 978185435Sbz */ 979185435Sbzint 980185435Sbzprison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only) 981185435Sbz{ 982185435Sbz 983185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 984185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 985185435Sbz 986185435Sbz if (!jailed(cred)) 987185435Sbz return (0); 988185435Sbz if (cred->cr_prison->pr_ip6 == NULL) 989185435Sbz return (1); 990185435Sbz if (IN6_IS_ADDR_LOOPBACK(ia6)) { 991185435Sbz bcopy(&cred->cr_prison->pr_ip6[0], ia6, 992185435Sbz sizeof(struct in6_addr)); 993185435Sbz return (0); 99481114Srwatson } 995185435Sbz 996185435Sbz /* 997185435Sbz * In case there is only 1 IPv6 address, and v6only is true, then 998185435Sbz * bind directly. 999185435Sbz */ 1000185435Sbz if (v6only != 0 && IN6_IS_ADDR_UNSPECIFIED(ia6) && 1001185435Sbz cred->cr_prison->pr_ip6s == 1) { 1002185435Sbz bcopy(&cred->cr_prison->pr_ip6[0], ia6, 1003185435Sbz sizeof(struct in6_addr)); 1004185435Sbz return (0); 1005185435Sbz } 1006185435Sbz if (IN6_IS_ADDR_UNSPECIFIED(ia6) || prison_check_ip6(cred, ia6)) 1007185435Sbz return (0); 1008185435Sbz return (1); 1009185435Sbz} 1010185435Sbz 1011185435Sbz/* 1012185435Sbz * Rewrite destination address in case we will connect to loopback address. 1013185435Sbz * 1014185435Sbz * Returns 0 on success, 1 on error. 1015185435Sbz */ 1016185435Sbzint 1017185435Sbzprison_remote_ip6(struct ucred *cred, struct in6_addr *ia6) 1018185435Sbz{ 1019185435Sbz 1020185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1021185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 1022185435Sbz 1023185435Sbz if (!jailed(cred)) 1024185435Sbz return (0); 1025185435Sbz if (cred->cr_prison->pr_ip6 == NULL) 102646155Sphk return (1); 1027185435Sbz if (IN6_IS_ADDR_LOOPBACK(ia6)) { 1028185435Sbz bcopy(&cred->cr_prison->pr_ip6[0], ia6, 1029185435Sbz sizeof(struct in6_addr)); 1030185435Sbz return (0); 1031185435Sbz } 1032185435Sbz 1033185435Sbz /* 1034185435Sbz * Return success because nothing had to be changed. 1035185435Sbz */ 103646155Sphk return (0); 103746155Sphk} 103846155Sphk 1039185435Sbz/* 1040185435Sbz * Check if given address belongs to the jail referenced by cred. 1041185435Sbz * 1042185435Sbz * Returns 1 if address belongs to jail, 0 if not. 1043185435Sbz */ 1044185435Sbzstatic int 1045185435Sbz_prison_check_ip6(struct prison *pr, struct in6_addr *ia6) 104646155Sphk{ 1047185435Sbz int i, a, z, d; 104846155Sphk 1049185435Sbz if (pr->pr_ip6 == NULL) 1050185435Sbz return (0); 1051185435Sbz 1052185435Sbz /* 1053185435Sbz * Check the primary IP. 1054185435Sbz */ 1055185435Sbz if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6)) 1056185435Sbz return (1); 1057185435Sbz 1058185435Sbz /* 1059185435Sbz * All the other IPs are sorted so we can do a binary search. 1060185435Sbz */ 1061185435Sbz a = 0; 1062185435Sbz z = pr->pr_ip6s - 2; 1063185435Sbz while (a <= z) { 1064185435Sbz i = (a + z) / 2; 1065185435Sbz d = qcmp_v6(&pr->pr_ip6[i+1], ia6); 1066185435Sbz if (d > 0) 1067185435Sbz z = i - 1; 1068185435Sbz else if (d < 0) 1069185435Sbz a = i + 1; 107046155Sphk else 1071185435Sbz return (1); 107246155Sphk } 1073185435Sbz return (0); 107446155Sphk} 107546155Sphk 107646155Sphkint 1077185435Sbzprison_check_ip6(struct ucred *cred, struct in6_addr *ia6) 1078185435Sbz{ 1079185435Sbz 1080185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1081185435Sbz KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); 1082185435Sbz 1083185435Sbz if (!jailed(cred)) 1084185435Sbz return (1); 1085185435Sbz 1086185435Sbz return (_prison_check_ip6(cred->cr_prison, ia6)); 1087185435Sbz} 1088185435Sbz#endif 1089185435Sbz 1090185435Sbz/* 1091185435Sbz * Check if given address belongs to the jail referenced by cred (wrapper to 1092185435Sbz * prison_check_ip[46]). 1093185435Sbz * 1094185435Sbz * Returns 1 if address belongs to jail, 0 if not. IPv4 Address passed in in 1095185435Sbz * NBO. 1096185435Sbz */ 1097185435Sbzint 109872786Srwatsonprison_if(struct ucred *cred, struct sockaddr *sa) 109946155Sphk{ 1100185435Sbz#ifdef INET 1101114168Smike struct sockaddr_in *sai; 1102185435Sbz#endif 1103185435Sbz#ifdef INET6 1104185435Sbz struct sockaddr_in6 *sai6; 1105185435Sbz#endif 110646155Sphk int ok; 110746155Sphk 1108185435Sbz KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); 1109185435Sbz KASSERT(sa != NULL, ("%s: sa is NULL", __func__)); 1110185435Sbz 1111185435Sbz ok = 0; 1112185435Sbz switch(sa->sa_family) 1113185435Sbz { 1114185435Sbz#ifdef INET 1115185435Sbz case AF_INET: 1116185435Sbz sai = (struct sockaddr_in *)sa; 1117185435Sbz if (prison_check_ip4(cred, &sai->sin_addr)) 1118185435Sbz ok = 1; 1119185435Sbz break; 1120185435Sbz 1121185435Sbz#endif 1122185435Sbz#ifdef INET6 1123185435Sbz case AF_INET6: 1124185435Sbz sai6 = (struct sockaddr_in6 *)sa; 1125185435Sbz if (prison_check_ip6(cred, (struct in6_addr *)&sai6->sin6_addr)) 1126185435Sbz ok = 1; 1127185435Sbz break; 1128185435Sbz 1129185435Sbz#endif 1130185435Sbz default: 1131185435Sbz if (!jail_socket_unixiproute_only) 1132185435Sbz ok = 1; 1133185435Sbz } 113446155Sphk return (ok); 113546155Sphk} 113672786Srwatson 113772786Srwatson/* 113872786Srwatson * Return 0 if jails permit p1 to frob p2, otherwise ESRCH. 113972786Srwatson */ 114072786Srwatsonint 1141114168Smikeprison_check(struct ucred *cred1, struct ucred *cred2) 114272786Srwatson{ 114372786Srwatson 114472786Srwatson if (jailed(cred1)) { 114572786Srwatson if (!jailed(cred2)) 114672786Srwatson return (ESRCH); 114772786Srwatson if (cred2->cr_prison != cred1->cr_prison) 114872786Srwatson return (ESRCH); 114972786Srwatson } 115072786Srwatson 115172786Srwatson return (0); 115272786Srwatson} 115372786Srwatson 115472786Srwatson/* 115572786Srwatson * Return 1 if the passed credential is in a jail, otherwise 0. 115672786Srwatson */ 115772786Srwatsonint 1158114168Smikejailed(struct ucred *cred) 115972786Srwatson{ 116072786Srwatson 116172786Srwatson return (cred->cr_prison != NULL); 116272786Srwatson} 116391384Srobert 116491384Srobert/* 116591384Srobert * Return the correct hostname for the passed credential. 116691384Srobert */ 116791391Srobertvoid 1168114168Smikegetcredhostname(struct ucred *cred, char *buf, size_t size) 116991384Srobert{ 1170183550Szec INIT_VPROCG(cred->cr_vimage->v_procg); 117191384Srobert 117291391Srobert if (jailed(cred)) { 117391391Srobert mtx_lock(&cred->cr_prison->pr_mtx); 1174105354Srobert strlcpy(buf, cred->cr_prison->pr_host, size); 117591391Srobert mtx_unlock(&cred->cr_prison->pr_mtx); 1176180291Srwatson } else { 1177180291Srwatson mtx_lock(&hostname_mtx); 1178181803Sbz strlcpy(buf, V_hostname, size); 1179180291Srwatson mtx_unlock(&hostname_mtx); 1180180291Srwatson } 118191384Srobert} 1182113275Smike 1183125804Srwatson/* 1184147185Spjd * Determine whether the subject represented by cred can "see" 1185147185Spjd * status of a mount point. 1186147185Spjd * Returns: 0 for permitted, ENOENT otherwise. 1187147185Spjd * XXX: This function should be called cr_canseemount() and should be 1188147185Spjd * placed in kern_prot.c. 1189125804Srwatson */ 1190125804Srwatsonint 1191147185Spjdprison_canseemount(struct ucred *cred, struct mount *mp) 1192125804Srwatson{ 1193147185Spjd struct prison *pr; 1194147185Spjd struct statfs *sp; 1195147185Spjd size_t len; 1196125804Srwatson 1197147185Spjd if (!jailed(cred) || jail_enforce_statfs == 0) 1198147185Spjd return (0); 1199147185Spjd pr = cred->cr_prison; 1200147185Spjd if (pr->pr_root->v_mount == mp) 1201147185Spjd return (0); 1202147185Spjd if (jail_enforce_statfs == 2) 1203147185Spjd return (ENOENT); 1204147185Spjd /* 1205147185Spjd * If jail's chroot directory is set to "/" we should be able to see 1206147185Spjd * all mount-points from inside a jail. 1207147185Spjd * This is ugly check, but this is the only situation when jail's 1208147185Spjd * directory ends with '/'. 1209147185Spjd */ 1210147185Spjd if (strcmp(pr->pr_path, "/") == 0) 1211147185Spjd return (0); 1212147185Spjd len = strlen(pr->pr_path); 1213147185Spjd sp = &mp->mnt_stat; 1214147185Spjd if (strncmp(pr->pr_path, sp->f_mntonname, len) != 0) 1215147185Spjd return (ENOENT); 1216147185Spjd /* 1217147185Spjd * Be sure that we don't have situation where jail's root directory 1218147185Spjd * is "/some/path" and mount point is "/some/pathpath". 1219147185Spjd */ 1220147185Spjd if (sp->f_mntonname[len] != '\0' && sp->f_mntonname[len] != '/') 1221147185Spjd return (ENOENT); 1222147185Spjd return (0); 1223147185Spjd} 1224147185Spjd 1225147185Spjdvoid 1226147185Spjdprison_enforce_statfs(struct ucred *cred, struct mount *mp, struct statfs *sp) 1227147185Spjd{ 1228147185Spjd char jpath[MAXPATHLEN]; 1229147185Spjd struct prison *pr; 1230147185Spjd size_t len; 1231147185Spjd 1232147185Spjd if (!jailed(cred) || jail_enforce_statfs == 0) 1233147185Spjd return; 1234147185Spjd pr = cred->cr_prison; 1235147185Spjd if (prison_canseemount(cred, mp) != 0) { 1236147185Spjd bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1237147185Spjd strlcpy(sp->f_mntonname, "[restricted]", 1238147185Spjd sizeof(sp->f_mntonname)); 1239147185Spjd return; 1240125804Srwatson } 1241147185Spjd if (pr->pr_root->v_mount == mp) { 1242147185Spjd /* 1243147185Spjd * Clear current buffer data, so we are sure nothing from 1244147185Spjd * the valid path left there. 1245147185Spjd */ 1246147185Spjd bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1247147185Spjd *sp->f_mntonname = '/'; 1248147185Spjd return; 1249147185Spjd } 1250147185Spjd /* 1251147185Spjd * If jail's chroot directory is set to "/" we should be able to see 1252147185Spjd * all mount-points from inside a jail. 1253147185Spjd */ 1254147185Spjd if (strcmp(pr->pr_path, "/") == 0) 1255147185Spjd return; 1256147185Spjd len = strlen(pr->pr_path); 1257147185Spjd strlcpy(jpath, sp->f_mntonname + len, sizeof(jpath)); 1258147185Spjd /* 1259147185Spjd * Clear current buffer data, so we are sure nothing from 1260147185Spjd * the valid path left there. 1261147185Spjd */ 1262147185Spjd bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1263147185Spjd if (*jpath == '\0') { 1264147185Spjd /* Should never happen. */ 1265147185Spjd *sp->f_mntonname = '/'; 1266147185Spjd } else { 1267147185Spjd strlcpy(sp->f_mntonname, jpath, sizeof(sp->f_mntonname)); 1268147185Spjd } 1269125804Srwatson} 1270125804Srwatson 1271164032Srwatson/* 1272164032Srwatson * Check with permission for a specific privilege is granted within jail. We 1273164032Srwatson * have a specific list of accepted privileges; the rest are denied. 1274164032Srwatson */ 1275164032Srwatsonint 1276164032Srwatsonprison_priv_check(struct ucred *cred, int priv) 1277164032Srwatson{ 1278164032Srwatson 1279164032Srwatson if (!jailed(cred)) 1280164032Srwatson return (0); 1281164032Srwatson 1282164032Srwatson switch (priv) { 1283164032Srwatson 1284164032Srwatson /* 1285164032Srwatson * Allow ktrace privileges for root in jail. 1286164032Srwatson */ 1287164032Srwatson case PRIV_KTRACE: 1288164032Srwatson 1289166827Srwatson#if 0 1290164032Srwatson /* 1291164032Srwatson * Allow jailed processes to configure audit identity and 1292164032Srwatson * submit audit records (login, etc). In the future we may 1293164032Srwatson * want to further refine the relationship between audit and 1294164032Srwatson * jail. 1295164032Srwatson */ 1296164032Srwatson case PRIV_AUDIT_GETAUDIT: 1297164032Srwatson case PRIV_AUDIT_SETAUDIT: 1298164032Srwatson case PRIV_AUDIT_SUBMIT: 1299166827Srwatson#endif 1300164032Srwatson 1301164032Srwatson /* 1302164032Srwatson * Allow jailed processes to manipulate process UNIX 1303164032Srwatson * credentials in any way they see fit. 1304164032Srwatson */ 1305164032Srwatson case PRIV_CRED_SETUID: 1306164032Srwatson case PRIV_CRED_SETEUID: 1307164032Srwatson case PRIV_CRED_SETGID: 1308164032Srwatson case PRIV_CRED_SETEGID: 1309164032Srwatson case PRIV_CRED_SETGROUPS: 1310164032Srwatson case PRIV_CRED_SETREUID: 1311164032Srwatson case PRIV_CRED_SETREGID: 1312164032Srwatson case PRIV_CRED_SETRESUID: 1313164032Srwatson case PRIV_CRED_SETRESGID: 1314164032Srwatson 1315164032Srwatson /* 1316164032Srwatson * Jail implements visibility constraints already, so allow 1317164032Srwatson * jailed root to override uid/gid-based constraints. 1318164032Srwatson */ 1319164032Srwatson case PRIV_SEEOTHERGIDS: 1320164032Srwatson case PRIV_SEEOTHERUIDS: 1321164032Srwatson 1322164032Srwatson /* 1323164032Srwatson * Jail implements inter-process debugging limits already, so 1324164032Srwatson * allow jailed root various debugging privileges. 1325164032Srwatson */ 1326164032Srwatson case PRIV_DEBUG_DIFFCRED: 1327164032Srwatson case PRIV_DEBUG_SUGID: 1328164032Srwatson case PRIV_DEBUG_UNPRIV: 1329164032Srwatson 1330164032Srwatson /* 1331164032Srwatson * Allow jail to set various resource limits and login 1332164032Srwatson * properties, and for now, exceed process resource limits. 1333164032Srwatson */ 1334164032Srwatson case PRIV_PROC_LIMIT: 1335164032Srwatson case PRIV_PROC_SETLOGIN: 1336164032Srwatson case PRIV_PROC_SETRLIMIT: 1337164032Srwatson 1338164032Srwatson /* 1339164032Srwatson * System V and POSIX IPC privileges are granted in jail. 1340164032Srwatson */ 1341164032Srwatson case PRIV_IPC_READ: 1342164032Srwatson case PRIV_IPC_WRITE: 1343164032Srwatson case PRIV_IPC_ADMIN: 1344164032Srwatson case PRIV_IPC_MSGSIZE: 1345164032Srwatson case PRIV_MQ_ADMIN: 1346164032Srwatson 1347164032Srwatson /* 1348164032Srwatson * Jail implements its own inter-process limits, so allow 1349164032Srwatson * root processes in jail to change scheduling on other 1350164032Srwatson * processes in the same jail. Likewise for signalling. 1351164032Srwatson */ 1352164032Srwatson case PRIV_SCHED_DIFFCRED: 1353185435Sbz case PRIV_SCHED_CPUSET: 1354164032Srwatson case PRIV_SIGNAL_DIFFCRED: 1355164032Srwatson case PRIV_SIGNAL_SUGID: 1356164032Srwatson 1357164032Srwatson /* 1358164032Srwatson * Allow jailed processes to write to sysctls marked as jail 1359164032Srwatson * writable. 1360164032Srwatson */ 1361164032Srwatson case PRIV_SYSCTL_WRITEJAIL: 1362164032Srwatson 1363164032Srwatson /* 1364164032Srwatson * Allow root in jail to manage a variety of quota 1365166831Srwatson * properties. These should likely be conditional on a 1366166831Srwatson * configuration option. 1367164032Srwatson */ 1368166832Srwatson case PRIV_VFS_GETQUOTA: 1369166832Srwatson case PRIV_VFS_SETQUOTA: 1370164032Srwatson 1371164032Srwatson /* 1372164032Srwatson * Since Jail relies on chroot() to implement file system 1373164032Srwatson * protections, grant many VFS privileges to root in jail. 1374164032Srwatson * Be careful to exclude mount-related and NFS-related 1375164032Srwatson * privileges. 1376164032Srwatson */ 1377164032Srwatson case PRIV_VFS_READ: 1378164032Srwatson case PRIV_VFS_WRITE: 1379164032Srwatson case PRIV_VFS_ADMIN: 1380164032Srwatson case PRIV_VFS_EXEC: 1381164032Srwatson case PRIV_VFS_LOOKUP: 1382164032Srwatson case PRIV_VFS_BLOCKRESERVE: /* XXXRW: Slightly surprising. */ 1383164032Srwatson case PRIV_VFS_CHFLAGS_DEV: 1384164032Srwatson case PRIV_VFS_CHOWN: 1385164032Srwatson case PRIV_VFS_CHROOT: 1386167152Spjd case PRIV_VFS_RETAINSUGID: 1387164032Srwatson case PRIV_VFS_FCHROOT: 1388164032Srwatson case PRIV_VFS_LINK: 1389164032Srwatson case PRIV_VFS_SETGID: 1390172860Srwatson case PRIV_VFS_STAT: 1391164032Srwatson case PRIV_VFS_STICKYFILE: 1392164032Srwatson return (0); 1393164032Srwatson 1394164032Srwatson /* 1395164032Srwatson * Depending on the global setting, allow privilege of 1396164032Srwatson * setting system flags. 1397164032Srwatson */ 1398164032Srwatson case PRIV_VFS_SYSFLAGS: 1399164032Srwatson if (jail_chflags_allowed) 1400164032Srwatson return (0); 1401164032Srwatson else 1402164032Srwatson return (EPERM); 1403164032Srwatson 1404164032Srwatson /* 1405168396Spjd * Depending on the global setting, allow privilege of 1406168396Spjd * mounting/unmounting file systems. 1407168396Spjd */ 1408168396Spjd case PRIV_VFS_MOUNT: 1409168396Spjd case PRIV_VFS_UNMOUNT: 1410168396Spjd case PRIV_VFS_MOUNT_NONUSER: 1411168699Spjd case PRIV_VFS_MOUNT_OWNER: 1412168396Spjd if (jail_mount_allowed) 1413168396Spjd return (0); 1414168396Spjd else 1415168396Spjd return (EPERM); 1416168396Spjd 1417168396Spjd /* 1418168591Srwatson * Allow jailed root to bind reserved ports and reuse in-use 1419168591Srwatson * ports. 1420164032Srwatson */ 1421164032Srwatson case PRIV_NETINET_RESERVEDPORT: 1422168591Srwatson case PRIV_NETINET_REUSEPORT: 1423164032Srwatson return (0); 1424164032Srwatson 1425164032Srwatson /* 1426175630Sbz * Allow jailed root to set certian IPv4/6 (option) headers. 1427175630Sbz */ 1428175630Sbz case PRIV_NETINET_SETHDROPTS: 1429175630Sbz return (0); 1430175630Sbz 1431175630Sbz /* 1432164032Srwatson * Conditionally allow creating raw sockets in jail. 1433164032Srwatson */ 1434164032Srwatson case PRIV_NETINET_RAW: 1435164032Srwatson if (jail_allow_raw_sockets) 1436164032Srwatson return (0); 1437164032Srwatson else 1438164032Srwatson return (EPERM); 1439164032Srwatson 1440164032Srwatson /* 1441164032Srwatson * Since jail implements its own visibility limits on netstat 1442164032Srwatson * sysctls, allow getcred. This allows identd to work in 1443164032Srwatson * jail. 1444164032Srwatson */ 1445164032Srwatson case PRIV_NETINET_GETCRED: 1446164032Srwatson return (0); 1447164032Srwatson 1448164032Srwatson default: 1449164032Srwatson /* 1450164032Srwatson * In all remaining cases, deny the privilege request. This 1451164032Srwatson * includes almost all network privileges, many system 1452164032Srwatson * configuration privileges. 1453164032Srwatson */ 1454164032Srwatson return (EPERM); 1455164032Srwatson } 1456164032Srwatson} 1457164032Srwatson 1458113275Smikestatic int 1459113275Smikesysctl_jail_list(SYSCTL_HANDLER_ARGS) 1460113275Smike{ 1461113275Smike struct xprison *xp, *sxp; 1462113275Smike struct prison *pr; 1463185435Sbz char *p; 1464185435Sbz size_t len; 1465113275Smike int count, error; 1466113275Smike 1467127020Spjd if (jailed(req->td->td_ucred)) 1468125806Srwatson return (0); 1469113275Smike 1470168401Spjd sx_slock(&allprison_lock); 1471168401Spjd if ((count = prisoncount) == 0) { 1472168401Spjd sx_sunlock(&allprison_lock); 1473113275Smike return (0); 1474168401Spjd } 1475113275Smike 1476185435Sbz len = sizeof(*xp) * count; 1477185435Sbz LIST_FOREACH(pr, &allprison, pr_list) { 1478185435Sbz#ifdef INET 1479185435Sbz len += pr->pr_ip4s * sizeof(struct in_addr); 1480185435Sbz#endif 1481185435Sbz#ifdef INET6 1482185435Sbz len += pr->pr_ip6s * sizeof(struct in6_addr); 1483185435Sbz#endif 1484185435Sbz } 1485167309Spjd 1486185435Sbz sxp = xp = malloc(len, M_TEMP, M_WAITOK | M_ZERO); 1487185435Sbz 1488113275Smike LIST_FOREACH(pr, &allprison, pr_list) { 1489113275Smike xp->pr_version = XPRISON_VERSION; 1490113275Smike xp->pr_id = pr->pr_id; 1491185435Sbz xp->pr_state = pr->pr_state; 1492185435Sbz xp->pr_cpusetid = pr->pr_cpuset->cs_id; 1493113275Smike strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path)); 1494168487Spjd mtx_lock(&pr->pr_mtx); 1495113275Smike strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host)); 1496185435Sbz strlcpy(xp->pr_name, pr->pr_name, sizeof(xp->pr_name)); 1497113275Smike mtx_unlock(&pr->pr_mtx); 1498185435Sbz#ifdef INET 1499185435Sbz xp->pr_ip4s = pr->pr_ip4s; 1500185435Sbz#endif 1501185435Sbz#ifdef INET6 1502185435Sbz xp->pr_ip6s = pr->pr_ip6s; 1503185435Sbz#endif 1504185435Sbz p = (char *)(xp + 1); 1505185435Sbz#ifdef INET 1506185435Sbz if (pr->pr_ip4s > 0) { 1507185435Sbz bcopy(pr->pr_ip4, (struct in_addr *)p, 1508185435Sbz pr->pr_ip4s * sizeof(struct in_addr)); 1509185435Sbz p += (pr->pr_ip4s * sizeof(struct in_addr)); 1510185435Sbz } 1511185435Sbz#endif 1512185435Sbz#ifdef INET6 1513185435Sbz if (pr->pr_ip6s > 0) { 1514185435Sbz bcopy(pr->pr_ip6, (struct in6_addr *)p, 1515185435Sbz pr->pr_ip6s * sizeof(struct in6_addr)); 1516185435Sbz p += (pr->pr_ip6s * sizeof(struct in6_addr)); 1517185435Sbz } 1518185435Sbz#endif 1519185435Sbz xp = (struct xprison *)p; 1520113275Smike } 1521168401Spjd sx_sunlock(&allprison_lock); 1522113275Smike 1523185435Sbz error = SYSCTL_OUT(req, sxp, len); 1524113275Smike free(sxp, M_TEMP); 1525167354Spjd return (error); 1526113275Smike} 1527113275Smike 1528113275SmikeSYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD, 1529113275Smike NULL, 0, sysctl_jail_list, "S", "List of active jails"); 1530126004Spjd 1531126004Spjdstatic int 1532126004Spjdsysctl_jail_jailed(SYSCTL_HANDLER_ARGS) 1533126004Spjd{ 1534126004Spjd int error, injail; 1535126004Spjd 1536126004Spjd injail = jailed(req->td->td_ucred); 1537126004Spjd error = SYSCTL_OUT(req, &injail, sizeof(injail)); 1538126004Spjd 1539126004Spjd return (error); 1540126004Spjd} 1541126004SpjdSYSCTL_PROC(_security_jail, OID_AUTO, jailed, CTLTYPE_INT | CTLFLAG_RD, 1542126004Spjd NULL, 0, sysctl_jail_jailed, "I", "Process in jail?"); 1543185435Sbz 1544185435Sbz#ifdef DDB 1545185435SbzDB_SHOW_COMMAND(jails, db_show_jails) 1546185435Sbz{ 1547185435Sbz struct prison *pr; 1548185435Sbz#ifdef INET 1549185435Sbz struct in_addr ia; 1550185435Sbz#endif 1551185435Sbz#ifdef INET6 1552185435Sbz char ip6buf[INET6_ADDRSTRLEN]; 1553185435Sbz#endif 1554185435Sbz const char *state; 1555185435Sbz#if defined(INET) || defined(INET6) 1556185435Sbz int i; 1557185435Sbz#endif 1558185435Sbz 1559185435Sbz db_printf( 1560185435Sbz " JID pr_ref pr_nprocs pr_ip4s pr_ip6s\n"); 1561185435Sbz db_printf( 1562185435Sbz " Hostname Path\n"); 1563185435Sbz db_printf( 1564185435Sbz " Name State\n"); 1565185435Sbz db_printf( 1566185435Sbz " Cpusetid\n"); 1567185435Sbz db_printf( 1568185435Sbz " IP Address(es)\n"); 1569185435Sbz LIST_FOREACH(pr, &allprison, pr_list) { 1570185435Sbz db_printf("%6d %6d %9d %7d %7d\n", 1571185435Sbz pr->pr_id, pr->pr_ref, pr->pr_nprocs, 1572185435Sbz pr->pr_ip4s, pr->pr_ip6s); 1573185435Sbz db_printf("%6s %-29.29s %.74s\n", 1574185435Sbz "", pr->pr_host, pr->pr_path); 1575185435Sbz if (pr->pr_state < 0 || pr->pr_state > (int)((sizeof( 1576185435Sbz prison_states) / sizeof(struct prison_state)))) 1577185435Sbz state = "(bogus)"; 1578185435Sbz else 1579185435Sbz state = prison_states[pr->pr_state].state_name; 1580185435Sbz db_printf("%6s %-29.29s %.74s\n", 1581185435Sbz "", (pr->pr_name != NULL) ? pr->pr_name : "", state); 1582185435Sbz db_printf("%6s %-6d\n", 1583185435Sbz "", pr->pr_cpuset->cs_id); 1584185435Sbz#ifdef INET 1585185435Sbz for (i=0; i < pr->pr_ip4s; i++) { 1586185435Sbz ia.s_addr = pr->pr_ip4[i].s_addr; 1587185435Sbz db_printf("%6s %s\n", "", inet_ntoa(ia)); 1588185435Sbz } 1589185435Sbz#endif 1590185435Sbz#ifdef INET6 1591185435Sbz for (i=0; i < pr->pr_ip6s; i++) 1592185435Sbz db_printf("%6s %s\n", 1593185435Sbz "", ip6_sprintf(ip6buf, &pr->pr_ip6[i])); 1594185435Sbz#endif /* INET6 */ 1595185435Sbz if (db_pager_quit) 1596185435Sbz break; 1597185435Sbz } 1598185435Sbz} 1599185435Sbz#endif /* DDB */ 1600