xref: /freebsd/sys/kern/kern_jail.c (revision 0fddbf874719b9bd50cf66ac26d1140bb3f2be69)
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$
10  *
11  */
12 
13 #include <sys/param.h>
14 #include <sys/types.h>
15 #include <sys/kernel.h>
16 #include <sys/systm.h>
17 #include <sys/errno.h>
18 #include <sys/sysproto.h>
19 #include <sys/malloc.h>
20 #include <sys/proc.h>
21 #include <sys/jail.h>
22 #include <sys/socket.h>
23 #include <sys/sysctl.h>
24 #include <net/if.h>
25 #include <netinet/in.h>
26 
27 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
28 
29 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
30     "Jail rules");
31 
32 int	jail_set_hostname_allowed = 1;
33 SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
34     &jail_set_hostname_allowed, 0,
35     "Processes in jail can set their hostnames");
36 
37 int	jail_socket_unixiproute_only = 1;
38 SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
39     &jail_socket_unixiproute_only, 0,
40     "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
41 
42 int	jail_sysvipc_allowed = 0;
43 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
44     &jail_sysvipc_allowed, 0,
45     "Processes in jail can use System V IPC primitives");
46 
47 /*
48  * MPSAFE
49  */
50 int
51 jail(p, uap)
52 	struct proc *p;
53 	struct jail_args /* {
54 		syscallarg(struct jail *) jail;
55 	} */ *uap;
56 {
57 	int error;
58 	struct prison *pr;
59 	struct jail j;
60 	struct chroot_args ca;
61 
62 	mtx_lock(&Giant);
63 
64 	/* Implicitly fail if already in jail.  */
65 	error = suser(p);
66 	if (error)
67 		goto done2;
68 	error = copyin(uap->jail, &j, sizeof j);
69 	if (error)
70 		goto done2;
71 	if (j.version != 0) {
72 		error = EINVAL;
73 		goto done2;
74 	}
75 	MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK | M_ZERO);
76 	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
77 	if (error)
78 		goto bail;
79 	pr->pr_ip = j.ip_number;
80 
81 	ca.path = j.path;
82 	error = chroot(p, &ca);
83 	if (error)
84 		goto bail;
85 
86 	p->p_ucred = crcopy(p->p_ucred);
87 	p->p_ucred->cr_prison = pr;
88 	pr->pr_ref = 1;
89 	mtx_unlock(&Giant);
90 	return (0);
91 
92 bail:
93 	FREE(pr, M_PRISON);
94 done2:
95 	mtx_unlock(&Giant);
96 	return (error);
97 }
98 
99 void
100 prison_free(struct prison *pr)
101 {
102 
103 	pr->pr_ref--;
104 	if (pr->pr_ref == 0) {
105 		if (pr->pr_linux != NULL)
106 			FREE(pr->pr_linux, M_PRISON);
107 		FREE(pr, M_PRISON);
108 	}
109 }
110 
111 void
112 prison_hold(struct prison *pr)
113 {
114 
115 	pr->pr_ref++;
116 }
117 
118 int
119 prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
120 {
121 	u_int32_t tmp;
122 
123 	if (!jailed(cred))
124 		return (0);
125 	if (flag)
126 		tmp = *ip;
127 	else
128 		tmp = ntohl(*ip);
129 	if (tmp == INADDR_ANY) {
130 		if (flag)
131 			*ip = cred->cr_prison->pr_ip;
132 		else
133 			*ip = htonl(cred->cr_prison->pr_ip);
134 		return (0);
135 	}
136 	if (tmp == INADDR_LOOPBACK) {
137 		if (flag)
138 			*ip = cred->cr_prison->pr_ip;
139 		else
140 			*ip = htonl(cred->cr_prison->pr_ip);
141 		return (0);
142 	}
143 	if (cred->cr_prison->pr_ip != tmp)
144 		return (1);
145 	return (0);
146 }
147 
148 void
149 prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip)
150 {
151 	u_int32_t tmp;
152 
153 	if (!jailed(cred))
154 		return;
155 	if (flag)
156 		tmp = *ip;
157 	else
158 		tmp = ntohl(*ip);
159 	if (tmp == INADDR_LOOPBACK) {
160 		if (flag)
161 			*ip = cred->cr_prison->pr_ip;
162 		else
163 			*ip = htonl(cred->cr_prison->pr_ip);
164 		return;
165 	}
166 	return;
167 }
168 
169 int
170 prison_if(struct ucred *cred, struct sockaddr *sa)
171 {
172 	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
173 	int ok;
174 
175 	if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
176 		ok = 1;
177 	else if (sai->sin_family != AF_INET)
178 		ok = 0;
179 	else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
180 		ok = 1;
181 	else
182 		ok = 0;
183 	return (ok);
184 }
185 
186 /*
187  * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
188  */
189 int
190 prison_check(cred1, cred2)
191 	struct ucred *cred1, *cred2;
192 {
193 
194 	if (jailed(cred1)) {
195 		if (!jailed(cred2))
196 			return (ESRCH);
197 		if (cred2->cr_prison != cred1->cr_prison)
198 			return (ESRCH);
199 	}
200 
201 	return (0);
202 }
203 
204 /*
205  * Return 1 if the passed credential is in a jail, otherwise 0.
206  */
207 int
208 jailed(cred)
209 	struct ucred *cred;
210 {
211 
212 	return (cred->cr_prison != NULL);
213 }
214