xref: /freebsd/sys/security/mac/mac_net.c (revision eca8a663d442468f64e21ed869817b9048ab5a7b)
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 
94eca8a663SRobert Watson static void	mac_socket_label_free(struct label *label);
95eca8a663SRobert Watson 
9683985c26SRobert Watson 
9710eeb10cSRobert Watson static struct label *
9810eeb10cSRobert Watson mbuf_to_label(struct mbuf *mbuf)
9910eeb10cSRobert Watson {
100225bff6fSRobert Watson 	struct m_tag *tag;
10110eeb10cSRobert Watson 	struct label *label;
10210eeb10cSRobert Watson 
103225bff6fSRobert Watson 	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
104225bff6fSRobert Watson 	label = (struct label *)(tag+1);
10510eeb10cSRobert Watson 
10610eeb10cSRobert Watson 	return (label);
10710eeb10cSRobert Watson }
10810eeb10cSRobert Watson 
109eca8a663SRobert Watson static struct label *
110eca8a663SRobert Watson mac_bpfdesc_label_alloc(void)
111eca8a663SRobert Watson {
112eca8a663SRobert Watson 	struct label *label;
113eca8a663SRobert Watson 
114eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
115eca8a663SRobert Watson 	MAC_PERFORM(init_bpfdesc_label, label);
116eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacbpfdescs);
117eca8a663SRobert Watson 	return (label);
118eca8a663SRobert Watson }
119eca8a663SRobert Watson 
12008bcdc58SRobert Watson void
12187807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d)
12208bcdc58SRobert Watson {
12308bcdc58SRobert Watson 
124eca8a663SRobert Watson 	bpf_d->bd_label = mac_bpfdesc_label_alloc();
12508bcdc58SRobert Watson }
12608bcdc58SRobert Watson 
127eca8a663SRobert Watson static struct label *
128eca8a663SRobert Watson mac_ifnet_label_alloc(void)
129f7b951a8SRobert Watson {
130eca8a663SRobert Watson 	struct label *label;
131f7b951a8SRobert Watson 
132eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
133f7b951a8SRobert Watson 	MAC_PERFORM(init_ifnet_label, label);
1348d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacifnets);
135eca8a663SRobert Watson 	return (label);
136f7b951a8SRobert Watson }
137f7b951a8SRobert Watson 
13808bcdc58SRobert Watson void
13908bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp)
14008bcdc58SRobert Watson {
14108bcdc58SRobert Watson 
142eca8a663SRobert Watson 	ifp->if_label = mac_ifnet_label_alloc();
143eca8a663SRobert Watson }
144eca8a663SRobert Watson 
145eca8a663SRobert Watson static struct label *
146eca8a663SRobert Watson mac_ipq_label_alloc(int flag)
147eca8a663SRobert Watson {
148eca8a663SRobert Watson 	struct label *label;
149eca8a663SRobert Watson 	int error;
150eca8a663SRobert Watson 
151eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
152eca8a663SRobert Watson 	if (label == NULL)
153eca8a663SRobert Watson 		return (NULL);
154eca8a663SRobert Watson 
155eca8a663SRobert Watson 	MAC_CHECK(init_ipq_label, label, flag);
156eca8a663SRobert Watson 	if (error) {
157eca8a663SRobert Watson 		MAC_PERFORM(destroy_ipq_label, label);
158eca8a663SRobert Watson 		mac_labelzone_free(label);
159eca8a663SRobert Watson 		return (NULL);
160eca8a663SRobert Watson 	}
161eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacipqs);
162eca8a663SRobert Watson 	return (label);
16308bcdc58SRobert Watson }
16408bcdc58SRobert Watson 
1655e7ce478SRobert Watson int
1665e7ce478SRobert Watson mac_init_ipq(struct ipq *ipq, int flag)
16708bcdc58SRobert Watson {
16808bcdc58SRobert Watson 
169eca8a663SRobert Watson 	ipq->ipq_label = mac_ipq_label_alloc(flag);
170eca8a663SRobert Watson 	if (ipq->ipq_label == NULL)
171eca8a663SRobert Watson 		return (ENOMEM);
172eca8a663SRobert Watson 	return (0);
17308bcdc58SRobert Watson }
17408bcdc58SRobert Watson 
17587807196SRobert Watson int
176225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag)
17708bcdc58SRobert Watson {
178225bff6fSRobert Watson 	struct label *label;
1796d1a6a9aSRobert Watson 	int error;
18056c15412SRobert Watson 
181225bff6fSRobert Watson 	label = (struct label *) (tag + 1);
182225bff6fSRobert Watson 	mac_init_label(label);
18308bcdc58SRobert Watson 
1846d1a6a9aSRobert Watson 	MAC_CHECK(init_mbuf_label, label, flag);
18556c15412SRobert Watson 	if (error) {
186225bff6fSRobert Watson 		MAC_PERFORM(destroy_mbuf_label, label);
187225bff6fSRobert Watson 		mac_destroy_label(label);
1888d8d5ea8SRobert Watson 	} else {
1898d8d5ea8SRobert Watson 		MAC_DEBUG_COUNTER_INC(&nmacmbufs);
19056c15412SRobert Watson 	}
19156c15412SRobert Watson 	return (error);
19208bcdc58SRobert Watson }
19308bcdc58SRobert Watson 
194225bff6fSRobert Watson int
195225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag)
196225bff6fSRobert Watson {
197225bff6fSRobert Watson 	struct m_tag *tag;
198225bff6fSRobert Watson 	int error;
199225bff6fSRobert Watson 
200225bff6fSRobert Watson 	M_ASSERTPKTHDR(m);
201225bff6fSRobert Watson 
202225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
203225bff6fSRobert Watson 	/*
20419c3e120SRobert Watson 	 * If conditionally allocating mbuf labels, don't allocate unless
20519c3e120SRobert Watson 	 * they are required.
206225bff6fSRobert Watson 	 */
20719c3e120SRobert Watson 	if (!mac_labelmbufs)
20819c3e120SRobert Watson 		return (0);
209225bff6fSRobert Watson #endif
210225bff6fSRobert Watson 	tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
211225bff6fSRobert Watson 	    flag);
212225bff6fSRobert Watson 	if (tag == NULL)
213225bff6fSRobert Watson 		return (ENOMEM);
214225bff6fSRobert Watson 	error = mac_init_mbuf_tag(tag, flag);
215225bff6fSRobert Watson 	if (error) {
216225bff6fSRobert Watson 		m_tag_free(tag);
217225bff6fSRobert Watson 		return (error);
218225bff6fSRobert Watson 	}
219225bff6fSRobert Watson 	m_tag_prepend(m, tag);
220225bff6fSRobert Watson 	return (0);
221225bff6fSRobert Watson }
222225bff6fSRobert Watson 
223eca8a663SRobert Watson static struct label *
224eca8a663SRobert Watson mac_socket_label_alloc(int flag)
22508bcdc58SRobert Watson {
226eca8a663SRobert Watson 	struct label *label;
22783985c26SRobert Watson 	int error;
22808bcdc58SRobert Watson 
229eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
230eca8a663SRobert Watson 	if (label == NULL)
231eca8a663SRobert Watson 		return (NULL);
23283985c26SRobert Watson 
23383985c26SRobert Watson 	MAC_CHECK(init_socket_label, label, flag);
23483985c26SRobert Watson 	if (error) {
23583985c26SRobert Watson 		MAC_PERFORM(destroy_socket_label, label);
236eca8a663SRobert Watson 		mac_labelzone_free(label);
237eca8a663SRobert Watson 		return  (NULL);
238eca8a663SRobert Watson 	}
2398d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacsockets);
240eca8a663SRobert Watson 	return (label);
24183985c26SRobert Watson }
24283985c26SRobert Watson 
243eca8a663SRobert Watson static struct label *
244eca8a663SRobert Watson mac_socket_peer_label_alloc(int flag)
24583985c26SRobert Watson {
246eca8a663SRobert Watson 	struct label *label;
24783985c26SRobert Watson 	int error;
24883985c26SRobert Watson 
249eca8a663SRobert Watson 	label = mac_labelzone_alloc(flag);
250eca8a663SRobert Watson 	if (label == NULL)
251eca8a663SRobert Watson 		return (NULL);
25283985c26SRobert Watson 
25383985c26SRobert Watson 	MAC_CHECK(init_socket_peer_label, label, flag);
25483985c26SRobert Watson 	if (error) {
255bea2b56bSRobert Watson 		MAC_PERFORM(destroy_socket_peer_label, label);
256eca8a663SRobert Watson 		mac_labelzone_free(label);
257eca8a663SRobert Watson 		return  (NULL);
25883985c26SRobert Watson 	}
259eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacsockets);
260eca8a663SRobert Watson 	return (label);
26183985c26SRobert Watson }
26283985c26SRobert Watson 
26383985c26SRobert Watson int
264eca8a663SRobert Watson mac_init_socket(struct socket *so, int flag)
26583985c26SRobert Watson {
26683985c26SRobert Watson 
267eca8a663SRobert Watson 	so->so_label = mac_socket_label_alloc(flag);
268eca8a663SRobert Watson 	if (so->so_label == NULL)
269eca8a663SRobert Watson 		return (ENOMEM);
270eca8a663SRobert Watson 	so->so_peerlabel = mac_socket_peer_label_alloc(flag);
271eca8a663SRobert Watson 	if (so->so_peerlabel == NULL) {
272eca8a663SRobert Watson 		mac_socket_label_free(so->so_label);
273eca8a663SRobert Watson 		so->so_label = NULL;
274eca8a663SRobert Watson 		return (ENOMEM);
275eca8a663SRobert Watson 	}
276eca8a663SRobert Watson 	return (0);
277eca8a663SRobert Watson }
27883985c26SRobert Watson 
279eca8a663SRobert Watson static void
280eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label)
281eca8a663SRobert Watson {
28283985c26SRobert Watson 
283eca8a663SRobert Watson 	MAC_PERFORM(destroy_bpfdesc_label, label);
284eca8a663SRobert Watson 	mac_labelzone_free(label);
285eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs);
28687807196SRobert Watson }
28787807196SRobert Watson 
288763bbd2fSRobert Watson void
28908bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d)
29008bcdc58SRobert Watson {
29108bcdc58SRobert Watson 
292eca8a663SRobert Watson 	mac_bpfdesc_label_free(bpf_d->bd_label);
293eca8a663SRobert Watson 	bpf_d->bd_label = NULL;
29408bcdc58SRobert Watson }
29508bcdc58SRobert Watson 
296f7b951a8SRobert Watson static void
297eca8a663SRobert Watson mac_ifnet_label_free(struct label *label)
298f7b951a8SRobert Watson {
299f7b951a8SRobert Watson 
300f7b951a8SRobert Watson 	MAC_PERFORM(destroy_ifnet_label, label);
301eca8a663SRobert Watson 	mac_labelzone_free(label);
3028d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacifnets);
303f7b951a8SRobert Watson }
304f7b951a8SRobert Watson 
30587807196SRobert Watson void
30687807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp)
30787807196SRobert Watson {
30887807196SRobert Watson 
309eca8a663SRobert Watson 	mac_ifnet_label_free(ifp->if_label);
310eca8a663SRobert Watson 	ifp->if_label = NULL;
311eca8a663SRobert Watson }
312eca8a663SRobert Watson 
313eca8a663SRobert Watson static void
314eca8a663SRobert Watson mac_ipq_label_free(struct label *label)
315eca8a663SRobert Watson {
316eca8a663SRobert Watson 
317eca8a663SRobert Watson 	MAC_PERFORM(destroy_ipq_label, label);
318eca8a663SRobert Watson 	mac_labelzone_free(label);
319eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacipqs);
32087807196SRobert Watson }
32187807196SRobert Watson 
32287807196SRobert Watson void
32387807196SRobert Watson mac_destroy_ipq(struct ipq *ipq)
32487807196SRobert Watson {
32587807196SRobert Watson 
326eca8a663SRobert Watson 	mac_ipq_label_free(ipq->ipq_label);
327eca8a663SRobert Watson 	ipq->ipq_label = NULL;
32887807196SRobert Watson }
32987807196SRobert Watson 
33087807196SRobert Watson void
331225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag)
33287807196SRobert Watson {
333225bff6fSRobert Watson 	struct label *label;
33487807196SRobert Watson 
335225bff6fSRobert Watson 	label = (struct label *)(tag+1);
336225bff6fSRobert Watson 
337225bff6fSRobert Watson 	MAC_PERFORM(destroy_mbuf_label, label);
338225bff6fSRobert Watson 	mac_destroy_label(label);
3398d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacmbufs);
34008bcdc58SRobert Watson }
34108bcdc58SRobert Watson 
34283985c26SRobert Watson static void
343eca8a663SRobert Watson mac_socket_label_free(struct label *label)
34483985c26SRobert Watson {
34583985c26SRobert Watson 
34683985c26SRobert Watson 	MAC_PERFORM(destroy_socket_label, label);
347eca8a663SRobert Watson 	mac_labelzone_free(label);
3488d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacsockets);
34983985c26SRobert Watson }
35083985c26SRobert Watson 
35183985c26SRobert Watson static void
352eca8a663SRobert Watson mac_socket_peer_label_free(struct label *label)
35383985c26SRobert Watson {
35483985c26SRobert Watson 
35583985c26SRobert Watson 	MAC_PERFORM(destroy_socket_peer_label, label);
356eca8a663SRobert Watson 	mac_labelzone_free(label);
357eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacsockets);
35883985c26SRobert Watson }
35983985c26SRobert Watson 
36087807196SRobert Watson void
36187807196SRobert Watson mac_destroy_socket(struct socket *socket)
36287807196SRobert Watson {
36387807196SRobert Watson 
364eca8a663SRobert Watson 	mac_socket_label_free(socket->so_label);
365eca8a663SRobert Watson 	socket->so_label = NULL;
366eca8a663SRobert Watson 	mac_socket_peer_label_free(socket->so_peerlabel);
367eca8a663SRobert Watson 	socket->so_peerlabel = NULL;
36808bcdc58SRobert Watson }
36908bcdc58SRobert Watson 
370763bbd2fSRobert Watson void
371225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
372225bff6fSRobert Watson {
373225bff6fSRobert Watson 	struct label *src_label, *dest_label;
374225bff6fSRobert Watson 
375225bff6fSRobert Watson 	src_label = (struct label *)(src+1);
376225bff6fSRobert Watson 	dest_label = (struct label *)(dest+1);
377225bff6fSRobert Watson 
378225bff6fSRobert Watson 	/*
379225bff6fSRobert Watson 	 * mac_init_mbuf_tag() is called on the target tag in
380225bff6fSRobert Watson 	 * m_tag_copy(), so we don't need to call it here.
381225bff6fSRobert Watson 	 */
382225bff6fSRobert Watson 	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
383225bff6fSRobert Watson }
384225bff6fSRobert Watson 
38569bbb5b1SRobert Watson static int
386f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements,
38783b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
38869bbb5b1SRobert Watson {
38969bbb5b1SRobert Watson 	int error;
39069bbb5b1SRobert Watson 
391da77b2faSRobert Watson 	MAC_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
392f7b951a8SRobert Watson 
393f7b951a8SRobert Watson 	return (error);
394f7b951a8SRobert Watson }
395f7b951a8SRobert Watson 
396f7b951a8SRobert Watson static int
397f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements,
39883b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
399f7b951a8SRobert Watson {
400f7b951a8SRobert Watson 	int error;
401f7b951a8SRobert Watson 
402da77b2faSRobert Watson 	MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
403f7b951a8SRobert Watson 
404f7b951a8SRobert Watson 	return (error);
405f7b951a8SRobert Watson }
406f7b951a8SRobert Watson 
407f7b951a8SRobert Watson static int
408f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements,
40983b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
410f7b951a8SRobert Watson {
411f7b951a8SRobert Watson 	int error;
412f7b951a8SRobert Watson 
413da77b2faSRobert Watson 	MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
414f7b951a8SRobert Watson 
415f7b951a8SRobert Watson 	return (error);
416f7b951a8SRobert Watson }
417f7b951a8SRobert Watson 
418f7b951a8SRobert Watson static int
419f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string)
420f7b951a8SRobert Watson {
421f7b951a8SRobert Watson 	int error;
422f7b951a8SRobert Watson 
423da77b2faSRobert Watson 	MAC_INTERNALIZE(ifnet, label, string);
424f7b951a8SRobert Watson 
425f7b951a8SRobert Watson 	return (error);
426f7b951a8SRobert Watson }
427f7b951a8SRobert Watson 
428f7b951a8SRobert Watson static int
429f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string)
430f7b951a8SRobert Watson {
431f7b951a8SRobert Watson 	int error;
432f7b951a8SRobert Watson 
433da77b2faSRobert Watson 	MAC_INTERNALIZE(socket, label, string);
434f7b951a8SRobert Watson 
435f7b951a8SRobert Watson 	return (error);
436f7b951a8SRobert Watson }
437f7b951a8SRobert Watson 
43895fab37eSRobert Watson void
43995fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet)
44095fab37eSRobert Watson {
44195fab37eSRobert Watson 
442eca8a663SRobert Watson 	MAC_PERFORM(create_ifnet, ifnet, ifnet->if_label);
44395fab37eSRobert Watson }
44495fab37eSRobert Watson 
44595fab37eSRobert Watson void
44695fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
44795fab37eSRobert Watson {
44895fab37eSRobert Watson 
449eca8a663SRobert Watson 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, bpf_d->bd_label);
45095fab37eSRobert Watson }
45195fab37eSRobert Watson 
45295fab37eSRobert Watson void
45395fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket)
45495fab37eSRobert Watson {
45595fab37eSRobert Watson 
456eca8a663SRobert Watson 	MAC_PERFORM(create_socket, cred, socket, socket->so_label);
45795fab37eSRobert Watson }
45895fab37eSRobert Watson 
45995fab37eSRobert Watson void
46095fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket,
46195fab37eSRobert Watson     struct socket *newsocket)
46295fab37eSRobert Watson {
46395fab37eSRobert Watson 
464eca8a663SRobert Watson 	MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label,
465eca8a663SRobert Watson 	    newsocket, newsocket->so_label);
46695fab37eSRobert Watson }
46795fab37eSRobert Watson 
46895fab37eSRobert Watson static void
46995fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket,
47095fab37eSRobert Watson     struct label *newlabel)
47195fab37eSRobert Watson {
47295fab37eSRobert Watson 
473eca8a663SRobert Watson 	MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel);
47495fab37eSRobert Watson }
47595fab37eSRobert Watson 
47695fab37eSRobert Watson void
47795fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
47895fab37eSRobert Watson {
47910eeb10cSRobert Watson 	struct label *label;
48095fab37eSRobert Watson 
48110eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
48210eeb10cSRobert Watson 
48310eeb10cSRobert Watson 	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
484eca8a663SRobert Watson 	    socket->so_peerlabel);
48595fab37eSRobert Watson }
48695fab37eSRobert Watson 
48795fab37eSRobert Watson void
48895fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket,
48995fab37eSRobert Watson     struct socket *newsocket)
49095fab37eSRobert Watson {
49195fab37eSRobert Watson 
49295fab37eSRobert Watson 	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
493eca8a663SRobert Watson 	    oldsocket->so_label, newsocket, newsocket->so_peerlabel);
49495fab37eSRobert Watson }
49595fab37eSRobert Watson 
49695fab37eSRobert Watson void
49795fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
49895fab37eSRobert Watson {
49910eeb10cSRobert Watson 	struct label *label;
50010eeb10cSRobert Watson 
50110eeb10cSRobert Watson 	label = mbuf_to_label(datagram);
50295fab37eSRobert Watson 
503eca8a663SRobert Watson 	MAC_PERFORM(create_datagram_from_ipq, ipq, ipq->ipq_label,
50410eeb10cSRobert Watson 	    datagram, label);
50595fab37eSRobert Watson }
50695fab37eSRobert Watson 
50795fab37eSRobert Watson void
50895fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
50995fab37eSRobert Watson {
51010eeb10cSRobert Watson 	struct label *datagramlabel, *fragmentlabel;
51195fab37eSRobert Watson 
51210eeb10cSRobert Watson 	datagramlabel = mbuf_to_label(datagram);
51310eeb10cSRobert Watson 	fragmentlabel = mbuf_to_label(fragment);
51410eeb10cSRobert Watson 
51510eeb10cSRobert Watson 	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
51610eeb10cSRobert Watson 	    fragmentlabel);
51795fab37eSRobert Watson }
51895fab37eSRobert Watson 
51995fab37eSRobert Watson void
52095fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
52195fab37eSRobert Watson {
52210eeb10cSRobert Watson 	struct label *label;
52395fab37eSRobert Watson 
52410eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
52510eeb10cSRobert Watson 
526eca8a663SRobert Watson 	MAC_PERFORM(create_ipq, fragment, label, ipq, ipq->ipq_label);
52795fab37eSRobert Watson }
52895fab37eSRobert Watson 
52995fab37eSRobert Watson void
53095fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
53195fab37eSRobert Watson {
53210eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
53395fab37eSRobert Watson 
53410eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
53510eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
53610eeb10cSRobert Watson 
53710eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
53810eeb10cSRobert Watson 	    newmbuflabel);
53995fab37eSRobert Watson }
54095fab37eSRobert Watson 
54195fab37eSRobert Watson void
54295fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
54395fab37eSRobert Watson {
54410eeb10cSRobert Watson 	struct label *label;
54510eeb10cSRobert Watson 
54610eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
54795fab37eSRobert Watson 
548eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, bpf_d->bd_label, mbuf,
54910eeb10cSRobert Watson 	    label);
55095fab37eSRobert Watson }
55195fab37eSRobert Watson 
55295fab37eSRobert Watson void
55395fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
55495fab37eSRobert Watson {
55510eeb10cSRobert Watson 	struct label *label;
55610eeb10cSRobert Watson 
55710eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
55895fab37eSRobert Watson 
559eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_linklayer, ifnet, ifnet->if_label, mbuf,
56010eeb10cSRobert Watson 	    label);
56195fab37eSRobert Watson }
56295fab37eSRobert Watson 
56395fab37eSRobert Watson void
56495fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
56595fab37eSRobert Watson {
56610eeb10cSRobert Watson 	struct label *label;
56710eeb10cSRobert Watson 
56810eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
56995fab37eSRobert Watson 
570eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, ifnet->if_label, mbuf,
57110eeb10cSRobert Watson 	    label);
57295fab37eSRobert Watson }
57395fab37eSRobert Watson 
57495fab37eSRobert Watson void
57595fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
57695fab37eSRobert Watson     struct mbuf *newmbuf)
57795fab37eSRobert Watson {
57810eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
57995fab37eSRobert Watson 
58010eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
58110eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
58210eeb10cSRobert Watson 
58310eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
584eca8a663SRobert Watson 	    ifnet, ifnet->if_label, newmbuf, newmbuflabel);
58595fab37eSRobert Watson }
58695fab37eSRobert Watson 
58795fab37eSRobert Watson void
58895fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
58995fab37eSRobert Watson {
59010eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
59195fab37eSRobert Watson 
59210eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
59310eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
59410eeb10cSRobert Watson 
59510eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
59610eeb10cSRobert Watson 	    newmbuflabel);
59795fab37eSRobert Watson }
59895fab37eSRobert Watson 
59995fab37eSRobert Watson int
60095fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
60195fab37eSRobert Watson {
60210eeb10cSRobert Watson 	struct label *label;
60395fab37eSRobert Watson 	int result;
60495fab37eSRobert Watson 
60510eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
60610eeb10cSRobert Watson 
60795fab37eSRobert Watson 	result = 1;
60810eeb10cSRobert Watson 	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
609eca8a663SRobert Watson 	    ipq->ipq_label);
61095fab37eSRobert Watson 
61195fab37eSRobert Watson 	return (result);
61295fab37eSRobert Watson }
61395fab37eSRobert Watson 
61495fab37eSRobert Watson void
615eb8c7f99SRobert Watson mac_reflect_mbuf_icmp(struct mbuf *m)
616eb8c7f99SRobert Watson {
617eb8c7f99SRobert Watson 	struct label *label;
618eb8c7f99SRobert Watson 
619eb8c7f99SRobert Watson 	label = mbuf_to_label(m);
620eb8c7f99SRobert Watson 
621eb8c7f99SRobert Watson 	MAC_PERFORM(reflect_mbuf_icmp, m, label);
622eb8c7f99SRobert Watson }
623eb8c7f99SRobert Watson void
624eb8c7f99SRobert Watson mac_reflect_mbuf_tcp(struct mbuf *m)
625eb8c7f99SRobert Watson {
626eb8c7f99SRobert Watson 	struct label *label;
627eb8c7f99SRobert Watson 
628eb8c7f99SRobert Watson 	label = mbuf_to_label(m);
629eb8c7f99SRobert Watson 
630eb8c7f99SRobert Watson 	MAC_PERFORM(reflect_mbuf_tcp, m, label);
631eb8c7f99SRobert Watson }
632eb8c7f99SRobert Watson 
633eb8c7f99SRobert Watson void
63495fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
63595fab37eSRobert Watson {
63610eeb10cSRobert Watson 	struct label *label;
63795fab37eSRobert Watson 
63810eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
63910eeb10cSRobert Watson 
640eca8a663SRobert Watson 	MAC_PERFORM(update_ipq, fragment, label, ipq, ipq->ipq_label);
64195fab37eSRobert Watson }
64295fab37eSRobert Watson 
64395fab37eSRobert Watson void
64495fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
64595fab37eSRobert Watson {
64610eeb10cSRobert Watson 	struct label *label;
64710eeb10cSRobert Watson 
64810eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
64995fab37eSRobert Watson 
650eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf,
65110eeb10cSRobert Watson 	    label);
65295fab37eSRobert Watson }
65395fab37eSRobert Watson 
65495fab37eSRobert Watson int
65595fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
65695fab37eSRobert Watson {
65795fab37eSRobert Watson 	int error;
65895fab37eSRobert Watson 
65995fab37eSRobert Watson 	if (!mac_enforce_network)
66095fab37eSRobert Watson 		return (0);
66195fab37eSRobert Watson 
662eca8a663SRobert Watson 	MAC_CHECK(check_bpfdesc_receive, bpf_d, bpf_d->bd_label, ifnet,
663eca8a663SRobert Watson 	    ifnet->if_label);
66495fab37eSRobert Watson 
66595fab37eSRobert Watson 	return (error);
66695fab37eSRobert Watson }
66795fab37eSRobert Watson 
66895fab37eSRobert Watson int
66995fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
67095fab37eSRobert Watson {
67110eeb10cSRobert Watson 	struct label *label;
67295fab37eSRobert Watson 	int error;
67395fab37eSRobert Watson 
674225bff6fSRobert Watson 	M_ASSERTPKTHDR(mbuf);
675225bff6fSRobert Watson 
67695fab37eSRobert Watson 	if (!mac_enforce_network)
67795fab37eSRobert Watson 		return (0);
67895fab37eSRobert Watson 
67910eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
68095fab37eSRobert Watson 
681eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_transmit, ifnet, ifnet->if_label, mbuf,
68210eeb10cSRobert Watson 	    label);
68395fab37eSRobert Watson 
68495fab37eSRobert Watson 	return (error);
68595fab37eSRobert Watson }
68695fab37eSRobert Watson 
68795fab37eSRobert Watson int
68895fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
68995fab37eSRobert Watson     struct sockaddr *sockaddr)
69095fab37eSRobert Watson {
69195fab37eSRobert Watson 	int error;
69295fab37eSRobert Watson 
69395fab37eSRobert Watson 	if (!mac_enforce_socket)
69495fab37eSRobert Watson 		return (0);
69595fab37eSRobert Watson 
696eca8a663SRobert Watson 	MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label,
69795fab37eSRobert Watson 	    sockaddr);
69895fab37eSRobert Watson 
69995fab37eSRobert Watson 	return (error);
70095fab37eSRobert Watson }
70195fab37eSRobert Watson 
70295fab37eSRobert Watson int
70395fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket,
70495fab37eSRobert Watson     struct sockaddr *sockaddr)
70595fab37eSRobert Watson {
70695fab37eSRobert Watson 	int error;
70795fab37eSRobert Watson 
70895fab37eSRobert Watson 	if (!mac_enforce_socket)
70995fab37eSRobert Watson 		return (0);
71095fab37eSRobert Watson 
711eca8a663SRobert Watson 	MAC_CHECK(check_socket_connect, cred, socket, socket->so_label,
71295fab37eSRobert Watson 	    sockaddr);
71395fab37eSRobert Watson 
71495fab37eSRobert Watson 	return (error);
71595fab37eSRobert Watson }
71695fab37eSRobert Watson 
71795fab37eSRobert Watson int
718d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
719d61198e4SRobert Watson {
72010eeb10cSRobert Watson 	struct label *label;
721d61198e4SRobert Watson 	int error;
722d61198e4SRobert Watson 
723d61198e4SRobert Watson 	if (!mac_enforce_socket)
724d61198e4SRobert Watson 		return (0);
725d61198e4SRobert Watson 
72610eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
72710eeb10cSRobert Watson 
728eca8a663SRobert Watson 	MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf,
72910eeb10cSRobert Watson 	    label);
730d61198e4SRobert Watson 
731d61198e4SRobert Watson 	return (error);
732d61198e4SRobert Watson }
733d61198e4SRobert Watson 
734d61198e4SRobert Watson int
73595fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket)
73695fab37eSRobert Watson {
73795fab37eSRobert Watson 	int error;
73895fab37eSRobert Watson 
73995fab37eSRobert Watson 	if (!mac_enforce_socket)
74095fab37eSRobert Watson 		return (0);
74195fab37eSRobert Watson 
742eca8a663SRobert Watson 	MAC_CHECK(check_socket_listen, cred, socket, socket->so_label);
74395fab37eSRobert Watson 	return (error);
74495fab37eSRobert Watson }
74595fab37eSRobert Watson 
746b371c939SRobert Watson int
747b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so)
748b371c939SRobert Watson {
749b371c939SRobert Watson 	int error;
750b371c939SRobert Watson 
751b371c939SRobert Watson 	if (!mac_enforce_socket)
752b371c939SRobert Watson 		return (0);
753b371c939SRobert Watson 
754eca8a663SRobert Watson 	MAC_CHECK(check_socket_receive, cred, so, so->so_label);
755b371c939SRobert Watson 
756b371c939SRobert Watson 	return (error);
757b371c939SRobert Watson }
758b371c939SRobert Watson 
75995fab37eSRobert Watson static int
76095fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
76195fab37eSRobert Watson     struct label *newlabel)
76295fab37eSRobert Watson {
76395fab37eSRobert Watson 	int error;
76495fab37eSRobert Watson 
765eca8a663SRobert Watson 	MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label,
76695fab37eSRobert Watson 	    newlabel);
76795fab37eSRobert Watson 
76895fab37eSRobert Watson 	return (error);
76995fab37eSRobert Watson }
77095fab37eSRobert Watson 
77195fab37eSRobert Watson int
772b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so)
773b371c939SRobert Watson {
774b371c939SRobert Watson 	int error;
775b371c939SRobert Watson 
776b371c939SRobert Watson 	if (!mac_enforce_socket)
777b371c939SRobert Watson 		return (0);
778b371c939SRobert Watson 
779eca8a663SRobert Watson 	MAC_CHECK(check_socket_send, cred, so, so->so_label);
780b371c939SRobert Watson 
781b371c939SRobert Watson 	return (error);
782b371c939SRobert Watson }
783b371c939SRobert Watson 
784b371c939SRobert Watson int
78595fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket)
78695fab37eSRobert Watson {
78795fab37eSRobert Watson 	int error;
78895fab37eSRobert Watson 
78995fab37eSRobert Watson 	if (!mac_enforce_socket)
79095fab37eSRobert Watson 		return (0);
79195fab37eSRobert Watson 
792eca8a663SRobert Watson 	MAC_CHECK(check_socket_visible, cred, socket, socket->so_label);
79395fab37eSRobert Watson 
79495fab37eSRobert Watson 	return (error);
79595fab37eSRobert Watson }
79695fab37eSRobert Watson 
79795fab37eSRobert Watson int
79895fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
79995fab37eSRobert Watson     struct ifnet *ifnet)
80095fab37eSRobert Watson {
801f7b951a8SRobert Watson 	char *elements, *buffer;
802f7b951a8SRobert Watson 	struct mac mac;
80395fab37eSRobert Watson 	int error;
80495fab37eSRobert Watson 
805f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
80695fab37eSRobert Watson 	if (error)
80795fab37eSRobert Watson 		return (error);
80895fab37eSRobert Watson 
809f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
810f7b951a8SRobert Watson 	if (error)
811f7b951a8SRobert Watson 		return (error);
812f7b951a8SRobert Watson 
813a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
814f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
815f7b951a8SRobert Watson 	if (error) {
816f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
817f7b951a8SRobert Watson 		return (error);
818f7b951a8SRobert Watson 	}
819f7b951a8SRobert Watson 
820a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
821eca8a663SRobert Watson 	error = mac_externalize_ifnet_label(ifnet->if_label, elements,
82283b7b0edSRobert Watson 	    buffer, mac.m_buflen);
823f7b951a8SRobert Watson 	if (error == 0)
824f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
825f7b951a8SRobert Watson 
826f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
827f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
828f7b951a8SRobert Watson 
829f7b951a8SRobert Watson 	return (error);
83095fab37eSRobert Watson }
83195fab37eSRobert Watson 
83295fab37eSRobert Watson int
83395fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
83495fab37eSRobert Watson     struct ifnet *ifnet)
83595fab37eSRobert Watson {
836eca8a663SRobert Watson 	struct label *intlabel;
837f7b951a8SRobert Watson 	struct mac mac;
838f7b951a8SRobert Watson 	char *buffer;
83995fab37eSRobert Watson 	int error;
84095fab37eSRobert Watson 
841f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
84295fab37eSRobert Watson 	if (error)
84395fab37eSRobert Watson 		return (error);
84495fab37eSRobert Watson 
845f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
84695fab37eSRobert Watson 	if (error)
84795fab37eSRobert Watson 		return (error);
84895fab37eSRobert Watson 
849a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
850f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
851f7b951a8SRobert Watson 	if (error) {
852f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
853f7b951a8SRobert Watson 		return (error);
854f7b951a8SRobert Watson 	}
855f7b951a8SRobert Watson 
856eca8a663SRobert Watson 	intlabel = mac_ifnet_label_alloc();
857eca8a663SRobert Watson 	error = mac_internalize_ifnet_label(intlabel, buffer);
858f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
859f7b951a8SRobert Watson 	if (error) {
860eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
861f7b951a8SRobert Watson 		return (error);
862f7b951a8SRobert Watson 	}
863f7b951a8SRobert Watson 
86495fab37eSRobert Watson 	/*
86595fab37eSRobert Watson 	 * XXX: Note that this is a redundant privilege check, since
86695fab37eSRobert Watson 	 * policies impose this check themselves if required by the
86795fab37eSRobert Watson 	 * policy.  Eventually, this should go away.
86895fab37eSRobert Watson 	 */
86995fab37eSRobert Watson 	error = suser_cred(cred, 0);
870f7b951a8SRobert Watson 	if (error) {
871eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
872f7b951a8SRobert Watson 		return (error);
873f7b951a8SRobert Watson 	}
87495fab37eSRobert Watson 
875eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, ifnet->if_label,
876eca8a663SRobert Watson 	    intlabel);
877f7b951a8SRobert Watson 	if (error) {
878eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
879f7b951a8SRobert Watson 		return (error);
880f7b951a8SRobert Watson 	}
88195fab37eSRobert Watson 
882eca8a663SRobert Watson 	MAC_PERFORM(relabel_ifnet, cred, ifnet, ifnet->if_label, intlabel);
88395fab37eSRobert Watson 
884eca8a663SRobert Watson 	mac_ifnet_label_free(intlabel);
885f7b951a8SRobert Watson 	return (0);
88695fab37eSRobert Watson }
88795fab37eSRobert Watson 
88895fab37eSRobert Watson int
88995fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
890f7b951a8SRobert Watson     struct mac *mac)
89195fab37eSRobert Watson {
892eca8a663SRobert Watson 	struct label *intlabel;
893f7b951a8SRobert Watson 	char *buffer;
89495fab37eSRobert Watson 	int error;
89595fab37eSRobert Watson 
896f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
89795fab37eSRobert Watson 	if (error)
89895fab37eSRobert Watson 		return (error);
89995fab37eSRobert Watson 
900a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
901f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
902f7b951a8SRobert Watson 	if (error) {
903f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
904f7b951a8SRobert Watson 		return (error);
905f7b951a8SRobert Watson 	}
906f7b951a8SRobert Watson 
907eca8a663SRobert Watson 	intlabel = mac_socket_label_alloc(M_WAITOK);
908eca8a663SRobert Watson 	error = mac_internalize_socket_label(intlabel, buffer);
909f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
910f7b951a8SRobert Watson 	if (error) {
911eca8a663SRobert Watson 		mac_socket_label_free(intlabel);
912f7b951a8SRobert Watson 		return (error);
913f7b951a8SRobert Watson 	}
914f7b951a8SRobert Watson 
915eca8a663SRobert Watson 	mac_check_socket_relabel(cred, so, intlabel);
91695fab37eSRobert Watson 	if (error) {
917eca8a663SRobert Watson 		mac_socket_label_free(intlabel);
91895fab37eSRobert Watson 		return (error);
91995fab37eSRobert Watson 	}
92095fab37eSRobert Watson 
921eca8a663SRobert Watson 	mac_relabel_socket(cred, so, intlabel);
92295fab37eSRobert Watson 
923eca8a663SRobert Watson 	mac_socket_label_free(intlabel);
92495fab37eSRobert Watson 	return (0);
92595fab37eSRobert Watson }
92695fab37eSRobert Watson 
92795fab37eSRobert Watson int
92895fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
929f7b951a8SRobert Watson     struct mac *mac)
93095fab37eSRobert Watson {
931f7b951a8SRobert Watson 	char *buffer, *elements;
932f7b951a8SRobert Watson 	int error;
93395fab37eSRobert Watson 
934f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
935f7b951a8SRobert Watson 	if (error)
936f7b951a8SRobert Watson 		return (error);
937f7b951a8SRobert Watson 
938a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
939f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
940f7b951a8SRobert Watson 	if (error) {
941f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
942f7b951a8SRobert Watson 		return (error);
943f7b951a8SRobert Watson 	}
944f7b951a8SRobert Watson 
945a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
946eca8a663SRobert Watson 	error = mac_externalize_socket_label(so->so_label, elements,
94783b7b0edSRobert Watson 	    buffer, mac->m_buflen);
948f7b951a8SRobert Watson 	if (error == 0)
949f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
950f7b951a8SRobert Watson 
951f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
952f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
953f7b951a8SRobert Watson 
954f7b951a8SRobert Watson 	return (error);
95595fab37eSRobert Watson }
95695fab37eSRobert Watson 
95795fab37eSRobert Watson int
95895fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
959f7b951a8SRobert Watson     struct mac *mac)
96095fab37eSRobert Watson {
961f7b951a8SRobert Watson 	char *elements, *buffer;
962f7b951a8SRobert Watson 	int error;
96395fab37eSRobert Watson 
964f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
965f7b951a8SRobert Watson 	if (error)
966f7b951a8SRobert Watson 		return (error);
967f7b951a8SRobert Watson 
968a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
969f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
970f7b951a8SRobert Watson 	if (error) {
971f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
972f7b951a8SRobert Watson 		return (error);
973f7b951a8SRobert Watson 	}
974f7b951a8SRobert Watson 
975a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
976eca8a663SRobert Watson 	error = mac_externalize_socket_peer_label(so->so_peerlabel,
97783b7b0edSRobert Watson 	    elements, buffer, mac->m_buflen);
978f7b951a8SRobert Watson 	if (error == 0)
979f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
980f7b951a8SRobert Watson 
981f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
982f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
983f7b951a8SRobert Watson 
984f7b951a8SRobert Watson 	return (error);
98595fab37eSRobert Watson }
986