xref: /freebsd/sys/security/mac/mac_inet.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*-
2  * Copyright (c) 1999-2002, 2007 Robert N. M. Watson
3  * Copyright (c) 2001 Ilmar S. Habibulin
4  * Copyright (c) 2001-2004 Networks Associates Technology, Inc.
5  * Copyright (c) 2006 SPARTA, Inc.
6  * All rights reserved.
7  *
8  * This software was developed by Robert Watson and Ilmar Habibulin for the
9  * TrustedBSD Project.
10  *
11  * This software was developed for the FreeBSD Project in part by Network
12  * Associates Laboratories, the Security Research Division of Network
13  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
14  * as part of the DARPA CHATS research program.
15  *
16  * This software was enhanced by SPARTA ISSO under SPAWAR contract
17  * N66001-04-C-6019 ("SEFOS").
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  * 1. Redistributions of source code must retain the above copyright
23  *    notice, this list of conditions and the following disclaimer.
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in the
26  *    documentation and/or other materials provided with the distribution.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  */
40 
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43 
44 #include "opt_mac.h"
45 
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/lock.h>
49 #include <sys/malloc.h>
50 #include <sys/mutex.h>
51 #include <sys/sbuf.h>
52 #include <sys/systm.h>
53 #include <sys/mount.h>
54 #include <sys/file.h>
55 #include <sys/namei.h>
56 #include <sys/protosw.h>
57 #include <sys/socket.h>
58 #include <sys/socketvar.h>
59 #include <sys/sysctl.h>
60 
61 #include <net/if.h>
62 #include <net/if_var.h>
63 
64 #include <netinet/in.h>
65 #include <netinet/in_pcb.h>
66 #include <netinet/ip_var.h>
67 
68 #include <security/mac/mac_framework.h>
69 #include <security/mac/mac_internal.h>
70 #include <security/mac/mac_policy.h>
71 
72 static struct label *
73 mac_inpcb_label_alloc(int flag)
74 {
75 	struct label *label;
76 	int error;
77 
78 	label = mac_labelzone_alloc(flag);
79 	if (label == NULL)
80 		return (NULL);
81 	MAC_CHECK(inpcb_init_label, label, flag);
82 	if (error) {
83 		MAC_PERFORM(inpcb_destroy_label, label);
84 		mac_labelzone_free(label);
85 		return (NULL);
86 	}
87 	return (label);
88 }
89 
90 int
91 mac_inpcb_init(struct inpcb *inp, int flag)
92 {
93 
94 	inp->inp_label = mac_inpcb_label_alloc(flag);
95 	if (inp->inp_label == NULL)
96 		return (ENOMEM);
97 	return (0);
98 }
99 
100 static struct label *
101 mac_ipq_label_alloc(int flag)
102 {
103 	struct label *label;
104 	int error;
105 
106 	label = mac_labelzone_alloc(flag);
107 	if (label == NULL)
108 		return (NULL);
109 
110 	MAC_CHECK(ipq_init_label, label, flag);
111 	if (error) {
112 		MAC_PERFORM(ipq_destroy_label, label);
113 		mac_labelzone_free(label);
114 		return (NULL);
115 	}
116 	return (label);
117 }
118 
119 int
120 mac_ipq_init(struct ipq *ipq, int flag)
121 {
122 
123 	ipq->ipq_label = mac_ipq_label_alloc(flag);
124 	if (ipq->ipq_label == NULL)
125 		return (ENOMEM);
126 	return (0);
127 }
128 
129 static void
130 mac_inpcb_label_free(struct label *label)
131 {
132 
133 	MAC_PERFORM(inpcb_destroy_label, label);
134 	mac_labelzone_free(label);
135 }
136 
137 void
138 mac_inpcb_destroy(struct inpcb *inp)
139 {
140 
141 	mac_inpcb_label_free(inp->inp_label);
142 	inp->inp_label = NULL;
143 }
144 
145 static void
146 mac_ipq_label_free(struct label *label)
147 {
148 
149 	MAC_PERFORM(ipq_destroy_label, label);
150 	mac_labelzone_free(label);
151 }
152 
153 void
154 mac_ipq_destroy(struct ipq *ipq)
155 {
156 
157 	mac_ipq_label_free(ipq->ipq_label);
158 	ipq->ipq_label = NULL;
159 }
160 
161 void
162 mac_inpcb_create(struct socket *so, struct inpcb *inp)
163 {
164 
165 	MAC_PERFORM(inpcb_create, so, so->so_label, inp, inp->inp_label);
166 }
167 
168 void
169 mac_ipq_reassemble(struct ipq *ipq, struct mbuf *m)
170 {
171 	struct label *label;
172 
173 	label = mac_mbuf_to_label(m);
174 
175 	MAC_PERFORM(ipq_reassemble, ipq, ipq->ipq_label, m, label);
176 }
177 
178 void
179 mac_netinet_fragment(struct mbuf *m, struct mbuf *frag)
180 {
181 	struct label *mlabel, *fraglabel;
182 
183 	mlabel = mac_mbuf_to_label(m);
184 	fraglabel = mac_mbuf_to_label(frag);
185 
186 	MAC_PERFORM(netinet_fragment, m, mlabel, frag, fraglabel);
187 }
188 
189 void
190 mac_ipq_create(struct mbuf *m, struct ipq *ipq)
191 {
192 	struct label *label;
193 
194 	label = mac_mbuf_to_label(m);
195 
196 	MAC_PERFORM(ipq_create, m, label, ipq, ipq->ipq_label);
197 }
198 
199 void
200 mac_inpcb_create_mbuf(struct inpcb *inp, struct mbuf *m)
201 {
202 	struct label *mlabel;
203 
204 	INP_LOCK_ASSERT(inp);
205 	mlabel = mac_mbuf_to_label(m);
206 
207 	MAC_PERFORM(inpcb_create_mbuf, inp, inp->inp_label, m, mlabel);
208 }
209 
210 int
211 mac_ipq_match(struct mbuf *m, struct ipq *ipq)
212 {
213 	struct label *label;
214 	int result;
215 
216 	label = mac_mbuf_to_label(m);
217 
218 	result = 1;
219 	MAC_BOOLEAN(ipq_match, &&, m, label, ipq, ipq->ipq_label);
220 
221 	return (result);
222 }
223 
224 void
225 mac_netinet_arp_send(struct ifnet *ifp, struct mbuf *m)
226 {
227 	struct label *mlabel;
228 
229 	mlabel = mac_mbuf_to_label(m);
230 
231 	MAC_IFNET_LOCK(ifp);
232 	MAC_PERFORM(netinet_arp_send, ifp, ifp->if_label, m, mlabel);
233 	MAC_IFNET_UNLOCK(ifp);
234 }
235 
236 void
237 mac_netinet_icmp_reply(struct mbuf *mrecv, struct mbuf *msend)
238 {
239 	struct label *mrecvlabel, *msendlabel;
240 
241 	mrecvlabel = mac_mbuf_to_label(mrecv);
242 	msendlabel = mac_mbuf_to_label(msend);
243 
244 	MAC_PERFORM(netinet_icmp_reply, mrecv, mrecvlabel, msend,
245 	    msendlabel);
246 }
247 
248 void
249 mac_netinet_icmp_replyinplace(struct mbuf *m)
250 {
251 	struct label *label;
252 
253 	label = mac_mbuf_to_label(m);
254 
255 	MAC_PERFORM(netinet_icmp_replyinplace, m, label);
256 }
257 
258 void
259 mac_netinet_igmp_send(struct ifnet *ifp, struct mbuf *m)
260 {
261 	struct label *mlabel;
262 
263 	mlabel = mac_mbuf_to_label(m);
264 
265 	MAC_IFNET_LOCK(ifp);
266 	MAC_PERFORM(netinet_igmp_send, ifp, ifp->if_label, m, mlabel);
267 	MAC_IFNET_UNLOCK(ifp);
268 }
269 
270 void
271 mac_netinet_tcp_reply(struct mbuf *m)
272 {
273 	struct label *label;
274 
275 	label = mac_mbuf_to_label(m);
276 
277 	MAC_PERFORM(netinet_tcp_reply, m, label);
278 }
279 
280 void
281 mac_ipq_update(struct mbuf *m, struct ipq *ipq)
282 {
283 	struct label *label;
284 
285 	label = mac_mbuf_to_label(m);
286 
287 	MAC_PERFORM(ipq_update, m, label, ipq, ipq->ipq_label);
288 }
289 
290 int
291 mac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m)
292 {
293 	struct label *label;
294 	int error;
295 
296 	M_ASSERTPKTHDR(m);
297 
298 	label = mac_mbuf_to_label(m);
299 
300 	MAC_CHECK(inpcb_check_deliver, inp, inp->inp_label, m, label);
301 
302 	return (error);
303 }
304 
305 void
306 mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp)
307 {
308 
309 	INP_LOCK_ASSERT(inp);
310 	SOCK_LOCK_ASSERT(so);
311 	MAC_PERFORM(inpcb_sosetlabel, so, so->so_label, inp, inp->inp_label);
312 }
313 
314 void
315 mac_netinet_firewall_reply(struct mbuf *mrecv, struct mbuf *msend)
316 {
317 	struct label *mrecvlabel, *msendlabel;
318 
319 	M_ASSERTPKTHDR(mrecv);
320 	M_ASSERTPKTHDR(msend);
321 
322 	mrecvlabel = mac_mbuf_to_label(mrecv);
323 	msendlabel = mac_mbuf_to_label(msend);
324 
325 	MAC_PERFORM(netinet_firewall_reply, mrecv, mrecvlabel, msend,
326 	    msendlabel);
327 }
328 
329 void
330 mac_netinet_firewall_send(struct mbuf *m)
331 {
332 	struct label *label;
333 
334 	M_ASSERTPKTHDR(m);
335 	label = mac_mbuf_to_label(m);
336 	MAC_PERFORM(netinet_firewall_send, m, label);
337 }
338 
339 /*
340  * These functions really should be referencing the syncache structure
341  * instead of the label.  However, due to some of the complexities associated
342  * with exposing this syncache structure we operate directly on it's label
343  * pointer.  This should be OK since we aren't making any access control
344  * decisions within this code directly, we are merely allocating and copying
345  * label storage so we can properly initialize mbuf labels for any packets
346  * the syncache code might create.
347  */
348 void
349 mac_syncache_destroy(struct label **label)
350 {
351 
352 	MAC_PERFORM(syncache_destroy_label, *label);
353 	mac_labelzone_free(*label);
354 	*label = NULL;
355 }
356 
357 int
358 mac_syncache_init(struct label **label)
359 {
360 	int error;
361 
362 	*label = mac_labelzone_alloc(M_NOWAIT);
363 	if (*label == NULL)
364 		return (ENOMEM);
365 	/*
366 	 * Since we are holding the inpcb locks the policy can not allocate
367 	 * policy specific label storage using M_WAITOK.  So we need to do a
368 	 * MAC_CHECK instead of the typical MAC_PERFORM so we can propagate
369 	 * allocation failures back to the syncache code.
370 	 */
371 	MAC_CHECK(syncache_init_label, *label, M_NOWAIT);
372 	return (error);
373 }
374 
375 void
376 mac_syncache_create(struct label *label, struct inpcb *inp)
377 {
378 
379 	INP_LOCK_ASSERT(inp);
380 	MAC_PERFORM(syncache_create, label, inp);
381 }
382 
383 void
384 mac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m)
385 {
386 	struct label *mlabel;
387 
388 	M_ASSERTPKTHDR(m);
389 	mlabel = mac_mbuf_to_label(m);
390 	MAC_PERFORM(syncache_create_mbuf, sc_label, m, mlabel);
391 }
392