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__FBSDID("$FreeBSD: stable/11/sys/netinet6/in6_jail.c 316944 2017-04-14 22:02:08Z smh $");
31
32#include "opt_compat.h"
33#include "opt_ddb.h"
34#include "opt_inet.h"
35#include "opt_inet6.h"
36
37#include <sys/param.h>
38#include <sys/types.h>
39#include <sys/kernel.h>
40#include <sys/systm.h>
41#include <sys/errno.h>
42#include <sys/sysproto.h>
43#include <sys/malloc.h>
44#include <sys/osd.h>
45#include <sys/priv.h>
46#include <sys/proc.h>
47#include <sys/taskqueue.h>
48#include <sys/fcntl.h>
49#include <sys/jail.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/racct.h>
53#include <sys/refcount.h>
54#include <sys/sx.h>
55#include <sys/sysent.h>
56#include <sys/namei.h>
57#include <sys/mount.h>
58#include <sys/queue.h>
59#include <sys/socket.h>
60#include <sys/syscallsubr.h>
61#include <sys/sysctl.h>
62#include <sys/vnode.h>
63
64#include <net/if.h>
65#include <net/vnet.h>
66
67#include <netinet/in.h>
68
69int
70prison_qcmp_v6(const void *ip1, const void *ip2)
71{
72	const struct in6_addr *ia6a, *ia6b;
73	int i, rc;
74
75	ia6a = (const struct in6_addr *)ip1;
76	ia6b = (const struct in6_addr *)ip2;
77
78	rc = 0;
79	for (i = 0; rc == 0 && i < sizeof(struct in6_addr); i++) {
80		if (ia6a->s6_addr[i] > ia6b->s6_addr[i])
81			rc = 1;
82		else if (ia6a->s6_addr[i] < ia6b->s6_addr[i])
83			rc = -1;
84	}
85	return (rc);
86}
87
88int
89prison_restrict_ip6(struct prison *pr, struct in6_addr *newip6)
90{
91	int ii, ij, used;
92	struct prison *ppr;
93
94	ppr = pr->pr_parent;
95	if (!(pr->pr_flags & PR_IP6_USER)) {
96		/* This has no user settings, so just copy the parent's list. */
97		if (pr->pr_ip6s < ppr->pr_ip6s) {
98			/*
99			 * There's no room for the parent's list.  Use the
100			 * new list buffer, which is assumed to be big enough
101			 * (if it was passed).  If there's no buffer, try to
102			 * allocate one.
103			 */
104			used = 1;
105			if (newip6 == NULL) {
106				newip6 = malloc(ppr->pr_ip6s * sizeof(*newip6),
107				    M_PRISON, M_NOWAIT);
108				if (newip6 != NULL)
109					used = 0;
110			}
111			if (newip6 != NULL) {
112				bcopy(ppr->pr_ip6, newip6,
113				    ppr->pr_ip6s * sizeof(*newip6));
114				free(pr->pr_ip6, M_PRISON);
115				pr->pr_ip6 = newip6;
116				pr->pr_ip6s = ppr->pr_ip6s;
117			}
118			return (used);
119		}
120		pr->pr_ip6s = ppr->pr_ip6s;
121		if (pr->pr_ip6s > 0)
122			bcopy(ppr->pr_ip6, pr->pr_ip6,
123			    pr->pr_ip6s * sizeof(*newip6));
124		else if (pr->pr_ip6 != NULL) {
125			free(pr->pr_ip6, M_PRISON);
126			pr->pr_ip6 = NULL;
127		}
128	} else if (pr->pr_ip6s > 0) {
129		/* Remove addresses that aren't in the parent. */
130		for (ij = 0; ij < ppr->pr_ip6s; ij++)
131			if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0],
132			    &ppr->pr_ip6[ij]))
133				break;
134		if (ij < ppr->pr_ip6s)
135			ii = 1;
136		else {
137			bcopy(pr->pr_ip6 + 1, pr->pr_ip6,
138			    --pr->pr_ip6s * sizeof(*pr->pr_ip6));
139			ii = 0;
140		}
141		for (ij = 1; ii < pr->pr_ip6s; ) {
142			if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[ii],
143			    &ppr->pr_ip6[0])) {
144				ii++;
145				continue;
146			}
147			switch (ij >= ppr->pr_ip6s ? -1 :
148				prison_qcmp_v6(&pr->pr_ip6[ii], &ppr->pr_ip6[ij])) {
149			case -1:
150				bcopy(pr->pr_ip6 + ii + 1, pr->pr_ip6 + ii,
151				    (--pr->pr_ip6s - ii) * sizeof(*pr->pr_ip6));
152				break;
153			case 0:
154				ii++;
155				ij++;
156				break;
157			case 1:
158				ij++;
159				break;
160			}
161		}
162		if (pr->pr_ip6s == 0) {
163			free(pr->pr_ip6, M_PRISON);
164			pr->pr_ip6 = NULL;
165		}
166	}
167	return 0;
168}
169
170/*
171 * Pass back primary IPv6 address for this jail.
172 *
173 * If not restricted return success but do not alter the address.  Caller has
174 * to make sure to initialize it correctly (e.g. IN6ADDR_ANY_INIT).
175 *
176 * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
177 */
178int
179prison_get_ip6(struct ucred *cred, struct in6_addr *ia6)
180{
181	struct prison *pr;
182
183	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
184	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
185
186	pr = cred->cr_prison;
187	if (!(pr->pr_flags & PR_IP6))
188		return (0);
189	mtx_lock(&pr->pr_mtx);
190	if (!(pr->pr_flags & PR_IP6)) {
191		mtx_unlock(&pr->pr_mtx);
192		return (0);
193	}
194	if (pr->pr_ip6 == NULL) {
195		mtx_unlock(&pr->pr_mtx);
196		return (EAFNOSUPPORT);
197	}
198
199	bcopy(&pr->pr_ip6[0], ia6, sizeof(struct in6_addr));
200	mtx_unlock(&pr->pr_mtx);
201	return (0);
202}
203
204/*
205 * Return 1 if we should do proper source address selection or are not jailed.
206 * We will return 0 if we should bypass source address selection in favour
207 * of the primary jail IPv6 address. Only in this case *ia will be updated and
208 * returned in NBO.
209 * Return EAFNOSUPPORT, in case this jail does not allow IPv6.
210 */
211int
212prison_saddrsel_ip6(struct ucred *cred, struct in6_addr *ia6)
213{
214	struct prison *pr;
215	struct in6_addr lia6;
216	int error;
217
218	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
219	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
220
221	if (!jailed(cred))
222		return (1);
223
224	pr = cred->cr_prison;
225	if (pr->pr_flags & PR_IP6_SADDRSEL)
226		return (1);
227
228	lia6 = in6addr_any;
229	error = prison_get_ip6(cred, &lia6);
230	if (error)
231		return (error);
232	if (IN6_IS_ADDR_UNSPECIFIED(&lia6))
233		return (1);
234
235	bcopy(&lia6, ia6, sizeof(struct in6_addr));
236	return (0);
237}
238
239/*
240 * Return true if pr1 and pr2 have the same IPv6 address restrictions.
241 */
242int
243prison_equal_ip6(struct prison *pr1, struct prison *pr2)
244{
245
246	if (pr1 == pr2)
247		return (1);
248
249	while (pr1 != &prison0 &&
250#ifdef VIMAGE
251	       !(pr1->pr_flags & PR_VNET) &&
252#endif
253	       !(pr1->pr_flags & PR_IP6_USER))
254		pr1 = pr1->pr_parent;
255	while (pr2 != &prison0 &&
256#ifdef VIMAGE
257	       !(pr2->pr_flags & PR_VNET) &&
258#endif
259	       !(pr2->pr_flags & PR_IP6_USER))
260		pr2 = pr2->pr_parent;
261	return (pr1 == pr2);
262}
263
264/*
265 * Make sure our (source) address is set to something meaningful to this jail.
266 *
267 * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0)
268 * when needed while binding.
269 *
270 * Returns 0 if jail doesn't restrict IPv6 or if address belongs to jail,
271 * EADDRNOTAVAIL if the address doesn't belong, or EAFNOSUPPORT if the jail
272 * doesn't allow IPv6.
273 */
274int
275prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only)
276{
277	struct prison *pr;
278	int error;
279
280	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
281	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
282
283	pr = cred->cr_prison;
284	if (!(pr->pr_flags & PR_IP6))
285		return (0);
286	mtx_lock(&pr->pr_mtx);
287	if (!(pr->pr_flags & PR_IP6)) {
288		mtx_unlock(&pr->pr_mtx);
289		return (0);
290	}
291	if (pr->pr_ip6 == NULL) {
292		mtx_unlock(&pr->pr_mtx);
293		return (EAFNOSUPPORT);
294	}
295
296	if (IN6_IS_ADDR_UNSPECIFIED(ia6)) {
297		/*
298		 * In case there is only 1 IPv6 address, and v6only is true,
299		 * then bind directly.
300		 */
301		if (v6only != 0 && pr->pr_ip6s == 1)
302			bcopy(&pr->pr_ip6[0], ia6, sizeof(struct in6_addr));
303		mtx_unlock(&pr->pr_mtx);
304		return (0);
305	}
306
307	error = prison_check_ip6_locked(pr, ia6);
308	if (error == EADDRNOTAVAIL && IN6_IS_ADDR_LOOPBACK(ia6)) {
309		bcopy(&pr->pr_ip6[0], ia6, sizeof(struct in6_addr));
310		error = 0;
311	}
312
313	mtx_unlock(&pr->pr_mtx);
314	return (error);
315}
316
317/*
318 * Rewrite destination address in case we will connect to loopback address.
319 *
320 * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
321 */
322int
323prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6)
324{
325	struct prison *pr;
326
327	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
328	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
329
330	pr = cred->cr_prison;
331	if (!(pr->pr_flags & PR_IP6))
332		return (0);
333	mtx_lock(&pr->pr_mtx);
334	if (!(pr->pr_flags & PR_IP6)) {
335		mtx_unlock(&pr->pr_mtx);
336		return (0);
337	}
338	if (pr->pr_ip6 == NULL) {
339		mtx_unlock(&pr->pr_mtx);
340		return (EAFNOSUPPORT);
341	}
342
343	if (IN6_IS_ADDR_LOOPBACK(ia6) &&
344            prison_check_ip6_locked(pr, ia6) == EADDRNOTAVAIL) {
345		bcopy(&pr->pr_ip6[0], ia6, sizeof(struct in6_addr));
346		mtx_unlock(&pr->pr_mtx);
347		return (0);
348	}
349
350	/*
351	 * Return success because nothing had to be changed.
352	 */
353	mtx_unlock(&pr->pr_mtx);
354	return (0);
355}
356
357/*
358 * Check if given address belongs to the jail referenced by cred/prison.
359 *
360 * Returns 0 if address belongs to jail,
361 * EADDRNOTAVAIL if the address doesn't belong to the jail.
362 */
363int
364prison_check_ip6_locked(const struct prison *pr, const struct in6_addr *ia6)
365{
366	int i, a, z, d;
367
368	/*
369	 * Check the primary IP.
370	 */
371	if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6))
372		return (0);
373
374	/*
375	 * All the other IPs are sorted so we can do a binary search.
376	 */
377	a = 0;
378	z = pr->pr_ip6s - 2;
379	while (a <= z) {
380		i = (a + z) / 2;
381		d = prison_qcmp_v6(&pr->pr_ip6[i+1], ia6);
382		if (d > 0)
383			z = i - 1;
384		else if (d < 0)
385			a = i + 1;
386		else
387			return (0);
388	}
389
390	return (EADDRNOTAVAIL);
391}
392
393int
394prison_check_ip6(const struct ucred *cred, const struct in6_addr *ia6)
395{
396	struct prison *pr;
397	int error;
398
399	KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
400	KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
401
402	pr = cred->cr_prison;
403	if (!(pr->pr_flags & PR_IP6))
404		return (0);
405	mtx_lock(&pr->pr_mtx);
406	if (!(pr->pr_flags & PR_IP6)) {
407		mtx_unlock(&pr->pr_mtx);
408		return (0);
409	}
410	if (pr->pr_ip6 == NULL) {
411		mtx_unlock(&pr->pr_mtx);
412		return (EAFNOSUPPORT);
413	}
414
415	error = prison_check_ip6_locked(pr, ia6);
416	mtx_unlock(&pr->pr_mtx);
417	return (error);
418}
419