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