kern_jail.c revision 187684
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 187684 2009-01-25 10:11:58Z 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;
296186606Spho	} else
297186606Spho		j->ip4 = NULL;
298185435Sbz#endif
299185435Sbz#ifdef INET6
300185435Sbz	if (j->ip6s > 0) {
301185435Sbz		ip6 = (struct in6_addr *)malloc(j->ip6s * sizeof(struct in6_addr),
302185435Sbz		    M_PRISON, M_WAITOK | M_ZERO);
303185435Sbz		error = copyin(j->ip6, ip6, j->ip6s * sizeof(struct in6_addr));
304185435Sbz		if (error)
305185435Sbz			goto e_free_ip;
306185435Sbz		/* Sort all but the first IPv6 address. */
307185435Sbz		if (j->ip6s > 1)
308185435Sbz			qsort((ip6 + 1), j->ip6s - 1,
309185435Sbz			    sizeof(struct in6_addr), qcmp_v6);
310185435Sbz		for (i=0; i<j->ip6s; i++) {
311185435Sbz			if (IN6_IS_ADDR_UNSPECIFIED(&ip6[i])) {
312185435Sbz				error = EINVAL;
313185435Sbz				goto e_free_ip;
314185435Sbz			}
315185435Sbz			if ((i+1) < j->ip6s &&
316185435Sbz			    (IN6_ARE_ADDR_EQUAL(&ip6[0], &ip6[i+1]) ||
317185435Sbz			    IN6_ARE_ADDR_EQUAL(&ip6[i], &ip6[i+1]))) {
318185435Sbz				error = EINVAL;
319185435Sbz				goto e_free_ip;
320185435Sbz			}
321185435Sbz		}
322185435Sbz
323185435Sbz		j->ip6 = ip6;
324186606Spho	} else
325186606Spho		j->ip6 = NULL;
326185435Sbz#endif
327185435Sbz	return (0);
328185435Sbz
329185435Sbze_free_ip:
330185435Sbz#ifdef INET6
331185435Sbz	free(ip6, M_PRISON);
332185435Sbz#endif
333185435Sbz#ifdef INET
334185435Sbz	free(ip4, M_PRISON);
335185435Sbz#endif
336185435Sbz	return (error);
337185435Sbz}
338185435Sbz#endif /* INET || INET6 */
339185435Sbz
340185435Sbzstatic int
341185435Sbzjail_handle_ips(struct jail *j)
342185435Sbz{
343185435Sbz#if defined(INET) || defined(INET6)
344185435Sbz	int error;
345185435Sbz#endif
346185435Sbz
347185435Sbz	/*
348185435Sbz	 * Finish conversion for older versions, copyin and setup IPs.
349185435Sbz	 */
350185435Sbz	switch (j->version) {
351185435Sbz	case 0:
352185435Sbz	{
353185435Sbz#ifdef INET
354185435Sbz		/* FreeBSD single IPv4 jails. */
355185435Sbz		struct in_addr *ip4;
356185435Sbz
357185435Sbz		if (j->ip4s == INADDR_ANY || j->ip4s == INADDR_BROADCAST)
358185435Sbz			return (EINVAL);
359185435Sbz		ip4 = (struct in_addr *)malloc(sizeof(struct in_addr),
360185435Sbz		    M_PRISON, M_WAITOK | M_ZERO);
361185435Sbz
362185435Sbz		/*
363185435Sbz		 * Jail version 0 still used HBO for the IPv4 address.
364185435Sbz		 */
365185435Sbz		ip4->s_addr = htonl(j->ip4s);
366185435Sbz		j->ip4s = 1;
367185435Sbz		j->ip4 = ip4;
368185435Sbz		break;
369185435Sbz#else
370185435Sbz		return (EINVAL);
371185435Sbz#endif
372185435Sbz	}
373185435Sbz
374185435Sbz	case 1:
375185435Sbz		/*
376185435Sbz		 * Version 1 was used by multi-IPv4 jail implementations
377185435Sbz		 * that never made it into the official kernel.
378185435Sbz		 * We should never hit this here; jail() should catch it.
379185435Sbz		 */
380185435Sbz		return (EINVAL);
381185435Sbz
382185435Sbz	case 2:	/* JAIL_API_VERSION */
383185435Sbz		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
384185435Sbz#if defined(INET) || defined(INET6)
385185435Sbz#ifdef INET
386185435Sbz		if (j->ip4s > jail_max_af_ips)
387185435Sbz			return (EINVAL);
388185435Sbz#else
389185435Sbz		if (j->ip4s != 0)
390185435Sbz			return (EINVAL);
391185435Sbz#endif
392185435Sbz#ifdef INET6
393185435Sbz		if (j->ip6s > jail_max_af_ips)
394185435Sbz			return (EINVAL);
395185435Sbz#else
396185435Sbz		if (j->ip6s != 0)
397185435Sbz			return (EINVAL);
398185435Sbz#endif
399185435Sbz		error = jail_copyin_ips(j);
400185435Sbz		if (error)
401185435Sbz			return (error);
402185435Sbz#endif
403185435Sbz		break;
404185435Sbz
405185435Sbz	default:
406185435Sbz		/* Sci-Fi jails are not supported, sorry. */
407185435Sbz		return (EINVAL);
408185435Sbz	}
409185435Sbz
410185435Sbz	return (0);
411185435Sbz}
412185435Sbz
413185435Sbz
41482710Sdillon/*
415114168Smike * struct jail_args {
416114168Smike *	struct jail *jail;
417114168Smike * };
41882710Sdillon */
41946155Sphkint
420114168Smikejail(struct thread *td, struct jail_args *uap)
42146155Sphk{
422185435Sbz	uint32_t version;
423185435Sbz	int error;
424185435Sbz	struct jail j;
425185435Sbz
426185435Sbz	error = copyin(uap->jail, &version, sizeof(uint32_t));
427185435Sbz	if (error)
428185435Sbz		return (error);
429185435Sbz
430185435Sbz	switch (version) {
431185435Sbz	case 0:
432185435Sbz		/* FreeBSD single IPv4 jails. */
433185435Sbz	{
434185435Sbz		struct jail_v0 j0;
435185435Sbz
436185435Sbz		bzero(&j, sizeof(struct jail));
437185435Sbz		error = copyin(uap->jail, &j0, sizeof(struct jail_v0));
438185435Sbz		if (error)
439185435Sbz			return (error);
440185435Sbz		j.version = j0.version;
441185435Sbz		j.path = j0.path;
442185435Sbz		j.hostname = j0.hostname;
443185435Sbz		j.ip4s = j0.ip_number;
444185435Sbz		break;
445185435Sbz	}
446185435Sbz
447185435Sbz	case 1:
448185435Sbz		/*
449185435Sbz		 * Version 1 was used by multi-IPv4 jail implementations
450185435Sbz		 * that never made it into the official kernel.
451185435Sbz		 */
452185435Sbz		return (EINVAL);
453185435Sbz
454185435Sbz	case 2:	/* JAIL_API_VERSION */
455185435Sbz		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
456185435Sbz		error = copyin(uap->jail, &j, sizeof(struct jail));
457185435Sbz		if (error)
458185435Sbz			return (error);
459185435Sbz		break;
460185435Sbz
461185435Sbz	default:
462185435Sbz		/* Sci-Fi jails are not supported, sorry. */
463185435Sbz		return (EINVAL);
464185435Sbz	}
465185435Sbz	return (kern_jail(td, &j));
466185435Sbz}
467185435Sbz
468185435Sbzint
469185435Sbzkern_jail(struct thread *td, struct jail *j)
470185435Sbz{
471113275Smike	struct nameidata nd;
472179881Sdelphij	struct prison *pr, *tpr;
473113275Smike	struct jail_attach_args jaa;
474179881Sdelphij	int vfslocked, error, tryprid;
47546155Sphk
476185435Sbz	KASSERT(j != NULL, ("%s: j is NULL", __func__));
477185435Sbz
478185435Sbz	/* Handle addresses - convert old structs, copyin, check IPs. */
479185435Sbz	error = jail_handle_ips(j);
48046155Sphk	if (error)
48184828Sjhb		return (error);
48284828Sjhb
483185435Sbz	/* Allocate struct prison and fill it with life. */
484184205Sdes	pr = malloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
48593818Sjhb	mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF);
486113275Smike	pr->pr_ref = 1;
487185435Sbz	error = copyinstr(j->path, &pr->pr_path, sizeof(pr->pr_path), NULL);
488113275Smike	if (error)
489113275Smike		goto e_killmtx;
490150652Scsjp	NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE,
491150652Scsjp	    pr->pr_path, td);
492113275Smike	error = namei(&nd);
493150652Scsjp	if (error)
494113275Smike		goto e_killmtx;
495150652Scsjp	vfslocked = NDHASGIANT(&nd);
496113275Smike	pr->pr_root = nd.ni_vp;
497175294Sattilio	VOP_UNLOCK(nd.ni_vp, 0);
498113275Smike	NDFREE(&nd, NDF_ONLY_PNBUF);
499150652Scsjp	VFS_UNLOCK_GIANT(vfslocked);
500185435Sbz	error = copyinstr(j->hostname, &pr->pr_host, sizeof(pr->pr_host), NULL);
50184828Sjhb	if (error)
502113275Smike		goto e_dropvnref;
503185435Sbz	if (j->jailname != NULL) {
504185435Sbz		error = copyinstr(j->jailname, &pr->pr_name,
505185435Sbz		    sizeof(pr->pr_name), NULL);
506185435Sbz		if (error)
507185435Sbz			goto e_dropvnref;
508185435Sbz	}
509185435Sbz	if (j->ip4s > 0) {
510185435Sbz		pr->pr_ip4 = j->ip4;
511185435Sbz		pr->pr_ip4s = j->ip4s;
512185435Sbz	}
513185435Sbz#ifdef INET6
514185435Sbz	if (j->ip6s > 0) {
515185435Sbz		pr->pr_ip6 = j->ip6;
516185435Sbz		pr->pr_ip6s = j->ip6s;
517185435Sbz	}
518185435Sbz#endif
519113275Smike	pr->pr_linux = NULL;
520113275Smike	pr->pr_securelevel = securelevel;
521185029Spjd	bzero(&pr->pr_osd, sizeof(pr->pr_osd));
522113275Smike
523185435Sbz	/*
524185435Sbz	 * Pre-set prison state to ALIVE upon cration.  This is needed so we
525185435Sbz	 * can later attach the process to it, etc (avoiding another extra
526185435Sbz	 * state for ther process of creation, complicating things).
527185435Sbz	 */
528185435Sbz	pr->pr_state = PRISON_STATE_ALIVE;
529185435Sbz
530185435Sbz	/* Allocate a dedicated cpuset for each jail. */
531185435Sbz	error = cpuset_create_root(td, &pr->pr_cpuset);
532185435Sbz	if (error)
533185435Sbz		goto e_dropvnref;
534185435Sbz
535185435Sbz	sx_xlock(&allprison_lock);
536185435Sbz	/* Make sure we cannot run into problems with ambiguous bind()ings. */
537185441Sbz#if defined(INET) || defined(INET6)
538185435Sbz	error = prison_check_conflicting_ips(pr);
539185435Sbz	if (error) {
540185435Sbz		sx_xunlock(&allprison_lock);
541185435Sbz		goto e_dropcpuset;
542185435Sbz	}
543185441Sbz#endif
544185435Sbz
545179881Sdelphij	/* Determine next pr_id and add prison to allprison list. */
546179881Sdelphij	tryprid = lastprid + 1;
547179881Sdelphij	if (tryprid == JAIL_MAX)
548179881Sdelphij		tryprid = 1;
549179881Sdelphijnext:
550179881Sdelphij	LIST_FOREACH(tpr, &allprison, pr_list) {
551179881Sdelphij		if (tpr->pr_id == tryprid) {
552179881Sdelphij			tryprid++;
553179881Sdelphij			if (tryprid == JAIL_MAX) {
554179881Sdelphij				sx_xunlock(&allprison_lock);
555179881Sdelphij				error = EAGAIN;
556185435Sbz				goto e_dropcpuset;
557179881Sdelphij			}
558179881Sdelphij			goto next;
559179881Sdelphij		}
560179881Sdelphij	}
561179881Sdelphij	pr->pr_id = jaa.jid = lastprid = tryprid;
562113275Smike	LIST_INSERT_HEAD(&allprison, pr, pr_list);
563113275Smike	prisoncount++;
564185029Spjd	sx_xunlock(&allprison_lock);
565113275Smike
566113275Smike	error = jail_attach(td, &jaa);
567113275Smike	if (error)
568113275Smike		goto e_dropprref;
569113275Smike	mtx_lock(&pr->pr_mtx);
570113275Smike	pr->pr_ref--;
571113275Smike	mtx_unlock(&pr->pr_mtx);
572113275Smike	td->td_retval[0] = jaa.jid;
573113275Smike	return (0);
574113275Smikee_dropprref:
575168401Spjd	sx_xlock(&allprison_lock);
576113275Smike	LIST_REMOVE(pr, pr_list);
577113275Smike	prisoncount--;
578185029Spjd	sx_xunlock(&allprison_lock);
579185435Sbze_dropcpuset:
580185435Sbz	cpuset_rel(pr->pr_cpuset);
581113275Smikee_dropvnref:
582150652Scsjp	vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
583113275Smike	vrele(pr->pr_root);
584150652Scsjp	VFS_UNLOCK_GIANT(vfslocked);
585113275Smikee_killmtx:
586113275Smike	mtx_destroy(&pr->pr_mtx);
587184205Sdes	free(pr, M_PRISON);
588185435Sbz#ifdef INET6
589185435Sbz	free(j->ip6, M_PRISON);
590185435Sbz#endif
591185435Sbz#ifdef INET
592185435Sbz	free(j->ip4, M_PRISON);
593185435Sbz#endif
594113275Smike	return (error);
595113275Smike}
596113275Smike
597113275Smike/*
598114168Smike * struct jail_attach_args {
599114168Smike *	int jid;
600114168Smike * };
601113275Smike */
602113275Smikeint
603114168Smikejail_attach(struct thread *td, struct jail_attach_args *uap)
604113275Smike{
605113275Smike	struct proc *p;
606113275Smike	struct ucred *newcred, *oldcred;
607113275Smike	struct prison *pr;
608150652Scsjp	int vfslocked, error;
609167309Spjd
610126023Snectar	/*
611126023Snectar	 * XXX: Note that there is a slight race here if two threads
612126023Snectar	 * in the same privileged process attempt to attach to two
613126023Snectar	 * different jails at the same time.  It is important for
614126023Snectar	 * user processes not to do this, or they might end up with
615126023Snectar	 * a process root from one prison, but attached to the jail
616126023Snectar	 * of another.
617126023Snectar	 */
618164032Srwatson	error = priv_check(td, PRIV_JAIL_ATTACH);
619126023Snectar	if (error)
620126023Snectar		return (error);
621126023Snectar
622113275Smike	p = td->td_proc;
623168401Spjd	sx_slock(&allprison_lock);
624113275Smike	pr = prison_find(uap->jid);
625113275Smike	if (pr == NULL) {
626168401Spjd		sx_sunlock(&allprison_lock);
627113275Smike		return (EINVAL);
628113275Smike	}
629185435Sbz
630185435Sbz	/*
631185435Sbz	 * Do not allow a process to attach to a prison that is not
632185435Sbz	 * considered to be "ALIVE".
633185435Sbz	 */
634185435Sbz	if (pr->pr_state != PRISON_STATE_ALIVE) {
635185435Sbz		mtx_unlock(&pr->pr_mtx);
636185435Sbz		sx_sunlock(&allprison_lock);
637185435Sbz		return (EINVAL);
638185435Sbz	}
639113275Smike	pr->pr_ref++;
640113275Smike	mtx_unlock(&pr->pr_mtx);
641168401Spjd	sx_sunlock(&allprison_lock);
642113275Smike
643185435Sbz	/*
644185435Sbz	 * Reparent the newly attached process to this jail.
645185435Sbz	 */
646185435Sbz	error = cpuset_setproc_update_set(p, pr->pr_cpuset);
647185435Sbz	if (error)
648185435Sbz		goto e_unref;
649185435Sbz
650150652Scsjp	vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
651175202Sattilio	vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY);
652113275Smike	if ((error = change_dir(pr->pr_root, td)) != 0)
653113275Smike		goto e_unlock;
654113275Smike#ifdef MAC
655172930Srwatson	if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root)))
656113275Smike		goto e_unlock;
657113275Smike#endif
658175294Sattilio	VOP_UNLOCK(pr->pr_root, 0);
659113275Smike	change_root(pr->pr_root, td);
660150652Scsjp	VFS_UNLOCK_GIANT(vfslocked);
661113275Smike
66284828Sjhb	newcred = crget();
66384828Sjhb	PROC_LOCK(p);
66484828Sjhb	oldcred = p->p_ucred;
665113275Smike	setsugid(p);
66684828Sjhb	crcopy(newcred, oldcred);
667113630Sjhb	newcred->cr_prison = pr;
66884828Sjhb	p->p_ucred = newcred;
669185435Sbz	prison_proc_hold(pr);
67084828Sjhb	PROC_UNLOCK(p);
67184828Sjhb	crfree(oldcred);
67246155Sphk	return (0);
673113275Smikee_unlock:
674175294Sattilio	VOP_UNLOCK(pr->pr_root, 0);
675150652Scsjp	VFS_UNLOCK_GIANT(vfslocked);
676185435Sbze_unref:
677113275Smike	mtx_lock(&pr->pr_mtx);
678113275Smike	pr->pr_ref--;
679113275Smike	mtx_unlock(&pr->pr_mtx);
68046155Sphk	return (error);
68146155Sphk}
68246155Sphk
683113275Smike/*
684113275Smike * Returns a locked prison instance, or NULL on failure.
685113275Smike */
686168399Spjdstruct prison *
687113275Smikeprison_find(int prid)
688113275Smike{
689113275Smike	struct prison *pr;
690113275Smike
691168401Spjd	sx_assert(&allprison_lock, SX_LOCKED);
692113275Smike	LIST_FOREACH(pr, &allprison, pr_list) {
693113275Smike		if (pr->pr_id == prid) {
694113275Smike			mtx_lock(&pr->pr_mtx);
695168489Spjd			if (pr->pr_ref == 0) {
696168489Spjd				mtx_unlock(&pr->pr_mtx);
697168489Spjd				break;
698168489Spjd			}
699113275Smike			return (pr);
700113275Smike		}
701113275Smike	}
702113275Smike	return (NULL);
703113275Smike}
704113275Smike
70572786Srwatsonvoid
706185029Spjdprison_free_locked(struct prison *pr)
70772786Srwatson{
70872786Srwatson
709185029Spjd	mtx_assert(&pr->pr_mtx, MA_OWNED);
71072786Srwatson	pr->pr_ref--;
71172786Srwatson	if (pr->pr_ref == 0) {
712168483Spjd		mtx_unlock(&pr->pr_mtx);
713124882Srwatson		TASK_INIT(&pr->pr_task, 0, prison_complete, pr);
714144660Sjeff		taskqueue_enqueue(taskqueue_thread, &pr->pr_task);
71587275Srwatson		return;
71672786Srwatson	}
71787275Srwatson	mtx_unlock(&pr->pr_mtx);
71872786Srwatson}
71972786Srwatson
720185029Spjdvoid
721185029Spjdprison_free(struct prison *pr)
722185029Spjd{
723185029Spjd
724185029Spjd	mtx_lock(&pr->pr_mtx);
725185029Spjd	prison_free_locked(pr);
726185029Spjd}
727185029Spjd
728124882Srwatsonstatic void
729124882Srwatsonprison_complete(void *context, int pending)
730124882Srwatson{
731124882Srwatson	struct prison *pr;
732150652Scsjp	int vfslocked;
733124882Srwatson
734124882Srwatson	pr = (struct prison *)context;
735124882Srwatson
736168489Spjd	sx_xlock(&allprison_lock);
737168489Spjd	LIST_REMOVE(pr, pr_list);
738168489Spjd	prisoncount--;
739185029Spjd	sx_xunlock(&allprison_lock);
740168489Spjd
741185435Sbz	cpuset_rel(pr->pr_cpuset);
742185435Sbz
743185029Spjd	/* Free all OSD associated to this jail. */
744185029Spjd	osd_jail_exit(pr);
745185029Spjd
746150652Scsjp	vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
747124882Srwatson	vrele(pr->pr_root);
748150652Scsjp	VFS_UNLOCK_GIANT(vfslocked);
749124882Srwatson
750124882Srwatson	mtx_destroy(&pr->pr_mtx);
751185435Sbz	free(pr->pr_linux, M_PRISON);
752185435Sbz#ifdef INET6
753185435Sbz	free(pr->pr_ip6, M_PRISON);
754185435Sbz#endif
755185435Sbz#ifdef INET
756185435Sbz	free(pr->pr_ip4, M_PRISON);
757185435Sbz#endif
758184205Sdes	free(pr, M_PRISON);
759124882Srwatson}
760124882Srwatson
76172786Srwatsonvoid
762185029Spjdprison_hold_locked(struct prison *pr)
76372786Srwatson{
76472786Srwatson
765185029Spjd	mtx_assert(&pr->pr_mtx, MA_OWNED);
766168489Spjd	KASSERT(pr->pr_ref > 0,
767168489Spjd	    ("Trying to hold dead prison (id=%d).", pr->pr_id));
76872786Srwatson	pr->pr_ref++;
769185029Spjd}
770185029Spjd
771185029Spjdvoid
772185029Spjdprison_hold(struct prison *pr)
773185029Spjd{
774185029Spjd
775185029Spjd	mtx_lock(&pr->pr_mtx);
776185029Spjd	prison_hold_locked(pr);
77787275Srwatson	mtx_unlock(&pr->pr_mtx);
77872786Srwatson}
77972786Srwatson
780185435Sbzvoid
781185435Sbzprison_proc_hold(struct prison *pr)
78287275Srwatson{
78387275Srwatson
784185435Sbz	mtx_lock(&pr->pr_mtx);
785185435Sbz	KASSERT(pr->pr_state == PRISON_STATE_ALIVE,
786185435Sbz	    ("Cannot add a process to a non-alive prison (id=%d).", pr->pr_id));
787185435Sbz	pr->pr_nprocs++;
788185435Sbz	mtx_unlock(&pr->pr_mtx);
78987275Srwatson}
79087275Srwatson
791185435Sbzvoid
792185435Sbzprison_proc_free(struct prison *pr)
793185435Sbz{
794185435Sbz
795185435Sbz	mtx_lock(&pr->pr_mtx);
796185435Sbz	KASSERT(pr->pr_state == PRISON_STATE_ALIVE && pr->pr_nprocs > 0,
797185435Sbz	    ("Trying to kill a process in a dead prison (id=%d).", pr->pr_id));
798185435Sbz	pr->pr_nprocs--;
799185435Sbz	if (pr->pr_nprocs == 0)
800185435Sbz		pr->pr_state = PRISON_STATE_DYING;
801185435Sbz	mtx_unlock(&pr->pr_mtx);
802185435Sbz}
803185435Sbz
804185435Sbz
805185435Sbz#ifdef INET
806185435Sbz/*
807185435Sbz * Pass back primary IPv4 address of this jail.
808185435Sbz *
809185435Sbz * If not jailed return success but do not alter the address.  Caller has to
810185435Sbz * make sure to intialize it correctly (INADDR_ANY).
811185435Sbz *
812185435Sbz * Returns 0 on success, 1 on error.  Address returned in NBO.
813185435Sbz */
81446155Sphkint
815187684Sbzprison_get_ip4(struct ucred *cred, struct in_addr *ia)
81646155Sphk{
81746155Sphk
818185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
819185435Sbz	KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
820185435Sbz
82172786Srwatson	if (!jailed(cred))
822185435Sbz		/* Do not change address passed in. */
82346155Sphk		return (0);
824185435Sbz
825185435Sbz	if (cred->cr_prison->pr_ip4 == NULL)
826185435Sbz		return (1);
827185435Sbz
828185435Sbz	ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
829185435Sbz	return (0);
830185435Sbz}
831185435Sbz
832185435Sbz/*
833185435Sbz * Make sure our (source) address is set to something meaningful to this
834185435Sbz * jail.
835185435Sbz *
836185435Sbz * Returns 0 on success, 1 on error.  Address passed in in NBO and returned
837185435Sbz * in NBO.
838185435Sbz */
839185435Sbzint
840185435Sbzprison_local_ip4(struct ucred *cred, struct in_addr *ia)
841185435Sbz{
842185435Sbz	struct in_addr ia0;
843185435Sbz
844185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
845185435Sbz	KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
846185435Sbz
847185435Sbz	if (!jailed(cred))
84846155Sphk		return (0);
849185435Sbz	if (cred->cr_prison->pr_ip4 == NULL)
850185435Sbz		return (1);
851185435Sbz
852185435Sbz	ia0.s_addr = ntohl(ia->s_addr);
853185435Sbz	if (ia0.s_addr == INADDR_LOOPBACK) {
854185435Sbz		ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
855185435Sbz		return (0);
85646155Sphk	}
857185435Sbz
858185435Sbz	/*
859185435Sbz	 * In case there is only 1 IPv4 address, bind directly.
860185435Sbz	 */
861185435Sbz	if (ia0.s_addr == INADDR_ANY && cred->cr_prison->pr_ip4s == 1) {
862185435Sbz		ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
863185435Sbz		return (0);
864185435Sbz	}
865185435Sbz
866185435Sbz	if (ia0.s_addr == INADDR_ANY || prison_check_ip4(cred, ia))
867185435Sbz		return (0);
868185435Sbz
869185435Sbz	return (1);
870185435Sbz}
871185435Sbz
872185435Sbz/*
873185435Sbz * Rewrite destination address in case we will connect to loopback address.
874185435Sbz *
875185435Sbz * Returns 0 on success, 1 on error.  Address passed in in NBO and returned
876185435Sbz * in NBO.
877185435Sbz */
878185435Sbzint
879185435Sbzprison_remote_ip4(struct ucred *cred, struct in_addr *ia)
880185435Sbz{
881185435Sbz
882185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
883185435Sbz	KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
884185435Sbz
885185435Sbz	if (!jailed(cred))
886185435Sbz		return (0);
887185435Sbz	if (cred->cr_prison->pr_ip4 == NULL)
888185435Sbz		return (1);
889185435Sbz	if (ntohl(ia->s_addr) == INADDR_LOOPBACK) {
890185435Sbz		ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
891185435Sbz		return (0);
892185435Sbz	}
893185435Sbz
894185435Sbz	/*
895185435Sbz	 * Return success because nothing had to be changed.
896185435Sbz	 */
897185435Sbz	return (0);
898185435Sbz}
899185435Sbz
900185435Sbz/*
901185435Sbz * Check if given address belongs to the jail referenced by cred.
902185435Sbz *
903185435Sbz * Returns 1 if address belongs to jail, 0 if not.  Address passed in in NBO.
904185435Sbz */
905185435Sbzstatic int
906185435Sbz_prison_check_ip4(struct prison *pr, struct in_addr *ia)
907185435Sbz{
908185435Sbz	int i, a, z, d;
909185435Sbz
910185435Sbz	if (pr->pr_ip4 == NULL)
911185435Sbz		return (0);
912185435Sbz
913185435Sbz	/*
914185435Sbz	 * Check the primary IP.
915185435Sbz	 */
916185435Sbz	if (pr->pr_ip4[0].s_addr == ia->s_addr)
917185435Sbz		return (1);
918185435Sbz
919185435Sbz	/*
920185435Sbz	 * All the other IPs are sorted so we can do a binary search.
921185435Sbz	 */
922185435Sbz	a = 0;
923185435Sbz	z = pr->pr_ip4s - 2;
924185435Sbz	while (a <= z) {
925185435Sbz		i = (a + z) / 2;
926185435Sbz		d = qcmp_v4(&pr->pr_ip4[i+1], ia);
927185435Sbz		if (d > 0)
928185435Sbz			z = i - 1;
929185435Sbz		else if (d < 0)
930185435Sbz			a = i + 1;
93181114Srwatson		else
932185435Sbz			return (1);
933185435Sbz	}
934185435Sbz	return (0);
935185435Sbz}
936185435Sbz
937185435Sbzint
938185435Sbzprison_check_ip4(struct ucred *cred, struct in_addr *ia)
939185435Sbz{
940185435Sbz
941185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
942185435Sbz	KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
943185435Sbz
944185435Sbz	if (!jailed(cred))
945185435Sbz		return (1);
946185435Sbz
947185435Sbz	return (_prison_check_ip4(cred->cr_prison, ia));
948185435Sbz}
949185435Sbz#endif
950185435Sbz
951185435Sbz#ifdef INET6
952185435Sbz/*
953185435Sbz * Pass back primary IPv6 address for this jail.
954185435Sbz *
955185435Sbz * If not jailed return success but do not alter the address.  Caller has to
956185435Sbz * make sure to intialize it correctly (IN6ADDR_ANY_INIT).
957185435Sbz *
958185435Sbz * Returns 0 on success, 1 on error.
959185435Sbz */
960185435Sbzint
961187684Sbzprison_get_ip6(struct ucred *cred, struct in6_addr *ia6)
962185435Sbz{
963185435Sbz
964185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
965185435Sbz	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
966185435Sbz
967185435Sbz	if (!jailed(cred))
96881114Srwatson		return (0);
969185435Sbz	if (cred->cr_prison->pr_ip6 == NULL)
970185435Sbz		return (1);
971185435Sbz	bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr));
972185435Sbz	return (0);
973185435Sbz}
974185435Sbz
975185435Sbz/*
976185435Sbz * Make sure our (source) address is set to something meaningful to this jail.
977185435Sbz *
978185435Sbz * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0)
979185435Sbz * when needed while binding.
980185435Sbz *
981185435Sbz * Returns 0 on success, 1 on error.
982185435Sbz */
983185435Sbzint
984185435Sbzprison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only)
985185435Sbz{
986185435Sbz
987185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
988185435Sbz	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
989185435Sbz
990185435Sbz	if (!jailed(cred))
991185435Sbz		return (0);
992185435Sbz	if (cred->cr_prison->pr_ip6 == NULL)
993185435Sbz		return (1);
994185435Sbz	if (IN6_IS_ADDR_LOOPBACK(ia6)) {
995185435Sbz		bcopy(&cred->cr_prison->pr_ip6[0], ia6,
996185435Sbz		    sizeof(struct in6_addr));
997185435Sbz		return (0);
99881114Srwatson	}
999185435Sbz
1000185435Sbz	/*
1001185435Sbz	 * In case there is only 1 IPv6 address, and v6only is true, then
1002185435Sbz	 * bind directly.
1003185435Sbz	 */
1004185435Sbz	if (v6only != 0 && IN6_IS_ADDR_UNSPECIFIED(ia6) &&
1005185435Sbz	    cred->cr_prison->pr_ip6s == 1) {
1006185435Sbz		bcopy(&cred->cr_prison->pr_ip6[0], ia6,
1007185435Sbz		    sizeof(struct in6_addr));
1008185435Sbz		return (0);
1009185435Sbz	}
1010185435Sbz	if (IN6_IS_ADDR_UNSPECIFIED(ia6) || prison_check_ip6(cred, ia6))
1011185435Sbz		return (0);
1012185435Sbz	return (1);
1013185435Sbz}
1014185435Sbz
1015185435Sbz/*
1016185435Sbz * Rewrite destination address in case we will connect to loopback address.
1017185435Sbz *
1018185435Sbz * Returns 0 on success, 1 on error.
1019185435Sbz */
1020185435Sbzint
1021185435Sbzprison_remote_ip6(struct ucred *cred, struct in6_addr *ia6)
1022185435Sbz{
1023185435Sbz
1024185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
1025185435Sbz	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
1026185435Sbz
1027185435Sbz	if (!jailed(cred))
1028185435Sbz		return (0);
1029185435Sbz	if (cred->cr_prison->pr_ip6 == NULL)
103046155Sphk		return (1);
1031185435Sbz	if (IN6_IS_ADDR_LOOPBACK(ia6)) {
1032185435Sbz		bcopy(&cred->cr_prison->pr_ip6[0], ia6,
1033185435Sbz		    sizeof(struct in6_addr));
1034185435Sbz		return (0);
1035185435Sbz	}
1036185435Sbz
1037185435Sbz	/*
1038185435Sbz	 * Return success because nothing had to be changed.
1039185435Sbz	 */
104046155Sphk	return (0);
104146155Sphk}
104246155Sphk
1043185435Sbz/*
1044185435Sbz * Check if given address belongs to the jail referenced by cred.
1045185435Sbz *
1046185435Sbz * Returns 1 if address belongs to jail, 0 if not.
1047185435Sbz */
1048185435Sbzstatic int
1049185435Sbz_prison_check_ip6(struct prison *pr, struct in6_addr *ia6)
105046155Sphk{
1051185435Sbz	int i, a, z, d;
105246155Sphk
1053185435Sbz	if (pr->pr_ip6 == NULL)
1054185435Sbz		return (0);
1055185435Sbz
1056185435Sbz	/*
1057185435Sbz	 * Check the primary IP.
1058185435Sbz	 */
1059185435Sbz	if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6))
1060185435Sbz		return (1);
1061185435Sbz
1062185435Sbz	/*
1063185435Sbz	 * All the other IPs are sorted so we can do a binary search.
1064185435Sbz	 */
1065185435Sbz	a = 0;
1066185435Sbz	z = pr->pr_ip6s - 2;
1067185435Sbz	while (a <= z) {
1068185435Sbz		i = (a + z) / 2;
1069185435Sbz		d = qcmp_v6(&pr->pr_ip6[i+1], ia6);
1070185435Sbz		if (d > 0)
1071185435Sbz			z = i - 1;
1072185435Sbz		else if (d < 0)
1073185435Sbz			a = i + 1;
107446155Sphk		else
1075185435Sbz			return (1);
107646155Sphk	}
1077185435Sbz	return (0);
107846155Sphk}
107946155Sphk
108046155Sphkint
1081185435Sbzprison_check_ip6(struct ucred *cred, struct in6_addr *ia6)
1082185435Sbz{
1083185435Sbz
1084185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
1085185435Sbz	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
1086185435Sbz
1087185435Sbz	if (!jailed(cred))
1088185435Sbz		return (1);
1089185435Sbz
1090185435Sbz	return (_prison_check_ip6(cred->cr_prison, ia6));
1091185435Sbz}
1092185435Sbz#endif
1093185435Sbz
1094185435Sbz/*
1095185435Sbz * Check if given address belongs to the jail referenced by cred (wrapper to
1096185435Sbz * prison_check_ip[46]).
1097185435Sbz *
1098185435Sbz * Returns 1 if address belongs to jail, 0 if not.  IPv4 Address passed in in
1099185435Sbz * NBO.
1100185435Sbz */
1101185435Sbzint
110272786Srwatsonprison_if(struct ucred *cred, struct sockaddr *sa)
110346155Sphk{
1104185435Sbz#ifdef INET
1105114168Smike	struct sockaddr_in *sai;
1106185435Sbz#endif
1107185435Sbz#ifdef INET6
1108185435Sbz	struct sockaddr_in6 *sai6;
1109185435Sbz#endif
111046155Sphk	int ok;
111146155Sphk
1112185435Sbz	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
1113185435Sbz	KASSERT(sa != NULL, ("%s: sa is NULL", __func__));
1114185435Sbz
1115185435Sbz	ok = 0;
1116185435Sbz	switch(sa->sa_family)
1117185435Sbz	{
1118185435Sbz#ifdef INET
1119185435Sbz	case AF_INET:
1120185435Sbz		sai = (struct sockaddr_in *)sa;
1121185435Sbz		if (prison_check_ip4(cred, &sai->sin_addr))
1122185435Sbz			ok = 1;
1123185435Sbz		break;
1124185435Sbz
1125185435Sbz#endif
1126185435Sbz#ifdef INET6
1127185435Sbz	case AF_INET6:
1128185435Sbz		sai6 = (struct sockaddr_in6 *)sa;
1129185435Sbz		if (prison_check_ip6(cred, (struct in6_addr *)&sai6->sin6_addr))
1130185435Sbz			ok = 1;
1131185435Sbz		break;
1132185435Sbz
1133185435Sbz#endif
1134185435Sbz	default:
1135185435Sbz		if (!jail_socket_unixiproute_only)
1136185435Sbz			ok = 1;
1137185435Sbz	}
113846155Sphk	return (ok);
113946155Sphk}
114072786Srwatson
114172786Srwatson/*
114272786Srwatson * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
114372786Srwatson */
114472786Srwatsonint
1145114168Smikeprison_check(struct ucred *cred1, struct ucred *cred2)
114672786Srwatson{
114772786Srwatson
114872786Srwatson	if (jailed(cred1)) {
114972786Srwatson		if (!jailed(cred2))
115072786Srwatson			return (ESRCH);
115172786Srwatson		if (cred2->cr_prison != cred1->cr_prison)
115272786Srwatson			return (ESRCH);
115372786Srwatson	}
115472786Srwatson
115572786Srwatson	return (0);
115672786Srwatson}
115772786Srwatson
115872786Srwatson/*
115972786Srwatson * Return 1 if the passed credential is in a jail, otherwise 0.
116072786Srwatson */
116172786Srwatsonint
1162114168Smikejailed(struct ucred *cred)
116372786Srwatson{
116472786Srwatson
116572786Srwatson	return (cred->cr_prison != NULL);
116672786Srwatson}
116791384Srobert
116891384Srobert/*
116991384Srobert * Return the correct hostname for the passed credential.
117091384Srobert */
117191391Srobertvoid
1172114168Smikegetcredhostname(struct ucred *cred, char *buf, size_t size)
117391384Srobert{
1174183550Szec	INIT_VPROCG(cred->cr_vimage->v_procg);
117591384Srobert
117691391Srobert	if (jailed(cred)) {
117791391Srobert		mtx_lock(&cred->cr_prison->pr_mtx);
1178105354Srobert		strlcpy(buf, cred->cr_prison->pr_host, size);
117991391Srobert		mtx_unlock(&cred->cr_prison->pr_mtx);
1180180291Srwatson	} else {
1181180291Srwatson		mtx_lock(&hostname_mtx);
1182181803Sbz		strlcpy(buf, V_hostname, size);
1183180291Srwatson		mtx_unlock(&hostname_mtx);
1184180291Srwatson	}
118591384Srobert}
1186113275Smike
1187125804Srwatson/*
1188147185Spjd * Determine whether the subject represented by cred can "see"
1189147185Spjd * status of a mount point.
1190147185Spjd * Returns: 0 for permitted, ENOENT otherwise.
1191147185Spjd * XXX: This function should be called cr_canseemount() and should be
1192147185Spjd *      placed in kern_prot.c.
1193125804Srwatson */
1194125804Srwatsonint
1195147185Spjdprison_canseemount(struct ucred *cred, struct mount *mp)
1196125804Srwatson{
1197147185Spjd	struct prison *pr;
1198147185Spjd	struct statfs *sp;
1199147185Spjd	size_t len;
1200125804Srwatson
1201147185Spjd	if (!jailed(cred) || jail_enforce_statfs == 0)
1202147185Spjd		return (0);
1203147185Spjd	pr = cred->cr_prison;
1204147185Spjd	if (pr->pr_root->v_mount == mp)
1205147185Spjd		return (0);
1206147185Spjd	if (jail_enforce_statfs == 2)
1207147185Spjd		return (ENOENT);
1208147185Spjd	/*
1209147185Spjd	 * If jail's chroot directory is set to "/" we should be able to see
1210147185Spjd	 * all mount-points from inside a jail.
1211147185Spjd	 * This is ugly check, but this is the only situation when jail's
1212147185Spjd	 * directory ends with '/'.
1213147185Spjd	 */
1214147185Spjd	if (strcmp(pr->pr_path, "/") == 0)
1215147185Spjd		return (0);
1216147185Spjd	len = strlen(pr->pr_path);
1217147185Spjd	sp = &mp->mnt_stat;
1218147185Spjd	if (strncmp(pr->pr_path, sp->f_mntonname, len) != 0)
1219147185Spjd		return (ENOENT);
1220147185Spjd	/*
1221147185Spjd	 * Be sure that we don't have situation where jail's root directory
1222147185Spjd	 * is "/some/path" and mount point is "/some/pathpath".
1223147185Spjd	 */
1224147185Spjd	if (sp->f_mntonname[len] != '\0' && sp->f_mntonname[len] != '/')
1225147185Spjd		return (ENOENT);
1226147185Spjd	return (0);
1227147185Spjd}
1228147185Spjd
1229147185Spjdvoid
1230147185Spjdprison_enforce_statfs(struct ucred *cred, struct mount *mp, struct statfs *sp)
1231147185Spjd{
1232147185Spjd	char jpath[MAXPATHLEN];
1233147185Spjd	struct prison *pr;
1234147185Spjd	size_t len;
1235147185Spjd
1236147185Spjd	if (!jailed(cred) || jail_enforce_statfs == 0)
1237147185Spjd		return;
1238147185Spjd	pr = cred->cr_prison;
1239147185Spjd	if (prison_canseemount(cred, mp) != 0) {
1240147185Spjd		bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1241147185Spjd		strlcpy(sp->f_mntonname, "[restricted]",
1242147185Spjd		    sizeof(sp->f_mntonname));
1243147185Spjd		return;
1244125804Srwatson	}
1245147185Spjd	if (pr->pr_root->v_mount == mp) {
1246147185Spjd		/*
1247147185Spjd		 * Clear current buffer data, so we are sure nothing from
1248147185Spjd		 * the valid path left there.
1249147185Spjd		 */
1250147185Spjd		bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1251147185Spjd		*sp->f_mntonname = '/';
1252147185Spjd		return;
1253147185Spjd	}
1254147185Spjd	/*
1255147185Spjd	 * If jail's chroot directory is set to "/" we should be able to see
1256147185Spjd	 * all mount-points from inside a jail.
1257147185Spjd	 */
1258147185Spjd	if (strcmp(pr->pr_path, "/") == 0)
1259147185Spjd		return;
1260147185Spjd	len = strlen(pr->pr_path);
1261147185Spjd	strlcpy(jpath, sp->f_mntonname + len, sizeof(jpath));
1262147185Spjd	/*
1263147185Spjd	 * Clear current buffer data, so we are sure nothing from
1264147185Spjd	 * the valid path left there.
1265147185Spjd	 */
1266147185Spjd	bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1267147185Spjd	if (*jpath == '\0') {
1268147185Spjd		/* Should never happen. */
1269147185Spjd		*sp->f_mntonname = '/';
1270147185Spjd	} else {
1271147185Spjd		strlcpy(sp->f_mntonname, jpath, sizeof(sp->f_mntonname));
1272147185Spjd	}
1273125804Srwatson}
1274125804Srwatson
1275164032Srwatson/*
1276164032Srwatson * Check with permission for a specific privilege is granted within jail.  We
1277164032Srwatson * have a specific list of accepted privileges; the rest are denied.
1278164032Srwatson */
1279164032Srwatsonint
1280164032Srwatsonprison_priv_check(struct ucred *cred, int priv)
1281164032Srwatson{
1282164032Srwatson
1283164032Srwatson	if (!jailed(cred))
1284164032Srwatson		return (0);
1285164032Srwatson
1286164032Srwatson	switch (priv) {
1287164032Srwatson
1288164032Srwatson		/*
1289164032Srwatson		 * Allow ktrace privileges for root in jail.
1290164032Srwatson		 */
1291164032Srwatson	case PRIV_KTRACE:
1292164032Srwatson
1293166827Srwatson#if 0
1294164032Srwatson		/*
1295164032Srwatson		 * Allow jailed processes to configure audit identity and
1296164032Srwatson		 * submit audit records (login, etc).  In the future we may
1297164032Srwatson		 * want to further refine the relationship between audit and
1298164032Srwatson		 * jail.
1299164032Srwatson		 */
1300164032Srwatson	case PRIV_AUDIT_GETAUDIT:
1301164032Srwatson	case PRIV_AUDIT_SETAUDIT:
1302164032Srwatson	case PRIV_AUDIT_SUBMIT:
1303166827Srwatson#endif
1304164032Srwatson
1305164032Srwatson		/*
1306164032Srwatson		 * Allow jailed processes to manipulate process UNIX
1307164032Srwatson		 * credentials in any way they see fit.
1308164032Srwatson		 */
1309164032Srwatson	case PRIV_CRED_SETUID:
1310164032Srwatson	case PRIV_CRED_SETEUID:
1311164032Srwatson	case PRIV_CRED_SETGID:
1312164032Srwatson	case PRIV_CRED_SETEGID:
1313164032Srwatson	case PRIV_CRED_SETGROUPS:
1314164032Srwatson	case PRIV_CRED_SETREUID:
1315164032Srwatson	case PRIV_CRED_SETREGID:
1316164032Srwatson	case PRIV_CRED_SETRESUID:
1317164032Srwatson	case PRIV_CRED_SETRESGID:
1318164032Srwatson
1319164032Srwatson		/*
1320164032Srwatson		 * Jail implements visibility constraints already, so allow
1321164032Srwatson		 * jailed root to override uid/gid-based constraints.
1322164032Srwatson		 */
1323164032Srwatson	case PRIV_SEEOTHERGIDS:
1324164032Srwatson	case PRIV_SEEOTHERUIDS:
1325164032Srwatson
1326164032Srwatson		/*
1327164032Srwatson		 * Jail implements inter-process debugging limits already, so
1328164032Srwatson		 * allow jailed root various debugging privileges.
1329164032Srwatson		 */
1330164032Srwatson	case PRIV_DEBUG_DIFFCRED:
1331164032Srwatson	case PRIV_DEBUG_SUGID:
1332164032Srwatson	case PRIV_DEBUG_UNPRIV:
1333164032Srwatson
1334164032Srwatson		/*
1335164032Srwatson		 * Allow jail to set various resource limits and login
1336164032Srwatson		 * properties, and for now, exceed process resource limits.
1337164032Srwatson		 */
1338164032Srwatson	case PRIV_PROC_LIMIT:
1339164032Srwatson	case PRIV_PROC_SETLOGIN:
1340164032Srwatson	case PRIV_PROC_SETRLIMIT:
1341164032Srwatson
1342164032Srwatson		/*
1343164032Srwatson		 * System V and POSIX IPC privileges are granted in jail.
1344164032Srwatson		 */
1345164032Srwatson	case PRIV_IPC_READ:
1346164032Srwatson	case PRIV_IPC_WRITE:
1347164032Srwatson	case PRIV_IPC_ADMIN:
1348164032Srwatson	case PRIV_IPC_MSGSIZE:
1349164032Srwatson	case PRIV_MQ_ADMIN:
1350164032Srwatson
1351164032Srwatson		/*
1352164032Srwatson		 * Jail implements its own inter-process limits, so allow
1353164032Srwatson		 * root processes in jail to change scheduling on other
1354164032Srwatson		 * processes in the same jail.  Likewise for signalling.
1355164032Srwatson		 */
1356164032Srwatson	case PRIV_SCHED_DIFFCRED:
1357185435Sbz	case PRIV_SCHED_CPUSET:
1358164032Srwatson	case PRIV_SIGNAL_DIFFCRED:
1359164032Srwatson	case PRIV_SIGNAL_SUGID:
1360164032Srwatson
1361164032Srwatson		/*
1362164032Srwatson		 * Allow jailed processes to write to sysctls marked as jail
1363164032Srwatson		 * writable.
1364164032Srwatson		 */
1365164032Srwatson	case PRIV_SYSCTL_WRITEJAIL:
1366164032Srwatson
1367164032Srwatson		/*
1368164032Srwatson		 * Allow root in jail to manage a variety of quota
1369166831Srwatson		 * properties.  These should likely be conditional on a
1370166831Srwatson		 * configuration option.
1371164032Srwatson		 */
1372166832Srwatson	case PRIV_VFS_GETQUOTA:
1373166832Srwatson	case PRIV_VFS_SETQUOTA:
1374164032Srwatson
1375164032Srwatson		/*
1376164032Srwatson		 * Since Jail relies on chroot() to implement file system
1377164032Srwatson		 * protections, grant many VFS privileges to root in jail.
1378164032Srwatson		 * Be careful to exclude mount-related and NFS-related
1379164032Srwatson		 * privileges.
1380164032Srwatson		 */
1381164032Srwatson	case PRIV_VFS_READ:
1382164032Srwatson	case PRIV_VFS_WRITE:
1383164032Srwatson	case PRIV_VFS_ADMIN:
1384164032Srwatson	case PRIV_VFS_EXEC:
1385164032Srwatson	case PRIV_VFS_LOOKUP:
1386164032Srwatson	case PRIV_VFS_BLOCKRESERVE:	/* XXXRW: Slightly surprising. */
1387164032Srwatson	case PRIV_VFS_CHFLAGS_DEV:
1388164032Srwatson	case PRIV_VFS_CHOWN:
1389164032Srwatson	case PRIV_VFS_CHROOT:
1390167152Spjd	case PRIV_VFS_RETAINSUGID:
1391164032Srwatson	case PRIV_VFS_FCHROOT:
1392164032Srwatson	case PRIV_VFS_LINK:
1393164032Srwatson	case PRIV_VFS_SETGID:
1394172860Srwatson	case PRIV_VFS_STAT:
1395164032Srwatson	case PRIV_VFS_STICKYFILE:
1396164032Srwatson		return (0);
1397164032Srwatson
1398164032Srwatson		/*
1399164032Srwatson		 * Depending on the global setting, allow privilege of
1400164032Srwatson		 * setting system flags.
1401164032Srwatson		 */
1402164032Srwatson	case PRIV_VFS_SYSFLAGS:
1403164032Srwatson		if (jail_chflags_allowed)
1404164032Srwatson			return (0);
1405164032Srwatson		else
1406164032Srwatson			return (EPERM);
1407164032Srwatson
1408164032Srwatson		/*
1409168396Spjd		 * Depending on the global setting, allow privilege of
1410168396Spjd		 * mounting/unmounting file systems.
1411168396Spjd		 */
1412168396Spjd	case PRIV_VFS_MOUNT:
1413168396Spjd	case PRIV_VFS_UNMOUNT:
1414168396Spjd	case PRIV_VFS_MOUNT_NONUSER:
1415168699Spjd	case PRIV_VFS_MOUNT_OWNER:
1416168396Spjd		if (jail_mount_allowed)
1417168396Spjd			return (0);
1418168396Spjd		else
1419168396Spjd			return (EPERM);
1420168396Spjd
1421168396Spjd		/*
1422168591Srwatson		 * Allow jailed root to bind reserved ports and reuse in-use
1423168591Srwatson		 * ports.
1424164032Srwatson		 */
1425164032Srwatson	case PRIV_NETINET_RESERVEDPORT:
1426168591Srwatson	case PRIV_NETINET_REUSEPORT:
1427164032Srwatson		return (0);
1428164032Srwatson
1429164032Srwatson		/*
1430175630Sbz		 * Allow jailed root to set certian IPv4/6 (option) headers.
1431175630Sbz		 */
1432175630Sbz	case PRIV_NETINET_SETHDROPTS:
1433175630Sbz		return (0);
1434175630Sbz
1435175630Sbz		/*
1436164032Srwatson		 * Conditionally allow creating raw sockets in jail.
1437164032Srwatson		 */
1438164032Srwatson	case PRIV_NETINET_RAW:
1439164032Srwatson		if (jail_allow_raw_sockets)
1440164032Srwatson			return (0);
1441164032Srwatson		else
1442164032Srwatson			return (EPERM);
1443164032Srwatson
1444164032Srwatson		/*
1445164032Srwatson		 * Since jail implements its own visibility limits on netstat
1446164032Srwatson		 * sysctls, allow getcred.  This allows identd to work in
1447164032Srwatson		 * jail.
1448164032Srwatson		 */
1449164032Srwatson	case PRIV_NETINET_GETCRED:
1450164032Srwatson		return (0);
1451164032Srwatson
1452164032Srwatson	default:
1453164032Srwatson		/*
1454164032Srwatson		 * In all remaining cases, deny the privilege request.  This
1455164032Srwatson		 * includes almost all network privileges, many system
1456164032Srwatson		 * configuration privileges.
1457164032Srwatson		 */
1458164032Srwatson		return (EPERM);
1459164032Srwatson	}
1460164032Srwatson}
1461164032Srwatson
1462113275Smikestatic int
1463113275Smikesysctl_jail_list(SYSCTL_HANDLER_ARGS)
1464113275Smike{
1465113275Smike	struct xprison *xp, *sxp;
1466113275Smike	struct prison *pr;
1467185435Sbz	char *p;
1468185435Sbz	size_t len;
1469113275Smike	int count, error;
1470113275Smike
1471127020Spjd	if (jailed(req->td->td_ucred))
1472125806Srwatson		return (0);
1473113275Smike
1474168401Spjd	sx_slock(&allprison_lock);
1475168401Spjd	if ((count = prisoncount) == 0) {
1476168401Spjd		sx_sunlock(&allprison_lock);
1477113275Smike		return (0);
1478168401Spjd	}
1479113275Smike
1480185435Sbz	len = sizeof(*xp) * count;
1481185435Sbz	LIST_FOREACH(pr, &allprison, pr_list) {
1482185435Sbz#ifdef INET
1483185435Sbz		len += pr->pr_ip4s * sizeof(struct in_addr);
1484185435Sbz#endif
1485185435Sbz#ifdef INET6
1486185435Sbz		len += pr->pr_ip6s * sizeof(struct in6_addr);
1487185435Sbz#endif
1488185435Sbz	}
1489167309Spjd
1490185435Sbz	sxp = xp = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
1491185435Sbz
1492113275Smike	LIST_FOREACH(pr, &allprison, pr_list) {
1493113275Smike		xp->pr_version = XPRISON_VERSION;
1494113275Smike		xp->pr_id = pr->pr_id;
1495185435Sbz		xp->pr_state = pr->pr_state;
1496185435Sbz		xp->pr_cpusetid = pr->pr_cpuset->cs_id;
1497113275Smike		strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
1498168487Spjd		mtx_lock(&pr->pr_mtx);
1499113275Smike		strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));
1500185435Sbz		strlcpy(xp->pr_name, pr->pr_name, sizeof(xp->pr_name));
1501113275Smike		mtx_unlock(&pr->pr_mtx);
1502185435Sbz#ifdef INET
1503185435Sbz		xp->pr_ip4s = pr->pr_ip4s;
1504185435Sbz#endif
1505185435Sbz#ifdef INET6
1506185435Sbz		xp->pr_ip6s = pr->pr_ip6s;
1507185435Sbz#endif
1508185435Sbz		p = (char *)(xp + 1);
1509185435Sbz#ifdef INET
1510185435Sbz		if (pr->pr_ip4s > 0) {
1511185435Sbz			bcopy(pr->pr_ip4, (struct in_addr *)p,
1512185435Sbz			    pr->pr_ip4s * sizeof(struct in_addr));
1513185435Sbz			p += (pr->pr_ip4s * sizeof(struct in_addr));
1514185435Sbz		}
1515185435Sbz#endif
1516185435Sbz#ifdef INET6
1517185435Sbz		if (pr->pr_ip6s > 0) {
1518185435Sbz			bcopy(pr->pr_ip6, (struct in6_addr *)p,
1519185435Sbz			    pr->pr_ip6s * sizeof(struct in6_addr));
1520185435Sbz			p += (pr->pr_ip6s * sizeof(struct in6_addr));
1521185435Sbz		}
1522185435Sbz#endif
1523185435Sbz		xp = (struct xprison *)p;
1524113275Smike	}
1525168401Spjd	sx_sunlock(&allprison_lock);
1526113275Smike
1527185435Sbz	error = SYSCTL_OUT(req, sxp, len);
1528113275Smike	free(sxp, M_TEMP);
1529167354Spjd	return (error);
1530113275Smike}
1531113275Smike
1532113275SmikeSYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD,
1533113275Smike    NULL, 0, sysctl_jail_list, "S", "List of active jails");
1534126004Spjd
1535126004Spjdstatic int
1536126004Spjdsysctl_jail_jailed(SYSCTL_HANDLER_ARGS)
1537126004Spjd{
1538126004Spjd	int error, injail;
1539126004Spjd
1540126004Spjd	injail = jailed(req->td->td_ucred);
1541126004Spjd	error = SYSCTL_OUT(req, &injail, sizeof(injail));
1542126004Spjd
1543126004Spjd	return (error);
1544126004Spjd}
1545126004SpjdSYSCTL_PROC(_security_jail, OID_AUTO, jailed, CTLTYPE_INT | CTLFLAG_RD,
1546126004Spjd    NULL, 0, sysctl_jail_jailed, "I", "Process in jail?");
1547185435Sbz
1548185435Sbz#ifdef DDB
1549185435SbzDB_SHOW_COMMAND(jails, db_show_jails)
1550185435Sbz{
1551185435Sbz	struct prison *pr;
1552185435Sbz#ifdef INET
1553185435Sbz	struct in_addr ia;
1554185435Sbz#endif
1555185435Sbz#ifdef INET6
1556185435Sbz	char ip6buf[INET6_ADDRSTRLEN];
1557185435Sbz#endif
1558185435Sbz	const char *state;
1559185435Sbz#if defined(INET) || defined(INET6)
1560185435Sbz	int i;
1561185435Sbz#endif
1562185435Sbz
1563185435Sbz	db_printf(
1564185435Sbz	    "   JID  pr_ref  pr_nprocs  pr_ip4s  pr_ip6s\n");
1565185435Sbz	db_printf(
1566185435Sbz	    "        Hostname                      Path\n");
1567185435Sbz	db_printf(
1568185435Sbz	    "        Name                          State\n");
1569185435Sbz	db_printf(
1570185435Sbz	    "        Cpusetid\n");
1571185435Sbz	db_printf(
1572185435Sbz	    "        IP Address(es)\n");
1573185435Sbz	LIST_FOREACH(pr, &allprison, pr_list) {
1574185435Sbz		db_printf("%6d  %6d  %9d  %7d  %7d\n",
1575185435Sbz		    pr->pr_id, pr->pr_ref, pr->pr_nprocs,
1576185435Sbz		    pr->pr_ip4s, pr->pr_ip6s);
1577185435Sbz		db_printf("%6s  %-29.29s %.74s\n",
1578185435Sbz		    "", pr->pr_host, pr->pr_path);
1579185899Sbz		if (pr->pr_state < 0 || pr->pr_state >= (int)((sizeof(
1580185435Sbz		    prison_states) / sizeof(struct prison_state))))
1581185435Sbz			state = "(bogus)";
1582185435Sbz		else
1583185435Sbz			state = prison_states[pr->pr_state].state_name;
1584185435Sbz		db_printf("%6s  %-29.29s %.74s\n",
1585185899Sbz		    "", (pr->pr_name[0] != '\0') ? pr->pr_name : "", state);
1586185435Sbz		db_printf("%6s  %-6d\n",
1587185435Sbz		    "", pr->pr_cpuset->cs_id);
1588185435Sbz#ifdef INET
1589185435Sbz		for (i=0; i < pr->pr_ip4s; i++) {
1590185435Sbz			ia.s_addr = pr->pr_ip4[i].s_addr;
1591185435Sbz			db_printf("%6s  %s\n", "", inet_ntoa(ia));
1592185435Sbz		}
1593185435Sbz#endif
1594185435Sbz#ifdef INET6
1595185435Sbz		for (i=0; i < pr->pr_ip6s; i++)
1596185435Sbz			db_printf("%6s  %s\n",
1597185435Sbz			    "", ip6_sprintf(ip6buf, &pr->pr_ip6[i]));
1598185435Sbz#endif /* INET6 */
1599185435Sbz		if (db_pager_quit)
1600185435Sbz			break;
1601185435Sbz	}
1602185435Sbz}
1603185435Sbz#endif /* DDB */
1604