xref: /dragonfly/sys/kern/kern_jail.c (revision 4e7eb5cc)
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  * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $
10  * $DragonFly: src/sys/kern/kern_jail.c,v 1.5 2003/06/26 02:17:45 dillon Exp $
11  *
12  */
13 
14 #include <sys/param.h>
15 #include <sys/types.h>
16 #include <sys/kernel.h>
17 #include <sys/systm.h>
18 #include <sys/errno.h>
19 #include <sys/sysproto.h>
20 #include <sys/malloc.h>
21 #include <sys/proc.h>
22 #include <sys/jail.h>
23 #include <sys/socket.h>
24 #include <sys/sysctl.h>
25 #include <net/if.h>
26 #include <netinet/in.h>
27 
28 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
29 
30 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
31     "Jail rules");
32 
33 int	jail_set_hostname_allowed = 1;
34 SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
35     &jail_set_hostname_allowed, 0,
36     "Processes in jail can set their hostnames");
37 
38 int	jail_socket_unixiproute_only = 1;
39 SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
40     &jail_socket_unixiproute_only, 0,
41     "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
42 
43 int	jail_sysvipc_allowed = 0;
44 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
45     &jail_sysvipc_allowed, 0,
46     "Processes in jail can use System V IPC primitives");
47 
48 /*
49  * jail()
50  *
51  * jail_args(syscallarg(struct jail *) jail)
52  */
53 int
54 jail(struct jail_args *uap)
55 {
56 	int error;
57 	struct prison *pr;
58 	struct jail j;
59 	struct chroot_args ca;
60 	struct thread *td = curthread;
61 	struct proc *p = td->td_proc;
62 
63 	error = suser(td);
64 	if (error)
65 		return (error);
66 	error = copyin(uap->jail, &j, sizeof j);
67 	if (error)
68 		return (error);
69 	if (j.version != 0)
70 		return (EINVAL);
71 	MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK);
72 	bzero((caddr_t)pr, sizeof *pr);
73 	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
74 	if (error)
75 		goto bail;
76 	pr->pr_ip = j.ip_number;
77 
78 	ca.path = j.path;
79 	error = chroot(&ca);
80 	if (error)
81 		goto bail;
82 
83 	pr->pr_ref++;
84 	cratom(&p->p_ucred);
85 	p->p_ucred->cr_prison = pr;
86 	p->p_flag |= P_JAILED;
87 	return (0);
88 
89 bail:
90 	FREE(pr, M_PRISON);
91 	return (error);
92 }
93 
94 int
95 prison_ip(struct thread *td, int flag, u_int32_t *ip)
96 {
97 	u_int32_t tmp;
98 	struct prison *pr;
99 
100 	if (td->td_proc == NULL)
101 		return (0);
102 	if ((pr = td->td_proc->p_ucred->cr_prison) == NULL)
103 		return (0);
104 	if (flag)
105 		tmp = *ip;
106 	else
107 		tmp = ntohl(*ip);
108 	if (tmp == INADDR_ANY) {
109 		if (flag)
110 			*ip = pr->pr_ip;
111 		else
112 			*ip = htonl(pr->pr_ip);
113 		return (0);
114 	}
115 	if (tmp == INADDR_LOOPBACK) {
116 		if (flag)
117 			*ip = pr->pr_ip;
118 		else
119 			*ip = htonl(pr->pr_ip);
120 		return (0);
121 	}
122 	if (pr->pr_ip != tmp)
123 		return (1);
124 	return (0);
125 }
126 
127 void
128 prison_remote_ip(struct thread *td, int flag, u_int32_t *ip)
129 {
130 	u_int32_t tmp;
131 	struct prison *pr;
132 
133 	if (td == NULL || td->td_proc == NULL)
134 		return;
135 	if ((pr = td->td_proc->p_ucred->cr_prison) == NULL)
136 		return;
137 	if (flag)
138 		tmp = *ip;
139 	else
140 		tmp = ntohl(*ip);
141 	if (tmp == INADDR_LOOPBACK) {
142 		if (flag)
143 			*ip = pr->pr_ip;
144 		else
145 			*ip = htonl(pr->pr_ip);
146 	}
147 	return;
148 }
149 
150 int
151 prison_if(struct thread *td, struct sockaddr *sa)
152 {
153 	struct prison *pr;
154 	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
155 	int ok;
156 
157 	if (td->td_proc == NULL)
158 		return(0);
159 	pr = td->td_proc->p_ucred->cr_prison;
160 
161 	if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
162 		ok = 1;
163 	else if (sai->sin_family != AF_INET)
164 		ok = 0;
165 	else if (pr->pr_ip != ntohl(sai->sin_addr.s_addr))
166 		ok = 1;
167 	else
168 		ok = 0;
169 	return (ok);
170 }
171