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