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