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
65static void
66prison_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
72int
73prison_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
91bool
92prison_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 */
107int
108prison_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 */
140bool
141prison_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 */
169bool
170prison_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 */
201int
202prison_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 */
249int
250prison_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 */
290int
291prison_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
300int
301prison_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