Merge remote-tracking branch 'origin/vendor/BINUTILS227'
[dragonfly.git] / sys / kern / kern_jail.c
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         struct ucred *cr;
110         int error;
111
112         pr = prison_find(jid);
113         if (pr == NULL)
114                 return(EINVAL);
115
116         error = kern_chroot(&pr->pr_root);
117         if (error)
118                 return(error);
119
120         prison_hold(pr);
121         lwkt_gettoken(&p->p_token);
122         cr = cratom_proc(p);
123         cr->cr_prison = pr;
124         p->p_flags |= P_JAILED;
125         lwkt_reltoken(&p->p_token);
126
127         return(0);
128 }
129
130 static int
131 assign_prison_id(struct prison *pr)
132 {
133         int tryprid;
134         struct prison *tpr;
135
136         tryprid = lastprid + 1;
137         if (tryprid == JAIL_MAX)
138                 tryprid = 1;
139 next:
140         LIST_FOREACH(tpr, &allprison, pr_list) {
141                 if (tpr->pr_id != tryprid)
142                         continue;
143                 tryprid++;
144                 if (tryprid == JAIL_MAX) {
145                         return (ERANGE);
146                 }
147                 goto next;
148         }
149         pr->pr_id = lastprid = tryprid;
150
151         return (0);
152 }
153
154 static int
155 kern_jail(struct prison *pr, struct jail *j)
156 {
157         int error;
158         struct nlookupdata nd;
159
160         error = nlookup_init(&nd, j->path, UIO_USERSPACE, NLC_FOLLOW);
161         if (error) {
162                 nlookup_done(&nd);
163                 return (error);
164         }
165         error = nlookup(&nd);
166         if (error) {
167                 nlookup_done(&nd);
168                 return (error);
169         }
170         cache_copy(&nd.nl_nch, &pr->pr_root);
171
172         varsymset_init(&pr->pr_varsymset, NULL);
173         prison_ipcache_init(pr);
174
175         error = assign_prison_id(pr);
176         if (error) {
177                 varsymset_clean(&pr->pr_varsymset);
178                 nlookup_done(&nd);
179                 return (error);
180         }
181                 
182         LIST_INSERT_HEAD(&allprison, pr, pr_list);
183         ++prisoncount;
184
185         error = kern_jail_attach(pr->pr_id);
186         if (error) {
187                 LIST_REMOVE(pr, pr_list);
188                 --prisoncount;
189                 varsymset_clean(&pr->pr_varsymset);
190         }
191         nlookup_done(&nd);
192         return (error);
193 }
194
195 /*
196  * jail()
197  *
198  * jail_args(syscallarg(struct jail *) jail)
199  *
200  * MPALMOSTSAFE
201  */
202 int
203 sys_jail(struct jail_args *uap)
204 {
205         struct thread *td = curthread;
206         struct prison *pr;
207         struct jail_ip_storage *jip;
208         struct jail j;
209         int error;
210         uint32_t jversion;
211
212         uap->sysmsg_result = -1;
213
214         error = priv_check(td, PRIV_JAIL_CREATE);
215         if (error)
216                 return (error);
217
218         error = copyin(uap->jail, &jversion, sizeof(jversion));
219         if (error)
220                 return (error);
221
222         pr = kmalloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
223         SLIST_INIT(&pr->pr_ips);
224         get_mplock();
225
226         switch (jversion) {
227         case 0:
228                 /* Single IPv4 jails. */
229                 {
230                 struct jail_v0 jv0;
231                 struct sockaddr_in ip4addr;
232
233                 error = copyin(uap->jail, &jv0, sizeof(jv0));
234                 if (error)
235                         goto out;
236
237                 j.path = jv0.path;
238                 j.hostname = jv0.hostname; 
239
240                 jip = kmalloc(sizeof(*jip),  M_PRISON, M_WAITOK | M_ZERO);
241                 ip4addr.sin_family = AF_INET;
242                 ip4addr.sin_addr.s_addr = htonl(jv0.ip_number);
243                 memcpy(&jip->ip, &ip4addr, sizeof(ip4addr));
244                 SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
245                 break;
246                 }
247
248         case 1:
249                 /*
250                  * DragonFly multi noIP/IPv4/IPv6 jails
251                  *
252                  * NOTE: This version is unsupported by FreeBSD
253                  * (which uses version 2 instead).
254                  */
255
256                 error = copyin(uap->jail, &j, sizeof(j));
257                 if (error)
258                         goto out;
259
260                 for (int i = 0; i < j.n_ips; i++) {
261                         jip = kmalloc(sizeof(*jip), M_PRISON,
262                                       M_WAITOK | M_ZERO);
263                         SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
264                         error = copyin(&j.ips[i], &jip->ip,
265                                         sizeof(struct sockaddr_storage));
266                         if (error)
267                                 goto out;
268                 }
269                 break;
270         default:
271                 error = EINVAL;
272                 goto out;
273         }
274
275         error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
276         if (error)
277                 goto out;
278
279         error = kern_jail(pr, &j);
280         if (error)
281                 goto out;
282
283         uap->sysmsg_result = pr->pr_id;
284         rel_mplock();
285         return (0);
286
287 out:
288         /* Delete all ips */
289         while (!SLIST_EMPTY(&pr->pr_ips)) {
290                 jip = SLIST_FIRST(&pr->pr_ips);
291                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
292                 kfree(jip, M_PRISON);
293         }
294         rel_mplock();
295         kfree(pr, M_PRISON);
296         return (error);
297 }
298
299 /*
300  * int jail_attach(int jid);
301  *
302  * MPALMOSTSAFE
303  */
304 int
305 sys_jail_attach(struct jail_attach_args *uap)
306 {
307         struct thread *td = curthread;
308         int error;
309
310         error = priv_check(td, PRIV_JAIL_ATTACH);
311         if (error)
312                 return(error);
313         get_mplock();
314         error = kern_jail_attach(uap->jid);
315         rel_mplock();
316         return (error);
317 }
318
319 static void
320 prison_ipcache_init(struct prison *pr)
321 {
322         struct jail_ip_storage *jis;
323         struct sockaddr_in *ip4;
324         struct sockaddr_in6 *ip6;
325
326         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
327                 switch (jis->ip.ss_family) {
328                 case AF_INET:
329                         ip4 = (struct sockaddr_in *)&jis->ip;
330                         if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) ==
331                             IN_LOOPBACKNET) {
332                                 /* loopback address */
333                                 if (pr->local_ip4 == NULL)
334                                         pr->local_ip4 = ip4;
335                         } else {
336                                 /* public address */
337                                 if (pr->nonlocal_ip4 == NULL)
338                                         pr->nonlocal_ip4 = ip4;
339                         }
340                         break;
341
342                 case AF_INET6:
343                         ip6 = (struct sockaddr_in6 *)&jis->ip;
344                         if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) {
345                                 /* loopback address */
346                                 if (pr->local_ip6 == NULL)
347                                         pr->local_ip6 = ip6;
348                         } else {
349                                 /* public address */
350                                 if (pr->nonlocal_ip6 == NULL)
351                                         pr->nonlocal_ip6 = ip6;
352                         }
353                         break;
354                 }
355         }
356 }
357
358 /* 
359  * Changes INADDR_LOOPBACK for a valid jail address.
360  * ip is in network byte order.
361  * Returns 1 if the ip is among jail valid ips.
362  * Returns 0 if is not among jail valid ips or
363  * if couldn't replace INADDR_LOOPBACK for a valid
364  * IP.
365  */
366 int
367 prison_replace_wildcards(struct thread *td, struct sockaddr *ip)
368 {
369         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
370         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
371         struct prison *pr;
372
373         if (td->td_proc == NULL || td->td_ucred == NULL)
374                 return (1);
375         if ((pr = td->td_ucred->cr_prison) == NULL)
376                 return (1);
377
378         if ((ip->sa_family == AF_INET &&
379             ip4->sin_addr.s_addr == htonl(INADDR_ANY)) ||
380             (ip->sa_family == AF_INET6 &&
381             IN6_IS_ADDR_UNSPECIFIED(&ip6->sin6_addr)))
382                 return (1);
383         if ((ip->sa_family == AF_INET &&
384             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
385             (ip->sa_family == AF_INET6 &&
386             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
387                 if (!prison_get_local(pr, ip->sa_family, ip) &&
388                     !prison_get_nonlocal(pr, ip->sa_family, ip))
389                         return(0);
390                 else
391                         return(1);
392         }
393         if (jailed_ip(pr, ip))
394                 return(1);
395         return(0);
396 }
397
398 int
399 prison_remote_ip(struct thread *td, struct sockaddr *ip)
400 {
401         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
402         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
403         struct prison *pr;
404
405         if (td == NULL || td->td_proc == NULL || td->td_ucred == NULL)
406                 return(1);
407         if ((pr = td->td_ucred->cr_prison) == NULL)
408                 return(1);
409         if ((ip->sa_family == AF_INET &&
410             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
411             (ip->sa_family == AF_INET6 &&
412             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
413                 if (!prison_get_local(pr, ip->sa_family, ip) &&
414                     !prison_get_nonlocal(pr, ip->sa_family, ip))
415                         return(0);
416                 else
417                         return(1);
418         }
419         return(1);
420 }
421
422 /*
423  * Prison get non loopback ip:
424  * - af is the address family of the ip we want (AF_INET|AF_INET6).
425  * - If ip != NULL, put the first IP address that is not a loopback address
426  *   into *ip.
427  *
428  * ip is in network by order and we don't touch it unless we find a valid ip.
429  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
430  * or NULL.  This struct may not be modified.
431  */
432 struct sockaddr *
433 prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip)
434 {
435         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
436         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
437
438         /* Check if it is cached */
439         switch(af) {
440         case AF_INET:
441                 if (ip4 != NULL && pr->nonlocal_ip4 != NULL)
442                         ip4->sin_addr.s_addr = pr->nonlocal_ip4->sin_addr.s_addr;
443                 return (struct sockaddr *)pr->nonlocal_ip4;
444
445         case AF_INET6:
446                 if (ip6 != NULL && pr->nonlocal_ip6 != NULL)
447                         ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr;
448                 return (struct sockaddr *)pr->nonlocal_ip6;
449         }
450
451         /* NOTREACHED */
452         return NULL;
453 }
454
455 /*
456  * Prison get loopback ip.
457  * - af is the address family of the ip we want (AF_INET|AF_INET6).
458  * - If ip != NULL, put the first IP address that is not a loopback address
459  *   into *ip.
460  *
461  * ip is in network by order and we don't touch it unless we find a valid ip.
462  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
463  * or NULL.  This struct may not be modified.
464  */
465 struct sockaddr *
466 prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip)
467 {
468         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
469         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
470
471         /* Check if it is cached */
472         switch(af) {
473         case AF_INET:
474                 if (ip4 != NULL && pr->local_ip4 != NULL)
475                         ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr;
476                 return (struct sockaddr *)pr->local_ip4;
477
478         case AF_INET6:
479                 if (ip6 != NULL && pr->local_ip6 != NULL)
480                         ip6->sin6_addr = pr->local_ip6->sin6_addr;
481                 return (struct sockaddr *)pr->local_ip6;
482         }
483
484         /* NOTREACHED */
485         return NULL;
486 }
487
488 /* Check if the IP is among ours, if it is return 1, else 0 */
489 int
490 jailed_ip(struct prison *pr, struct sockaddr *ip)
491 {
492         struct jail_ip_storage *jis;
493         struct sockaddr_in *jip4, *ip4;
494         struct sockaddr_in6 *jip6, *ip6;
495
496         if (pr == NULL)
497                 return(0);
498         ip4 = (struct sockaddr_in *)ip;
499         ip6 = (struct sockaddr_in6 *)ip;
500         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
501                 switch (ip->sa_family) {
502                 case AF_INET:
503                         jip4 = (struct sockaddr_in *) &jis->ip;
504                         if (jip4->sin_family == AF_INET &&
505                             ip4->sin_addr.s_addr == jip4->sin_addr.s_addr)
506                                 return(1);
507                         break;
508                 case AF_INET6:
509                         jip6 = (struct sockaddr_in6 *) &jis->ip;
510                         if (jip6->sin6_family == AF_INET6 &&
511                             IN6_ARE_ADDR_EQUAL(&ip6->sin6_addr,
512                                                &jip6->sin6_addr))
513                                 return(1);
514                         break;
515                 }
516         }
517         /* Ip not in list */
518         return(0);
519 }
520
521 int
522 prison_if(struct ucred *cred, struct sockaddr *sa)
523 {
524         struct prison *pr;
525         struct sockaddr_in *sai = (struct sockaddr_in*) sa;
526
527         pr = cred->cr_prison;
528
529         if (((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
530             && jail_socket_unixiproute_only)
531                 return(1);
532         else if ((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
533                 return(0);
534         else if (jailed_ip(pr, sa))
535                 return(0);
536         return(1);
537 }
538
539 /*
540  * Returns a prison instance, or NULL on failure.
541  */
542 static struct prison *
543 prison_find(int prid)
544 {
545         struct prison *pr;
546
547         LIST_FOREACH(pr, &allprison, pr_list) {
548                 if (pr->pr_id == prid)
549                         break;
550         }
551         return(pr);
552 }
553
554 static int
555 sysctl_jail_list(SYSCTL_HANDLER_ARGS)
556 {
557         struct thread *td = curthread;
558         struct jail_ip_storage *jip;
559 #ifdef INET6
560         struct sockaddr_in6 *jsin6;
561 #endif
562         struct sockaddr_in *jsin;
563         struct lwp *lp;
564         struct prison *pr;
565         unsigned int jlssize, jlsused;
566         int count, error;
567         char *jls; /* Jail list */
568         char *oip; /* Output ip */
569         char *fullpath, *freepath;
570
571         jlsused = 0;
572
573         if (jailed(td->td_ucred))
574                 return (0);
575         lp = td->td_lwp;
576 retry:
577         count = prisoncount;
578
579         if (count == 0)
580                 return(0);
581
582         jlssize = (count * 1024);
583         jls = kmalloc(jlssize + 1, M_TEMP, M_WAITOK | M_ZERO);
584         if (count < prisoncount) {
585                 kfree(jls, M_TEMP);
586                 goto retry;
587         }
588         count = prisoncount;
589
590         LIST_FOREACH(pr, &allprison, pr_list) {
591                 error = cache_fullpath(lp->lwp_proc, &pr->pr_root, NULL,
592                                         &fullpath, &freepath, 0);
593                 if (error)
594                         continue;
595                 if (jlsused && jlsused < jlssize)
596                         jls[jlsused++] = '\n';
597                 count = ksnprintf(jls + jlsused, (jlssize - jlsused),
598                                  "%d %s %s", 
599                                  pr->pr_id, pr->pr_host, fullpath);
600                 kfree(freepath, M_TEMP);                
601                 if (count < 0)
602                         goto end;
603                 jlsused += count;
604
605                 /* Copy the IPS */
606                 SLIST_FOREACH(jip, &pr->pr_ips, entries) {
607                         jsin = (struct sockaddr_in *)&jip->ip;
608
609                         switch(jsin->sin_family) {
610                         case AF_INET:
611                                 oip = inet_ntoa(jsin->sin_addr);
612                                 break;
613 #ifdef INET6
614                         case AF_INET6:
615                                 jsin6 = (struct sockaddr_in6 *)&jip->ip;
616                                 oip = ip6_sprintf(&jsin6->sin6_addr);
617                                 break;
618 #endif
619                         default:
620                                 oip = "?family?";
621                                 break;
622                         }
623
624                         if ((jlssize - jlsused) < (strlen(oip) + 1)) {
625                                 error = ERANGE;
626                                 goto end;
627                         }
628                         count = ksnprintf(jls + jlsused, (jlssize - jlsused),
629                                           " %s", oip);
630                         if (count < 0)
631                                 goto end;
632                         jlsused += count;
633                 }
634         }
635
636         /* 
637          * The format is:
638          * pr_id <SPC> hostname1 <SPC> PATH1 <SPC> IP1 <SPC> IP2\npr_id...
639          */
640         error = SYSCTL_OUT(req, jls, jlsused);
641 end:
642         kfree(jls, M_TEMP);
643         return(error);
644 }
645
646 SYSCTL_OID(_jail, OID_AUTO, list, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
647            sysctl_jail_list, "A", "List of active jails");
648
649 /*
650  * MPSAFE
651  */
652 void
653 prison_hold(struct prison *pr)
654 {
655         atomic_add_int(&pr->pr_ref, 1);
656 }
657
658 /*
659  * MPALMOSTSAFE
660  */
661 void
662 prison_free(struct prison *pr)
663 {
664         struct jail_ip_storage *jls;
665
666         KKASSERT(pr->pr_ref > 0);
667         if (atomic_fetchadd_int(&pr->pr_ref, -1) != 1)
668                 return;
669
670         /*
671          * The MP lock is needed on the last ref to adjust
672          * the list.
673          */
674         get_mplock();
675         if (pr->pr_ref) {
676                 rel_mplock();
677                 return;
678         }
679         LIST_REMOVE(pr, pr_list);
680         --prisoncount;
681         rel_mplock();
682
683         /*
684          * Clean up
685          */
686         while (!SLIST_EMPTY(&pr->pr_ips)) {
687                 jls = SLIST_FIRST(&pr->pr_ips);
688                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
689                 kfree(jls, M_PRISON);
690         }
691
692         if (pr->pr_linux != NULL)
693                 kfree(pr->pr_linux, M_PRISON);
694         varsymset_clean(&pr->pr_varsymset);
695         cache_drop(&pr->pr_root);
696         kfree(pr, M_PRISON);
697 }
698
699 /*
700  * Check if permisson for a specific privilege is granted within jail.
701  *
702  * MPSAFE
703  */
704 int
705 prison_priv_check(struct ucred *cred, int priv)
706 {
707         if (!jailed(cred))
708                 return (0);
709
710         switch (priv) {
711         case PRIV_CRED_SETUID:
712         case PRIV_CRED_SETEUID:
713         case PRIV_CRED_SETGID:
714         case PRIV_CRED_SETEGID:
715         case PRIV_CRED_SETGROUPS:
716         case PRIV_CRED_SETREUID:
717         case PRIV_CRED_SETREGID:
718         case PRIV_CRED_SETRESUID:
719         case PRIV_CRED_SETRESGID:
720
721         case PRIV_VFS_SYSFLAGS:
722         case PRIV_VFS_CHOWN:
723         case PRIV_VFS_CHMOD:
724         case PRIV_VFS_CHROOT:
725         case PRIV_VFS_LINK:
726         case PRIV_VFS_CHFLAGS_DEV:
727         case PRIV_VFS_REVOKE:
728         case PRIV_VFS_MKNOD_BAD:
729         case PRIV_VFS_MKNOD_WHT:
730         case PRIV_VFS_MKNOD_DIR:
731         case PRIV_VFS_SETATTR:
732         case PRIV_VFS_SETGID:
733
734         case PRIV_PROC_SETRLIMIT:
735         case PRIV_PROC_SETLOGIN:
736
737         case PRIV_SYSCTL_WRITEJAIL:
738
739         case PRIV_VARSYM_SYS:
740
741         case PRIV_SETHOSTNAME:
742
743         case PRIV_PROC_TRESPASS:
744
745                 return (0);
746
747         case PRIV_UFS_QUOTAON:
748         case PRIV_UFS_QUOTAOFF:
749         case PRIV_VFS_SETQUOTA:
750         case PRIV_UFS_SETUSE:
751         case PRIV_VFS_GETQUOTA:
752                 return (0);
753
754
755         case PRIV_DEBUG_UNPRIV:
756                 return (0);
757
758
759                 /*
760                  * Allow jailed root to bind reserved ports.
761                  */
762         case PRIV_NETINET_RESERVEDPORT:
763                 return (0);
764
765
766                 /*
767                  * Conditionally allow creating raw sockets in jail.
768                  */
769         case PRIV_NETINET_RAW:
770                 if (jail_allow_raw_sockets)
771                         return (0);
772                 else
773                         return (EPERM);
774
775         case PRIV_HAMMER_IOCTL:
776                 return (0);
777
778         default:
779
780                 return (EPERM);
781         }
782 }