xref: /freebsd/sys/netinet6/in6_jail.c (revision 685dc743)
1 /*-
2  * Copyright (c) 1999 Poul-Henning Kamp.
3  * Copyright (c) 2008 Bjoern A. Zeeb.
4  * Copyright (c) 2009 James Gritton.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 #include "opt_ddb.h"
31 #include "opt_inet.h"
32 #include "opt_inet6.h"
33 
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/sysproto.h>
40 #include <sys/malloc.h>
41 #include <sys/osd.h>
42 #include <sys/priv.h>
43 #include <sys/proc.h>
44 #include <sys/taskqueue.h>
45 #include <sys/fcntl.h>
46 #include <sys/jail.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #include <sys/racct.h>
50 #include <sys/refcount.h>
51 #include <sys/sx.h>
52 #include <sys/namei.h>
53 #include <sys/mount.h>
54 #include <sys/queue.h>
55 #include <sys/socket.h>
56 #include <sys/syscallsubr.h>
57 #include <sys/sysctl.h>
58 #include <sys/vnode.h>
59 
60 #include <net/if.h>
61 #include <net/vnet.h>
62 
63 #include <netinet/in.h>
64 
65 static void
prison_bcopy_primary_ip6(const struct prison * pr,struct in6_addr * ia6)66 prison_bcopy_primary_ip6(const struct prison *pr, struct in6_addr *ia6)
67 {
68 
69 	bcopy(prison_ip_get0(pr, PR_INET6), ia6, sizeof(struct in6_addr));
70 }
71 
72 int
prison_qcmp_v6(const void * ip1,const void * ip2)73 prison_qcmp_v6(const void *ip1, const void *ip2)
74 {
75 	const struct in6_addr *ia6a, *ia6b;
76 	int i, rc;
77 
78 	ia6a = (const struct in6_addr *)ip1;
79 	ia6b = (const struct in6_addr *)ip2;
80 
81 	rc = 0;
82 	for (i = 0; rc == 0 && i < sizeof(struct in6_addr); i++) {
83 		if (ia6a->s6_addr[i] > ia6b->s6_addr[i])
84 			rc = 1;
85 		else if (ia6a->s6_addr[i] < ia6b->s6_addr[i])
86 			rc = -1;
87 	}
88 	return (rc);
89 }
90 
91 bool
prison_valid_v6(const void * ip)92 prison_valid_v6(const void *ip)
93 {
94 	const struct in6_addr *ia = ip;
95 
96 	return (!IN6_IS_ADDR_UNSPECIFIED(ia));
97 }
98 
99 /*
100  * Pass back primary IPv6 address for this jail.
101  *
102  * If not restricted return success but do not alter the address.  Caller has
103  * to make sure to initialize it correctly (e.g. IN6ADDR_ANY_INIT).
104  *
105  * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
106  */
107 int
prison_get_ip6(struct ucred * cred,struct in6_addr * ia6)108 prison_get_ip6(struct ucred *cred, struct in6_addr *ia6)
109 {
110 	struct prison *pr;
111 
112 	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
113 	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
114 
115 	pr = cred->cr_prison;
116 	if (!(pr->pr_flags & PR_IP6))
117 		return (0);
118 	mtx_lock(&pr->pr_mtx);
119 	if (!(pr->pr_flags & PR_IP6)) {
120 		mtx_unlock(&pr->pr_mtx);
121 		return (0);
122 	}
123 	if (pr->pr_addrs[PR_INET6] == NULL) {
124 		mtx_unlock(&pr->pr_mtx);
125 		return (EAFNOSUPPORT);
126 	}
127 
128 	prison_bcopy_primary_ip6(pr, ia6);
129 	mtx_unlock(&pr->pr_mtx);
130 	return (0);
131 }
132 
133 /*
134  * Return true if we should do proper source address selection or are not jailed.
135  * We will return false if we should bypass source address selection in favour
136  * of the primary jail IPv6 address. Only in this case *ia will be updated and
137  * returned in NBO.
138  * Return true, even in case this jail does not allow IPv6.
139  */
140 bool
prison_saddrsel_ip6(struct ucred * cred,struct in6_addr * ia6)141 prison_saddrsel_ip6(struct ucred *cred, struct in6_addr *ia6)
142 {
143 	struct prison *pr;
144 	struct in6_addr lia6;
145 
146 	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
147 	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
148 
149 	if (!jailed(cred))
150 		return (true);
151 
152 	pr = cred->cr_prison;
153 	if (pr->pr_flags & PR_IP6_SADDRSEL)
154 		return (true);
155 
156 	lia6 = in6addr_any;
157 	if (prison_get_ip6(cred, &lia6) != 0)
158 		return (true);
159 	if (IN6_IS_ADDR_UNSPECIFIED(&lia6))
160 		return (true);
161 
162 	bcopy(&lia6, ia6, sizeof(struct in6_addr));
163 	return (false);
164 }
165 
166 /*
167  * Return true if pr1 and pr2 have the same IPv6 address restrictions.
168  */
169 bool
prison_equal_ip6(struct prison * pr1,struct prison * pr2)170 prison_equal_ip6(struct prison *pr1, struct prison *pr2)
171 {
172 
173 	if (pr1 == pr2)
174 		return (true);
175 
176 	while (pr1 != &prison0 &&
177 #ifdef VIMAGE
178 	       !(pr1->pr_flags & PR_VNET) &&
179 #endif
180 	       !(pr1->pr_flags & PR_IP6_USER))
181 		pr1 = pr1->pr_parent;
182 	while (pr2 != &prison0 &&
183 #ifdef VIMAGE
184 	       !(pr2->pr_flags & PR_VNET) &&
185 #endif
186 	       !(pr2->pr_flags & PR_IP6_USER))
187 		pr2 = pr2->pr_parent;
188 	return (pr1 == pr2);
189 }
190 
191 /*
192  * Make sure our (source) address is set to something meaningful to this jail.
193  *
194  * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0)
195  * when needed while binding.
196  *
197  * Returns 0 if jail doesn't restrict IPv6 or if address belongs to jail,
198  * EADDRNOTAVAIL if the address doesn't belong, or EAFNOSUPPORT if the jail
199  * doesn't allow IPv6.
200  */
201 int
prison_local_ip6(struct ucred * cred,struct in6_addr * ia6,int v6only)202 prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only)
203 {
204 	struct prison *pr;
205 	int error;
206 
207 	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
208 	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
209 
210 	pr = cred->cr_prison;
211 	if (!(pr->pr_flags & PR_IP6))
212 		return (0);
213 	mtx_lock(&pr->pr_mtx);
214 	if (!(pr->pr_flags & PR_IP6)) {
215 		mtx_unlock(&pr->pr_mtx);
216 		return (0);
217 	}
218 	if (pr->pr_addrs[PR_INET6] == NULL) {
219 		mtx_unlock(&pr->pr_mtx);
220 		return (EAFNOSUPPORT);
221 	}
222 
223 	if (IN6_IS_ADDR_UNSPECIFIED(ia6)) {
224 		/*
225 		 * In case there is only 1 IPv6 address, and v6only is true,
226 		 * then bind directly.
227 		 */
228 		if (v6only != 0 && prison_ip_cnt(pr, PR_INET6) == 1)
229 			prison_bcopy_primary_ip6(pr, ia6);
230 		mtx_unlock(&pr->pr_mtx);
231 		return (0);
232 	}
233 
234 	error = prison_check_ip6_locked(pr, ia6);
235 	if (error == EADDRNOTAVAIL && IN6_IS_ADDR_LOOPBACK(ia6)) {
236 		prison_bcopy_primary_ip6(pr, ia6);
237 		error = 0;
238 	}
239 
240 	mtx_unlock(&pr->pr_mtx);
241 	return (error);
242 }
243 
244 /*
245  * Rewrite destination address in case we will connect to loopback address.
246  *
247  * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
248  */
249 int
prison_remote_ip6(struct ucred * cred,struct in6_addr * ia6)250 prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6)
251 {
252 	struct prison *pr;
253 
254 	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
255 	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
256 
257 	pr = cred->cr_prison;
258 	if (!(pr->pr_flags & PR_IP6))
259 		return (0);
260 	mtx_lock(&pr->pr_mtx);
261 	if (!(pr->pr_flags & PR_IP6)) {
262 		mtx_unlock(&pr->pr_mtx);
263 		return (0);
264 	}
265 	if (pr->pr_addrs[PR_INET6] == NULL) {
266 		mtx_unlock(&pr->pr_mtx);
267 		return (EAFNOSUPPORT);
268 	}
269 
270 	if (IN6_IS_ADDR_LOOPBACK(ia6) &&
271             prison_check_ip6_locked(pr, ia6) == EADDRNOTAVAIL) {
272 		prison_bcopy_primary_ip6(pr, ia6);
273 		mtx_unlock(&pr->pr_mtx);
274 		return (0);
275 	}
276 
277 	/*
278 	 * Return success because nothing had to be changed.
279 	 */
280 	mtx_unlock(&pr->pr_mtx);
281 	return (0);
282 }
283 
284 /*
285  * Check if given address belongs to the jail referenced by cred/prison.
286  *
287  * Returns 0 if address belongs to jail,
288  * EADDRNOTAVAIL if the address doesn't belong to the jail.
289  */
290 int
prison_check_ip6_locked(const struct prison * pr,const struct in6_addr * ia6)291 prison_check_ip6_locked(const struct prison *pr, const struct in6_addr *ia6)
292 {
293 
294 	if (!(pr->pr_flags & PR_IP6))
295 		return (0);
296 
297 	return (prison_ip_check(pr, PR_INET6, ia6));
298 }
299 
300 int
prison_check_ip6(const struct ucred * cred,const struct in6_addr * ia6)301 prison_check_ip6(const struct ucred *cred, const struct in6_addr *ia6)
302 {
303 	struct prison *pr;
304 	int error;
305 
306 	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
307 	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
308 
309 	pr = cred->cr_prison;
310 	if (!(pr->pr_flags & PR_IP6))
311 		return (0);
312 	mtx_lock(&pr->pr_mtx);
313 	if (!(pr->pr_flags & PR_IP6)) {
314 		mtx_unlock(&pr->pr_mtx);
315 		return (0);
316 	}
317 	if (pr->pr_addrs[PR_INET6] == NULL) {
318 		mtx_unlock(&pr->pr_mtx);
319 		return (EAFNOSUPPORT);
320 	}
321 
322 	error = prison_check_ip6_locked(pr, ia6);
323 	mtx_unlock(&pr->pr_mtx);
324 	return (error);
325 }
326