xref: /freebsd/sys/security/mac/mac_net.c (revision 0efd6615cd5f39b67cec82a7034e655f3b5801e3)
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>
48acd3428bSRobert Watson #include <sys/priv.h>
49f51e5803SRobert Watson #include <sys/sbuf.h>
5095fab37eSRobert Watson #include <sys/systm.h>
5195fab37eSRobert Watson #include <sys/mount.h>
5295fab37eSRobert Watson #include <sys/file.h>
5395fab37eSRobert Watson #include <sys/namei.h>
54a557af22SRobert Watson #include <sys/protosw.h>
5595fab37eSRobert Watson #include <sys/socket.h>
5695fab37eSRobert Watson #include <sys/socketvar.h>
5795fab37eSRobert Watson #include <sys/sysctl.h>
5895fab37eSRobert Watson 
5995fab37eSRobert Watson #include <net/bpfdesc.h>
6095fab37eSRobert Watson #include <net/if.h>
6195fab37eSRobert Watson #include <net/if_var.h>
6295fab37eSRobert Watson 
63aed55708SRobert Watson #include <security/mac/mac_framework.h>
6428e65e3dSRobert Watson #include <security/mac/mac_internal.h>
650efd6615SRobert Watson #include <security/mac/mac_policy.h>
66a3df768bSRobert Watson 
67c66b4d8dSRobert Watson /*
68e678cce9SRobert Watson  * XXXRW: struct ifnet locking is incomplete in the network code, so we use
69e678cce9SRobert Watson  * our own global mutex for struct ifnet.  Non-ideal, but should help in the
70e678cce9SRobert Watson  * SMP environment.
712220907bSRobert Watson  */
722220907bSRobert Watson static struct mtx mac_ifnet_mtx;
732220907bSRobert Watson MTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF);
742220907bSRobert Watson #define	MAC_IFNET_LOCK(ifp)	mtx_lock(&mac_ifnet_mtx)
752220907bSRobert Watson #define	MAC_IFNET_UNLOCK(ifp)	mtx_unlock(&mac_ifnet_mtx)
762220907bSRobert Watson 
77e678cce9SRobert Watson /*
78e678cce9SRobert Watson  * XXXRW: In order to use the MAC label UMA zone for all label allocations,
79e678cce9SRobert Watson  * we simply store a pointer to a UMA-allocated label in the mbuf tag.  This
80e678cce9SRobert Watson  * is inefficient and should likely change to using a label embedded in the
81e678cce9SRobert Watson  * tag.
82e678cce9SRobert Watson  */
83e678cce9SRobert Watson 
84e678cce9SRobert Watson /*
85e678cce9SRobert Watson  * Retrieve the label associated with an mbuf by searching for the tag.
86e678cce9SRobert Watson  * Depending on the value of mac_labelmbufs, it's possible that a label will
87e678cce9SRobert Watson  * not be present, in which case NULL is returned.  Policies must handle the
88e678cce9SRobert Watson  * possibility of an mbuf not having label storage if they do not enforce
89e678cce9SRobert Watson  * early loading.
90e678cce9SRobert Watson  */
91c66b4d8dSRobert Watson struct label *
92c66b4d8dSRobert Watson mac_mbuf_to_label(struct mbuf *mbuf)
9310eeb10cSRobert Watson {
94225bff6fSRobert Watson 	struct m_tag *tag;
9510eeb10cSRobert Watson 	struct label *label;
9610eeb10cSRobert Watson 
97583284e1SRobert Watson 	if (mbuf == NULL)
98583284e1SRobert Watson 		return (NULL);
99225bff6fSRobert Watson 	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
100583284e1SRobert Watson 	if (tag == NULL)
101583284e1SRobert Watson 		return (NULL);
102225bff6fSRobert Watson 	label = (struct label *)(tag+1);
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 	return (label);
114eca8a663SRobert Watson }
115eca8a663SRobert Watson 
11608bcdc58SRobert Watson void
11787807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d)
11808bcdc58SRobert Watson {
11908bcdc58SRobert Watson 
120eca8a663SRobert Watson 	bpf_d->bd_label = mac_bpfdesc_label_alloc();
12108bcdc58SRobert Watson }
12208bcdc58SRobert Watson 
123eca8a663SRobert Watson static struct label *
124eca8a663SRobert Watson mac_ifnet_label_alloc(void)
125f7b951a8SRobert Watson {
126eca8a663SRobert Watson 	struct label *label;
127f7b951a8SRobert Watson 
128eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
129f7b951a8SRobert Watson 	MAC_PERFORM(init_ifnet_label, label);
130eca8a663SRobert Watson 	return (label);
131f7b951a8SRobert Watson }
132f7b951a8SRobert Watson 
13308bcdc58SRobert Watson void
13408bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp)
13508bcdc58SRobert Watson {
13608bcdc58SRobert Watson 
137eca8a663SRobert Watson 	ifp->if_label = mac_ifnet_label_alloc();
138eca8a663SRobert Watson }
139eca8a663SRobert Watson 
14087807196SRobert Watson int
141225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag)
14208bcdc58SRobert Watson {
143225bff6fSRobert Watson 	struct label *label;
1446d1a6a9aSRobert Watson 	int error;
14556c15412SRobert Watson 
146225bff6fSRobert Watson 	label = (struct label *) (tag + 1);
147225bff6fSRobert Watson 	mac_init_label(label);
14808bcdc58SRobert Watson 
1496d1a6a9aSRobert Watson 	MAC_CHECK(init_mbuf_label, label, flag);
15056c15412SRobert Watson 	if (error) {
151225bff6fSRobert Watson 		MAC_PERFORM(destroy_mbuf_label, label);
152225bff6fSRobert Watson 		mac_destroy_label(label);
15356c15412SRobert Watson 	}
15456c15412SRobert Watson 	return (error);
15508bcdc58SRobert Watson }
15608bcdc58SRobert Watson 
157225bff6fSRobert Watson int
158225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag)
159225bff6fSRobert Watson {
160225bff6fSRobert Watson 	struct m_tag *tag;
161225bff6fSRobert Watson 	int error;
162225bff6fSRobert Watson 
163225bff6fSRobert Watson 	M_ASSERTPKTHDR(m);
164225bff6fSRobert Watson 
165225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
166225bff6fSRobert Watson 	/*
16719c3e120SRobert Watson 	 * If conditionally allocating mbuf labels, don't allocate unless
16819c3e120SRobert Watson 	 * they are required.
169225bff6fSRobert Watson 	 */
17019c3e120SRobert Watson 	if (!mac_labelmbufs)
17119c3e120SRobert Watson 		return (0);
172225bff6fSRobert Watson #endif
173225bff6fSRobert Watson 	tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
174225bff6fSRobert Watson 	    flag);
175225bff6fSRobert Watson 	if (tag == NULL)
176225bff6fSRobert Watson 		return (ENOMEM);
177225bff6fSRobert Watson 	error = mac_init_mbuf_tag(tag, flag);
178225bff6fSRobert Watson 	if (error) {
179225bff6fSRobert Watson 		m_tag_free(tag);
180225bff6fSRobert Watson 		return (error);
181225bff6fSRobert Watson 	}
182225bff6fSRobert Watson 	m_tag_prepend(m, tag);
183225bff6fSRobert Watson 	return (0);
184225bff6fSRobert Watson }
185225bff6fSRobert Watson 
186eca8a663SRobert Watson static void
187eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label)
188eca8a663SRobert Watson {
18983985c26SRobert Watson 
190eca8a663SRobert Watson 	MAC_PERFORM(destroy_bpfdesc_label, label);
191eca8a663SRobert Watson 	mac_labelzone_free(label);
19287807196SRobert Watson }
19387807196SRobert Watson 
194763bbd2fSRobert Watson void
19508bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d)
19608bcdc58SRobert Watson {
19708bcdc58SRobert Watson 
198eca8a663SRobert Watson 	mac_bpfdesc_label_free(bpf_d->bd_label);
199eca8a663SRobert Watson 	bpf_d->bd_label = NULL;
20008bcdc58SRobert Watson }
20108bcdc58SRobert Watson 
202f7b951a8SRobert Watson static void
203eca8a663SRobert Watson mac_ifnet_label_free(struct label *label)
204f7b951a8SRobert Watson {
205f7b951a8SRobert Watson 
206f7b951a8SRobert Watson 	MAC_PERFORM(destroy_ifnet_label, label);
207eca8a663SRobert Watson 	mac_labelzone_free(label);
208f7b951a8SRobert Watson }
209f7b951a8SRobert Watson 
21087807196SRobert Watson void
21187807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp)
21287807196SRobert Watson {
21387807196SRobert Watson 
214eca8a663SRobert Watson 	mac_ifnet_label_free(ifp->if_label);
215eca8a663SRobert Watson 	ifp->if_label = NULL;
216eca8a663SRobert Watson }
217eca8a663SRobert Watson 
21887807196SRobert Watson void
219225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag)
22087807196SRobert Watson {
221225bff6fSRobert Watson 	struct label *label;
22287807196SRobert Watson 
223225bff6fSRobert Watson 	label = (struct label *)(tag+1);
224225bff6fSRobert Watson 
225225bff6fSRobert Watson 	MAC_PERFORM(destroy_mbuf_label, label);
226225bff6fSRobert Watson 	mac_destroy_label(label);
22708bcdc58SRobert Watson }
22808bcdc58SRobert Watson 
229e678cce9SRobert Watson /*
230e678cce9SRobert Watson  * mac_copy_mbuf_tag is called when an mbuf header is duplicated, in which
231e678cce9SRobert Watson  * case the labels must also be duplicated.
232e678cce9SRobert Watson  */
233b0323ea3SRobert Watson void
234225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
235225bff6fSRobert Watson {
236225bff6fSRobert Watson 	struct label *src_label, *dest_label;
237225bff6fSRobert Watson 
238225bff6fSRobert Watson 	src_label = (struct label *)(src+1);
239225bff6fSRobert Watson 	dest_label = (struct label *)(dest+1);
240225bff6fSRobert Watson 
241225bff6fSRobert Watson 	/*
242e678cce9SRobert Watson 	 * mac_init_mbuf_tag() is called on the target tag in m_tag_copy(),
243e678cce9SRobert Watson 	 * so we don't need to call it here.
244225bff6fSRobert Watson 	 */
245225bff6fSRobert Watson 	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
246225bff6fSRobert Watson }
247225bff6fSRobert Watson 
2483c308b09SRobert Watson void
2493c308b09SRobert Watson mac_copy_mbuf(struct mbuf *m_from, struct mbuf *m_to)
2503c308b09SRobert Watson {
2513c308b09SRobert Watson 	struct label *src_label, *dest_label;
2523c308b09SRobert Watson 
2533c308b09SRobert Watson 	src_label = mac_mbuf_to_label(m_from);
2543c308b09SRobert Watson 	dest_label = mac_mbuf_to_label(m_to);
2553c308b09SRobert Watson 
2563c308b09SRobert Watson 	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
2573c308b09SRobert Watson }
2583c308b09SRobert Watson 
2592220907bSRobert Watson static void
2602220907bSRobert Watson mac_copy_ifnet_label(struct label *src, struct label *dest)
2612220907bSRobert Watson {
2622220907bSRobert Watson 
2632220907bSRobert Watson 	MAC_PERFORM(copy_ifnet_label, src, dest);
2642220907bSRobert Watson }
2652220907bSRobert Watson 
26669bbb5b1SRobert Watson static int
267f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements,
26883b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
26969bbb5b1SRobert Watson {
27069bbb5b1SRobert Watson 	int error;
27169bbb5b1SRobert Watson 
272da77b2faSRobert Watson 	MAC_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
273f7b951a8SRobert Watson 
274f7b951a8SRobert Watson 	return (error);
275f7b951a8SRobert Watson }
276f7b951a8SRobert Watson 
277f7b951a8SRobert Watson static int
278f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string)
279f7b951a8SRobert Watson {
280f7b951a8SRobert Watson 	int error;
281f7b951a8SRobert Watson 
282da77b2faSRobert Watson 	MAC_INTERNALIZE(ifnet, label, string);
283f7b951a8SRobert Watson 
284f7b951a8SRobert Watson 	return (error);
285f7b951a8SRobert Watson }
286f7b951a8SRobert Watson 
28795fab37eSRobert Watson void
28895fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet)
28995fab37eSRobert Watson {
29095fab37eSRobert Watson 
2912220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
292eca8a663SRobert Watson 	MAC_PERFORM(create_ifnet, ifnet, ifnet->if_label);
2932220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
29495fab37eSRobert Watson }
29595fab37eSRobert Watson 
29695fab37eSRobert Watson void
29795fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
29895fab37eSRobert Watson {
29995fab37eSRobert Watson 
300eca8a663SRobert Watson 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, bpf_d->bd_label);
30195fab37eSRobert Watson }
30295fab37eSRobert Watson 
30395fab37eSRobert Watson void
30495fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
30595fab37eSRobert Watson {
30610eeb10cSRobert Watson 	struct label *label;
30710eeb10cSRobert Watson 
308e33d9f29SRobert Watson 	BPFD_LOCK_ASSERT(bpf_d);
309e33d9f29SRobert Watson 
310c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
31195fab37eSRobert Watson 
312eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, bpf_d->bd_label, mbuf,
31310eeb10cSRobert Watson 	    label);
31495fab37eSRobert Watson }
31595fab37eSRobert Watson 
31695fab37eSRobert Watson void
31795fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
31895fab37eSRobert Watson {
31910eeb10cSRobert Watson 	struct label *label;
32010eeb10cSRobert Watson 
321c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
32295fab37eSRobert Watson 
3232220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
324eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_linklayer, ifnet, ifnet->if_label, mbuf,
32510eeb10cSRobert Watson 	    label);
3262220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
32795fab37eSRobert Watson }
32895fab37eSRobert Watson 
32995fab37eSRobert Watson void
33095fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
33195fab37eSRobert Watson {
33210eeb10cSRobert Watson 	struct label *label;
33310eeb10cSRobert Watson 
334c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
33595fab37eSRobert Watson 
3362220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
337eca8a663SRobert Watson 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, ifnet->if_label, mbuf,
33810eeb10cSRobert Watson 	    label);
3392220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
34095fab37eSRobert Watson }
34195fab37eSRobert Watson 
34295fab37eSRobert Watson void
34395fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
34495fab37eSRobert Watson     struct mbuf *newmbuf)
34595fab37eSRobert Watson {
34610eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
34795fab37eSRobert Watson 
348c66b4d8dSRobert Watson 	oldmbuflabel = mac_mbuf_to_label(oldmbuf);
349c66b4d8dSRobert Watson 	newmbuflabel = mac_mbuf_to_label(newmbuf);
35010eeb10cSRobert Watson 
3512220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
35210eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
353eca8a663SRobert Watson 	    ifnet, ifnet->if_label, newmbuf, newmbuflabel);
3542220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
35595fab37eSRobert Watson }
35695fab37eSRobert Watson 
35795fab37eSRobert Watson void
35895fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
35995fab37eSRobert Watson {
36010eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
36195fab37eSRobert Watson 
362c66b4d8dSRobert Watson 	oldmbuflabel = mac_mbuf_to_label(oldmbuf);
363c66b4d8dSRobert Watson 	newmbuflabel = mac_mbuf_to_label(newmbuf);
36410eeb10cSRobert Watson 
36510eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
36610eeb10cSRobert Watson 	    newmbuflabel);
36795fab37eSRobert Watson }
36895fab37eSRobert Watson 
36995fab37eSRobert Watson int
37095fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
37195fab37eSRobert Watson {
37295fab37eSRobert Watson 	int error;
37395fab37eSRobert Watson 
374e33d9f29SRobert Watson 	BPFD_LOCK_ASSERT(bpf_d);
375e33d9f29SRobert Watson 
3762220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
377eca8a663SRobert Watson 	MAC_CHECK(check_bpfdesc_receive, bpf_d, bpf_d->bd_label, ifnet,
378eca8a663SRobert Watson 	    ifnet->if_label);
3792220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
38095fab37eSRobert Watson 
38195fab37eSRobert Watson 	return (error);
38295fab37eSRobert Watson }
38395fab37eSRobert Watson 
38495fab37eSRobert Watson int
38595fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
38695fab37eSRobert Watson {
38710eeb10cSRobert Watson 	struct label *label;
38895fab37eSRobert Watson 	int error;
38995fab37eSRobert Watson 
390225bff6fSRobert Watson 	M_ASSERTPKTHDR(mbuf);
391225bff6fSRobert Watson 
392c66b4d8dSRobert Watson 	label = mac_mbuf_to_label(mbuf);
39395fab37eSRobert Watson 
3942220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
395eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_transmit, ifnet, ifnet->if_label, mbuf,
39610eeb10cSRobert Watson 	    label);
3972220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
39895fab37eSRobert Watson 
39995fab37eSRobert Watson 	return (error);
40095fab37eSRobert Watson }
40195fab37eSRobert Watson 
40295fab37eSRobert Watson int
40395fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
40495fab37eSRobert Watson     struct ifnet *ifnet)
40595fab37eSRobert Watson {
406f7b951a8SRobert Watson 	char *elements, *buffer;
4072220907bSRobert Watson 	struct label *intlabel;
408f7b951a8SRobert Watson 	struct mac mac;
40995fab37eSRobert Watson 	int error;
41095fab37eSRobert Watson 
411f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
41295fab37eSRobert Watson 	if (error)
41395fab37eSRobert Watson 		return (error);
41495fab37eSRobert Watson 
415f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
416f7b951a8SRobert Watson 	if (error)
417f7b951a8SRobert Watson 		return (error);
418f7b951a8SRobert Watson 
419a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
420f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
421f7b951a8SRobert Watson 	if (error) {
422f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
423f7b951a8SRobert Watson 		return (error);
424f7b951a8SRobert Watson 	}
425f7b951a8SRobert Watson 
426a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4272220907bSRobert Watson 	intlabel = mac_ifnet_label_alloc();
4282220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
4292220907bSRobert Watson 	mac_copy_ifnet_label(ifnet->if_label, intlabel);
4302220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
4318f3476b3SRobert Watson 	error = mac_externalize_ifnet_label(intlabel, elements, buffer,
4328f3476b3SRobert Watson 	    mac.m_buflen);
4332220907bSRobert Watson 	mac_ifnet_label_free(intlabel);
434f7b951a8SRobert Watson 	if (error == 0)
435f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
436f7b951a8SRobert Watson 
437f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
438f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
439f7b951a8SRobert Watson 
440f7b951a8SRobert Watson 	return (error);
44195fab37eSRobert Watson }
44295fab37eSRobert Watson 
44395fab37eSRobert Watson int
44495fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
44595fab37eSRobert Watson     struct ifnet *ifnet)
44695fab37eSRobert Watson {
447eca8a663SRobert Watson 	struct label *intlabel;
448f7b951a8SRobert Watson 	struct mac mac;
449f7b951a8SRobert Watson 	char *buffer;
45095fab37eSRobert Watson 	int error;
45195fab37eSRobert Watson 
452f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
45395fab37eSRobert Watson 	if (error)
45495fab37eSRobert Watson 		return (error);
45595fab37eSRobert Watson 
456f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
45795fab37eSRobert Watson 	if (error)
45895fab37eSRobert Watson 		return (error);
45995fab37eSRobert Watson 
460a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
461f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
462f7b951a8SRobert Watson 	if (error) {
463f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
464f7b951a8SRobert Watson 		return (error);
465f7b951a8SRobert Watson 	}
466f7b951a8SRobert Watson 
467eca8a663SRobert Watson 	intlabel = mac_ifnet_label_alloc();
468eca8a663SRobert Watson 	error = mac_internalize_ifnet_label(intlabel, buffer);
469f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
470f7b951a8SRobert Watson 	if (error) {
471eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
472f7b951a8SRobert Watson 		return (error);
473f7b951a8SRobert Watson 	}
474f7b951a8SRobert Watson 
47595fab37eSRobert Watson 	/*
476acd3428bSRobert Watson 	 * XXX: Note that this is a redundant privilege check, since policies
477e678cce9SRobert Watson 	 * impose this check themselves if required by the policy
478acd3428bSRobert Watson 	 * Eventually, this should go away.
47995fab37eSRobert Watson 	 */
480acd3428bSRobert Watson 	error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
481f7b951a8SRobert Watson 	if (error) {
482eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
483f7b951a8SRobert Watson 		return (error);
484f7b951a8SRobert Watson 	}
48595fab37eSRobert Watson 
4862220907bSRobert Watson 	MAC_IFNET_LOCK(ifnet);
487eca8a663SRobert Watson 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, ifnet->if_label,
488eca8a663SRobert Watson 	    intlabel);
489f7b951a8SRobert Watson 	if (error) {
4902220907bSRobert Watson 		MAC_IFNET_UNLOCK(ifnet);
491eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
492f7b951a8SRobert Watson 		return (error);
493f7b951a8SRobert Watson 	}
49495fab37eSRobert Watson 
495eca8a663SRobert Watson 	MAC_PERFORM(relabel_ifnet, cred, ifnet, ifnet->if_label, intlabel);
4962220907bSRobert Watson 	MAC_IFNET_UNLOCK(ifnet);
49795fab37eSRobert Watson 
498eca8a663SRobert Watson 	mac_ifnet_label_free(intlabel);
499f7b951a8SRobert Watson 	return (0);
50095fab37eSRobert Watson }
501