xref: /freebsd/sys/security/mac/mac_net.c (revision b0323ea3aaf2c98f85c4f28e247ad84759e6d02e)
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>
5395fab37eSRobert Watson #include <sys/socket.h>
5495fab37eSRobert Watson #include <sys/socketvar.h>
5595fab37eSRobert Watson #include <sys/sysctl.h>
5695fab37eSRobert Watson 
5795fab37eSRobert Watson #include <sys/mac_policy.h>
5895fab37eSRobert Watson 
5995fab37eSRobert Watson #include <net/bpfdesc.h>
6095fab37eSRobert Watson #include <net/if.h>
6195fab37eSRobert Watson #include <net/if_var.h>
6295fab37eSRobert Watson 
6395fab37eSRobert Watson #include <netinet/in.h>
6495fab37eSRobert Watson #include <netinet/ip_var.h>
6595fab37eSRobert Watson 
6628e65e3dSRobert Watson #include <security/mac/mac_internal.h>
67a3df768bSRobert Watson 
6895fab37eSRobert Watson static int	mac_enforce_network = 1;
6995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
7095fab37eSRobert Watson     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
7195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
7295fab37eSRobert Watson 
7395fab37eSRobert Watson static int	mac_enforce_socket = 1;
7495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
7595fab37eSRobert Watson     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
7695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
7795fab37eSRobert Watson 
78f050add5SRobert Watson #ifdef MAC_DEBUG
7928e65e3dSRobert Watson static unsigned int nmacmbufs, nmacifnets, nmacbpfdescs, nmacsockets,
8028e65e3dSRobert Watson     nmacipqs;
818d8d5ea8SRobert Watson 
82b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
8395fab37eSRobert Watson     &nmacmbufs, 0, "number of mbufs in use");
84b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
8595fab37eSRobert Watson     &nmacifnets, 0, "number of ifnets in use");
86b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
8795fab37eSRobert Watson     &nmacipqs, 0, "number of ipqs in use");
88b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
8995fab37eSRobert Watson     &nmacbpfdescs, 0, "number of bpfdescs in use");
90b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
9195fab37eSRobert Watson     &nmacsockets, 0, "number of sockets in use");
92f050add5SRobert Watson #endif
9395fab37eSRobert Watson 
9410eeb10cSRobert Watson static struct label *
9510eeb10cSRobert Watson mbuf_to_label(struct mbuf *mbuf)
9610eeb10cSRobert Watson {
97225bff6fSRobert Watson 	struct m_tag *tag;
9810eeb10cSRobert Watson 	struct label *label;
9910eeb10cSRobert Watson 
100225bff6fSRobert Watson 	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
101225bff6fSRobert Watson 	label = (struct label *)(tag+1);
10210eeb10cSRobert Watson 
10310eeb10cSRobert Watson 	return (label);
10410eeb10cSRobert Watson }
10510eeb10cSRobert Watson 
106eca8a663SRobert Watson static struct label *
107eca8a663SRobert Watson mac_bpfdesc_label_alloc(void)
108eca8a663SRobert Watson {
109eca8a663SRobert Watson 	struct label *label;
110eca8a663SRobert Watson 
111eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
112eca8a663SRobert Watson 	MAC_PERFORM(init_bpfdesc_label, label);
113eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacbpfdescs);
114eca8a663SRobert Watson 	return (label);
115eca8a663SRobert Watson }
116eca8a663SRobert Watson 
11708bcdc58SRobert Watson void
11887807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d)
11908bcdc58SRobert Watson {
12008bcdc58SRobert Watson 
121eca8a663SRobert Watson 	bpf_d->bd_label = mac_bpfdesc_label_alloc();
12208bcdc58SRobert Watson }
12308bcdc58SRobert Watson 
124eca8a663SRobert Watson static struct label *
125eca8a663SRobert Watson mac_ifnet_label_alloc(void)
126f7b951a8SRobert Watson {
127eca8a663SRobert Watson 	struct label *label;
128f7b951a8SRobert Watson 
129eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
130f7b951a8SRobert Watson 	MAC_PERFORM(init_ifnet_label, label);
1318d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacifnets);
132eca8a663SRobert Watson 	return (label);
133f7b951a8SRobert Watson }
134f7b951a8SRobert Watson 
13508bcdc58SRobert Watson void
13608bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp)
13708bcdc58SRobert Watson {
13808bcdc58SRobert Watson 
139eca8a663SRobert Watson 	ifp->if_label = mac_ifnet_label_alloc();
140eca8a663SRobert Watson }
141eca8a663SRobert Watson 
142eca8a663SRobert Watson static struct label *
143eca8a663SRobert Watson mac_ipq_label_alloc(int flag)
144eca8a663SRobert Watson {
145eca8a663SRobert Watson 	struct label *label;
146eca8a663SRobert Watson 	int error;
147eca8a663SRobert Watson 
148eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
149eca8a663SRobert Watson 	if (label == NULL)
150eca8a663SRobert Watson 		return (NULL);
151eca8a663SRobert Watson 
152eca8a663SRobert Watson 	MAC_CHECK(init_ipq_label, label, flag);
153eca8a663SRobert Watson 	if (error) {
154eca8a663SRobert Watson 		MAC_PERFORM(destroy_ipq_label, label);
155eca8a663SRobert Watson 		mac_labelzone_free(label);
156eca8a663SRobert Watson 		return (NULL);
157eca8a663SRobert Watson 	}
158eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacipqs);
159eca8a663SRobert Watson 	return (label);
16008bcdc58SRobert Watson }
16108bcdc58SRobert Watson 
1625e7ce478SRobert Watson int
1635e7ce478SRobert Watson mac_init_ipq(struct ipq *ipq, int flag)
16408bcdc58SRobert Watson {
16508bcdc58SRobert Watson 
166eca8a663SRobert Watson 	ipq->ipq_label = mac_ipq_label_alloc(flag);
167eca8a663SRobert Watson 	if (ipq->ipq_label == NULL)
168eca8a663SRobert Watson 		return (ENOMEM);
169eca8a663SRobert Watson 	return (0);
17008bcdc58SRobert Watson }
17108bcdc58SRobert Watson 
17287807196SRobert Watson int
173225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag)
17408bcdc58SRobert Watson {
175225bff6fSRobert Watson 	struct label *label;
1766d1a6a9aSRobert Watson 	int error;
17756c15412SRobert Watson 
178225bff6fSRobert Watson 	label = (struct label *) (tag + 1);
179225bff6fSRobert Watson 	mac_init_label(label);
18008bcdc58SRobert Watson 
1816d1a6a9aSRobert Watson 	MAC_CHECK(init_mbuf_label, label, flag);
18256c15412SRobert Watson 	if (error) {
183225bff6fSRobert Watson 		MAC_PERFORM(destroy_mbuf_label, label);
184225bff6fSRobert Watson 		mac_destroy_label(label);
1858d8d5ea8SRobert Watson 	} else {
1868d8d5ea8SRobert Watson 		MAC_DEBUG_COUNTER_INC(&nmacmbufs);
18756c15412SRobert Watson 	}
18856c15412SRobert Watson 	return (error);
18908bcdc58SRobert Watson }
19008bcdc58SRobert Watson 
191225bff6fSRobert Watson int
192225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag)
193225bff6fSRobert Watson {
194225bff6fSRobert Watson 	struct m_tag *tag;
195225bff6fSRobert Watson 	int error;
196225bff6fSRobert Watson 
197225bff6fSRobert Watson 	M_ASSERTPKTHDR(m);
198225bff6fSRobert Watson 
199225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
200225bff6fSRobert Watson 	/*
20119c3e120SRobert Watson 	 * If conditionally allocating mbuf labels, don't allocate unless
20219c3e120SRobert Watson 	 * they are required.
203225bff6fSRobert Watson 	 */
20419c3e120SRobert Watson 	if (!mac_labelmbufs)
20519c3e120SRobert Watson 		return (0);
206225bff6fSRobert Watson #endif
207225bff6fSRobert Watson 	tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
208225bff6fSRobert Watson 	    flag);
209225bff6fSRobert Watson 	if (tag == NULL)
210225bff6fSRobert Watson 		return (ENOMEM);
211225bff6fSRobert Watson 	error = mac_init_mbuf_tag(tag, flag);
212225bff6fSRobert Watson 	if (error) {
213225bff6fSRobert Watson 		m_tag_free(tag);
214225bff6fSRobert Watson 		return (error);
215225bff6fSRobert Watson 	}
216225bff6fSRobert Watson 	m_tag_prepend(m, tag);
217225bff6fSRobert Watson 	return (0);
218225bff6fSRobert Watson }
219225bff6fSRobert Watson 
220b0323ea3SRobert Watson struct label *
221eca8a663SRobert Watson mac_socket_label_alloc(int flag)
22208bcdc58SRobert Watson {
223eca8a663SRobert Watson 	struct label *label;
22483985c26SRobert Watson 	int error;
22508bcdc58SRobert Watson 
226eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
227eca8a663SRobert Watson 	if (label == NULL)
228eca8a663SRobert Watson 		return (NULL);
22983985c26SRobert Watson 
23083985c26SRobert Watson 	MAC_CHECK(init_socket_label, label, flag);
23183985c26SRobert Watson 	if (error) {
23283985c26SRobert Watson 		MAC_PERFORM(destroy_socket_label, label);
233eca8a663SRobert Watson 		mac_labelzone_free(label);
234eca8a663SRobert Watson 		return (NULL);
235eca8a663SRobert Watson 	}
2368d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacsockets);
237eca8a663SRobert Watson 	return (label);
23883985c26SRobert Watson }
23983985c26SRobert Watson 
240eca8a663SRobert Watson static struct label *
241eca8a663SRobert Watson mac_socket_peer_label_alloc(int flag)
24283985c26SRobert Watson {
243eca8a663SRobert Watson 	struct label *label;
24483985c26SRobert Watson 	int error;
24583985c26SRobert Watson 
246eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
247eca8a663SRobert Watson 	if (label == NULL)
248eca8a663SRobert Watson 		return (NULL);
24983985c26SRobert Watson 
25083985c26SRobert Watson 	MAC_CHECK(init_socket_peer_label, label, flag);
25183985c26SRobert Watson 	if (error) {
252bea2b56bSRobert Watson 		MAC_PERFORM(destroy_socket_peer_label, label);
253eca8a663SRobert Watson 		mac_labelzone_free(label);
254eca8a663SRobert Watson 		return (NULL);
25583985c26SRobert Watson 	}
256eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacsockets);
257eca8a663SRobert Watson 	return (label);
25883985c26SRobert Watson }
25983985c26SRobert Watson 
26083985c26SRobert Watson int
261eca8a663SRobert Watson mac_init_socket(struct socket *so, int flag)
26283985c26SRobert Watson {
26383985c26SRobert Watson 
264eca8a663SRobert Watson 	so->so_label = mac_socket_label_alloc(flag);
265eca8a663SRobert Watson 	if (so->so_label == NULL)
266eca8a663SRobert Watson 		return (ENOMEM);
267eca8a663SRobert Watson 	so->so_peerlabel = mac_socket_peer_label_alloc(flag);
268eca8a663SRobert Watson 	if (so->so_peerlabel == NULL) {
269eca8a663SRobert Watson 		mac_socket_label_free(so->so_label);
270eca8a663SRobert Watson 		so->so_label = NULL;
271eca8a663SRobert Watson 		return (ENOMEM);
272eca8a663SRobert Watson 	}
273eca8a663SRobert Watson 	return (0);
274eca8a663SRobert Watson }
27583985c26SRobert Watson 
276eca8a663SRobert Watson static void
277eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label)
278eca8a663SRobert Watson {
27983985c26SRobert Watson 
280eca8a663SRobert Watson 	MAC_PERFORM(destroy_bpfdesc_label, label);
281eca8a663SRobert Watson 	mac_labelzone_free(label);
282eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs);
28387807196SRobert Watson }
28487807196SRobert Watson 
285763bbd2fSRobert Watson void
28608bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d)
28708bcdc58SRobert Watson {
28808bcdc58SRobert Watson 
289eca8a663SRobert Watson 	mac_bpfdesc_label_free(bpf_d->bd_label);
290eca8a663SRobert Watson 	bpf_d->bd_label = NULL;
29108bcdc58SRobert Watson }
29208bcdc58SRobert Watson 
293f7b951a8SRobert Watson static void
294eca8a663SRobert Watson mac_ifnet_label_free(struct label *label)
295f7b951a8SRobert Watson {
296f7b951a8SRobert Watson 
297f7b951a8SRobert Watson 	MAC_PERFORM(destroy_ifnet_label, label);
298eca8a663SRobert Watson 	mac_labelzone_free(label);
2998d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacifnets);
300f7b951a8SRobert Watson }
301f7b951a8SRobert Watson 
30287807196SRobert Watson void
30387807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp)
30487807196SRobert Watson {
30587807196SRobert Watson 
306eca8a663SRobert Watson 	mac_ifnet_label_free(ifp->if_label);
307eca8a663SRobert Watson 	ifp->if_label = NULL;
308eca8a663SRobert Watson }
309eca8a663SRobert Watson 
310eca8a663SRobert Watson static void
311eca8a663SRobert Watson mac_ipq_label_free(struct label *label)
312eca8a663SRobert Watson {
313eca8a663SRobert Watson 
314eca8a663SRobert Watson 	MAC_PERFORM(destroy_ipq_label, label);
315eca8a663SRobert Watson 	mac_labelzone_free(label);
316eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacipqs);
31787807196SRobert Watson }
31887807196SRobert Watson 
31987807196SRobert Watson void
32087807196SRobert Watson mac_destroy_ipq(struct ipq *ipq)
32187807196SRobert Watson {
32287807196SRobert Watson 
323eca8a663SRobert Watson 	mac_ipq_label_free(ipq->ipq_label);
324eca8a663SRobert Watson 	ipq->ipq_label = NULL;
32587807196SRobert Watson }
32687807196SRobert Watson 
32787807196SRobert Watson void
328225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag)
32987807196SRobert Watson {
330225bff6fSRobert Watson 	struct label *label;
33187807196SRobert Watson 
332225bff6fSRobert Watson 	label = (struct label *)(tag+1);
333225bff6fSRobert Watson 
334225bff6fSRobert Watson 	MAC_PERFORM(destroy_mbuf_label, label);
335225bff6fSRobert Watson 	mac_destroy_label(label);
3368d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacmbufs);
33708bcdc58SRobert Watson }
33808bcdc58SRobert Watson 
339b0323ea3SRobert Watson void
340eca8a663SRobert Watson mac_socket_label_free(struct label *label)
34183985c26SRobert Watson {
34283985c26SRobert Watson 
34383985c26SRobert Watson 	MAC_PERFORM(destroy_socket_label, label);
344eca8a663SRobert Watson 	mac_labelzone_free(label);
3458d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacsockets);
34683985c26SRobert Watson }
34783985c26SRobert Watson 
34883985c26SRobert Watson static void
349eca8a663SRobert Watson mac_socket_peer_label_free(struct label *label)
35083985c26SRobert Watson {
35183985c26SRobert Watson 
35283985c26SRobert Watson 	MAC_PERFORM(destroy_socket_peer_label, label);
353eca8a663SRobert Watson 	mac_labelzone_free(label);
354eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacsockets);
35583985c26SRobert Watson }
35683985c26SRobert Watson 
35787807196SRobert Watson void
35887807196SRobert Watson mac_destroy_socket(struct socket *socket)
35987807196SRobert Watson {
36087807196SRobert Watson 
361eca8a663SRobert Watson 	mac_socket_label_free(socket->so_label);
362eca8a663SRobert Watson 	socket->so_label = NULL;
363eca8a663SRobert Watson 	mac_socket_peer_label_free(socket->so_peerlabel);
364eca8a663SRobert Watson 	socket->so_peerlabel = NULL;
36508bcdc58SRobert Watson }
36608bcdc58SRobert Watson 
367763bbd2fSRobert Watson void
368225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
369225bff6fSRobert Watson {
370225bff6fSRobert Watson 	struct label *src_label, *dest_label;
371225bff6fSRobert Watson 
372225bff6fSRobert Watson 	src_label = (struct label *)(src+1);
373225bff6fSRobert Watson 	dest_label = (struct label *)(dest+1);
374225bff6fSRobert Watson 
375225bff6fSRobert Watson 	/*
376225bff6fSRobert Watson 	 * mac_init_mbuf_tag() is called on the target tag in
377225bff6fSRobert Watson 	 * m_tag_copy(), so we don't need to call it here.
378225bff6fSRobert Watson 	 */
379225bff6fSRobert Watson 	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
380225bff6fSRobert Watson }
381225bff6fSRobert Watson 
382b0323ea3SRobert Watson void
383b0323ea3SRobert Watson mac_copy_socket_label(struct label *src, struct label *dest)
384b0323ea3SRobert Watson {
385b0323ea3SRobert Watson 
386b0323ea3SRobert Watson 	MAC_PERFORM(copy_socket_label, src, dest);
387b0323ea3SRobert Watson }
388b0323ea3SRobert Watson 
38969bbb5b1SRobert Watson static int
390f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements,
39183b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
39269bbb5b1SRobert Watson {
39369bbb5b1SRobert Watson 	int error;
39469bbb5b1SRobert Watson 
395da77b2faSRobert Watson 	MAC_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
396f7b951a8SRobert Watson 
397f7b951a8SRobert Watson 	return (error);
398f7b951a8SRobert Watson }
399f7b951a8SRobert Watson 
400b0323ea3SRobert Watson int
401f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements,
40283b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
403f7b951a8SRobert Watson {
404f7b951a8SRobert Watson 	int error;
405f7b951a8SRobert Watson 
406da77b2faSRobert Watson 	MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
407f7b951a8SRobert Watson 
408f7b951a8SRobert Watson 	return (error);
409f7b951a8SRobert Watson }
410f7b951a8SRobert Watson 
411f7b951a8SRobert Watson static int
412f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements,
41383b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
414f7b951a8SRobert Watson {
415f7b951a8SRobert Watson 	int error;
416f7b951a8SRobert Watson 
417da77b2faSRobert Watson 	MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
418f7b951a8SRobert Watson 
419f7b951a8SRobert Watson 	return (error);
420f7b951a8SRobert Watson }
421f7b951a8SRobert Watson 
422f7b951a8SRobert Watson static int
423f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string)
424f7b951a8SRobert Watson {
425f7b951a8SRobert Watson 	int error;
426f7b951a8SRobert Watson 
427da77b2faSRobert Watson 	MAC_INTERNALIZE(ifnet, label, string);
428f7b951a8SRobert Watson 
429f7b951a8SRobert Watson 	return (error);
430f7b951a8SRobert Watson }
431f7b951a8SRobert Watson 
432b0323ea3SRobert Watson int
433f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string)
434f7b951a8SRobert Watson {
435f7b951a8SRobert Watson 	int error;
436f7b951a8SRobert Watson 
437da77b2faSRobert Watson 	MAC_INTERNALIZE(socket, label, string);
438f7b951a8SRobert Watson 
439f7b951a8SRobert Watson 	return (error);
440f7b951a8SRobert Watson }
441f7b951a8SRobert Watson 
44295fab37eSRobert Watson void
44395fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet)
44495fab37eSRobert Watson {
44595fab37eSRobert Watson 
446eca8a663SRobert Watson 	MAC_PERFORM(create_ifnet, ifnet, ifnet->if_label);
44795fab37eSRobert Watson }
44895fab37eSRobert Watson 
44995fab37eSRobert Watson void
45095fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
45195fab37eSRobert Watson {
45295fab37eSRobert Watson 
453eca8a663SRobert Watson 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, bpf_d->bd_label);
45495fab37eSRobert Watson }
45595fab37eSRobert Watson 
45695fab37eSRobert Watson void
45795fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket)
45895fab37eSRobert Watson {
45995fab37eSRobert Watson 
460eca8a663SRobert Watson 	MAC_PERFORM(create_socket, cred, socket, socket->so_label);
46195fab37eSRobert Watson }
46295fab37eSRobert Watson 
46395fab37eSRobert Watson void
46495fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket,
46595fab37eSRobert Watson     struct socket *newsocket)
46695fab37eSRobert Watson {
46795fab37eSRobert Watson 
468eca8a663SRobert Watson 	MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label,
469eca8a663SRobert Watson 	    newsocket, newsocket->so_label);
47095fab37eSRobert Watson }
47195fab37eSRobert Watson 
47295fab37eSRobert Watson static void
47395fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket,
47495fab37eSRobert Watson     struct label *newlabel)
47595fab37eSRobert Watson {
47695fab37eSRobert Watson 
477eca8a663SRobert Watson 	MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel);
47895fab37eSRobert Watson }
47995fab37eSRobert Watson 
48095fab37eSRobert Watson void
48195fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
48295fab37eSRobert Watson {
48310eeb10cSRobert Watson 	struct label *label;
48495fab37eSRobert Watson 
48510eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
48610eeb10cSRobert Watson 
48710eeb10cSRobert Watson 	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
488eca8a663SRobert Watson 	    socket->so_peerlabel);
48995fab37eSRobert Watson }
49095fab37eSRobert Watson 
49195fab37eSRobert Watson void
49295fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket,
49395fab37eSRobert Watson     struct socket *newsocket)
49495fab37eSRobert Watson {
49595fab37eSRobert Watson 
49695fab37eSRobert Watson 	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
497eca8a663SRobert Watson 	    oldsocket->so_label, newsocket, newsocket->so_peerlabel);
49895fab37eSRobert Watson }
49995fab37eSRobert Watson 
50095fab37eSRobert Watson void
50195fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
50295fab37eSRobert Watson {
50310eeb10cSRobert Watson 	struct label *label;
50410eeb10cSRobert Watson 
50510eeb10cSRobert Watson 	label = mbuf_to_label(datagram);
50695fab37eSRobert Watson 
507eca8a663SRobert Watson 	MAC_PERFORM(create_datagram_from_ipq, ipq, ipq->ipq_label,
50810eeb10cSRobert Watson 	    datagram, label);
50995fab37eSRobert Watson }
51095fab37eSRobert Watson 
51195fab37eSRobert Watson void
51295fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
51395fab37eSRobert Watson {
51410eeb10cSRobert Watson 	struct label *datagramlabel, *fragmentlabel;
51595fab37eSRobert Watson 
51610eeb10cSRobert Watson 	datagramlabel = mbuf_to_label(datagram);
51710eeb10cSRobert Watson 	fragmentlabel = mbuf_to_label(fragment);
51810eeb10cSRobert Watson 
51910eeb10cSRobert Watson 	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
52010eeb10cSRobert Watson 	    fragmentlabel);
52195fab37eSRobert Watson }
52295fab37eSRobert Watson 
52395fab37eSRobert Watson void
52495fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
52595fab37eSRobert Watson {
52610eeb10cSRobert Watson 	struct label *label;
52795fab37eSRobert Watson 
52810eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
52910eeb10cSRobert Watson 
530eca8a663SRobert Watson 	MAC_PERFORM(create_ipq, fragment, label, ipq, ipq->ipq_label);
53195fab37eSRobert Watson }
53295fab37eSRobert Watson 
53395fab37eSRobert Watson void
53495fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
53595fab37eSRobert Watson {
53610eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
53795fab37eSRobert Watson 
53810eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
53910eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
54010eeb10cSRobert Watson 
54110eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
54210eeb10cSRobert Watson 	    newmbuflabel);
54395fab37eSRobert Watson }
54495fab37eSRobert Watson 
54595fab37eSRobert Watson void
54695fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
54795fab37eSRobert Watson {
54810eeb10cSRobert Watson 	struct label *label;
54910eeb10cSRobert Watson 
55010eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
55195fab37eSRobert Watson 
552eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, bpf_d->bd_label, mbuf,
55310eeb10cSRobert Watson 	    label);
55495fab37eSRobert Watson }
55595fab37eSRobert Watson 
55695fab37eSRobert Watson void
55795fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
55895fab37eSRobert Watson {
55910eeb10cSRobert Watson 	struct label *label;
56010eeb10cSRobert Watson 
56110eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
56295fab37eSRobert Watson 
563eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_linklayer, ifnet, ifnet->if_label, mbuf,
56410eeb10cSRobert Watson 	    label);
56595fab37eSRobert Watson }
56695fab37eSRobert Watson 
56795fab37eSRobert Watson void
56895fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
56995fab37eSRobert Watson {
57010eeb10cSRobert Watson 	struct label *label;
57110eeb10cSRobert Watson 
57210eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
57395fab37eSRobert Watson 
574eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, ifnet->if_label, mbuf,
57510eeb10cSRobert Watson 	    label);
57695fab37eSRobert Watson }
57795fab37eSRobert Watson 
57895fab37eSRobert Watson void
57995fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
58095fab37eSRobert Watson     struct mbuf *newmbuf)
58195fab37eSRobert Watson {
58210eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
58395fab37eSRobert Watson 
58410eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
58510eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
58610eeb10cSRobert Watson 
58710eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
588eca8a663SRobert Watson 	    ifnet, ifnet->if_label, newmbuf, newmbuflabel);
58995fab37eSRobert Watson }
59095fab37eSRobert Watson 
59195fab37eSRobert Watson void
59295fab37eSRobert Watson mac_create_mbuf_netlayer(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_netlayer, oldmbuf, oldmbuflabel, newmbuf,
60010eeb10cSRobert Watson 	    newmbuflabel);
60195fab37eSRobert Watson }
60295fab37eSRobert Watson 
60395fab37eSRobert Watson int
60495fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
60595fab37eSRobert Watson {
60610eeb10cSRobert Watson 	struct label *label;
60795fab37eSRobert Watson 	int result;
60895fab37eSRobert Watson 
60910eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
61010eeb10cSRobert Watson 
61195fab37eSRobert Watson 	result = 1;
61210eeb10cSRobert Watson 	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
613eca8a663SRobert Watson 	    ipq->ipq_label);
61495fab37eSRobert Watson 
61595fab37eSRobert Watson 	return (result);
61695fab37eSRobert Watson }
61795fab37eSRobert Watson 
61895fab37eSRobert Watson void
619eb8c7f99SRobert Watson mac_reflect_mbuf_icmp(struct mbuf *m)
620eb8c7f99SRobert Watson {
621eb8c7f99SRobert Watson 	struct label *label;
622eb8c7f99SRobert Watson 
623eb8c7f99SRobert Watson 	label = mbuf_to_label(m);
624eb8c7f99SRobert Watson 
625eb8c7f99SRobert Watson 	MAC_PERFORM(reflect_mbuf_icmp, m, label);
626eb8c7f99SRobert Watson }
627eb8c7f99SRobert Watson void
628eb8c7f99SRobert Watson mac_reflect_mbuf_tcp(struct mbuf *m)
629eb8c7f99SRobert Watson {
630eb8c7f99SRobert Watson 	struct label *label;
631eb8c7f99SRobert Watson 
632eb8c7f99SRobert Watson 	label = mbuf_to_label(m);
633eb8c7f99SRobert Watson 
634eb8c7f99SRobert Watson 	MAC_PERFORM(reflect_mbuf_tcp, m, label);
635eb8c7f99SRobert Watson }
636eb8c7f99SRobert Watson 
637eb8c7f99SRobert Watson void
63895fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
63995fab37eSRobert Watson {
64010eeb10cSRobert Watson 	struct label *label;
64195fab37eSRobert Watson 
64210eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
64310eeb10cSRobert Watson 
644eca8a663SRobert Watson 	MAC_PERFORM(update_ipq, fragment, label, ipq, ipq->ipq_label);
64595fab37eSRobert Watson }
64695fab37eSRobert Watson 
64795fab37eSRobert Watson void
64895fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
64995fab37eSRobert Watson {
65010eeb10cSRobert Watson 	struct label *label;
65110eeb10cSRobert Watson 
65210eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
65395fab37eSRobert Watson 
654eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf,
65510eeb10cSRobert Watson 	    label);
65695fab37eSRobert Watson }
65795fab37eSRobert Watson 
65895fab37eSRobert Watson int
65995fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
66095fab37eSRobert Watson {
66195fab37eSRobert Watson 	int error;
66295fab37eSRobert Watson 
66395fab37eSRobert Watson 	if (!mac_enforce_network)
66495fab37eSRobert Watson 		return (0);
66595fab37eSRobert Watson 
666eca8a663SRobert Watson 	MAC_CHECK(check_bpfdesc_receive, bpf_d, bpf_d->bd_label, ifnet,
667eca8a663SRobert Watson 	    ifnet->if_label);
66895fab37eSRobert Watson 
66995fab37eSRobert Watson 	return (error);
67095fab37eSRobert Watson }
67195fab37eSRobert Watson 
67295fab37eSRobert Watson int
67395fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
67495fab37eSRobert Watson {
67510eeb10cSRobert Watson 	struct label *label;
67695fab37eSRobert Watson 	int error;
67795fab37eSRobert Watson 
678225bff6fSRobert Watson 	M_ASSERTPKTHDR(mbuf);
679225bff6fSRobert Watson 
68095fab37eSRobert Watson 	if (!mac_enforce_network)
68195fab37eSRobert Watson 		return (0);
68295fab37eSRobert Watson 
68310eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
68495fab37eSRobert Watson 
685eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_transmit, ifnet, ifnet->if_label, mbuf,
68610eeb10cSRobert Watson 	    label);
68795fab37eSRobert Watson 
68895fab37eSRobert Watson 	return (error);
68995fab37eSRobert Watson }
69095fab37eSRobert Watson 
69195fab37eSRobert Watson int
69295fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
69395fab37eSRobert Watson     struct sockaddr *sockaddr)
69495fab37eSRobert Watson {
69595fab37eSRobert Watson 	int error;
69695fab37eSRobert Watson 
69795fab37eSRobert Watson 	if (!mac_enforce_socket)
69895fab37eSRobert Watson 		return (0);
69995fab37eSRobert Watson 
700eca8a663SRobert Watson 	MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label,
70195fab37eSRobert Watson 	    sockaddr);
70295fab37eSRobert Watson 
70395fab37eSRobert Watson 	return (error);
70495fab37eSRobert Watson }
70595fab37eSRobert Watson 
70695fab37eSRobert Watson int
70795fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket,
70895fab37eSRobert Watson     struct sockaddr *sockaddr)
70995fab37eSRobert Watson {
71095fab37eSRobert Watson 	int error;
71195fab37eSRobert Watson 
71295fab37eSRobert Watson 	if (!mac_enforce_socket)
71395fab37eSRobert Watson 		return (0);
71495fab37eSRobert Watson 
715eca8a663SRobert Watson 	MAC_CHECK(check_socket_connect, cred, socket, socket->so_label,
71695fab37eSRobert Watson 	    sockaddr);
71795fab37eSRobert Watson 
71895fab37eSRobert Watson 	return (error);
71995fab37eSRobert Watson }
72095fab37eSRobert Watson 
72195fab37eSRobert Watson int
722d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
723d61198e4SRobert Watson {
72410eeb10cSRobert Watson 	struct label *label;
725d61198e4SRobert Watson 	int error;
726d61198e4SRobert Watson 
727d61198e4SRobert Watson 	if (!mac_enforce_socket)
728d61198e4SRobert Watson 		return (0);
729d61198e4SRobert Watson 
73010eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
73110eeb10cSRobert Watson 
732eca8a663SRobert Watson 	MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf,
73310eeb10cSRobert Watson 	    label);
734d61198e4SRobert Watson 
735d61198e4SRobert Watson 	return (error);
736d61198e4SRobert Watson }
737d61198e4SRobert Watson 
738d61198e4SRobert Watson int
73995fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket)
74095fab37eSRobert Watson {
74195fab37eSRobert Watson 	int error;
74295fab37eSRobert Watson 
74395fab37eSRobert Watson 	if (!mac_enforce_socket)
74495fab37eSRobert Watson 		return (0);
74595fab37eSRobert Watson 
746eca8a663SRobert Watson 	MAC_CHECK(check_socket_listen, cred, socket, socket->so_label);
74795fab37eSRobert Watson 	return (error);
74895fab37eSRobert Watson }
74995fab37eSRobert Watson 
750b371c939SRobert Watson int
751b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so)
752b371c939SRobert Watson {
753b371c939SRobert Watson 	int error;
754b371c939SRobert Watson 
755b371c939SRobert Watson 	if (!mac_enforce_socket)
756b371c939SRobert Watson 		return (0);
757b371c939SRobert Watson 
758eca8a663SRobert Watson 	MAC_CHECK(check_socket_receive, cred, so, so->so_label);
759b371c939SRobert Watson 
760b371c939SRobert Watson 	return (error);
761b371c939SRobert Watson }
762b371c939SRobert Watson 
76395fab37eSRobert Watson static int
76495fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
76595fab37eSRobert Watson     struct label *newlabel)
76695fab37eSRobert Watson {
76795fab37eSRobert Watson 	int error;
76895fab37eSRobert Watson 
769eca8a663SRobert Watson 	MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label,
77095fab37eSRobert Watson 	    newlabel);
77195fab37eSRobert Watson 
77295fab37eSRobert Watson 	return (error);
77395fab37eSRobert Watson }
77495fab37eSRobert Watson 
77595fab37eSRobert Watson int
776b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so)
777b371c939SRobert Watson {
778b371c939SRobert Watson 	int error;
779b371c939SRobert Watson 
780b371c939SRobert Watson 	if (!mac_enforce_socket)
781b371c939SRobert Watson 		return (0);
782b371c939SRobert Watson 
783eca8a663SRobert Watson 	MAC_CHECK(check_socket_send, cred, so, so->so_label);
784b371c939SRobert Watson 
785b371c939SRobert Watson 	return (error);
786b371c939SRobert Watson }
787b371c939SRobert Watson 
788b371c939SRobert Watson int
78995fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket)
79095fab37eSRobert Watson {
79195fab37eSRobert Watson 	int error;
79295fab37eSRobert Watson 
79395fab37eSRobert Watson 	if (!mac_enforce_socket)
79495fab37eSRobert Watson 		return (0);
79595fab37eSRobert Watson 
796eca8a663SRobert Watson 	MAC_CHECK(check_socket_visible, cred, socket, socket->so_label);
79795fab37eSRobert Watson 
79895fab37eSRobert Watson 	return (error);
79995fab37eSRobert Watson }
80095fab37eSRobert Watson 
80195fab37eSRobert Watson int
80295fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
80395fab37eSRobert Watson     struct ifnet *ifnet)
80495fab37eSRobert Watson {
805f7b951a8SRobert Watson 	char *elements, *buffer;
806f7b951a8SRobert Watson 	struct mac mac;
80795fab37eSRobert Watson 	int error;
80895fab37eSRobert Watson 
809f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
81095fab37eSRobert Watson 	if (error)
81195fab37eSRobert Watson 		return (error);
81295fab37eSRobert Watson 
813f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
814f7b951a8SRobert Watson 	if (error)
815f7b951a8SRobert Watson 		return (error);
816f7b951a8SRobert Watson 
817a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
818f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
819f7b951a8SRobert Watson 	if (error) {
820f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
821f7b951a8SRobert Watson 		return (error);
822f7b951a8SRobert Watson 	}
823f7b951a8SRobert Watson 
824a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
825eca8a663SRobert Watson 	error = mac_externalize_ifnet_label(ifnet->if_label, elements,
82683b7b0edSRobert Watson 	    buffer, mac.m_buflen);
827f7b951a8SRobert Watson 	if (error == 0)
828f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
829f7b951a8SRobert Watson 
830f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
831f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
832f7b951a8SRobert Watson 
833f7b951a8SRobert Watson 	return (error);
83495fab37eSRobert Watson }
83595fab37eSRobert Watson 
83695fab37eSRobert Watson int
83795fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
83895fab37eSRobert Watson     struct ifnet *ifnet)
83995fab37eSRobert Watson {
840eca8a663SRobert Watson 	struct label *intlabel;
841f7b951a8SRobert Watson 	struct mac mac;
842f7b951a8SRobert Watson 	char *buffer;
84395fab37eSRobert Watson 	int error;
84495fab37eSRobert Watson 
845f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
84695fab37eSRobert Watson 	if (error)
84795fab37eSRobert Watson 		return (error);
84895fab37eSRobert Watson 
849f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
85095fab37eSRobert Watson 	if (error)
85195fab37eSRobert Watson 		return (error);
85295fab37eSRobert Watson 
853a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
854f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
855f7b951a8SRobert Watson 	if (error) {
856f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
857f7b951a8SRobert Watson 		return (error);
858f7b951a8SRobert Watson 	}
859f7b951a8SRobert Watson 
860eca8a663SRobert Watson 	intlabel = mac_ifnet_label_alloc();
861eca8a663SRobert Watson 	error = mac_internalize_ifnet_label(intlabel, buffer);
862f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
863f7b951a8SRobert Watson 	if (error) {
864eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
865f7b951a8SRobert Watson 		return (error);
866f7b951a8SRobert Watson 	}
867f7b951a8SRobert Watson 
86895fab37eSRobert Watson 	/*
86995fab37eSRobert Watson 	 * XXX: Note that this is a redundant privilege check, since
87095fab37eSRobert Watson 	 * policies impose this check themselves if required by the
87195fab37eSRobert Watson 	 * policy.  Eventually, this should go away.
87295fab37eSRobert Watson 	 */
87395fab37eSRobert Watson 	error = suser_cred(cred, 0);
874f7b951a8SRobert Watson 	if (error) {
875eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
876f7b951a8SRobert Watson 		return (error);
877f7b951a8SRobert Watson 	}
87895fab37eSRobert Watson 
879eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, ifnet->if_label,
880eca8a663SRobert Watson 	    intlabel);
881f7b951a8SRobert Watson 	if (error) {
882eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
883f7b951a8SRobert Watson 		return (error);
884f7b951a8SRobert Watson 	}
88595fab37eSRobert Watson 
886eca8a663SRobert Watson 	MAC_PERFORM(relabel_ifnet, cred, ifnet, ifnet->if_label, intlabel);
88795fab37eSRobert Watson 
888eca8a663SRobert Watson 	mac_ifnet_label_free(intlabel);
889f7b951a8SRobert Watson 	return (0);
89095fab37eSRobert Watson }
89195fab37eSRobert Watson 
89295fab37eSRobert Watson int
893c9ea2dcfSRobert Watson mac_socket_label_set(struct ucred *cred, struct socket *so,
894c9ea2dcfSRobert Watson     struct label *label)
895c9ea2dcfSRobert Watson {
896c9ea2dcfSRobert Watson 	int error;
897c9ea2dcfSRobert Watson 
898c9ea2dcfSRobert Watson 	error = mac_check_socket_relabel(cred, so, label);
899c9ea2dcfSRobert Watson 	if (error)
900c9ea2dcfSRobert Watson 		return (error);
901c9ea2dcfSRobert Watson 
902c9ea2dcfSRobert Watson 	mac_relabel_socket(cred, so, label);
903c9ea2dcfSRobert Watson 	return (0);
904c9ea2dcfSRobert Watson }
905c9ea2dcfSRobert Watson 
906c9ea2dcfSRobert Watson int
9079e71dd0fSRobert Watson mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
90895fab37eSRobert Watson {
909eca8a663SRobert Watson 	struct label *intlabel;
910f7b951a8SRobert Watson 	char *buffer;
91195fab37eSRobert Watson 	int error;
91295fab37eSRobert Watson 
913f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
91495fab37eSRobert Watson 	if (error)
91595fab37eSRobert Watson 		return (error);
91695fab37eSRobert Watson 
917a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
918f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
919f7b951a8SRobert Watson 	if (error) {
920f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
921f7b951a8SRobert Watson 		return (error);
922f7b951a8SRobert Watson 	}
923f7b951a8SRobert Watson 
924eca8a663SRobert Watson 	intlabel = mac_socket_label_alloc(M_WAITOK);
925eca8a663SRobert Watson 	error = mac_internalize_socket_label(intlabel, buffer);
926f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
927c9ea2dcfSRobert Watson 	if (error)
928c9ea2dcfSRobert Watson 		goto out;
929c9ea2dcfSRobert Watson 
930c9ea2dcfSRobert Watson 	/* XXX: Socket lock here. */
931c9ea2dcfSRobert Watson 	error = mac_socket_label_set(cred, so, intlabel);
932c9ea2dcfSRobert Watson 	/* XXX: Socket unlock here. */
933c9ea2dcfSRobert Watson out:
934eca8a663SRobert Watson 	mac_socket_label_free(intlabel);
935f7b951a8SRobert Watson 	return (error);
936f7b951a8SRobert Watson }
937f7b951a8SRobert Watson 
93895fab37eSRobert Watson int
9399e71dd0fSRobert Watson mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
94095fab37eSRobert Watson {
941f7b951a8SRobert Watson 	char *buffer, *elements;
942f7b951a8SRobert Watson 	int error;
94395fab37eSRobert Watson 
944f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
945f7b951a8SRobert Watson 	if (error)
946f7b951a8SRobert Watson 		return (error);
947f7b951a8SRobert Watson 
948a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
949f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
950f7b951a8SRobert Watson 	if (error) {
951f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
952f7b951a8SRobert Watson 		return (error);
953f7b951a8SRobert Watson 	}
954f7b951a8SRobert Watson 
955a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
956eca8a663SRobert Watson 	error = mac_externalize_socket_label(so->so_label, elements,
95783b7b0edSRobert Watson 	    buffer, mac->m_buflen);
958f7b951a8SRobert Watson 	if (error == 0)
959f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
960f7b951a8SRobert Watson 
961f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
962f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
963f7b951a8SRobert Watson 
964f7b951a8SRobert Watson 	return (error);
96595fab37eSRobert Watson }
96695fab37eSRobert Watson 
96795fab37eSRobert Watson int
9689e71dd0fSRobert Watson mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
969f7b951a8SRobert Watson     struct mac *mac)
97095fab37eSRobert Watson {
971f7b951a8SRobert Watson 	char *elements, *buffer;
972f7b951a8SRobert Watson 	int error;
97395fab37eSRobert Watson 
974f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
975f7b951a8SRobert Watson 	if (error)
976f7b951a8SRobert Watson 		return (error);
977f7b951a8SRobert Watson 
978a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
979f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
980f7b951a8SRobert Watson 	if (error) {
981f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
982f7b951a8SRobert Watson 		return (error);
983f7b951a8SRobert Watson 	}
984f7b951a8SRobert Watson 
985a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
986eca8a663SRobert Watson 	error = mac_externalize_socket_peer_label(so->so_peerlabel,
98783b7b0edSRobert Watson 	    elements, buffer, mac->m_buflen);
988f7b951a8SRobert Watson 	if (error == 0)
989f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
990f7b951a8SRobert Watson 
991f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
992f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
993f7b951a8SRobert Watson 
994f7b951a8SRobert Watson 	return (error);
99595fab37eSRobert Watson }
996