jail - Rework sysctl configuration variables
[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/kern_syscall.h>
58 #include <net/if.h>
59 #include <netinet/in.h>
60 #include <netinet6/in6_var.h>
61
62 #include <sys/mplock2.h>
63
64 static struct prison    *prison_find(int);
65 static void             prison_ipcache_init(struct prison *);
66
67 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
68
69 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
70     "All jails settings");
71
72 SYSCTL_NODE(_jail, OID_AUTO, defaults, CTLFLAG_RW, 0,
73     "Default options for jails");
74
75 int     jail_set_hostname_allowed = 1;
76 SYSCTL_INT(_jail_defaults, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
77     &jail_set_hostname_allowed, 0,
78     "Processes in jail can set their hostnames");
79
80 int     jail_socket_unixiproute_only = 1;
81 SYSCTL_INT(_jail_defaults, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
82     &jail_socket_unixiproute_only, 0,
83     "Processes in jail are limited to creating UNIX/IPv[46]/route sockets only");
84
85 int     jail_sysvipc_allowed = 0;
86 SYSCTL_INT(_jail_defaults, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
87     &jail_sysvipc_allowed, 0,
88     "Processes in jail can use System V IPC primitives");
89
90 int    jail_chflags_allowed = 0;
91 SYSCTL_INT(_jail_defaults, OID_AUTO, chflags_allowed, CTLFLAG_RW,
92     &jail_chflags_allowed, 0,
93     "Processes in jail can alter system file flags");
94
95 int    jail_allow_raw_sockets = 0;
96 SYSCTL_INT(_jail_defaults, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,
97     &jail_allow_raw_sockets, 0,
98     "Process in jail can create raw sockets");
99
100 int     lastprid = 0;
101 int     prisoncount = 0;
102
103 LIST_HEAD(prisonlist, prison);
104 struct  prisonlist allprison = LIST_HEAD_INITIALIZER(&allprison);
105
106 static int
107 kern_jail_attach(int jid)
108 {
109         struct proc *p = curthread->td_proc;
110         struct prison *pr;
111         struct ucred *cr;
112         int error;
113
114         pr = prison_find(jid);
115         if (pr == NULL)
116                 return(EINVAL);
117
118         error = kern_chroot(&pr->pr_root);
119         if (error)
120                 return(error);
121
122         prison_hold(pr);
123         lwkt_gettoken(&p->p_token);
124         cr = cratom_proc(p);
125         cr->cr_prison = pr;
126         p->p_flags |= P_JAILED;
127         lwkt_reltoken(&p->p_token);
128
129         return(0);
130 }
131
132 static int
133 assign_prison_id(struct prison *pr)
134 {
135         int tryprid;
136         struct prison *tpr;
137
138         tryprid = lastprid + 1;
139         if (tryprid == JAIL_MAX)
140                 tryprid = 1;
141 next:
142         LIST_FOREACH(tpr, &allprison, pr_list) {
143                 if (tpr->pr_id != tryprid)
144                         continue;
145                 tryprid++;
146                 if (tryprid == JAIL_MAX) {
147                         return (ERANGE);
148                 }
149                 goto next;
150         }
151         pr->pr_id = lastprid = tryprid;
152
153         return (0);
154 }
155
156 static int
157 kern_jail(struct prison *pr, struct jail *j)
158 {
159         int error;
160         struct nlookupdata nd;
161
162         error = nlookup_init(&nd, j->path, UIO_USERSPACE, NLC_FOLLOW);
163         if (error) {
164                 nlookup_done(&nd);
165                 return (error);
166         }
167         error = nlookup(&nd);
168         if (error) {
169                 nlookup_done(&nd);
170                 return (error);
171         }
172         cache_copy(&nd.nl_nch, &pr->pr_root);
173
174         varsymset_init(&pr->pr_varsymset, NULL);
175         prison_ipcache_init(pr);
176
177         error = assign_prison_id(pr);
178         if (error) {
179                 varsymset_clean(&pr->pr_varsymset);
180                 nlookup_done(&nd);
181                 return (error);
182         }
183
184         LIST_INSERT_HEAD(&allprison, pr, pr_list);
185         ++prisoncount;
186
187         error = prison_sysctl_create(pr);
188         if (error)
189                 goto out;
190
191         error = kern_jail_attach(pr->pr_id);
192         if (error)
193                 goto out2;
194
195         nlookup_done(&nd);
196         return 0;
197
198 out2:
199         prison_sysctl_done(pr);
200
201 out:
202         LIST_REMOVE(pr, pr_list);
203         --prisoncount;
204         varsymset_clean(&pr->pr_varsymset);
205         nlookup_done(&nd);
206         return (error);
207 }
208
209 /*
210  * jail()
211  *
212  * jail_args(syscallarg(struct jail *) jail)
213  *
214  * MPALMOSTSAFE
215  */
216 int
217 sys_jail(struct jail_args *uap)
218 {
219         struct thread *td = curthread;
220         struct prison *pr;
221         struct jail_ip_storage *jip;
222         struct jail j;
223         int error;
224         uint32_t jversion;
225
226         uap->sysmsg_result = -1;
227
228         error = priv_check(td, PRIV_JAIL_CREATE);
229         if (error)
230                 return (error);
231
232         error = copyin(uap->jail, &jversion, sizeof(jversion));
233         if (error)
234                 return (error);
235
236         pr = kmalloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
237         SLIST_INIT(&pr->pr_ips);
238         get_mplock();
239
240         switch (jversion) {
241         case 0:
242                 /* Single IPv4 jails. */
243                 {
244                 struct jail_v0 jv0;
245                 struct sockaddr_in ip4addr;
246
247                 error = copyin(uap->jail, &jv0, sizeof(jv0));
248                 if (error)
249                         goto out;
250
251                 j.path = jv0.path;
252                 j.hostname = jv0.hostname; 
253
254                 jip = kmalloc(sizeof(*jip),  M_PRISON, M_WAITOK | M_ZERO);
255                 ip4addr.sin_family = AF_INET;
256                 ip4addr.sin_addr.s_addr = htonl(jv0.ip_number);
257                 memcpy(&jip->ip, &ip4addr, sizeof(ip4addr));
258                 SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
259                 break;
260                 }
261
262         case 1:
263                 /*
264                  * DragonFly multi noIP/IPv4/IPv6 jails
265                  *
266                  * NOTE: This version is unsupported by FreeBSD
267                  * (which uses version 2 instead).
268                  */
269
270                 error = copyin(uap->jail, &j, sizeof(j));
271                 if (error)
272                         goto out;
273
274                 for (int i = 0; i < j.n_ips; i++) {
275                         jip = kmalloc(sizeof(*jip), M_PRISON,
276                                       M_WAITOK | M_ZERO);
277                         SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
278                         error = copyin(&j.ips[i], &jip->ip,
279                                         sizeof(struct sockaddr_storage));
280                         if (error)
281                                 goto out;
282                 }
283                 break;
284         default:
285                 error = EINVAL;
286                 goto out;
287         }
288
289         error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
290         if (error)
291                 goto out;
292
293         /* Global settings are the default for all jails */
294         pr->pr_set_hostname_allowed = jail_set_hostname_allowed;
295         pr->pr_socket_unixiproute_only = jail_socket_unixiproute_only;
296         pr->pr_sysvipc_allowed = jail_sysvipc_allowed;
297         pr->pr_chflags_allowed = jail_chflags_allowed;
298         pr->pr_allow_raw_sockets = jail_allow_raw_sockets;
299
300         error = kern_jail(pr, &j);
301         if (error)
302                 goto out;
303
304         uap->sysmsg_result = pr->pr_id;
305         rel_mplock();
306         return (0);
307
308 out:
309         /* Delete all ips */
310         while (!SLIST_EMPTY(&pr->pr_ips)) {
311                 jip = SLIST_FIRST(&pr->pr_ips);
312                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
313                 kfree(jip, M_PRISON);
314         }
315         rel_mplock();
316         kfree(pr, M_PRISON);
317         return (error);
318 }
319
320 /*
321  * int jail_attach(int jid);
322  *
323  * MPALMOSTSAFE
324  */
325 int
326 sys_jail_attach(struct jail_attach_args *uap)
327 {
328         struct thread *td = curthread;
329         int error;
330
331         error = priv_check(td, PRIV_JAIL_ATTACH);
332         if (error)
333                 return(error);
334         get_mplock();
335         error = kern_jail_attach(uap->jid);
336         rel_mplock();
337         return (error);
338 }
339
340 static void
341 prison_ipcache_init(struct prison *pr)
342 {
343         struct jail_ip_storage *jis;
344         struct sockaddr_in *ip4;
345         struct sockaddr_in6 *ip6;
346
347         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
348                 switch (jis->ip.ss_family) {
349                 case AF_INET:
350                         ip4 = (struct sockaddr_in *)&jis->ip;
351                         if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) ==
352                             IN_LOOPBACKNET) {
353                                 /* loopback address */
354                                 if (pr->local_ip4 == NULL)
355                                         pr->local_ip4 = ip4;
356                         } else {
357                                 /* public address */
358                                 if (pr->nonlocal_ip4 == NULL)
359                                         pr->nonlocal_ip4 = ip4;
360                         }
361                         break;
362
363                 case AF_INET6:
364                         ip6 = (struct sockaddr_in6 *)&jis->ip;
365                         if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) {
366                                 /* loopback address */
367                                 if (pr->local_ip6 == NULL)
368                                         pr->local_ip6 = ip6;
369                         } else {
370                                 /* public address */
371                                 if (pr->nonlocal_ip6 == NULL)
372                                         pr->nonlocal_ip6 = ip6;
373                         }
374                         break;
375                 }
376         }
377 }
378
379 /* 
380  * Changes INADDR_LOOPBACK for a valid jail address.
381  * ip is in network byte order.
382  * Returns 1 if the ip is among jail valid ips.
383  * Returns 0 if is not among jail valid ips or
384  * if couldn't replace INADDR_LOOPBACK for a valid
385  * IP.
386  */
387 int
388 prison_replace_wildcards(struct thread *td, struct sockaddr *ip)
389 {
390         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
391         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
392         struct prison *pr;
393
394         if (td->td_proc == NULL || td->td_ucred == NULL)
395                 return (1);
396         if ((pr = td->td_ucred->cr_prison) == NULL)
397                 return (1);
398
399         if ((ip->sa_family == AF_INET &&
400             ip4->sin_addr.s_addr == htonl(INADDR_ANY)) ||
401             (ip->sa_family == AF_INET6 &&
402             IN6_IS_ADDR_UNSPECIFIED(&ip6->sin6_addr)))
403                 return (1);
404         if ((ip->sa_family == AF_INET &&
405             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
406             (ip->sa_family == AF_INET6 &&
407             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
408                 if (!prison_get_local(pr, ip->sa_family, ip) &&
409                     !prison_get_nonlocal(pr, ip->sa_family, ip))
410                         return(0);
411                 else
412                         return(1);
413         }
414         if (jailed_ip(pr, ip))
415                 return(1);
416         return(0);
417 }
418
419 int
420 prison_remote_ip(struct thread *td, struct sockaddr *ip)
421 {
422         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
423         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
424         struct prison *pr;
425
426         if (td == NULL || td->td_proc == NULL || td->td_ucred == NULL)
427                 return(1);
428         if ((pr = td->td_ucred->cr_prison) == NULL)
429                 return(1);
430         if ((ip->sa_family == AF_INET &&
431             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
432             (ip->sa_family == AF_INET6 &&
433             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
434                 if (!prison_get_local(pr, ip->sa_family, ip) &&
435                     !prison_get_nonlocal(pr, ip->sa_family, ip))
436                         return(0);
437                 else
438                         return(1);
439         }
440         return(1);
441 }
442
443 /*
444  * Prison get non loopback ip:
445  * - af is the address family of the ip we want (AF_INET|AF_INET6).
446  * - If ip != NULL, put the first IP address that is not a loopback address
447  *   into *ip.
448  *
449  * ip is in network by order and we don't touch it unless we find a valid ip.
450  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
451  * or NULL.  This struct may not be modified.
452  */
453 struct sockaddr *
454 prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip)
455 {
456         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
457         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
458
459         /* Check if it is cached */
460         switch(af) {
461         case AF_INET:
462                 if (ip4 != NULL && pr->nonlocal_ip4 != NULL)
463                         ip4->sin_addr.s_addr = pr->nonlocal_ip4->sin_addr.s_addr;
464                 return (struct sockaddr *)pr->nonlocal_ip4;
465
466         case AF_INET6:
467                 if (ip6 != NULL && pr->nonlocal_ip6 != NULL)
468                         ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr;
469                 return (struct sockaddr *)pr->nonlocal_ip6;
470         }
471
472         /* NOTREACHED */
473         return NULL;
474 }
475
476 /*
477  * Prison get loopback ip.
478  * - af is the address family of the ip we want (AF_INET|AF_INET6).
479  * - If ip != NULL, put the first IP address that is not a loopback address
480  *   into *ip.
481  *
482  * ip is in network by order and we don't touch it unless we find a valid ip.
483  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
484  * or NULL.  This struct may not be modified.
485  */
486 struct sockaddr *
487 prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip)
488 {
489         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
490         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
491
492         /* Check if it is cached */
493         switch(af) {
494         case AF_INET:
495                 if (ip4 != NULL && pr->local_ip4 != NULL)
496                         ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr;
497                 return (struct sockaddr *)pr->local_ip4;
498
499         case AF_INET6:
500                 if (ip6 != NULL && pr->local_ip6 != NULL)
501                         ip6->sin6_addr = pr->local_ip6->sin6_addr;
502                 return (struct sockaddr *)pr->local_ip6;
503         }
504
505         /* NOTREACHED */
506         return NULL;
507 }
508
509 /* Check if the IP is among ours, if it is return 1, else 0 */
510 int
511 jailed_ip(struct prison *pr, struct sockaddr *ip)
512 {
513         struct jail_ip_storage *jis;
514         struct sockaddr_in *jip4, *ip4;
515         struct sockaddr_in6 *jip6, *ip6;
516
517         if (pr == NULL)
518                 return(0);
519         ip4 = (struct sockaddr_in *)ip;
520         ip6 = (struct sockaddr_in6 *)ip;
521         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
522                 switch (ip->sa_family) {
523                 case AF_INET:
524                         jip4 = (struct sockaddr_in *) &jis->ip;
525                         if (jip4->sin_family == AF_INET &&
526                             ip4->sin_addr.s_addr == jip4->sin_addr.s_addr)
527                                 return(1);
528                         break;
529                 case AF_INET6:
530                         jip6 = (struct sockaddr_in6 *) &jis->ip;
531                         if (jip6->sin6_family == AF_INET6 &&
532                             IN6_ARE_ADDR_EQUAL(&ip6->sin6_addr,
533                                                &jip6->sin6_addr))
534                                 return(1);
535                         break;
536                 }
537         }
538         /* Ip not in list */
539         return(0);
540 }
541
542 int
543 prison_if(struct ucred *cred, struct sockaddr *sa)
544 {
545         struct prison *pr;
546         struct sockaddr_in *sai = (struct sockaddr_in*) sa;
547
548         pr = cred->cr_prison;
549
550         if (((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
551             && jail_socket_unixiproute_only)
552                 return(1);
553         else if ((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
554                 return(0);
555         else if (jailed_ip(pr, sa))
556                 return(0);
557         return(1);
558 }
559
560 /*
561  * Returns a prison instance, or NULL on failure.
562  */
563 static struct prison *
564 prison_find(int prid)
565 {
566         struct prison *pr;
567
568         LIST_FOREACH(pr, &allprison, pr_list) {
569                 if (pr->pr_id == prid)
570                         break;
571         }
572         return(pr);
573 }
574
575 static int
576 sysctl_jail_list(SYSCTL_HANDLER_ARGS)
577 {
578         struct thread *td = curthread;
579         struct jail_ip_storage *jip;
580 #ifdef INET6
581         struct sockaddr_in6 *jsin6;
582 #endif
583         struct sockaddr_in *jsin;
584         struct lwp *lp;
585         struct prison *pr;
586         unsigned int jlssize, jlsused;
587         int count, error;
588         char *jls; /* Jail list */
589         char *oip; /* Output ip */
590         char *fullpath, *freepath;
591
592         jlsused = 0;
593
594         if (jailed(td->td_ucred))
595                 return (0);
596         lp = td->td_lwp;
597 retry:
598         count = prisoncount;
599
600         if (count == 0)
601                 return(0);
602
603         jlssize = (count * 1024);
604         jls = kmalloc(jlssize + 1, M_TEMP, M_WAITOK | M_ZERO);
605         if (count < prisoncount) {
606                 kfree(jls, M_TEMP);
607                 goto retry;
608         }
609         count = prisoncount;
610
611         LIST_FOREACH(pr, &allprison, pr_list) {
612                 error = cache_fullpath(lp->lwp_proc, &pr->pr_root, NULL,
613                                         &fullpath, &freepath, 0);
614                 if (error)
615                         continue;
616                 if (jlsused && jlsused < jlssize)
617                         jls[jlsused++] = '\n';
618                 count = ksnprintf(jls + jlsused, (jlssize - jlsused),
619                                  "%d %s %s", 
620                                  pr->pr_id, pr->pr_host, fullpath);
621                 kfree(freepath, M_TEMP);                
622                 if (count < 0)
623                         goto end;
624                 jlsused += count;
625
626                 /* Copy the IPS */
627                 SLIST_FOREACH(jip, &pr->pr_ips, entries) {
628                         char buf[INET_ADDRSTRLEN];
629
630                         jsin = (struct sockaddr_in *)&jip->ip;
631
632                         switch(jsin->sin_family) {
633                         case AF_INET:
634                                 oip = kinet_ntoa(jsin->sin_addr, buf);
635                                 break;
636 #ifdef INET6
637                         case AF_INET6:
638                                 jsin6 = (struct sockaddr_in6 *)&jip->ip;
639                                 oip = ip6_sprintf(&jsin6->sin6_addr);
640                                 break;
641 #endif
642                         default:
643                                 oip = "?family?";
644                                 break;
645                         }
646
647                         if ((jlssize - jlsused) < (strlen(oip) + 1)) {
648                                 error = ERANGE;
649                                 goto end;
650                         }
651                         count = ksnprintf(jls + jlsused, (jlssize - jlsused),
652                                           " %s", oip);
653                         if (count < 0)
654                                 goto end;
655                         jlsused += count;
656                 }
657         }
658
659         /* 
660          * The format is:
661          * pr_id <SPC> hostname1 <SPC> PATH1 <SPC> IP1 <SPC> IP2\npr_id...
662          */
663         error = SYSCTL_OUT(req, jls, jlsused);
664 end:
665         kfree(jls, M_TEMP);
666         return(error);
667 }
668
669 SYSCTL_OID(_jail, OID_AUTO, list, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
670            sysctl_jail_list, "A", "List of active jails");
671
672 static int
673 sysctl_jail_jailed(SYSCTL_HANDLER_ARGS)
674 {
675         int error, injail;
676
677         injail = jailed(req->td->td_ucred);
678         error = SYSCTL_OUT(req, &injail, sizeof(injail));
679
680         return (error);
681 }
682
683 SYSCTL_PROC(_jail, OID_AUTO, jailed,
684             CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NOLOCK, NULL, 0,
685             sysctl_jail_jailed, "I", "Process in jail?");
686
687 /*
688  * MPSAFE
689  */
690 void
691 prison_hold(struct prison *pr)
692 {
693         atomic_add_int(&pr->pr_ref, 1);
694 }
695
696 /*
697  * MPALMOSTSAFE
698  */
699 void
700 prison_free(struct prison *pr)
701 {
702         struct jail_ip_storage *jls;
703
704         KKASSERT(pr->pr_ref > 0);
705         if (atomic_fetchadd_int(&pr->pr_ref, -1) != 1)
706                 return;
707
708         /*
709          * The MP lock is needed on the last ref to adjust
710          * the list.
711          */
712         get_mplock();
713         if (pr->pr_ref) {
714                 rel_mplock();
715                 return;
716         }
717         LIST_REMOVE(pr, pr_list);
718         --prisoncount;
719         rel_mplock();
720
721         /*
722          * Clean up
723          */
724         while (!SLIST_EMPTY(&pr->pr_ips)) {
725                 jls = SLIST_FIRST(&pr->pr_ips);
726                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
727                 kfree(jls, M_PRISON);
728         }
729
730         if (pr->pr_linux != NULL)
731                 kfree(pr->pr_linux, M_PRISON);
732         varsymset_clean(&pr->pr_varsymset);
733
734         /* Release the sysctl tree */
735         prison_sysctl_done(pr);
736
737         cache_drop(&pr->pr_root);
738         kfree(pr, M_PRISON);
739 }
740
741 /*
742  * Check if permisson for a specific privilege is granted within jail.
743  *
744  * MPSAFE
745  */
746 int
747 prison_priv_check(struct ucred *cred, int priv)
748 {
749         struct prison *pr = cred->cr_prison;
750
751         if (!jailed(cred))
752                 return (0);
753
754         switch (priv) {
755         case PRIV_CRED_SETUID:
756         case PRIV_CRED_SETEUID:
757         case PRIV_CRED_SETGID:
758         case PRIV_CRED_SETEGID:
759         case PRIV_CRED_SETGROUPS:
760         case PRIV_CRED_SETREUID:
761         case PRIV_CRED_SETREGID:
762         case PRIV_CRED_SETRESUID:
763         case PRIV_CRED_SETRESGID:
764
765         case PRIV_VFS_SYSFLAGS:
766         case PRIV_VFS_CHOWN:
767         case PRIV_VFS_CHMOD:
768         case PRIV_VFS_CHROOT:
769         case PRIV_VFS_LINK:
770         case PRIV_VFS_CHFLAGS_DEV:
771         case PRIV_VFS_REVOKE:
772         case PRIV_VFS_MKNOD_BAD:
773         case PRIV_VFS_MKNOD_WHT:
774         case PRIV_VFS_MKNOD_DIR:
775         case PRIV_VFS_SETATTR:
776         case PRIV_VFS_SETGID:
777
778         case PRIV_PROC_SETRLIMIT:
779         case PRIV_PROC_SETLOGIN:
780
781         case PRIV_SYSCTL_WRITEJAIL:
782
783         case PRIV_VARSYM_SYS:
784
785         case PRIV_SETHOSTNAME:
786
787         case PRIV_PROC_TRESPASS:
788
789                 return (0);
790
791         case PRIV_UFS_QUOTAON:
792         case PRIV_UFS_QUOTAOFF:
793         case PRIV_VFS_SETQUOTA:
794         case PRIV_UFS_SETUSE:
795         case PRIV_VFS_GETQUOTA:
796                 return (0);
797
798
799         case PRIV_DEBUG_UNPRIV:
800                 return (0);
801
802
803                 /*
804                  * Allow jailed root to bind reserved ports.
805                  */
806         case PRIV_NETINET_RESERVEDPORT:
807                 return (0);
808
809
810                 /*
811                  * Conditionally allow creating raw sockets in jail.
812                  */
813         case PRIV_NETINET_RAW:
814                 if (pr->pr_allow_raw_sockets)
815                         return (0);
816                 else
817                         return (EPERM);
818
819         case PRIV_HAMMER_IOCTL:
820                 return (0);
821
822         default:
823
824                 return (EPERM);
825         }
826 }
827
828 static int
829 sysctl_prison_switch_int8(SYSCTL_HANDLER_ARGS, int8_t *val)
830 {
831         int new_val;
832         int error;
833
834         new_val = *val;
835
836         error = sysctl_handle_int(oidp, &new_val, 0, req);
837         if (error != 0 || req->newptr == NULL)
838                 return error;
839
840         if (new_val != 0 && new_val != 1)
841                 return EINVAL;
842
843         *val = new_val;
844
845         return error;
846
847 }
848
849 static int
850 sysctl_prison_set_hostname_allowed(SYSCTL_HANDLER_ARGS)
851 {
852         struct prison *pr;
853         int error;
854
855         if (arg1 == NULL)
856                 return EINVAL;
857         pr = arg1;
858
859         error = sysctl_prison_switch_int8(oidp, arg1, arg2, req,
860             &pr->pr_set_hostname_allowed);
861
862         return error;
863 }
864
865 static int
866 sysctl_prison_socket_unixiproute_only(SYSCTL_HANDLER_ARGS)
867 {
868         struct prison *pr;
869         int error;
870
871         if (arg1 == NULL)
872                 return EINVAL;
873         pr = arg1;
874
875         error = sysctl_prison_switch_int8(oidp, arg1, arg2, req,
876             &pr->pr_socket_unixiproute_only);
877
878         return error;
879 }
880
881 static int
882 sysctl_prison_sysvipc_allowed(SYSCTL_HANDLER_ARGS)
883 {
884         struct prison *pr;
885         int error;
886
887         if (arg1 == NULL)
888                 return EINVAL;
889         pr = arg1;
890
891         error = sysctl_prison_switch_int8(oidp, arg1, arg2, req,
892             &pr->pr_sysvipc_allowed);
893
894         return error;
895 }
896
897 static int
898 sysctl_prison_chflags_allowed(SYSCTL_HANDLER_ARGS)
899 {
900         struct prison *pr;
901         int error;
902
903         if (arg1 == NULL)
904                 return EINVAL;
905         pr = arg1;
906
907         error = sysctl_prison_switch_int8(oidp, arg1, arg2, req,
908             &pr->pr_chflags_allowed);
909
910         return error;
911 }
912
913 static int
914 sysctl_prison_allow_raw_sockets(SYSCTL_HANDLER_ARGS)
915 {
916         struct prison *pr;
917         int error;
918
919         if (arg1 == NULL)
920                 return EINVAL;
921         pr = arg1;
922
923         error = sysctl_prison_switch_int8(oidp, arg1, arg2, req,
924             &pr->pr_allow_raw_sockets);
925
926         return error;
927 }
928
929 /*
930  * Create a per-jail sysctl tree to control the prison
931  */
932 int
933 prison_sysctl_create(struct prison *pr)
934 {
935         char id_str[7];
936
937         ksnprintf(id_str, 6, "%d", pr->pr_id);
938
939         pr->pr_sysctl_ctx = (struct sysctl_ctx_list *) kmalloc(
940                 sizeof(struct sysctl_ctx_list), M_TEMP, M_WAITOK | M_ZERO);
941
942         sysctl_ctx_init(pr->pr_sysctl_ctx);
943
944         /* Main jail node */
945         pr->pr_sysctl_tree = SYSCTL_ADD_NODE(pr->pr_sysctl_ctx,
946             SYSCTL_STATIC_CHILDREN(_jail),
947             OID_AUTO, id_str, CTLFLAG_RD, 0,
948             "Jail specific settings");
949
950         SYSCTL_ADD_PROC(pr->pr_sysctl_ctx,
951             SYSCTL_CHILDREN(pr->pr_sysctl_tree), OID_AUTO,
952             "set_hostname_allowed", CTLTYPE_INT | CTLFLAG_RW,
953             pr, sizeof(pr->pr_set_hostname_allowed),
954             sysctl_prison_set_hostname_allowed, "I",
955             "Processes in jail can set their hostnames");
956         SYSCTL_ADD_PROC(pr->pr_sysctl_ctx,
957             SYSCTL_CHILDREN(pr->pr_sysctl_tree), OID_AUTO,
958             "socket_unixiproute_only", CTLTYPE_INT | CTLFLAG_RW,
959             pr, sizeof(pr->pr_socket_unixiproute_only),
960             sysctl_prison_socket_unixiproute_only, "I",
961             "Processes in jail are limited to creating UNIX/IPv[46]/route sockets only");
962         SYSCTL_ADD_PROC(pr->pr_sysctl_ctx,
963             SYSCTL_CHILDREN(pr->pr_sysctl_tree), OID_AUTO,
964             "sysvipc_allowed", CTLTYPE_INT | CTLFLAG_RW,
965             pr, sizeof(pr->pr_sysvipc_allowed),
966             sysctl_prison_sysvipc_allowed, "I",
967             "Processes in jail can use System V IPC primitives");
968         SYSCTL_ADD_PROC(pr->pr_sysctl_ctx,
969             SYSCTL_CHILDREN(pr->pr_sysctl_tree), OID_AUTO,
970             "chflags_allowed", CTLTYPE_INT | CTLFLAG_RW,
971             pr, sizeof(pr->pr_chflags_allowed),
972             sysctl_prison_chflags_allowed, "I",
973             "Processes in jail can alter system file flags");
974         SYSCTL_ADD_PROC(pr->pr_sysctl_ctx,
975             SYSCTL_CHILDREN(pr->pr_sysctl_tree), OID_AUTO,
976             "allow_raw_sockets", CTLTYPE_INT | CTLFLAG_RW,
977             pr, sizeof(pr->pr_allow_raw_sockets),
978             sysctl_prison_allow_raw_sockets, "I",
979             "Process in jail can create raw sockets");
980
981         return 0;
982 }
983
984 int
985 prison_sysctl_done(struct prison *pr)
986 {
987         if (pr->pr_sysctl_tree) {
988                 sysctl_ctx_free(pr->pr_sysctl_ctx);
989                 kfree(pr->pr_sysctl_ctx, M_TEMP);
990                 pr->pr_sysctl_tree = NULL;
991         }
992
993         return 0;
994 }