Merge from vendor branch BIND:
[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.17 2007/01/18 12:34:46 victor Exp $
40  */
41
42
43 #include <sys/param.h>
44 #include <sys/types.h>
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
47 #include <sys/errno.h>
48 #include <sys/sysproto.h>
49 #include <sys/malloc.h>
50 #include <sys/nlookup.h>
51 #include <sys/namecache.h>
52 #include <sys/proc.h>
53 #include <sys/jail.h>
54 #include <sys/socket.h>
55 #include <sys/sysctl.h>
56 #include <sys/kern_syscall.h>
57 #include <net/if.h>
58 #include <netinet/in.h>
59 #include <netinet6/in6_var.h>
60
61 static struct prison    *prison_find(int);
62 static void             prison_ipcache_init(struct prison *);
63
64 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
65
66 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
67     "Jail rules");
68
69 int     jail_set_hostname_allowed = 1;
70 SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
71     &jail_set_hostname_allowed, 0,
72     "Processes in jail can set their hostnames");
73
74 int     jail_socket_unixiproute_only = 1;
75 SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
76     &jail_socket_unixiproute_only, 0,
77     "Processes in jail are limited to creating UNIX/IPv[46]/route sockets only");
78
79 int     jail_sysvipc_allowed = 0;
80 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
81     &jail_sysvipc_allowed, 0,
82     "Processes in jail can use System V IPC primitives");
83
84 int    jail_chflags_allowed = 0;
85 SYSCTL_INT(_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,
86     &jail_chflags_allowed, 0,
87     "Process in jail can set chflags(1)");
88
89 int     lastprid = 0;
90 int     prisoncount = 0;
91
92 LIST_HEAD(prisonlist, prison);
93 struct  prisonlist allprison = LIST_HEAD_INITIALIZER(&allprison);
94
95 static int
96 kern_jail_attach(int jid)
97 {
98         struct proc *p = curthread->td_proc;
99         struct prison *pr;
100         int error;
101
102         pr = prison_find(jid);
103         if (pr == NULL)
104                 return(EINVAL);
105
106         error = kern_chroot(&pr->pr_root);
107         if (error)
108                 return(error);
109
110         prison_hold(pr);
111         cratom(&p->p_ucred);
112         p->p_ucred->cr_prison = pr;
113         p->p_flag |= P_JAILED;
114
115         return(0);
116 }
117
118 /*
119  * jail()
120  *
121  * jail_args(syscallarg(struct jail *) jail)
122  */
123 int
124 sys_jail(struct jail_args *uap)
125 {
126         struct prison *pr, *tpr;
127         struct jail j;
128         struct jail_v0 jv0;
129         struct thread *td = curthread;
130         int error, tryprid, i;
131         uint32_t jversion;
132         struct nlookupdata nd;
133         /* Multiip */
134         struct sockaddr_storage *uips; /* Userland ips */
135         struct sockaddr_in ip4addr;
136         struct jail_ip_storage *jip;
137         /* Multiip */
138
139         error = suser(td);
140         if (error) {
141                 uap->sysmsg_result = -1;
142                 return(error);
143         }
144         error = copyin(uap->jail, &jversion, sizeof jversion);
145         if (error) {
146                 uap->sysmsg_result = -1;
147                 return(error);
148         }
149         pr = kmalloc(sizeof *pr , M_PRISON, M_WAITOK | M_ZERO);
150         SLIST_INIT(&pr->pr_ips);
151
152         switch (jversion) {
153         case 0:
154                 error = copyin(uap->jail, &jv0, sizeof(struct jail_v0));
155                 if (error)
156                         goto bail;
157                 jip = kmalloc(sizeof(*jip),  M_PRISON, M_WAITOK | M_ZERO);
158                 ip4addr.sin_family = AF_INET;
159                 ip4addr.sin_addr.s_addr = htonl(jv0.ip_number);
160                 memcpy(&jip->ip, &ip4addr, sizeof(ip4addr));
161                 SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
162                 break;
163         case 1:
164                 error = copyin(uap->jail, &j, sizeof(j));
165                 if (error)
166                         goto bail;
167                 uips = kmalloc((sizeof(*uips) * j.n_ips), M_PRISON,
168                                 M_WAITOK | M_ZERO);
169                 error = copyin(j.ips, uips, (sizeof(*uips) * j.n_ips));
170                 if (error) {
171                         kfree(uips, M_PRISON);
172                         goto bail;
173                 }
174                 for (i = 0; i < j.n_ips; i++) {
175                         jip = kmalloc(sizeof(*jip),  M_PRISON,
176                                       M_WAITOK | M_ZERO);
177                         memcpy(&jip->ip, &uips[i], sizeof(*uips));
178                         SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries);
179                 }
180                 kfree(uips, M_PRISON);
181                 break;
182         default:
183                 error = EINVAL;
184                 goto bail;
185         }
186
187         error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
188         if (error)
189                 goto bail;
190         error = nlookup_init(&nd, j.path, UIO_USERSPACE, NLC_FOLLOW);
191         if (error)
192                 goto nlookup_init_clean;
193         error = nlookup(&nd);
194         if (error)
195                 goto nlookup_init_clean;
196         cache_copy(&nd.nl_nch, &pr->pr_root);
197
198         varsymset_init(&pr->pr_varsymset, NULL);
199         prison_ipcache_init(pr);
200
201         tryprid = lastprid + 1;
202         if (tryprid == JAIL_MAX)
203                 tryprid = 1;
204 next:
205         LIST_FOREACH(tpr, &allprison, pr_list) {
206                 if (tpr->pr_id != tryprid)
207                         continue;
208                 tryprid++;
209                 if (tryprid == JAIL_MAX) {
210                         error = ERANGE;
211                         goto varsym_clean;
212                 }
213                 goto next;
214         }
215         pr->pr_id = lastprid = tryprid;
216         LIST_INSERT_HEAD(&allprison, pr, pr_list);
217         prisoncount++;
218
219         error = kern_jail_attach(pr->pr_id);
220         if (error)
221                 goto jail_attach_clean;
222
223         nlookup_done(&nd);
224         uap->sysmsg_result = pr->pr_id;
225         return (0);
226
227 jail_attach_clean:
228         LIST_REMOVE(pr, pr_list);
229 varsym_clean:
230         varsymset_clean(&pr->pr_varsymset);
231 nlookup_init_clean:
232         nlookup_done(&nd);
233 bail:
234         /* Delete all ips */
235         while (!SLIST_EMPTY(&pr->pr_ips)) {
236                 jip = SLIST_FIRST(&pr->pr_ips);
237                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
238                 FREE(jip, M_PRISON);
239         }
240         FREE(pr, M_PRISON);
241         return(error);
242 }
243
244 /*
245  * int jail_attach(int jid);
246  */
247 int
248 sys_jail_attach(struct jail_attach_args *uap)
249 {
250         struct thread *td = curthread;
251         int error;
252
253         error = suser(td);
254         if (error)
255                 return(error);
256
257         return(kern_jail_attach(uap->jid));
258 }
259
260 static void
261 prison_ipcache_init(struct prison *pr)
262 {
263         struct jail_ip_storage *jis;
264         struct sockaddr_in *ip4;
265         struct sockaddr_in6 *ip6;
266
267         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
268                 switch (jis->ip.ss_family) {
269                 case AF_INET:
270                         ip4 = (struct sockaddr_in *)&jis->ip;
271                         if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) ==
272                             IN_LOOPBACKNET) {
273                                 /* loopback address */
274                                 if (pr->local_ip4 == NULL)
275                                         pr->local_ip4 = ip4;
276                         } else {
277                                 /* public address */
278                                 if (pr->nonlocal_ip4 == NULL)
279                                         pr->nonlocal_ip4 = ip4;
280                         }
281                         break;
282
283                 case AF_INET6:
284                         ip6 = (struct sockaddr_in6 *)&jis->ip;
285                         if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) {
286                                 /* loopback address */
287                                 if (pr->local_ip6 == NULL)
288                                         pr->local_ip6 = ip6;
289                         } else {
290                                 /* public address */
291                                 if (pr->nonlocal_ip6 == NULL)
292                                         pr->nonlocal_ip6 = ip6;
293                         }
294                         break;
295                 }
296         }
297 }
298
299 /* 
300  * Changes INADDR_LOOPBACK for a valid jail address.
301  * ip is in network byte order.
302  * Returns 1 if the ip is among jail valid ips.
303  * Returns 0 if is not among jail valid ips or
304  * if couldn't replace INADDR_LOOPBACK for a valid
305  * IP.
306  */
307 int
308 prison_replace_wildcards(struct thread *td, struct sockaddr *ip)
309 {
310         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
311         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
312         struct prison *pr;
313
314         if (td->td_proc == NULL)
315                 return (1);
316         if ((pr = td->td_proc->p_ucred->cr_prison) == NULL)
317                 return (1);
318
319         if ((ip->sa_family == AF_INET &&
320             ip4->sin_addr.s_addr == htonl(INADDR_ANY)) ||
321             (ip->sa_family == AF_INET6 &&
322             IN6_IS_ADDR_UNSPECIFIED(&ip6->sin6_addr)))
323                 return (1);
324         if ((ip->sa_family == AF_INET &&
325             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
326             (ip->sa_family == AF_INET6 &&
327             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
328                 if (!prison_get_local(pr, ip->sa_family, ip) &&
329                     !prison_get_nonlocal(pr, ip->sa_family, ip))
330                         return(0);
331                 else
332                         return(1);
333         }
334         if (jailed_ip(pr, ip))
335                 return(1);
336         return(0);
337 }
338
339 int
340 prison_remote_ip(struct thread *td, struct sockaddr *ip)
341 {
342         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
343         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
344         struct prison *pr;
345
346         if (td == NULL || td->td_proc == NULL)
347                 return(1);
348         if ((pr = td->td_proc->p_ucred->cr_prison) == NULL)
349                 return(1);
350         if ((ip->sa_family == AF_INET &&
351             ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
352             (ip->sa_family == AF_INET6 &&
353             IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
354                 if (!prison_get_local(pr, ip->sa_family, ip) &&
355                     !prison_get_nonlocal(pr, ip->sa_family, ip))
356                         return(0);
357                 else
358                         return(1);
359         }
360         return(1);
361 }
362
363 /*
364  * Prison get non loopback ip:
365  * - af is the address family of the ip we want (AF_INET|AF_INET6).
366  * - If ip != NULL, put the first IP address that is not a loopback address
367  *   into *ip.
368  *
369  * ip is in network by order and we don't touch it unless we find a valid ip.
370  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
371  * or NULL.  This struct may not be modified.
372  */
373 struct sockaddr *
374 prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip)
375 {
376         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
377         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
378
379         /* Check if it is cached */
380         switch(af) {
381         case AF_INET:
382                 if (ip4 != NULL && pr->nonlocal_ip4 != NULL)
383                         ip4->sin_addr.s_addr = pr->nonlocal_ip4->sin_addr.s_addr;
384                 return (struct sockaddr *)pr->nonlocal_ip4;
385
386         case AF_INET6:
387                 if (ip6 != NULL && pr->nonlocal_ip6 != NULL)
388                         ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr;
389                 return (struct sockaddr *)pr->nonlocal_ip6;
390         }
391
392         /* NOTREACHED */
393         return NULL;
394 }
395
396 /*
397  * Prison get loopback ip.
398  * - af is the address family of the ip we want (AF_INET|AF_INET6).
399  * - If ip != NULL, put the first IP address that is not a loopback address
400  *   into *ip.
401  *
402  * ip is in network by order and we don't touch it unless we find a valid ip.
403  * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
404  * or NULL.  This struct may not be modified.
405  */
406 struct sockaddr *
407 prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip)
408 {
409         struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
410         struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
411
412         /* Check if it is cached */
413         switch(af) {
414         case AF_INET:
415                 if (ip4 != NULL && pr->local_ip4 != NULL)
416                         ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr;
417                 return (struct sockaddr *)pr->local_ip4;
418
419         case AF_INET6:
420                 if (ip6 != NULL && pr->local_ip6 != NULL)
421                         ip6->sin6_addr = pr->local_ip6->sin6_addr;
422                 return (struct sockaddr *)pr->local_ip6;
423         }
424
425         /* NOTREACHED */
426         return NULL;
427 }
428
429 /* Check if the IP is among ours, if it is return 1, else 0 */
430 int
431 jailed_ip(struct prison *pr, struct sockaddr *ip)
432 {
433         struct jail_ip_storage *jis;
434         struct sockaddr_in *jip4, *ip4;
435         struct sockaddr_in6 *jip6, *ip6;
436
437         if (pr == NULL)
438                 return(0);
439         ip4 = (struct sockaddr_in *)ip;
440         ip6 = (struct sockaddr_in6 *)ip;
441         SLIST_FOREACH(jis, &pr->pr_ips, entries) {
442                 switch (ip->sa_family) {
443                 case AF_INET:
444                         jip4 = (struct sockaddr_in *) &jis->ip;
445                         if (jip4->sin_family == AF_INET &&
446                             ip4->sin_addr.s_addr == jip4->sin_addr.s_addr)
447                                 return(1);
448                         break;
449                 case AF_INET6:
450                         jip6 = (struct sockaddr_in6 *) &jis->ip;
451                         if (jip6->sin6_family == AF_INET6 &&
452                             IN6_ARE_ADDR_EQUAL(&ip6->sin6_addr,
453                                                &jip6->sin6_addr))
454                                 return(1);
455                         break;
456                 }
457         }
458         /* Ip not in list */
459         return(0);
460 }
461
462 int
463 prison_if(struct ucred *cred, struct sockaddr *sa)
464 {
465         struct prison *pr;
466         struct sockaddr_in *sai = (struct sockaddr_in*) sa;
467
468         pr = cred->cr_prison;
469
470         if (((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
471             && jail_socket_unixiproute_only)
472                 return(1);
473         else if ((sai->sin_family != AF_INET) && (sai->sin_family != AF_INET6))
474                 return(0);
475         else if (jailed_ip(pr, sa))
476                 return(0);
477         return(1);
478 }
479
480 /*
481  * Returns a prison instance, or NULL on failure.
482  */
483 static struct prison *
484 prison_find(int prid)
485 {
486         struct prison *pr;
487
488         LIST_FOREACH(pr, &allprison, pr_list) {
489                 if (pr->pr_id == prid)
490                         break;
491         }
492         return(pr);
493 }
494
495 static int
496 sysctl_jail_list(SYSCTL_HANDLER_ARGS)
497 {
498         struct jail_ip_storage *jip;
499 #ifdef INET6
500         struct sockaddr_in6 *jsin6;
501 #endif
502         struct sockaddr_in *jsin;
503         struct proc *p;
504         struct prison *pr;
505         unsigned int jlssize, jlsused;
506         int count, error;
507         char *jls; /* Jail list */
508         char *oip; /* Output ip */
509         char *fullpath, *freepath;
510
511         jlsused = 0;
512         p = curthread->td_proc;
513
514         if (jailed(p->p_ucred))
515                 return (0);
516 retry:
517         count = prisoncount;
518
519         if (count == 0)
520                 return(0);
521
522         jlssize = (count * 1024);
523         jls = kmalloc(jlssize + 1, M_TEMP, M_WAITOK | M_ZERO);
524         if (count < prisoncount) {
525                 kfree(jls, M_TEMP);
526                 goto retry;
527         }
528         count = prisoncount;
529
530         LIST_FOREACH(pr, &allprison, pr_list) {
531                 error = cache_fullpath(p, &pr->pr_root, &fullpath, &freepath);
532                 if (error)
533                         continue;
534                 if (jlsused && jlsused < jlssize)
535                         jls[jlsused++] = '\n';
536                 count = ksnprintf(jls + jlsused, (jlssize - jlsused),
537                                  "%d %s %s", 
538                                  pr->pr_id, pr->pr_host, fullpath);
539                 kfree(freepath, M_TEMP);                
540                 if (count < 0)
541                         goto end;
542                 jlsused += count;
543
544                 /* Copy the IPS */
545                 SLIST_FOREACH(jip, &pr->pr_ips, entries) {
546                         jsin = (struct sockaddr_in *)&jip->ip;
547
548                         switch(jsin->sin_family) {
549                         case AF_INET:
550                                 oip = inet_ntoa(jsin->sin_addr);
551                                 break;
552 #ifdef INET6
553                         case AF_INET6:
554                                 jsin6 = (struct sockaddr_in6 *)&jip->ip;
555                                 oip = ip6_sprintf(&jsin6->sin6_addr);
556                                 break;
557 #endif
558                         default:
559                                 oip = "?family?";
560                                 break;
561                         }
562
563                         if ((jlssize - jlsused) < (strlen(oip) + 1)) {
564                                 error = ERANGE;
565                                 goto end;
566                         }
567                         count = ksnprintf(jls + jlsused, (jlssize - jlsused),
568                                           " %s", oip);
569                         if (count < 0)
570                                 goto end;
571                         jlsused += count;
572                 }
573         }
574
575         /* 
576          * The format is:
577          * pr_id <SPC> hostname1 <SPC> PATH1 <SPC> IP1 <SPC> IP2\npr_id...
578          */
579         error = SYSCTL_OUT(req, jls, jlsused);
580 end:
581         kfree(jls, M_TEMP);
582         return(error);
583 }
584
585 SYSCTL_OID(_jail, OID_AUTO, list, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
586            sysctl_jail_list, "A", "List of active jails");
587
588 void
589 prison_hold(struct prison *pr)
590 {
591         pr->pr_ref++;
592 }
593
594 void
595 prison_free(struct prison *pr)
596 {
597         struct jail_ip_storage *jls;
598         KKASSERT(pr->pr_ref >= 1);
599
600         if (--pr->pr_ref > 0)
601                 return;
602
603         /* Delete all ips */
604         while (!SLIST_EMPTY(&pr->pr_ips)) {
605                 jls = SLIST_FIRST(&pr->pr_ips);
606                 SLIST_REMOVE_HEAD(&pr->pr_ips, entries);
607                 FREE(jls, M_PRISON);
608         }
609         LIST_REMOVE(pr, pr_list);
610         prisoncount--;
611
612         if (pr->pr_linux != NULL)
613                 kfree(pr->pr_linux, M_PRISON);
614         varsymset_clean(&pr->pr_varsymset);
615         cache_drop(&pr->pr_root);
616         kfree(pr, M_PRISON);
617 }