xref: /freebsd/sys/security/mac/mac_net.c (revision a557af222b70694470f63e2a0f1bf58c9dcc73fd)
17bc82500SRobert Watson /*-
27bc82500SRobert Watson  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
37bc82500SRobert Watson  * Copyright (c) 2001 Ilmar S. Habibulin
42d3db0b8SRobert Watson  * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
57bc82500SRobert Watson  * All rights reserved.
67bc82500SRobert Watson  *
77bc82500SRobert Watson  * This software was developed by Robert Watson and Ilmar Habibulin for the
87bc82500SRobert Watson  * TrustedBSD Project.
97bc82500SRobert Watson  *
106201265bSRobert Watson  * This software was developed for the FreeBSD Project in part by Network
116201265bSRobert Watson  * Associates Laboratories, the Security Research Division of Network
126201265bSRobert Watson  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
136201265bSRobert Watson  * as part of the DARPA CHATS research program.
147bc82500SRobert Watson  *
157bc82500SRobert Watson  * Redistribution and use in source and binary forms, with or without
167bc82500SRobert Watson  * modification, are permitted provided that the following conditions
177bc82500SRobert Watson  * are met:
187bc82500SRobert Watson  * 1. Redistributions of source code must retain the above copyright
197bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer.
207bc82500SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
217bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
227bc82500SRobert Watson  *    documentation and/or other materials provided with the distribution.
237bc82500SRobert Watson  *
247bc82500SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
257bc82500SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
267bc82500SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
277bc82500SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
287bc82500SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
297bc82500SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
307bc82500SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
317bc82500SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
327bc82500SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
337bc82500SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
347bc82500SRobert Watson  * SUCH DAMAGE.
357bc82500SRobert Watson  */
36677b542eSDavid E. O'Brien 
37677b542eSDavid E. O'Brien #include <sys/cdefs.h>
38677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
39677b542eSDavid E. O'Brien 
407bc82500SRobert Watson #include "opt_mac.h"
41f9d0d524SRobert Watson 
427bc82500SRobert Watson #include <sys/param.h>
4395fab37eSRobert Watson #include <sys/kernel.h>
4495fab37eSRobert Watson #include <sys/lock.h>
45b656366bSBruce Evans #include <sys/malloc.h>
4695fab37eSRobert Watson #include <sys/mutex.h>
4795fab37eSRobert Watson #include <sys/mac.h>
48f51e5803SRobert Watson #include <sys/sbuf.h>
4995fab37eSRobert Watson #include <sys/systm.h>
5095fab37eSRobert Watson #include <sys/mount.h>
5195fab37eSRobert Watson #include <sys/file.h>
5295fab37eSRobert Watson #include <sys/namei.h>
53a557af22SRobert Watson #include <sys/protosw.h>
5495fab37eSRobert Watson #include <sys/socket.h>
5595fab37eSRobert Watson #include <sys/socketvar.h>
5695fab37eSRobert Watson #include <sys/sysctl.h>
5795fab37eSRobert Watson 
5895fab37eSRobert Watson #include <sys/mac_policy.h>
5995fab37eSRobert Watson 
6095fab37eSRobert Watson #include <net/bpfdesc.h>
6195fab37eSRobert Watson #include <net/if.h>
6295fab37eSRobert Watson #include <net/if_var.h>
6395fab37eSRobert Watson 
6495fab37eSRobert Watson #include <netinet/in.h>
65a557af22SRobert Watson #include <netinet/in_pcb.h>
6695fab37eSRobert Watson #include <netinet/ip_var.h>
6795fab37eSRobert Watson 
6828e65e3dSRobert Watson #include <security/mac/mac_internal.h>
69a3df768bSRobert Watson 
7095fab37eSRobert Watson static int	mac_enforce_network = 1;
7195fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
7295fab37eSRobert Watson     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
7395fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
7495fab37eSRobert Watson 
7595fab37eSRobert Watson static int	mac_enforce_socket = 1;
7695fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
7795fab37eSRobert Watson     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
7895fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
7995fab37eSRobert Watson 
80f050add5SRobert Watson #ifdef MAC_DEBUG
8128e65e3dSRobert Watson static unsigned int nmacmbufs, nmacifnets, nmacbpfdescs, nmacsockets,
82a557af22SRobert Watson     nmacinpcbs, nmacipqs;
838d8d5ea8SRobert Watson 
84b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
8595fab37eSRobert Watson     &nmacmbufs, 0, "number of mbufs in use");
86b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
8795fab37eSRobert Watson     &nmacifnets, 0, "number of ifnets in use");
88a557af22SRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, inpcbs, CTLFLAG_RD,
89a557af22SRobert Watson     &nmacinpcbs, 0, "number of inpcbs in use");
90b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
9195fab37eSRobert Watson     &nmacipqs, 0, "number of ipqs in use");
92b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
9395fab37eSRobert Watson     &nmacbpfdescs, 0, "number of bpfdescs in use");
94b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
9595fab37eSRobert Watson     &nmacsockets, 0, "number of sockets in use");
96f050add5SRobert Watson #endif
9795fab37eSRobert Watson 
9810eeb10cSRobert Watson static struct label *
9910eeb10cSRobert Watson mbuf_to_label(struct mbuf *mbuf)
10010eeb10cSRobert Watson {
101225bff6fSRobert Watson 	struct m_tag *tag;
10210eeb10cSRobert Watson 	struct label *label;
10310eeb10cSRobert Watson 
104225bff6fSRobert Watson 	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
105225bff6fSRobert Watson 	label = (struct label *)(tag+1);
10610eeb10cSRobert Watson 
10710eeb10cSRobert Watson 	return (label);
10810eeb10cSRobert Watson }
10910eeb10cSRobert Watson 
110eca8a663SRobert Watson static struct label *
111eca8a663SRobert Watson mac_bpfdesc_label_alloc(void)
112eca8a663SRobert Watson {
113eca8a663SRobert Watson 	struct label *label;
114eca8a663SRobert Watson 
115eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
116eca8a663SRobert Watson 	MAC_PERFORM(init_bpfdesc_label, label);
117eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacbpfdescs);
118eca8a663SRobert Watson 	return (label);
119eca8a663SRobert Watson }
120eca8a663SRobert Watson 
12108bcdc58SRobert Watson void
12287807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d)
12308bcdc58SRobert Watson {
12408bcdc58SRobert Watson 
125eca8a663SRobert Watson 	bpf_d->bd_label = mac_bpfdesc_label_alloc();
12608bcdc58SRobert Watson }
12708bcdc58SRobert Watson 
128eca8a663SRobert Watson static struct label *
129eca8a663SRobert Watson mac_ifnet_label_alloc(void)
130f7b951a8SRobert Watson {
131eca8a663SRobert Watson 	struct label *label;
132f7b951a8SRobert Watson 
133eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
134f7b951a8SRobert Watson 	MAC_PERFORM(init_ifnet_label, label);
1358d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacifnets);
136eca8a663SRobert Watson 	return (label);
137f7b951a8SRobert Watson }
138f7b951a8SRobert Watson 
13908bcdc58SRobert Watson void
14008bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp)
14108bcdc58SRobert Watson {
14208bcdc58SRobert Watson 
143eca8a663SRobert Watson 	ifp->if_label = mac_ifnet_label_alloc();
144eca8a663SRobert Watson }
145eca8a663SRobert Watson 
146eca8a663SRobert Watson static struct label *
147a557af22SRobert Watson mac_inpcb_label_alloc(int flag)
148a557af22SRobert Watson {
149a557af22SRobert Watson 	struct label *label;
150a557af22SRobert Watson 	int error;
151a557af22SRobert Watson 
152a557af22SRobert Watson 	label = mac_labelzone_alloc(flag);
153a557af22SRobert Watson 	if (label == NULL)
154a557af22SRobert Watson 		return (NULL);
155a557af22SRobert Watson 	MAC_CHECK(init_inpcb_label, label, flag);
156a557af22SRobert Watson 	if (error) {
157a557af22SRobert Watson 		MAC_PERFORM(destroy_inpcb_label, label);
158a557af22SRobert Watson 		mac_labelzone_free(label);
159a557af22SRobert Watson 		return (NULL);
160a557af22SRobert Watson 	}
161a557af22SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacinpcbs);
162a557af22SRobert Watson 	return (label);
163a557af22SRobert Watson }
164a557af22SRobert Watson 
165a557af22SRobert Watson int
166a557af22SRobert Watson mac_init_inpcb(struct inpcb *inp, int flag)
167a557af22SRobert Watson {
168a557af22SRobert Watson 
169a557af22SRobert Watson 	inp->inp_label = mac_inpcb_label_alloc(flag);
170a557af22SRobert Watson 	if (inp->inp_label == NULL)
171a557af22SRobert Watson 		return (ENOMEM);
172a557af22SRobert Watson 	return (0);
173a557af22SRobert Watson }
174a557af22SRobert Watson 
175a557af22SRobert Watson static struct label *
176eca8a663SRobert Watson mac_ipq_label_alloc(int flag)
177eca8a663SRobert Watson {
178eca8a663SRobert Watson 	struct label *label;
179eca8a663SRobert Watson 	int error;
180eca8a663SRobert Watson 
181eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
182eca8a663SRobert Watson 	if (label == NULL)
183eca8a663SRobert Watson 		return (NULL);
184eca8a663SRobert Watson 
185eca8a663SRobert Watson 	MAC_CHECK(init_ipq_label, label, flag);
186eca8a663SRobert Watson 	if (error) {
187eca8a663SRobert Watson 		MAC_PERFORM(destroy_ipq_label, label);
188eca8a663SRobert Watson 		mac_labelzone_free(label);
189eca8a663SRobert Watson 		return (NULL);
190eca8a663SRobert Watson 	}
191eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacipqs);
192eca8a663SRobert Watson 	return (label);
19308bcdc58SRobert Watson }
19408bcdc58SRobert Watson 
1955e7ce478SRobert Watson int
1965e7ce478SRobert Watson mac_init_ipq(struct ipq *ipq, int flag)
19708bcdc58SRobert Watson {
19808bcdc58SRobert Watson 
199eca8a663SRobert Watson 	ipq->ipq_label = mac_ipq_label_alloc(flag);
200eca8a663SRobert Watson 	if (ipq->ipq_label == NULL)
201eca8a663SRobert Watson 		return (ENOMEM);
202eca8a663SRobert Watson 	return (0);
20308bcdc58SRobert Watson }
20408bcdc58SRobert Watson 
20587807196SRobert Watson int
206225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag)
20708bcdc58SRobert Watson {
208225bff6fSRobert Watson 	struct label *label;
2096d1a6a9aSRobert Watson 	int error;
21056c15412SRobert Watson 
211225bff6fSRobert Watson 	label = (struct label *) (tag + 1);
212225bff6fSRobert Watson 	mac_init_label(label);
21308bcdc58SRobert Watson 
2146d1a6a9aSRobert Watson 	MAC_CHECK(init_mbuf_label, label, flag);
21556c15412SRobert Watson 	if (error) {
216225bff6fSRobert Watson 		MAC_PERFORM(destroy_mbuf_label, label);
217225bff6fSRobert Watson 		mac_destroy_label(label);
2188d8d5ea8SRobert Watson 	} else {
2198d8d5ea8SRobert Watson 		MAC_DEBUG_COUNTER_INC(&nmacmbufs);
22056c15412SRobert Watson 	}
22156c15412SRobert Watson 	return (error);
22208bcdc58SRobert Watson }
22308bcdc58SRobert Watson 
224225bff6fSRobert Watson int
225225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag)
226225bff6fSRobert Watson {
227225bff6fSRobert Watson 	struct m_tag *tag;
228225bff6fSRobert Watson 	int error;
229225bff6fSRobert Watson 
230225bff6fSRobert Watson 	M_ASSERTPKTHDR(m);
231225bff6fSRobert Watson 
232225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
233225bff6fSRobert Watson 	/*
23419c3e120SRobert Watson 	 * If conditionally allocating mbuf labels, don't allocate unless
23519c3e120SRobert Watson 	 * they are required.
236225bff6fSRobert Watson 	 */
23719c3e120SRobert Watson 	if (!mac_labelmbufs)
23819c3e120SRobert Watson 		return (0);
239225bff6fSRobert Watson #endif
240225bff6fSRobert Watson 	tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
241225bff6fSRobert Watson 	    flag);
242225bff6fSRobert Watson 	if (tag == NULL)
243225bff6fSRobert Watson 		return (ENOMEM);
244225bff6fSRobert Watson 	error = mac_init_mbuf_tag(tag, flag);
245225bff6fSRobert Watson 	if (error) {
246225bff6fSRobert Watson 		m_tag_free(tag);
247225bff6fSRobert Watson 		return (error);
248225bff6fSRobert Watson 	}
249225bff6fSRobert Watson 	m_tag_prepend(m, tag);
250225bff6fSRobert Watson 	return (0);
251225bff6fSRobert Watson }
252225bff6fSRobert Watson 
253b0323ea3SRobert Watson struct label *
254eca8a663SRobert Watson mac_socket_label_alloc(int flag)
25508bcdc58SRobert Watson {
256eca8a663SRobert Watson 	struct label *label;
25783985c26SRobert Watson 	int error;
25808bcdc58SRobert Watson 
259eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
260eca8a663SRobert Watson 	if (label == NULL)
261eca8a663SRobert Watson 		return (NULL);
26283985c26SRobert Watson 
26383985c26SRobert Watson 	MAC_CHECK(init_socket_label, label, flag);
26483985c26SRobert Watson 	if (error) {
26583985c26SRobert Watson 		MAC_PERFORM(destroy_socket_label, label);
266eca8a663SRobert Watson 		mac_labelzone_free(label);
267eca8a663SRobert Watson 		return (NULL);
268eca8a663SRobert Watson 	}
2698d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacsockets);
270eca8a663SRobert Watson 	return (label);
27183985c26SRobert Watson }
27283985c26SRobert Watson 
273eca8a663SRobert Watson static struct label *
274eca8a663SRobert Watson mac_socket_peer_label_alloc(int flag)
27583985c26SRobert Watson {
276eca8a663SRobert Watson 	struct label *label;
27783985c26SRobert Watson 	int error;
27883985c26SRobert Watson 
279eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
280eca8a663SRobert Watson 	if (label == NULL)
281eca8a663SRobert Watson 		return (NULL);
28283985c26SRobert Watson 
28383985c26SRobert Watson 	MAC_CHECK(init_socket_peer_label, label, flag);
28483985c26SRobert Watson 	if (error) {
285bea2b56bSRobert Watson 		MAC_PERFORM(destroy_socket_peer_label, label);
286eca8a663SRobert Watson 		mac_labelzone_free(label);
287eca8a663SRobert Watson 		return (NULL);
28883985c26SRobert Watson 	}
289eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacsockets);
290eca8a663SRobert Watson 	return (label);
29183985c26SRobert Watson }
29283985c26SRobert Watson 
29383985c26SRobert Watson int
294eca8a663SRobert Watson mac_init_socket(struct socket *so, int flag)
29583985c26SRobert Watson {
29683985c26SRobert Watson 
297eca8a663SRobert Watson 	so->so_label = mac_socket_label_alloc(flag);
298eca8a663SRobert Watson 	if (so->so_label == NULL)
299eca8a663SRobert Watson 		return (ENOMEM);
300eca8a663SRobert Watson 	so->so_peerlabel = mac_socket_peer_label_alloc(flag);
301eca8a663SRobert Watson 	if (so->so_peerlabel == NULL) {
302eca8a663SRobert Watson 		mac_socket_label_free(so->so_label);
303eca8a663SRobert Watson 		so->so_label = NULL;
304eca8a663SRobert Watson 		return (ENOMEM);
305eca8a663SRobert Watson 	}
306eca8a663SRobert Watson 	return (0);
307eca8a663SRobert Watson }
30883985c26SRobert Watson 
309eca8a663SRobert Watson static void
310eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label)
311eca8a663SRobert Watson {
31283985c26SRobert Watson 
313eca8a663SRobert Watson 	MAC_PERFORM(destroy_bpfdesc_label, label);
314eca8a663SRobert Watson 	mac_labelzone_free(label);
315eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs);
31687807196SRobert Watson }
31787807196SRobert Watson 
318763bbd2fSRobert Watson void
31908bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d)
32008bcdc58SRobert Watson {
32108bcdc58SRobert Watson 
322eca8a663SRobert Watson 	mac_bpfdesc_label_free(bpf_d->bd_label);
323eca8a663SRobert Watson 	bpf_d->bd_label = NULL;
32408bcdc58SRobert Watson }
32508bcdc58SRobert Watson 
326f7b951a8SRobert Watson static void
327eca8a663SRobert Watson mac_ifnet_label_free(struct label *label)
328f7b951a8SRobert Watson {
329f7b951a8SRobert Watson 
330f7b951a8SRobert Watson 	MAC_PERFORM(destroy_ifnet_label, label);
331eca8a663SRobert Watson 	mac_labelzone_free(label);
3328d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacifnets);
333f7b951a8SRobert Watson }
334f7b951a8SRobert Watson 
33587807196SRobert Watson void
33687807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp)
33787807196SRobert Watson {
33887807196SRobert Watson 
339eca8a663SRobert Watson 	mac_ifnet_label_free(ifp->if_label);
340eca8a663SRobert Watson 	ifp->if_label = NULL;
341eca8a663SRobert Watson }
342eca8a663SRobert Watson 
343eca8a663SRobert Watson static void
344a557af22SRobert Watson mac_inpcb_label_free(struct label *label)
345a557af22SRobert Watson {
346a557af22SRobert Watson 
347a557af22SRobert Watson 	MAC_PERFORM(destroy_inpcb_label, label);
348a557af22SRobert Watson 	mac_labelzone_free(label);
349a557af22SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacinpcbs);
350a557af22SRobert Watson }
351a557af22SRobert Watson 
352a557af22SRobert Watson void
353a557af22SRobert Watson mac_destroy_inpcb(struct inpcb *inp)
354a557af22SRobert Watson {
355a557af22SRobert Watson 
356a557af22SRobert Watson 	mac_inpcb_label_free(inp->inp_label);
357a557af22SRobert Watson 	inp->inp_label = NULL;
358a557af22SRobert Watson }
359a557af22SRobert Watson 
360a557af22SRobert Watson static void
361eca8a663SRobert Watson mac_ipq_label_free(struct label *label)
362eca8a663SRobert Watson {
363eca8a663SRobert Watson 
364eca8a663SRobert Watson 	MAC_PERFORM(destroy_ipq_label, label);
365eca8a663SRobert Watson 	mac_labelzone_free(label);
366eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacipqs);
36787807196SRobert Watson }
36887807196SRobert Watson 
36987807196SRobert Watson void
37087807196SRobert Watson mac_destroy_ipq(struct ipq *ipq)
37187807196SRobert Watson {
37287807196SRobert Watson 
373eca8a663SRobert Watson 	mac_ipq_label_free(ipq->ipq_label);
374eca8a663SRobert Watson 	ipq->ipq_label = NULL;
37587807196SRobert Watson }
37687807196SRobert Watson 
37787807196SRobert Watson void
378225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag)
37987807196SRobert Watson {
380225bff6fSRobert Watson 	struct label *label;
38187807196SRobert Watson 
382225bff6fSRobert Watson 	label = (struct label *)(tag+1);
383225bff6fSRobert Watson 
384225bff6fSRobert Watson 	MAC_PERFORM(destroy_mbuf_label, label);
385225bff6fSRobert Watson 	mac_destroy_label(label);
3868d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacmbufs);
38708bcdc58SRobert Watson }
38808bcdc58SRobert Watson 
389b0323ea3SRobert Watson void
390eca8a663SRobert Watson mac_socket_label_free(struct label *label)
39183985c26SRobert Watson {
39283985c26SRobert Watson 
39383985c26SRobert Watson 	MAC_PERFORM(destroy_socket_label, label);
394eca8a663SRobert Watson 	mac_labelzone_free(label);
3958d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacsockets);
39683985c26SRobert Watson }
39783985c26SRobert Watson 
39883985c26SRobert Watson static void
399eca8a663SRobert Watson mac_socket_peer_label_free(struct label *label)
40083985c26SRobert Watson {
40183985c26SRobert Watson 
40283985c26SRobert Watson 	MAC_PERFORM(destroy_socket_peer_label, label);
403eca8a663SRobert Watson 	mac_labelzone_free(label);
404eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacsockets);
40583985c26SRobert Watson }
40683985c26SRobert Watson 
40787807196SRobert Watson void
40887807196SRobert Watson mac_destroy_socket(struct socket *socket)
40987807196SRobert Watson {
41087807196SRobert Watson 
411eca8a663SRobert Watson 	mac_socket_label_free(socket->so_label);
412eca8a663SRobert Watson 	socket->so_label = NULL;
413eca8a663SRobert Watson 	mac_socket_peer_label_free(socket->so_peerlabel);
414eca8a663SRobert Watson 	socket->so_peerlabel = NULL;
41508bcdc58SRobert Watson }
41608bcdc58SRobert Watson 
417763bbd2fSRobert Watson void
418225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
419225bff6fSRobert Watson {
420225bff6fSRobert Watson 	struct label *src_label, *dest_label;
421225bff6fSRobert Watson 
422225bff6fSRobert Watson 	src_label = (struct label *)(src+1);
423225bff6fSRobert Watson 	dest_label = (struct label *)(dest+1);
424225bff6fSRobert Watson 
425225bff6fSRobert Watson 	/*
426225bff6fSRobert Watson 	 * mac_init_mbuf_tag() is called on the target tag in
427225bff6fSRobert Watson 	 * m_tag_copy(), so we don't need to call it here.
428225bff6fSRobert Watson 	 */
429225bff6fSRobert Watson 	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
430225bff6fSRobert Watson }
431225bff6fSRobert Watson 
432b0323ea3SRobert Watson void
433b0323ea3SRobert Watson mac_copy_socket_label(struct label *src, struct label *dest)
434b0323ea3SRobert Watson {
435b0323ea3SRobert Watson 
436b0323ea3SRobert Watson 	MAC_PERFORM(copy_socket_label, src, dest);
437b0323ea3SRobert Watson }
438b0323ea3SRobert Watson 
43969bbb5b1SRobert Watson static int
440f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements,
44183b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
44269bbb5b1SRobert Watson {
44369bbb5b1SRobert Watson 	int error;
44469bbb5b1SRobert Watson 
445da77b2faSRobert Watson 	MAC_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
446f7b951a8SRobert Watson 
447f7b951a8SRobert Watson 	return (error);
448f7b951a8SRobert Watson }
449f7b951a8SRobert Watson 
450b0323ea3SRobert Watson int
451f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements,
45283b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
453f7b951a8SRobert Watson {
454f7b951a8SRobert Watson 	int error;
455f7b951a8SRobert Watson 
456da77b2faSRobert Watson 	MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
457f7b951a8SRobert Watson 
458f7b951a8SRobert Watson 	return (error);
459f7b951a8SRobert Watson }
460f7b951a8SRobert Watson 
461f7b951a8SRobert Watson static int
462f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements,
46383b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
464f7b951a8SRobert Watson {
465f7b951a8SRobert Watson 	int error;
466f7b951a8SRobert Watson 
467da77b2faSRobert Watson 	MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
468f7b951a8SRobert Watson 
469f7b951a8SRobert Watson 	return (error);
470f7b951a8SRobert Watson }
471f7b951a8SRobert Watson 
472f7b951a8SRobert Watson static int
473f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string)
474f7b951a8SRobert Watson {
475f7b951a8SRobert Watson 	int error;
476f7b951a8SRobert Watson 
477da77b2faSRobert Watson 	MAC_INTERNALIZE(ifnet, label, string);
478f7b951a8SRobert Watson 
479f7b951a8SRobert Watson 	return (error);
480f7b951a8SRobert Watson }
481f7b951a8SRobert Watson 
482b0323ea3SRobert Watson int
483f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string)
484f7b951a8SRobert Watson {
485f7b951a8SRobert Watson 	int error;
486f7b951a8SRobert Watson 
487da77b2faSRobert Watson 	MAC_INTERNALIZE(socket, label, string);
488f7b951a8SRobert Watson 
489f7b951a8SRobert Watson 	return (error);
490f7b951a8SRobert Watson }
491f7b951a8SRobert Watson 
49295fab37eSRobert Watson void
49395fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet)
49495fab37eSRobert Watson {
49595fab37eSRobert Watson 
496eca8a663SRobert Watson 	MAC_PERFORM(create_ifnet, ifnet, ifnet->if_label);
49795fab37eSRobert Watson }
49895fab37eSRobert Watson 
49995fab37eSRobert Watson void
500a557af22SRobert Watson mac_create_inpcb_from_socket(struct socket *so, struct inpcb *inp)
501a557af22SRobert Watson {
502a557af22SRobert Watson 
503a557af22SRobert Watson 	MAC_PERFORM(create_inpcb_from_socket, so, so->so_label, inp,
504a557af22SRobert Watson 	    inp->inp_label);
505a557af22SRobert Watson }
506a557af22SRobert Watson 
507a557af22SRobert Watson void
50895fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
50995fab37eSRobert Watson {
51095fab37eSRobert Watson 
511eca8a663SRobert Watson 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, bpf_d->bd_label);
51295fab37eSRobert Watson }
51395fab37eSRobert Watson 
51495fab37eSRobert Watson void
51595fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket)
51695fab37eSRobert Watson {
51795fab37eSRobert Watson 
518eca8a663SRobert Watson 	MAC_PERFORM(create_socket, cred, socket, socket->so_label);
51995fab37eSRobert Watson }
52095fab37eSRobert Watson 
52195fab37eSRobert Watson void
52295fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket,
52395fab37eSRobert Watson     struct socket *newsocket)
52495fab37eSRobert Watson {
52595fab37eSRobert Watson 
526eca8a663SRobert Watson 	MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label,
527eca8a663SRobert Watson 	    newsocket, newsocket->so_label);
52895fab37eSRobert Watson }
52995fab37eSRobert Watson 
53095fab37eSRobert Watson static void
53195fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket,
53295fab37eSRobert Watson     struct label *newlabel)
53395fab37eSRobert Watson {
53495fab37eSRobert Watson 
535eca8a663SRobert Watson 	MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel);
53695fab37eSRobert Watson }
53795fab37eSRobert Watson 
53895fab37eSRobert Watson void
53995fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
54095fab37eSRobert Watson {
54110eeb10cSRobert Watson 	struct label *label;
54295fab37eSRobert Watson 
54310eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
54410eeb10cSRobert Watson 
54510eeb10cSRobert Watson 	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
546eca8a663SRobert Watson 	    socket->so_peerlabel);
54795fab37eSRobert Watson }
54895fab37eSRobert Watson 
54995fab37eSRobert Watson void
55095fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket,
55195fab37eSRobert Watson     struct socket *newsocket)
55295fab37eSRobert Watson {
55395fab37eSRobert Watson 
55495fab37eSRobert Watson 	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
555eca8a663SRobert Watson 	    oldsocket->so_label, newsocket, newsocket->so_peerlabel);
55695fab37eSRobert Watson }
55795fab37eSRobert Watson 
55895fab37eSRobert Watson void
55995fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
56095fab37eSRobert Watson {
56110eeb10cSRobert Watson 	struct label *label;
56210eeb10cSRobert Watson 
56310eeb10cSRobert Watson 	label = mbuf_to_label(datagram);
56495fab37eSRobert Watson 
565eca8a663SRobert Watson 	MAC_PERFORM(create_datagram_from_ipq, ipq, ipq->ipq_label,
56610eeb10cSRobert Watson 	    datagram, label);
56795fab37eSRobert Watson }
56895fab37eSRobert Watson 
56995fab37eSRobert Watson void
57095fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
57195fab37eSRobert Watson {
57210eeb10cSRobert Watson 	struct label *datagramlabel, *fragmentlabel;
57395fab37eSRobert Watson 
57410eeb10cSRobert Watson 	datagramlabel = mbuf_to_label(datagram);
57510eeb10cSRobert Watson 	fragmentlabel = mbuf_to_label(fragment);
57610eeb10cSRobert Watson 
57710eeb10cSRobert Watson 	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
57810eeb10cSRobert Watson 	    fragmentlabel);
57995fab37eSRobert Watson }
58095fab37eSRobert Watson 
58195fab37eSRobert Watson void
58295fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
58395fab37eSRobert Watson {
58410eeb10cSRobert Watson 	struct label *label;
58595fab37eSRobert Watson 
58610eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
58710eeb10cSRobert Watson 
588eca8a663SRobert Watson 	MAC_PERFORM(create_ipq, fragment, label, ipq, ipq->ipq_label);
58995fab37eSRobert Watson }
59095fab37eSRobert Watson 
59195fab37eSRobert Watson void
59295fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
59395fab37eSRobert Watson {
59410eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
59595fab37eSRobert Watson 
59610eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
59710eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
59810eeb10cSRobert Watson 
59910eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
60010eeb10cSRobert Watson 	    newmbuflabel);
60195fab37eSRobert Watson }
60295fab37eSRobert Watson 
60395fab37eSRobert Watson void
60495fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
60595fab37eSRobert Watson {
60610eeb10cSRobert Watson 	struct label *label;
60710eeb10cSRobert Watson 
60810eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
60995fab37eSRobert Watson 
610eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, bpf_d->bd_label, mbuf,
61110eeb10cSRobert Watson 	    label);
61295fab37eSRobert Watson }
61395fab37eSRobert Watson 
61495fab37eSRobert Watson void
61595fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
61695fab37eSRobert Watson {
61710eeb10cSRobert Watson 	struct label *label;
61810eeb10cSRobert Watson 
61910eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
62095fab37eSRobert Watson 
621eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_linklayer, ifnet, ifnet->if_label, mbuf,
62210eeb10cSRobert Watson 	    label);
62395fab37eSRobert Watson }
62495fab37eSRobert Watson 
62595fab37eSRobert Watson void
62695fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
62795fab37eSRobert Watson {
62810eeb10cSRobert Watson 	struct label *label;
62910eeb10cSRobert Watson 
63010eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
63195fab37eSRobert Watson 
632eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, ifnet->if_label, mbuf,
63310eeb10cSRobert Watson 	    label);
63495fab37eSRobert Watson }
63595fab37eSRobert Watson 
63695fab37eSRobert Watson void
63795fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
63895fab37eSRobert Watson     struct mbuf *newmbuf)
63995fab37eSRobert Watson {
64010eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
64195fab37eSRobert Watson 
64210eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
64310eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
64410eeb10cSRobert Watson 
64510eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
646eca8a663SRobert Watson 	    ifnet, ifnet->if_label, newmbuf, newmbuflabel);
64795fab37eSRobert Watson }
64895fab37eSRobert Watson 
64995fab37eSRobert Watson void
65095fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
65195fab37eSRobert Watson {
65210eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
65395fab37eSRobert Watson 
65410eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
65510eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
65610eeb10cSRobert Watson 
65710eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
65810eeb10cSRobert Watson 	    newmbuflabel);
65995fab37eSRobert Watson }
66095fab37eSRobert Watson 
66195fab37eSRobert Watson int
66295fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
66395fab37eSRobert Watson {
66410eeb10cSRobert Watson 	struct label *label;
66595fab37eSRobert Watson 	int result;
66695fab37eSRobert Watson 
66710eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
66810eeb10cSRobert Watson 
66995fab37eSRobert Watson 	result = 1;
67010eeb10cSRobert Watson 	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
671eca8a663SRobert Watson 	    ipq->ipq_label);
67295fab37eSRobert Watson 
67395fab37eSRobert Watson 	return (result);
67495fab37eSRobert Watson }
67595fab37eSRobert Watson 
67695fab37eSRobert Watson void
677eb8c7f99SRobert Watson mac_reflect_mbuf_icmp(struct mbuf *m)
678eb8c7f99SRobert Watson {
679eb8c7f99SRobert Watson 	struct label *label;
680eb8c7f99SRobert Watson 
681eb8c7f99SRobert Watson 	label = mbuf_to_label(m);
682eb8c7f99SRobert Watson 
683eb8c7f99SRobert Watson 	MAC_PERFORM(reflect_mbuf_icmp, m, label);
684eb8c7f99SRobert Watson }
685eb8c7f99SRobert Watson void
686eb8c7f99SRobert Watson mac_reflect_mbuf_tcp(struct mbuf *m)
687eb8c7f99SRobert Watson {
688eb8c7f99SRobert Watson 	struct label *label;
689eb8c7f99SRobert Watson 
690eb8c7f99SRobert Watson 	label = mbuf_to_label(m);
691eb8c7f99SRobert Watson 
692eb8c7f99SRobert Watson 	MAC_PERFORM(reflect_mbuf_tcp, m, label);
693eb8c7f99SRobert Watson }
694eb8c7f99SRobert Watson 
695eb8c7f99SRobert Watson void
69695fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
69795fab37eSRobert Watson {
69810eeb10cSRobert Watson 	struct label *label;
69995fab37eSRobert Watson 
70010eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
70110eeb10cSRobert Watson 
702eca8a663SRobert Watson 	MAC_PERFORM(update_ipq, fragment, label, ipq, ipq->ipq_label);
70395fab37eSRobert Watson }
70495fab37eSRobert Watson 
70595fab37eSRobert Watson void
70695fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
70795fab37eSRobert Watson {
70810eeb10cSRobert Watson 	struct label *label;
70910eeb10cSRobert Watson 
71010eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
71195fab37eSRobert Watson 
712eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf,
71310eeb10cSRobert Watson 	    label);
71495fab37eSRobert Watson }
71595fab37eSRobert Watson 
71695fab37eSRobert Watson int
71795fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
71895fab37eSRobert Watson {
71995fab37eSRobert Watson 	int error;
72095fab37eSRobert Watson 
72195fab37eSRobert Watson 	if (!mac_enforce_network)
72295fab37eSRobert Watson 		return (0);
72395fab37eSRobert Watson 
724eca8a663SRobert Watson 	MAC_CHECK(check_bpfdesc_receive, bpf_d, bpf_d->bd_label, ifnet,
725eca8a663SRobert Watson 	    ifnet->if_label);
72695fab37eSRobert Watson 
72795fab37eSRobert Watson 	return (error);
72895fab37eSRobert Watson }
72995fab37eSRobert Watson 
73095fab37eSRobert Watson int
73195fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
73295fab37eSRobert Watson {
73310eeb10cSRobert Watson 	struct label *label;
73495fab37eSRobert Watson 	int error;
73595fab37eSRobert Watson 
736225bff6fSRobert Watson 	M_ASSERTPKTHDR(mbuf);
737225bff6fSRobert Watson 
73895fab37eSRobert Watson 	if (!mac_enforce_network)
73995fab37eSRobert Watson 		return (0);
74095fab37eSRobert Watson 
74110eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
74295fab37eSRobert Watson 
743eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_transmit, ifnet, ifnet->if_label, mbuf,
74410eeb10cSRobert Watson 	    label);
74595fab37eSRobert Watson 
74695fab37eSRobert Watson 	return (error);
74795fab37eSRobert Watson }
74895fab37eSRobert Watson 
74995fab37eSRobert Watson int
750a557af22SRobert Watson mac_check_inpcb_deliver(struct inpcb *inp, struct mbuf *m)
751a557af22SRobert Watson {
752a557af22SRobert Watson 	struct label *label;
753a557af22SRobert Watson 	int error;
754a557af22SRobert Watson 
755a557af22SRobert Watson 	M_ASSERTPKTHDR(m);
756a557af22SRobert Watson 
757a557af22SRobert Watson 	if (!mac_enforce_socket)
758a557af22SRobert Watson 		return (0);
759a557af22SRobert Watson 
760a557af22SRobert Watson 	label = mbuf_to_label(m);
761a557af22SRobert Watson 
762a557af22SRobert Watson 	MAC_CHECK(check_inpcb_deliver, inp, inp->inp_label, m, label);
763a557af22SRobert Watson 
764a557af22SRobert Watson 	return (error);
765a557af22SRobert Watson }
766a557af22SRobert Watson 
767a557af22SRobert Watson int
76895fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
76995fab37eSRobert Watson     struct sockaddr *sockaddr)
77095fab37eSRobert Watson {
77195fab37eSRobert Watson 	int error;
77295fab37eSRobert Watson 
77395fab37eSRobert Watson 	if (!mac_enforce_socket)
77495fab37eSRobert Watson 		return (0);
77595fab37eSRobert Watson 
776eca8a663SRobert Watson 	MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label,
77795fab37eSRobert Watson 	    sockaddr);
77895fab37eSRobert Watson 
77995fab37eSRobert Watson 	return (error);
78095fab37eSRobert Watson }
78195fab37eSRobert Watson 
78295fab37eSRobert Watson int
78395fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket,
78495fab37eSRobert Watson     struct sockaddr *sockaddr)
78595fab37eSRobert Watson {
78695fab37eSRobert Watson 	int error;
78795fab37eSRobert Watson 
78895fab37eSRobert Watson 	if (!mac_enforce_socket)
78995fab37eSRobert Watson 		return (0);
79095fab37eSRobert Watson 
791eca8a663SRobert Watson 	MAC_CHECK(check_socket_connect, cred, socket, socket->so_label,
79295fab37eSRobert Watson 	    sockaddr);
79395fab37eSRobert Watson 
79495fab37eSRobert Watson 	return (error);
79595fab37eSRobert Watson }
79695fab37eSRobert Watson 
79795fab37eSRobert Watson int
798d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
799d61198e4SRobert Watson {
80010eeb10cSRobert Watson 	struct label *label;
801d61198e4SRobert Watson 	int error;
802d61198e4SRobert Watson 
803d61198e4SRobert Watson 	if (!mac_enforce_socket)
804d61198e4SRobert Watson 		return (0);
805d61198e4SRobert Watson 
80610eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
80710eeb10cSRobert Watson 
808eca8a663SRobert Watson 	MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf,
80910eeb10cSRobert Watson 	    label);
810d61198e4SRobert Watson 
811d61198e4SRobert Watson 	return (error);
812d61198e4SRobert Watson }
813d61198e4SRobert Watson 
814d61198e4SRobert Watson int
81595fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket)
81695fab37eSRobert Watson {
81795fab37eSRobert Watson 	int error;
81895fab37eSRobert Watson 
81995fab37eSRobert Watson 	if (!mac_enforce_socket)
82095fab37eSRobert Watson 		return (0);
82195fab37eSRobert Watson 
822eca8a663SRobert Watson 	MAC_CHECK(check_socket_listen, cred, socket, socket->so_label);
82395fab37eSRobert Watson 	return (error);
82495fab37eSRobert Watson }
82595fab37eSRobert Watson 
826b371c939SRobert Watson int
827b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so)
828b371c939SRobert Watson {
829b371c939SRobert Watson 	int error;
830b371c939SRobert Watson 
831b371c939SRobert Watson 	if (!mac_enforce_socket)
832b371c939SRobert Watson 		return (0);
833b371c939SRobert Watson 
834eca8a663SRobert Watson 	MAC_CHECK(check_socket_receive, cred, so, so->so_label);
835b371c939SRobert Watson 
836b371c939SRobert Watson 	return (error);
837b371c939SRobert Watson }
838b371c939SRobert Watson 
83995fab37eSRobert Watson static int
84095fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
84195fab37eSRobert Watson     struct label *newlabel)
84295fab37eSRobert Watson {
84395fab37eSRobert Watson 	int error;
84495fab37eSRobert Watson 
845eca8a663SRobert Watson 	MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label,
84695fab37eSRobert Watson 	    newlabel);
84795fab37eSRobert Watson 
84895fab37eSRobert Watson 	return (error);
84995fab37eSRobert Watson }
85095fab37eSRobert Watson 
85195fab37eSRobert Watson int
852b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so)
853b371c939SRobert Watson {
854b371c939SRobert Watson 	int error;
855b371c939SRobert Watson 
856b371c939SRobert Watson 	if (!mac_enforce_socket)
857b371c939SRobert Watson 		return (0);
858b371c939SRobert Watson 
859eca8a663SRobert Watson 	MAC_CHECK(check_socket_send, cred, so, so->so_label);
860b371c939SRobert Watson 
861b371c939SRobert Watson 	return (error);
862b371c939SRobert Watson }
863b371c939SRobert Watson 
864b371c939SRobert Watson int
86595fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket)
86695fab37eSRobert Watson {
86795fab37eSRobert Watson 	int error;
86895fab37eSRobert Watson 
86995fab37eSRobert Watson 	if (!mac_enforce_socket)
87095fab37eSRobert Watson 		return (0);
87195fab37eSRobert Watson 
872eca8a663SRobert Watson 	MAC_CHECK(check_socket_visible, cred, socket, socket->so_label);
87395fab37eSRobert Watson 
87495fab37eSRobert Watson 	return (error);
87595fab37eSRobert Watson }
87695fab37eSRobert Watson 
87795fab37eSRobert Watson int
87895fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
87995fab37eSRobert Watson     struct ifnet *ifnet)
88095fab37eSRobert Watson {
881f7b951a8SRobert Watson 	char *elements, *buffer;
882f7b951a8SRobert Watson 	struct mac mac;
88395fab37eSRobert Watson 	int error;
88495fab37eSRobert Watson 
885f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
88695fab37eSRobert Watson 	if (error)
88795fab37eSRobert Watson 		return (error);
88895fab37eSRobert Watson 
889f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
890f7b951a8SRobert Watson 	if (error)
891f7b951a8SRobert Watson 		return (error);
892f7b951a8SRobert Watson 
893a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
894f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
895f7b951a8SRobert Watson 	if (error) {
896f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
897f7b951a8SRobert Watson 		return (error);
898f7b951a8SRobert Watson 	}
899f7b951a8SRobert Watson 
900a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
901eca8a663SRobert Watson 	error = mac_externalize_ifnet_label(ifnet->if_label, elements,
90283b7b0edSRobert Watson 	    buffer, mac.m_buflen);
903f7b951a8SRobert Watson 	if (error == 0)
904f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
905f7b951a8SRobert Watson 
906f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
907f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
908f7b951a8SRobert Watson 
909f7b951a8SRobert Watson 	return (error);
91095fab37eSRobert Watson }
91195fab37eSRobert Watson 
91295fab37eSRobert Watson int
91395fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
91495fab37eSRobert Watson     struct ifnet *ifnet)
91595fab37eSRobert Watson {
916eca8a663SRobert Watson 	struct label *intlabel;
917f7b951a8SRobert Watson 	struct mac mac;
918f7b951a8SRobert Watson 	char *buffer;
91995fab37eSRobert Watson 	int error;
92095fab37eSRobert Watson 
921f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
92295fab37eSRobert Watson 	if (error)
92395fab37eSRobert Watson 		return (error);
92495fab37eSRobert Watson 
925f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
92695fab37eSRobert Watson 	if (error)
92795fab37eSRobert Watson 		return (error);
92895fab37eSRobert Watson 
929a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
930f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
931f7b951a8SRobert Watson 	if (error) {
932f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
933f7b951a8SRobert Watson 		return (error);
934f7b951a8SRobert Watson 	}
935f7b951a8SRobert Watson 
936eca8a663SRobert Watson 	intlabel = mac_ifnet_label_alloc();
937eca8a663SRobert Watson 	error = mac_internalize_ifnet_label(intlabel, buffer);
938f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
939f7b951a8SRobert Watson 	if (error) {
940eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
941f7b951a8SRobert Watson 		return (error);
942f7b951a8SRobert Watson 	}
943f7b951a8SRobert Watson 
94495fab37eSRobert Watson 	/*
94595fab37eSRobert Watson 	 * XXX: Note that this is a redundant privilege check, since
94695fab37eSRobert Watson 	 * policies impose this check themselves if required by the
94795fab37eSRobert Watson 	 * policy.  Eventually, this should go away.
94895fab37eSRobert Watson 	 */
94995fab37eSRobert Watson 	error = suser_cred(cred, 0);
950f7b951a8SRobert Watson 	if (error) {
951eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
952f7b951a8SRobert Watson 		return (error);
953f7b951a8SRobert Watson 	}
95495fab37eSRobert Watson 
955eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, ifnet->if_label,
956eca8a663SRobert Watson 	    intlabel);
957f7b951a8SRobert Watson 	if (error) {
958eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
959f7b951a8SRobert Watson 		return (error);
960f7b951a8SRobert Watson 	}
96195fab37eSRobert Watson 
962eca8a663SRobert Watson 	MAC_PERFORM(relabel_ifnet, cred, ifnet, ifnet->if_label, intlabel);
96395fab37eSRobert Watson 
964eca8a663SRobert Watson 	mac_ifnet_label_free(intlabel);
965f7b951a8SRobert Watson 	return (0);
96695fab37eSRobert Watson }
96795fab37eSRobert Watson 
968a557af22SRobert Watson void
969a557af22SRobert Watson mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp)
970a557af22SRobert Watson {
971a557af22SRobert Watson 
972a557af22SRobert Watson 	/* XXX: assert socket lock. */
973a557af22SRobert Watson 	INP_LOCK_ASSERT(inp);
974a557af22SRobert Watson 	MAC_PERFORM(inpcb_sosetlabel, so, so->so_label, inp, inp->inp_label);
975a557af22SRobert Watson }
976a557af22SRobert Watson 
97795fab37eSRobert Watson int
978c9ea2dcfSRobert Watson mac_socket_label_set(struct ucred *cred, struct socket *so,
979c9ea2dcfSRobert Watson     struct label *label)
980c9ea2dcfSRobert Watson {
981c9ea2dcfSRobert Watson 	int error;
982c9ea2dcfSRobert Watson 
983c9ea2dcfSRobert Watson 	error = mac_check_socket_relabel(cred, so, label);
984c9ea2dcfSRobert Watson 	if (error)
985c9ea2dcfSRobert Watson 		return (error);
986c9ea2dcfSRobert Watson 
987c9ea2dcfSRobert Watson 	mac_relabel_socket(cred, so, label);
988a557af22SRobert Watson 
989a557af22SRobert Watson 	/*
990a557af22SRobert Watson 	 * If the protocol has expressed interest in socket layer changes,
991a557af22SRobert Watson 	 * such as if it needs to propagate changes to a cached pcb
992a557af22SRobert Watson 	 * label from the socket, notify it of the label change while
993a557af22SRobert Watson 	 * holding the socket lock.
994a557af22SRobert Watson 	 */
995a557af22SRobert Watson 	if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL)
996a557af22SRobert Watson 		(so->so_proto->pr_usrreqs->pru_sosetlabel)(so);
997a557af22SRobert Watson 
998c9ea2dcfSRobert Watson 	return (0);
999c9ea2dcfSRobert Watson }
1000c9ea2dcfSRobert Watson 
1001c9ea2dcfSRobert Watson int
10029e71dd0fSRobert Watson mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
100395fab37eSRobert Watson {
1004eca8a663SRobert Watson 	struct label *intlabel;
1005f7b951a8SRobert Watson 	char *buffer;
100695fab37eSRobert Watson 	int error;
100795fab37eSRobert Watson 
1008f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
100995fab37eSRobert Watson 	if (error)
101095fab37eSRobert Watson 		return (error);
101195fab37eSRobert Watson 
1012a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
1013f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
1014f7b951a8SRobert Watson 	if (error) {
1015f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
1016f7b951a8SRobert Watson 		return (error);
1017f7b951a8SRobert Watson 	}
1018f7b951a8SRobert Watson 
1019eca8a663SRobert Watson 	intlabel = mac_socket_label_alloc(M_WAITOK);
1020eca8a663SRobert Watson 	error = mac_internalize_socket_label(intlabel, buffer);
1021f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
1022c9ea2dcfSRobert Watson 	if (error)
1023c9ea2dcfSRobert Watson 		goto out;
1024c9ea2dcfSRobert Watson 
1025c9ea2dcfSRobert Watson 	/* XXX: Socket lock here. */
1026c9ea2dcfSRobert Watson 	error = mac_socket_label_set(cred, so, intlabel);
1027c9ea2dcfSRobert Watson 	/* XXX: Socket unlock here. */
1028c9ea2dcfSRobert Watson out:
1029eca8a663SRobert Watson 	mac_socket_label_free(intlabel);
1030f7b951a8SRobert Watson 	return (error);
1031f7b951a8SRobert Watson }
1032f7b951a8SRobert Watson 
103395fab37eSRobert Watson int
10349e71dd0fSRobert Watson mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
103595fab37eSRobert Watson {
1036f7b951a8SRobert Watson 	char *buffer, *elements;
1037f7b951a8SRobert Watson 	int error;
103895fab37eSRobert Watson 
1039f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
1040f7b951a8SRobert Watson 	if (error)
1041f7b951a8SRobert Watson 		return (error);
1042f7b951a8SRobert Watson 
1043a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
1044f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
1045f7b951a8SRobert Watson 	if (error) {
1046f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
1047f7b951a8SRobert Watson 		return (error);
1048f7b951a8SRobert Watson 	}
1049f7b951a8SRobert Watson 
1050a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1051eca8a663SRobert Watson 	error = mac_externalize_socket_label(so->so_label, elements,
105283b7b0edSRobert Watson 	    buffer, mac->m_buflen);
1053f7b951a8SRobert Watson 	if (error == 0)
1054f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
1055f7b951a8SRobert Watson 
1056f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
1057f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
1058f7b951a8SRobert Watson 
1059f7b951a8SRobert Watson 	return (error);
106095fab37eSRobert Watson }
106195fab37eSRobert Watson 
106295fab37eSRobert Watson int
10639e71dd0fSRobert Watson mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
1064f7b951a8SRobert Watson     struct mac *mac)
106595fab37eSRobert Watson {
1066f7b951a8SRobert Watson 	char *elements, *buffer;
1067f7b951a8SRobert Watson 	int error;
106895fab37eSRobert Watson 
1069f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
1070f7b951a8SRobert Watson 	if (error)
1071f7b951a8SRobert Watson 		return (error);
1072f7b951a8SRobert Watson 
1073a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
1074f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
1075f7b951a8SRobert Watson 	if (error) {
1076f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
1077f7b951a8SRobert Watson 		return (error);
1078f7b951a8SRobert Watson 	}
1079f7b951a8SRobert Watson 
1080a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1081eca8a663SRobert Watson 	error = mac_externalize_socket_peer_label(so->so_peerlabel,
108283b7b0edSRobert Watson 	    elements, buffer, mac->m_buflen);
1083f7b951a8SRobert Watson 	if (error == 0)
1084f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
1085f7b951a8SRobert Watson 
1086f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
1087f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
1088f7b951a8SRobert Watson 
1089f7b951a8SRobert Watson 	return (error);
109095fab37eSRobert Watson }
1091