xref: /freebsd/sys/security/mac/mac_net.c (revision 2220907b6ece3ccf47b7696ff8b5d2d4b35be066)
17bc82500SRobert Watson /*-
2f6a41092SRobert Watson  * Copyright (c) 1999-2002 Robert N. M. Watson
37bc82500SRobert Watson  * Copyright (c) 2001 Ilmar S. Habibulin
4c66b4d8dSRobert Watson  * Copyright (c) 2001-2004 Networks Associates Technology, Inc.
57bc82500SRobert Watson  * All rights reserved.
67bc82500SRobert Watson  *
77bc82500SRobert Watson  * This software was developed by Robert Watson and Ilmar Habibulin for the
87bc82500SRobert Watson  * TrustedBSD Project.
97bc82500SRobert Watson  *
106201265bSRobert Watson  * This software was developed for the FreeBSD Project in part by Network
116201265bSRobert Watson  * Associates Laboratories, the Security Research Division of Network
126201265bSRobert Watson  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
136201265bSRobert Watson  * as part of the DARPA CHATS research program.
147bc82500SRobert Watson  *
157bc82500SRobert Watson  * Redistribution and use in source and binary forms, with or without
167bc82500SRobert Watson  * modification, are permitted provided that the following conditions
177bc82500SRobert Watson  * are met:
187bc82500SRobert Watson  * 1. Redistributions of source code must retain the above copyright
197bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer.
207bc82500SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
217bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
227bc82500SRobert Watson  *    documentation and/or other materials provided with the distribution.
237bc82500SRobert Watson  *
247bc82500SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
257bc82500SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
267bc82500SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
277bc82500SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
287bc82500SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
297bc82500SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
307bc82500SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
317bc82500SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
327bc82500SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
337bc82500SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
347bc82500SRobert Watson  * SUCH DAMAGE.
357bc82500SRobert Watson  */
36677b542eSDavid E. O'Brien 
37677b542eSDavid E. O'Brien #include <sys/cdefs.h>
38677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
39677b542eSDavid E. O'Brien 
407bc82500SRobert Watson #include "opt_mac.h"
41f9d0d524SRobert Watson 
427bc82500SRobert Watson #include <sys/param.h>
4395fab37eSRobert Watson #include <sys/kernel.h>
4495fab37eSRobert Watson #include <sys/lock.h>
45b656366bSBruce Evans #include <sys/malloc.h>
4695fab37eSRobert Watson #include <sys/mutex.h>
4795fab37eSRobert Watson #include <sys/mac.h>
48f51e5803SRobert Watson #include <sys/sbuf.h>
4995fab37eSRobert Watson #include <sys/systm.h>
5095fab37eSRobert Watson #include <sys/mount.h>
5195fab37eSRobert Watson #include <sys/file.h>
5295fab37eSRobert Watson #include <sys/namei.h>
53a557af22SRobert Watson #include <sys/protosw.h>
5495fab37eSRobert Watson #include <sys/socket.h>
5595fab37eSRobert Watson #include <sys/socketvar.h>
5695fab37eSRobert Watson #include <sys/sysctl.h>
5795fab37eSRobert Watson 
5895fab37eSRobert Watson #include <sys/mac_policy.h>
5995fab37eSRobert Watson 
6095fab37eSRobert Watson #include <net/bpfdesc.h>
6195fab37eSRobert Watson #include <net/if.h>
6295fab37eSRobert Watson #include <net/if_var.h>
6395fab37eSRobert Watson 
6428e65e3dSRobert Watson #include <security/mac/mac_internal.h>
65a3df768bSRobert Watson 
66c66b4d8dSRobert Watson /*
67c66b4d8dSRobert Watson  * mac_enforce_network is used by IPv4 and IPv6 checks, and so must
68c66b4d8dSRobert Watson  * be non-static for now.
69c66b4d8dSRobert Watson  */
70c66b4d8dSRobert Watson int	mac_enforce_network = 1;
7195fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
7295fab37eSRobert Watson     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
7395fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
7495fab37eSRobert Watson 
75f050add5SRobert Watson #ifdef MAC_DEBUG
76c66b4d8dSRobert Watson static unsigned int nmacbpfdescs, nmacifnets, nmacmbufs;
778d8d5ea8SRobert Watson 
78b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
7995fab37eSRobert Watson     &nmacbpfdescs, 0, "number of bpfdescs in use");
80c66b4d8dSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
81c66b4d8dSRobert Watson     &nmacifnets, 0, "number of ifnets in use");
82c66b4d8dSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
83c66b4d8dSRobert Watson     &nmacmbufs, 0, "number of mbufs in use");
84f050add5SRobert Watson #endif
8595fab37eSRobert Watson 
862220907bSRobert Watson /*
872220907bSRobert Watson  * XXXRW: struct ifnet locking is incomplete in the network code, so we
882220907bSRobert Watson  * use our own global mutex for struct ifnet.  Non-ideal, but should help
892220907bSRobert Watson  * in the SMP environment.
902220907bSRobert Watson  */
912220907bSRobert Watson static struct mtx mac_ifnet_mtx;
922220907bSRobert Watson MTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF);
932220907bSRobert Watson #define	MAC_IFNET_LOCK(ifp)	mtx_lock(&mac_ifnet_mtx)
942220907bSRobert Watson #define	MAC_IFNET_UNLOCK(ifp)	mtx_unlock(&mac_ifnet_mtx)
952220907bSRobert Watson 
96c66b4d8dSRobert Watson struct label *
97c66b4d8dSRobert Watson mac_mbuf_to_label(struct mbuf *mbuf)
9810eeb10cSRobert Watson {
99225bff6fSRobert Watson 	struct m_tag *tag;
10010eeb10cSRobert Watson 	struct label *label;
10110eeb10cSRobert Watson 
102583284e1SRobert Watson 	if (mbuf == NULL)
103583284e1SRobert Watson 		return (NULL);
104225bff6fSRobert Watson 	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
105583284e1SRobert Watson 	if (tag == NULL)
106583284e1SRobert Watson 		return (NULL);
107225bff6fSRobert Watson 	label = (struct label *)(tag+1);
10810eeb10cSRobert Watson 	return (label);
10910eeb10cSRobert Watson }
11010eeb10cSRobert Watson 
111eca8a663SRobert Watson static struct label *
112eca8a663SRobert Watson mac_bpfdesc_label_alloc(void)
113eca8a663SRobert Watson {
114eca8a663SRobert Watson 	struct label *label;
115eca8a663SRobert Watson 
116eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
117eca8a663SRobert Watson 	MAC_PERFORM(init_bpfdesc_label, label);
118eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacbpfdescs);
119eca8a663SRobert Watson 	return (label);
120eca8a663SRobert Watson }
121eca8a663SRobert Watson 
12208bcdc58SRobert Watson void
12387807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d)
12408bcdc58SRobert Watson {
12508bcdc58SRobert Watson 
126eca8a663SRobert Watson 	bpf_d->bd_label = mac_bpfdesc_label_alloc();
12708bcdc58SRobert Watson }
12808bcdc58SRobert Watson 
129eca8a663SRobert Watson static struct label *
130eca8a663SRobert Watson mac_ifnet_label_alloc(void)
131f7b951a8SRobert Watson {
132eca8a663SRobert Watson 	struct label *label;
133f7b951a8SRobert Watson 
134eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
135f7b951a8SRobert Watson 	MAC_PERFORM(init_ifnet_label, label);
1368d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_INC(&nmacifnets);
137eca8a663SRobert Watson 	return (label);
138f7b951a8SRobert Watson }
139f7b951a8SRobert Watson 
14008bcdc58SRobert Watson void
14108bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp)
14208bcdc58SRobert Watson {
14308bcdc58SRobert Watson 
144eca8a663SRobert Watson 	ifp->if_label = mac_ifnet_label_alloc();
145eca8a663SRobert Watson }
146eca8a663SRobert Watson 
14787807196SRobert Watson int
148225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag)
14908bcdc58SRobert Watson {
150225bff6fSRobert Watson 	struct label *label;
1516d1a6a9aSRobert Watson 	int error;
15256c15412SRobert Watson 
153225bff6fSRobert Watson 	label = (struct label *) (tag + 1);
154225bff6fSRobert Watson 	mac_init_label(label);
15508bcdc58SRobert Watson 
1566d1a6a9aSRobert Watson 	MAC_CHECK(init_mbuf_label, label, flag);
15756c15412SRobert Watson 	if (error) {
158225bff6fSRobert Watson 		MAC_PERFORM(destroy_mbuf_label, label);
159225bff6fSRobert Watson 		mac_destroy_label(label);
1608d8d5ea8SRobert Watson 	} else {
1618d8d5ea8SRobert Watson 		MAC_DEBUG_COUNTER_INC(&nmacmbufs);
16256c15412SRobert Watson 	}
16356c15412SRobert Watson 	return (error);
16408bcdc58SRobert Watson }
16508bcdc58SRobert Watson 
166225bff6fSRobert Watson int
167225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag)
168225bff6fSRobert Watson {
169225bff6fSRobert Watson 	struct m_tag *tag;
170225bff6fSRobert Watson 	int error;
171225bff6fSRobert Watson 
172225bff6fSRobert Watson 	M_ASSERTPKTHDR(m);
173225bff6fSRobert Watson 
174225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
175225bff6fSRobert Watson 	/*
17619c3e120SRobert Watson 	 * If conditionally allocating mbuf labels, don't allocate unless
17719c3e120SRobert Watson 	 * they are required.
178225bff6fSRobert Watson 	 */
17919c3e120SRobert Watson 	if (!mac_labelmbufs)
18019c3e120SRobert Watson 		return (0);
181225bff6fSRobert Watson #endif
182225bff6fSRobert Watson 	tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
183225bff6fSRobert Watson 	    flag);
184225bff6fSRobert Watson 	if (tag == NULL)
185225bff6fSRobert Watson 		return (ENOMEM);
186225bff6fSRobert Watson 	error = mac_init_mbuf_tag(tag, flag);
187225bff6fSRobert Watson 	if (error) {
188225bff6fSRobert Watson 		m_tag_free(tag);
189225bff6fSRobert Watson 		return (error);
190225bff6fSRobert Watson 	}
191225bff6fSRobert Watson 	m_tag_prepend(m, tag);
192225bff6fSRobert Watson 	return (0);
193225bff6fSRobert Watson }
194225bff6fSRobert Watson 
195eca8a663SRobert Watson static void
196eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label)
197eca8a663SRobert Watson {
19883985c26SRobert Watson 
199eca8a663SRobert Watson 	MAC_PERFORM(destroy_bpfdesc_label, label);
200eca8a663SRobert Watson 	mac_labelzone_free(label);
201eca8a663SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs);
20287807196SRobert Watson }
20387807196SRobert Watson 
204763bbd2fSRobert Watson void
20508bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d)
20608bcdc58SRobert Watson {
20708bcdc58SRobert Watson 
208eca8a663SRobert Watson 	mac_bpfdesc_label_free(bpf_d->bd_label);
209eca8a663SRobert Watson 	bpf_d->bd_label = NULL;
21008bcdc58SRobert Watson }
21108bcdc58SRobert Watson 
212f7b951a8SRobert Watson static void
213eca8a663SRobert Watson mac_ifnet_label_free(struct label *label)
214f7b951a8SRobert Watson {
215f7b951a8SRobert Watson 
216f7b951a8SRobert Watson 	MAC_PERFORM(destroy_ifnet_label, label);
217eca8a663SRobert Watson 	mac_labelzone_free(label);
2188d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacifnets);
219f7b951a8SRobert Watson }
220f7b951a8SRobert Watson 
22187807196SRobert Watson void
22287807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp)
22387807196SRobert Watson {
22487807196SRobert Watson 
225eca8a663SRobert Watson 	mac_ifnet_label_free(ifp->if_label);
226eca8a663SRobert Watson 	ifp->if_label = NULL;
227eca8a663SRobert Watson }
228eca8a663SRobert Watson 
22987807196SRobert Watson void
230225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag)
23187807196SRobert Watson {
232225bff6fSRobert Watson 	struct label *label;
23387807196SRobert Watson 
234225bff6fSRobert Watson 	label = (struct label *)(tag+1);
235225bff6fSRobert Watson 
236225bff6fSRobert Watson 	MAC_PERFORM(destroy_mbuf_label, label);
237225bff6fSRobert Watson 	mac_destroy_label(label);
2388d8d5ea8SRobert Watson 	MAC_DEBUG_COUNTER_DEC(&nmacmbufs);
23908bcdc58SRobert Watson }
24008bcdc58SRobert Watson 
241b0323ea3SRobert Watson void
242225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
243225bff6fSRobert Watson {
244225bff6fSRobert Watson 	struct label *src_label, *dest_label;
245225bff6fSRobert Watson 
246225bff6fSRobert Watson 	src_label = (struct label *)(src+1);
247225bff6fSRobert Watson 	dest_label = (struct label *)(dest+1);
248225bff6fSRobert Watson 
249225bff6fSRobert Watson 	/*
250225bff6fSRobert Watson 	 * mac_init_mbuf_tag() is called on the target tag in
251225bff6fSRobert Watson 	 * m_tag_copy(), so we don't need to call it here.
252225bff6fSRobert Watson 	 */
253225bff6fSRobert Watson 	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
254225bff6fSRobert Watson }
255225bff6fSRobert Watson 
2562220907bSRobert Watson static void
2572220907bSRobert Watson mac_copy_ifnet_label(struct label *src, struct label *dest)
2582220907bSRobert Watson {
2592220907bSRobert Watson 
2602220907bSRobert Watson 	MAC_PERFORM(copy_ifnet_label, src, dest);
2612220907bSRobert Watson }
2622220907bSRobert Watson 
26369bbb5b1SRobert Watson static int
264f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements,
26583b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
26669bbb5b1SRobert Watson {
26769bbb5b1SRobert Watson 	int error;
26869bbb5b1SRobert Watson 
269da77b2faSRobert Watson 	MAC_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
270f7b951a8SRobert Watson 
271f7b951a8SRobert Watson 	return (error);
272f7b951a8SRobert Watson }
273f7b951a8SRobert Watson 
274f7b951a8SRobert Watson static int
275f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string)
276f7b951a8SRobert Watson {
277f7b951a8SRobert Watson 	int error;
278f7b951a8SRobert Watson 
279da77b2faSRobert Watson 	MAC_INTERNALIZE(ifnet, label, string);
280f7b951a8SRobert Watson 
281f7b951a8SRobert Watson 	return (error);
282f7b951a8SRobert Watson }
283f7b951a8SRobert Watson 
28495fab37eSRobert Watson void
28595fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet)
28695fab37eSRobert Watson {
28795fab37eSRobert Watson 
2882220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
289eca8a663SRobert Watson 	MAC_PERFORM(create_ifnet, ifnet, ifnet->if_label);
2902220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
29195fab37eSRobert Watson }
29295fab37eSRobert Watson 
29395fab37eSRobert Watson void
29495fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
29595fab37eSRobert Watson {
29695fab37eSRobert Watson 
297eca8a663SRobert Watson 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, bpf_d->bd_label);
29895fab37eSRobert Watson }
29995fab37eSRobert Watson 
30095fab37eSRobert Watson void
30195fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
30295fab37eSRobert Watson {
30310eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
30495fab37eSRobert Watson 
305c66b4d8dSRobert Watson 	oldmbuflabel = mac_mbuf_to_label(oldmbuf);
306c66b4d8dSRobert Watson 	newmbuflabel = mac_mbuf_to_label(newmbuf);
30710eeb10cSRobert Watson 
30810eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
30910eeb10cSRobert Watson 	    newmbuflabel);
31095fab37eSRobert Watson }
31195fab37eSRobert Watson 
31295fab37eSRobert Watson void
31395fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
31495fab37eSRobert Watson {
31510eeb10cSRobert Watson 	struct label *label;
31610eeb10cSRobert Watson 
317e33d9f29SRobert Watson 	BPFD_LOCK_ASSERT(bpf_d);
318e33d9f29SRobert Watson 
319c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
32095fab37eSRobert Watson 
321eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, bpf_d->bd_label, mbuf,
32210eeb10cSRobert Watson 	    label);
32395fab37eSRobert Watson }
32495fab37eSRobert Watson 
32595fab37eSRobert Watson void
32695fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
32795fab37eSRobert Watson {
32810eeb10cSRobert Watson 	struct label *label;
32910eeb10cSRobert Watson 
330c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
33195fab37eSRobert Watson 
3322220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
333eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_linklayer, ifnet, ifnet->if_label, mbuf,
33410eeb10cSRobert Watson 	    label);
3352220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
33695fab37eSRobert Watson }
33795fab37eSRobert Watson 
33895fab37eSRobert Watson void
33995fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
34095fab37eSRobert Watson {
34110eeb10cSRobert Watson 	struct label *label;
34210eeb10cSRobert Watson 
343c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
34495fab37eSRobert Watson 
3452220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
346eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, ifnet->if_label, mbuf,
34710eeb10cSRobert Watson 	    label);
3482220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
34995fab37eSRobert Watson }
35095fab37eSRobert Watson 
35195fab37eSRobert Watson void
35295fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
35395fab37eSRobert Watson     struct mbuf *newmbuf)
35495fab37eSRobert Watson {
35510eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
35695fab37eSRobert Watson 
357c66b4d8dSRobert Watson 	oldmbuflabel = mac_mbuf_to_label(oldmbuf);
358c66b4d8dSRobert Watson 	newmbuflabel = mac_mbuf_to_label(newmbuf);
35910eeb10cSRobert Watson 
3602220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
36110eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
362eca8a663SRobert Watson 	    ifnet, ifnet->if_label, newmbuf, newmbuflabel);
3632220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
36495fab37eSRobert Watson }
36595fab37eSRobert Watson 
36695fab37eSRobert Watson void
36795fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
36895fab37eSRobert Watson {
36910eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
37095fab37eSRobert Watson 
371c66b4d8dSRobert Watson 	oldmbuflabel = mac_mbuf_to_label(oldmbuf);
372c66b4d8dSRobert Watson 	newmbuflabel = mac_mbuf_to_label(newmbuf);
37310eeb10cSRobert Watson 
37410eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
37510eeb10cSRobert Watson 	    newmbuflabel);
37695fab37eSRobert Watson }
37795fab37eSRobert Watson 
37895fab37eSRobert Watson int
37995fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
38095fab37eSRobert Watson {
38195fab37eSRobert Watson 	int error;
38295fab37eSRobert Watson 
383e33d9f29SRobert Watson 	BPFD_LOCK_ASSERT(bpf_d);
384e33d9f29SRobert Watson 
38595fab37eSRobert Watson 	if (!mac_enforce_network)
38695fab37eSRobert Watson 		return (0);
38795fab37eSRobert Watson 
3882220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
389eca8a663SRobert Watson 	MAC_CHECK(check_bpfdesc_receive, bpf_d, bpf_d->bd_label, ifnet,
390eca8a663SRobert Watson 	    ifnet->if_label);
3912220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
39295fab37eSRobert Watson 
39395fab37eSRobert Watson 	return (error);
39495fab37eSRobert Watson }
39595fab37eSRobert Watson 
39695fab37eSRobert Watson int
39795fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
39895fab37eSRobert Watson {
39910eeb10cSRobert Watson 	struct label *label;
40095fab37eSRobert Watson 	int error;
40195fab37eSRobert Watson 
402225bff6fSRobert Watson 	M_ASSERTPKTHDR(mbuf);
403225bff6fSRobert Watson 
40495fab37eSRobert Watson 	if (!mac_enforce_network)
40595fab37eSRobert Watson 		return (0);
40695fab37eSRobert Watson 
407c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
40895fab37eSRobert Watson 
4092220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
410eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_transmit, ifnet, ifnet->if_label, mbuf,
41110eeb10cSRobert Watson 	    label);
4122220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
41395fab37eSRobert Watson 
41495fab37eSRobert Watson 	return (error);
41595fab37eSRobert Watson }
41695fab37eSRobert Watson 
41795fab37eSRobert Watson int
41895fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
41995fab37eSRobert Watson     struct ifnet *ifnet)
42095fab37eSRobert Watson {
421f7b951a8SRobert Watson 	char *elements, *buffer;
4222220907bSRobert Watson 	struct label *intlabel;
423f7b951a8SRobert Watson 	struct mac mac;
42495fab37eSRobert Watson 	int error;
42595fab37eSRobert Watson 
426f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
42795fab37eSRobert Watson 	if (error)
42895fab37eSRobert Watson 		return (error);
42995fab37eSRobert Watson 
430f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
431f7b951a8SRobert Watson 	if (error)
432f7b951a8SRobert Watson 		return (error);
433f7b951a8SRobert Watson 
434a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
435f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
436f7b951a8SRobert Watson 	if (error) {
437f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
438f7b951a8SRobert Watson 		return (error);
439f7b951a8SRobert Watson 	}
440f7b951a8SRobert Watson 
441a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4422220907bSRobert Watson 	intlabel = mac_ifnet_label_alloc();
4432220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
4442220907bSRobert Watson 	mac_copy_ifnet_label(ifnet->if_label, intlabel);
4452220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
446eca8a663SRobert Watson 	error = mac_externalize_ifnet_label(ifnet->if_label, elements,
44783b7b0edSRobert Watson 	    buffer, mac.m_buflen);
4482220907bSRobert Watson 	mac_ifnet_label_free(intlabel);
449f7b951a8SRobert Watson 	if (error == 0)
450f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
451f7b951a8SRobert Watson 
452f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
453f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
454f7b951a8SRobert Watson 
455f7b951a8SRobert Watson 	return (error);
45695fab37eSRobert Watson }
45795fab37eSRobert Watson 
45895fab37eSRobert Watson int
45995fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
46095fab37eSRobert Watson     struct ifnet *ifnet)
46195fab37eSRobert Watson {
462eca8a663SRobert Watson 	struct label *intlabel;
463f7b951a8SRobert Watson 	struct mac mac;
464f7b951a8SRobert Watson 	char *buffer;
46595fab37eSRobert Watson 	int error;
46695fab37eSRobert Watson 
467f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
46895fab37eSRobert Watson 	if (error)
46995fab37eSRobert Watson 		return (error);
47095fab37eSRobert Watson 
471f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
47295fab37eSRobert Watson 	if (error)
47395fab37eSRobert Watson 		return (error);
47495fab37eSRobert Watson 
475a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
476f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
477f7b951a8SRobert Watson 	if (error) {
478f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
479f7b951a8SRobert Watson 		return (error);
480f7b951a8SRobert Watson 	}
481f7b951a8SRobert Watson 
482eca8a663SRobert Watson 	intlabel = mac_ifnet_label_alloc();
483eca8a663SRobert Watson 	error = mac_internalize_ifnet_label(intlabel, buffer);
484f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
485f7b951a8SRobert Watson 	if (error) {
486eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
487f7b951a8SRobert Watson 		return (error);
488f7b951a8SRobert Watson 	}
489f7b951a8SRobert Watson 
49095fab37eSRobert Watson 	/*
49195fab37eSRobert Watson 	 * XXX: Note that this is a redundant privilege check, since
49295fab37eSRobert Watson 	 * policies impose this check themselves if required by the
49395fab37eSRobert Watson 	 * policy.  Eventually, this should go away.
49495fab37eSRobert Watson 	 */
49595fab37eSRobert Watson 	error = suser_cred(cred, 0);
496f7b951a8SRobert Watson 	if (error) {
497eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
498f7b951a8SRobert Watson 		return (error);
499f7b951a8SRobert Watson 	}
50095fab37eSRobert Watson 
5012220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
502eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, ifnet->if_label,
503eca8a663SRobert Watson 	    intlabel);
504f7b951a8SRobert Watson 	if (error) {
5052220907bSRobert Watson 		MAC_IFNET_UNLOCK(ifnet);
506eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
507f7b951a8SRobert Watson 		return (error);
508f7b951a8SRobert Watson 	}
50995fab37eSRobert Watson 
510eca8a663SRobert Watson 	MAC_PERFORM(relabel_ifnet, cred, ifnet, ifnet->if_label, intlabel);
5112220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
51295fab37eSRobert Watson 
513eca8a663SRobert Watson 	mac_ifnet_label_free(intlabel);
514f7b951a8SRobert Watson 	return (0);
51595fab37eSRobert Watson }
516