xref: /dragonfly/sys/kern/kern_jail.c (revision 926deccb)
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  */
10 /*-
11  * Copyright (c) 2006 Victor Balada Diaz <victor@bsdes.net>
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 
37 /*
38  * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $
39  * $DragonFly: src/sys/kern/kern_jail.c,v 1.19 2008/05/17 18:20:33 dillon Exp $
40  */
41 
42 #include "opt_inet6.h"
43 
44 #include <sys/param.h>
45 #include <sys/types.h>
46 #include <sys/kernel.h>
47 #include <sys/systm.h>
48 #include <sys/errno.h>
49 #include <sys/sysproto.h>
50 #include <sys/malloc.h>
51 #include <sys/nlookup.h>
52 #include <sys/namecache.h>
53 #include <sys/proc.h>
54 #include <sys/priv.h>
55 #include <sys/jail.h>
56 #include <sys/socket.h>
57 #include <sys/sysctl.h>
58 #include <sys/kern_syscall.h>
59 #include <net/if.h>
60 #include <netinet/in.h>
61 #include <netinet6/in6_var.h>
62 
63 #include <sys/mplock2.h>
64 
65 static struct prison	*prison_find(int);
66 static void		prison_ipcache_init(struct prison *);
67 
68 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
69 
70 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
71     "Jail rules");
72 
73 int	jail_set_hostname_allowed = 1;
74 SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
75     &jail_set_hostname_allowed, 0,
76     "Processes in jail can set their hostnames");
77 
78 int	jail_socket_unixiproute_only = 1;
79 SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
80     &jail_socket_unixiproute_only, 0,
81     "Processes in jail are limited to creating UNIX/IPv[46]/route sockets only");
82 
83 int	jail_sysvipc_allowed = 0;
84 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
85     &jail_sysvipc_allowed, 0,
86     "Processes in jail can use System V IPC primitives");
87 
88 int    jail_chflags_allowed = 0;
89 SYSCTL_INT(_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,
90     &jail_chflags_allowed, 0,
91     "Process in jail can set chflags(1)");
92 
93 int    jail_allow_raw_sockets = 0;
94 SYSCTL_INT(_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,
95     &jail_allow_raw_sockets, 0,
96     "Process in jail can create raw sockets");
97 
98 int	lastprid = 0;
99 int	prisoncount = 0;
100 
101 LIST_HEAD(prisonlist, prison);
102 struct	prisonlist allprison = LIST_HEAD_INITIALIZER(&allprison);
103 
104 static int
105 kern_jail_attach(int jid)
106 {
107 	struct proc *p = curthread->td_proc;
108 	struct prison *pr;
109 	int error;
110 
111 	pr = prison_find(jid);
112 	if (pr == NULL)
113 		return(EINVAL);
114 
115 	error = kern_chroot(&pr->pr_root);
116 	if (error)
117 		return(error);
118 
119 	prison_hold(pr);
120 	lwkt_gettoken(&p->p_token);
121 	cratom(&p->p_ucred);
122 	p->p_ucred->cr_prison = pr;
123 	p->p_flags |= P_JAILED;
124 	lwkt_reltoken(&p->p_token);
125 
126 	return(0);
127 }
128 
129 static int
130 assign_prison_id(struct prison *pr)
131 {
132 	int tryprid;
133 	struct prison *tpr;
134 
135 	tryprid = lastprid + 1;
136 	if (tryprid == JAIL_MAX)
137 		tryprid = 1;
138 next:
139 	LIST_FOREACH(tpr, &allprison, pr_list) {
140 		if (tpr->pr_id != tryprid)
141 			continue;
142 		tryprid++;
143 		if (tryprid == JAIL_MAX) {
144 			return (ERANGE);
145 		}
146 		goto next;
147 	}
148 	pr->pr_id = lastprid = tryprid;
149 
150 	return (0);
151 }
152 
153 static int
154 kern_jail(struct prison *pr, struct jail *j)
155 {
156 	int error;
157 	struct nlookupdata nd;
158 
159 	error = nlookup_init(&nd, j->path, UIO_USERSPACE, NLC_FOLLOW);
160 	if (error) {
161 		nlookup_done(&nd);
162 		return (error);
163 	}
164 	error = nlookup(&nd);
165 	if (error) {
166 		nlookup_done(&nd);
167 		return (error);
168 	}
169 	cache_copy(&nd.nl_nch, &pr->pr_root);
170 
171 	varsymset_init(&pr->pr_varsymset, NULL);
172 	prison_ipcache_init(pr);
173 
174 	error = assign_prison_id(pr);
175 	if (error) {
176 		varsymset_clean(&pr->pr_varsymset);
177 		nlookup_done(&nd);
178 		return (error);
179 	}
180 
181 	LIST_INSERT_HEAD(&allprison, pr, pr_list);
182 	++prisoncount;
183 
184 	error = kern_jail_attach(pr->pr_id);
185 	if (error) {
186 		LIST_REMOVE(pr, pr_list);
187 		--prisoncount;
188 		varsymset_clean(&pr->pr_varsymset);
189 	}
190 	nlookup_done(&nd);
191 	return (error);
192 }
193 
194 /*
195  * jail()
196  *
197  * jail_args(syscallarg(struct jail *) jail)
198  *
199  * MPALMOSTSAFE
200  */
201 int
202 sys_jail(struct jail_args *uap)
203 {
204 	struct thread *td = curthread;
205 	struct prison *pr;
206 	struct jail_ip_storage *jip;
207 	struct jail j;
208 	int error;
209 	uint32_t jversion;
210 
211 	uap->sysmsg_result = -1;
212 
213 	error = priv_check(td, PRIV_JAIL_CREATE);
214 	if (error)
215 		return (error);
216 
217 	error = copyin(uap->jail, &jversion, sizeof(jversion));
218 	if (error)
219 		return (error);
220 
221 	pr = kmalloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
222 	SLIST_INIT(&pr->pr_ips);
223 	get_mplock();
224 
225 	switch (jversion) {
226 	case 0:
227 		/* Single IPv4 jails. */
228 		{
229 		struct jail_v0 jv0;
230 		struct sockaddr_in ip4addr;
231 
232 		error = copyin(uap->jail, &jv0, sizeof(jv0));
233 		if (error)
234 			goto out;
235 
236 		j.path = jv0.path;
237 		j.hostname = jv0.hostname;
238 
239 		jip = kmalloc(sizeof(*jip),  M_PRISON, M_WAITOK | M_ZERO);
240 		ip4addr.sin_family = AF_INET;
241 		ip4addr.sin_addr.s_addr = htonl(jv0.ip_number);
242 		memcpy(&jip->ip, &ip4addr, sizeof(ip4addr));
243 		SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
244 		break;
245 		}
246 
247 	case 1:
248 		/*
249 		 * DragonFly multi noIP/IPv4/IPv6 jails
250 		 *
251 		 * NOTE: This version is unsupported by FreeBSD
252 		 * (which uses version 2 instead).
253 		 */
254 
255 		error = copyin(uap->jail, &j, sizeof(j));
256 		if (error)
257 			goto out;
258 
259 		for (int i = 0; i < j.n_ips; i++) {
260 			jip = kmalloc(sizeof(*jip), M_PRISON,
261 				      M_WAITOK | M_ZERO);
262 			SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
263 			error = copyin(&j.ips[i], &jip->ip,
264 					sizeof(struct sockaddr_storage));
265 			if (error)
266 				goto out;
267 		}
268 		break;
269 	default:
270 		error = EINVAL;
271 		goto out;
272 	}
273 
274 	error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
275 	if (error)
276 		goto out;
277 
278 	error = kern_jail(pr, &j);
279 	if (error)
280 		goto out;
281 
282 	uap->sysmsg_result = pr->pr_id;
283 	rel_mplock();
284 	return (0);
285 
286 out:
287 	/* Delete all ips */
288 	while (!SLIST_EMPTY(&pr->pr_ips)) {
289 		jip = SLIST_FIRST(&pr->pr_ips);
290 		SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
291 		kfree(jip, M_PRISON);
292 	}
293 	rel_mplock();
294 	kfree(pr, M_PRISON);
295 	return (error);
296 }
297 
298 /*
299  * int jail_attach(int jid);
300  *
301  * MPALMOSTSAFE
302  */
303 int
304 sys_jail_attach(struct jail_attach_args *uap)
305 {
306 	struct thread *td = curthread;
307 	int error;
308 
309 	error = priv_check(td, PRIV_JAIL_ATTACH);
310 	if (error)
311 		return(error);
312 	get_mplock();
313 	error = kern_jail_attach(uap->jid);
314 	rel_mplock();
315 	return (error);
316 }
317 
318 static void
319 prison_ipcache_init(struct prison *pr)
320 {
321 	struct jail_ip_storage *jis;
322 	struct sockaddr_in *ip4;
323 	struct sockaddr_in6 *ip6;
324 
325 	SLIST_FOREACH(jis, &pr->pr_ips, entries) {
326 		switch (jis->ip.ss_family) {
327 		case AF_INET:
328 			ip4 = (struct sockaddr_in *)&jis->ip;
329 			if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) ==
330 			    IN_LOOPBACKNET) {
331 				/* loopback address */
332 				if (pr->local_ip4 == NULL)
333 					pr->local_ip4 = ip4;
334 			} else {
335 				/* public address */
336 				if (pr->nonlocal_ip4 == NULL)
337 					pr->nonlocal_ip4 = ip4;
338 			}
339 			break;
340 
341 		case AF_INET6:
342 			ip6 = (struct sockaddr_in6 *)&jis->ip;
343 			if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) {
344 				/* loopback address */
345 				if (pr->local_ip6 == NULL)
346 					pr->local_ip6 = ip6;
347 			} else {
348 				/* public address */
349 				if (pr->nonlocal_ip6 == NULL)
350 					pr->nonlocal_ip6 = ip6;
351 			}
352 			break;
353 		}
354 	}
355 }
356 
357 /*
358  * Changes INADDR_LOOPBACK for a valid jail address.
359  * ip is in network byte order.
360  * Returns 1 if the ip is among jail valid ips.
361  * Returns 0 if is not among jail valid ips or
362  * if couldn't replace INADDR_LOOPBACK for a valid
363  * IP.
364  */
365 int
366 prison_replace_wildcards(struct thread *td, struct sockaddr *ip)
367 {
368 	struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
369 	struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
370 	struct prison *pr;
371 
372 	if (td->td_proc == NULL || td->td_ucred == NULL)
373 		return (1);
374 	if ((pr = td->td_ucred->cr_prison) == NULL)
375 		return (1);
376 
377 	if ((ip->sa_family == AF_INET &&
378 	    ip4->sin_addr.s_addr == htonl(INADDR_ANY)) ||
379 	    (ip->sa_family == AF_INET6 &&
380 	    IN6_IS_ADDR_UNSPECIFIED(&ip6->sin6_addr)))
381 		return (1);
382 	if ((ip->sa_family == AF_INET &&
383 	    ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
384 	    (ip->sa_family == AF_INET6 &&
385 	    IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
386 		if (!prison_get_local(pr, ip->sa_family, ip) &&
387 		    !prison_get_nonlocal(pr, ip->sa_family, ip))
388 			return(0);
389 		else
390 			return(1);
391 	}
392 	if (jailed_ip(pr, ip))
393 		return(1);
394 	return(0);
395 }
396 
397 int
398 prison_remote_ip(struct thread *td, struct sockaddr *ip)
399 {
400 	struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
401 	struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
402 	struct prison *pr;
403 
404 	if (td == NULL || td->td_proc == NULL || td->td_ucred == NULL)
405 		return(1);
406 	if ((pr = td->td_ucred->cr_prison) == NULL)
407 		return(1);
408 	if ((ip->sa_family == AF_INET &&
409 	    ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
410 	    (ip->sa_family == AF_INET6 &&
411 	    IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
412 		if (!prison_get_local(pr, ip->sa_family, ip) &&
413 		    !prison_get_nonlocal(pr, ip->sa_family, ip))
414 			return(0);
415 		else
416 			return(1);
417 	}
418 	return(1);
419 }
420 
421 /*
422  * Prison get non loopback ip:
423  * - af is the address family of the ip we want (AF_INET|AF_INET6).
424  * - If ip != NULL, put the first IP address that is not a loopback address
425  *   into *ip.
426  *
427  * ip is in network by order and we don't touch it unless we find a valid ip.
428  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
429  * or NULL.  This struct may not be modified.
430  */
431 struct sockaddr *
432 prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip)
433 {
434 	struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
435 	struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
436 
437 	/* Check if it is cached */
438 	switch(af) {
439 	case AF_INET:
440 		if (ip4 != NULL && pr->nonlocal_ip4 != NULL)
441 			ip4->sin_addr.s_addr = pr->nonlocal_ip4->sin_addr.s_addr;
442 		return (struct sockaddr *)pr->nonlocal_ip4;
443 
444 	case AF_INET6:
445 		if (ip6 != NULL && pr->nonlocal_ip6 != NULL)
446 			ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr;
447 		return (struct sockaddr *)pr->nonlocal_ip6;
448 	}
449 
450 	/* NOTREACHED */
451 	return NULL;
452 }
453 
454 /*
455  * Prison get loopback ip.
456  * - af is the address family of the ip we want (AF_INET|AF_INET6).
457  * - If ip != NULL, put the first IP address that is not a loopback address
458  *   into *ip.
459  *
460  * ip is in network by order and we don't touch it unless we find a valid ip.
461  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
462  * or NULL.  This struct may not be modified.
463  */
464 struct sockaddr *
465 prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip)
466 {
467 	struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
468 	struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
469 
470 	/* Check if it is cached */
471 	switch(af) {
472 	case AF_INET:
473 		if (ip4 != NULL && pr->local_ip4 != NULL)
474 			ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr;
475 		return (struct sockaddr *)pr->local_ip4;
476 
477 	case AF_INET6:
478 		if (ip6 != NULL && pr->local_ip6 != NULL)
479 			ip6->sin6_addr = pr->local_ip6->sin6_addr;
480 		return (struct sockaddr *)pr->local_ip6;
481 	}
482 
483 	/* NOTREACHED */
484 	return NULL;
485 }
486 
487 /* Check if the IP is among ours, if it is return 1, else 0 */
488 int
489 jailed_ip(struct prison *pr, struct sockaddr *ip)
490 {
491 	struct jail_ip_storage *jis;
492 	struct sockaddr_in *jip4, *ip4;
493 	struct sockaddr_in6 *jip6, *ip6;
494 
495 	if (pr == NULL)
496 		return(0);
497 	ip4 = (struct sockaddr_in *)ip;
498 	ip6 = (struct sockaddr_in6 *)ip;
499 	SLIST_FOREACH(jis, &pr->pr_ips, entries) {
500 		switch (ip->sa_family) {
501 		case AF_INET:
502 			jip4 = (struct sockaddr_in *) &jis->ip;
503 			if (jip4->sin_family == AF_INET &&
504 			    ip4->sin_addr.s_addr == jip4->sin_addr.s_addr)
505 				return(1);
506 			break;
507 		case AF_INET6:
508 			jip6 = (struct sockaddr_in6 *) &jis->ip;
509 			if (jip6->sin6_family == AF_INET6 &&
510 			    IN6_ARE_ADDR_EQUAL(&ip6->sin6_addr,
511 					       &jip6->sin6_addr))
512 				return(1);
513 			break;
514 		}
515 	}
516 	/* Ip not in list */
517 	return(0);
518 }
519 
520 int
521 prison_if(struct ucred *cred, struct sockaddr *sa)
522 {
523 	struct prison *pr;
524 	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
525 
526 	pr = cred->cr_prison;
527 
528 	if (((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
529 	    && jail_socket_unixiproute_only)
530 		return(1);
531 	else if ((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
532 		return(0);
533 	else if (jailed_ip(pr, sa))
534 		return(0);
535 	return(1);
536 }
537 
538 /*
539  * Returns a prison instance, or NULL on failure.
540  */
541 static struct prison *
542 prison_find(int prid)
543 {
544 	struct prison *pr;
545 
546 	LIST_FOREACH(pr, &allprison, pr_list) {
547 		if (pr->pr_id == prid)
548 			break;
549 	}
550 	return(pr);
551 }
552 
553 static int
554 sysctl_jail_list(SYSCTL_HANDLER_ARGS)
555 {
556 	struct thread *td = curthread;
557 	struct jail_ip_storage *jip;
558 #ifdef INET6
559 	struct sockaddr_in6 *jsin6;
560 #endif
561 	struct sockaddr_in *jsin;
562 	struct lwp *lp;
563 	struct prison *pr;
564 	unsigned int jlssize, jlsused;
565 	int count, error;
566 	char *jls; /* Jail list */
567 	char *oip; /* Output ip */
568 	char *fullpath, *freepath;
569 
570 	jlsused = 0;
571 
572 	if (jailed(td->td_ucred))
573 		return (0);
574 	lp = td->td_lwp;
575 retry:
576 	count = prisoncount;
577 
578 	if (count == 0)
579 		return(0);
580 
581 	jlssize = (count * 1024);
582 	jls = kmalloc(jlssize + 1, M_TEMP, M_WAITOK | M_ZERO);
583 	if (count < prisoncount) {
584 		kfree(jls, M_TEMP);
585 		goto retry;
586 	}
587 	count = prisoncount;
588 
589 	LIST_FOREACH(pr, &allprison, pr_list) {
590 		error = cache_fullpath(lp->lwp_proc, &pr->pr_root, NULL,
591 					&fullpath, &freepath, 0);
592 		if (error)
593 			continue;
594 		if (jlsused && jlsused < jlssize)
595 			jls[jlsused++] = '\n';
596 		count = ksnprintf(jls + jlsused, (jlssize - jlsused),
597 				 "%d %s %s",
598 				 pr->pr_id, pr->pr_host, fullpath);
599 		kfree(freepath, M_TEMP);
600 		if (count < 0)
601 			goto end;
602 		jlsused += count;
603 
604 		/* Copy the IPS */
605 		SLIST_FOREACH(jip, &pr->pr_ips, entries) {
606 			jsin = (struct sockaddr_in *)&jip->ip;
607 
608 			switch(jsin->sin_family) {
609 			case AF_INET:
610 				oip = inet_ntoa(jsin->sin_addr);
611 				break;
612 #ifdef INET6
613 			case AF_INET6:
614 				jsin6 = (struct sockaddr_in6 *)&jip->ip;
615 				oip = ip6_sprintf(&jsin6->sin6_addr);
616 				break;
617 #endif
618 			default:
619 				oip = "?family?";
620 				break;
621 			}
622 
623 			if ((jlssize - jlsused) < (strlen(oip) + 1)) {
624 				error = ERANGE;
625 				goto end;
626 			}
627 			count = ksnprintf(jls + jlsused, (jlssize - jlsused),
628 					  " %s", oip);
629 			if (count < 0)
630 				goto end;
631 			jlsused += count;
632 		}
633 	}
634 
635 	/*
636 	 * The format is:
637 	 * pr_id <SPC> hostname1 <SPC> PATH1 <SPC> IP1 <SPC> IP2\npr_id...
638 	 */
639 	error = SYSCTL_OUT(req, jls, jlsused);
640 end:
641 	kfree(jls, M_TEMP);
642 	return(error);
643 }
644 
645 SYSCTL_OID(_jail, OID_AUTO, list, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
646 	   sysctl_jail_list, "A", "List of active jails");
647 
648 /*
649  * MPSAFE
650  */
651 void
652 prison_hold(struct prison *pr)
653 {
654 	atomic_add_int(&pr->pr_ref, 1);
655 }
656 
657 /*
658  * MPALMOSTSAFE
659  */
660 void
661 prison_free(struct prison *pr)
662 {
663 	struct jail_ip_storage *jls;
664 
665 	KKASSERT(pr->pr_ref > 0);
666 	if (atomic_fetchadd_int(&pr->pr_ref, -1) != 1)
667 		return;
668 
669 	/*
670 	 * The MP lock is needed on the last ref to adjust
671 	 * the list.
672 	 */
673 	get_mplock();
674 	if (pr->pr_ref) {
675 		rel_mplock();
676 		return;
677 	}
678 	LIST_REMOVE(pr, pr_list);
679 	--prisoncount;
680 	rel_mplock();
681 
682 	/*
683 	 * Clean up
684 	 */
685 	while (!SLIST_EMPTY(&pr->pr_ips)) {
686 		jls = SLIST_FIRST(&pr->pr_ips);
687 		SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
688 		kfree(jls, M_PRISON);
689 	}
690 
691 	if (pr->pr_linux != NULL)
692 		kfree(pr->pr_linux, M_PRISON);
693 	varsymset_clean(&pr->pr_varsymset);
694 	cache_drop(&pr->pr_root);
695 	kfree(pr, M_PRISON);
696 }
697 
698 /*
699  * Check if permisson for a specific privilege is granted within jail.
700  *
701  * MPSAFE
702  */
703 int
704 prison_priv_check(struct ucred *cred, int priv)
705 {
706 	if (!jailed(cred))
707 		return (0);
708 
709 	switch (priv) {
710 	case PRIV_CRED_SETUID:
711 	case PRIV_CRED_SETEUID:
712 	case PRIV_CRED_SETGID:
713 	case PRIV_CRED_SETEGID:
714 	case PRIV_CRED_SETGROUPS:
715 	case PRIV_CRED_SETREUID:
716 	case PRIV_CRED_SETREGID:
717 	case PRIV_CRED_SETRESUID:
718 	case PRIV_CRED_SETRESGID:
719 
720 	case PRIV_VFS_SYSFLAGS:
721 	case PRIV_VFS_CHOWN:
722 	case PRIV_VFS_CHMOD:
723 	case PRIV_VFS_CHROOT:
724 	case PRIV_VFS_LINK:
725 	case PRIV_VFS_CHFLAGS_DEV:
726 	case PRIV_VFS_REVOKE:
727 	case PRIV_VFS_MKNOD_BAD:
728 	case PRIV_VFS_MKNOD_WHT:
729 	case PRIV_VFS_MKNOD_DIR:
730 	case PRIV_VFS_SETATTR:
731 	case PRIV_VFS_SETGID:
732 
733 	case PRIV_PROC_SETRLIMIT:
734 	case PRIV_PROC_SETLOGIN:
735 
736 	case PRIV_SYSCTL_WRITEJAIL:
737 
738 	case PRIV_VARSYM_SYS:
739 
740 	case PRIV_SETHOSTNAME:
741 
742 	case PRIV_PROC_TRESPASS:
743 
744 		return (0);
745 
746 	case PRIV_UFS_QUOTAON:
747 	case PRIV_UFS_QUOTAOFF:
748 	case PRIV_VFS_SETQUOTA:
749 	case PRIV_UFS_SETUSE:
750 	case PRIV_VFS_GETQUOTA:
751 		return (0);
752 
753 
754 	case PRIV_DEBUG_UNPRIV:
755 		return (0);
756 
757 
758 		/*
759 		 * Allow jailed root to bind reserved ports.
760 		 */
761 	case PRIV_NETINET_RESERVEDPORT:
762 		return (0);
763 
764 
765 		/*
766 		 * Conditionally allow creating raw sockets in jail.
767 		 */
768 	case PRIV_NETINET_RAW:
769 		if (jail_allow_raw_sockets)
770 			return (0);
771 		else
772 			return (EPERM);
773 
774 	case PRIV_HAMMER_IOCTL:
775 		return (0);
776 
777 	default:
778 
779 		return (EPERM);
780 	}
781 }
782