xref: /freebsd/sys/security/mac/mac_net.c (revision b9b0dac33ba72ade7976c47a2ce3d500fcfd27f5)
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.
530d239bcSRobert Watson  * Copyright (c) 2006 SPARTA, Inc.
67bc82500SRobert Watson  * All rights reserved.
77bc82500SRobert Watson  *
87bc82500SRobert Watson  * This software was developed by Robert Watson and Ilmar Habibulin for the
97bc82500SRobert Watson  * TrustedBSD Project.
107bc82500SRobert Watson  *
1130d239bcSRobert Watson  * This software was enhanced by SPARTA ISSO under SPAWAR contract
1230d239bcSRobert Watson  * N66001-04-C-6019 ("SEFOS").
1330d239bcSRobert Watson  *
146201265bSRobert Watson  * This software was developed for the FreeBSD Project in part by Network
156201265bSRobert Watson  * Associates Laboratories, the Security Research Division of Network
166201265bSRobert Watson  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
176201265bSRobert Watson  * as part of the DARPA CHATS research program.
187bc82500SRobert Watson  *
197bc82500SRobert Watson  * Redistribution and use in source and binary forms, with or without
207bc82500SRobert Watson  * modification, are permitted provided that the following conditions
217bc82500SRobert Watson  * are met:
227bc82500SRobert Watson  * 1. Redistributions of source code must retain the above copyright
237bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer.
247bc82500SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
257bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
267bc82500SRobert Watson  *    documentation and/or other materials provided with the distribution.
277bc82500SRobert Watson  *
287bc82500SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
297bc82500SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
307bc82500SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
317bc82500SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
327bc82500SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
337bc82500SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
347bc82500SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
357bc82500SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
367bc82500SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
377bc82500SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
387bc82500SRobert Watson  * SUCH DAMAGE.
397bc82500SRobert Watson  */
40677b542eSDavid E. O'Brien 
41677b542eSDavid E. O'Brien #include <sys/cdefs.h>
42677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
43677b542eSDavid E. O'Brien 
447bc82500SRobert Watson #include "opt_mac.h"
45f9d0d524SRobert Watson 
467bc82500SRobert Watson #include <sys/param.h>
4795fab37eSRobert Watson #include <sys/kernel.h>
4895fab37eSRobert Watson #include <sys/lock.h>
49b656366bSBruce Evans #include <sys/malloc.h>
5095fab37eSRobert Watson #include <sys/mutex.h>
5195fab37eSRobert Watson #include <sys/mac.h>
52acd3428bSRobert Watson #include <sys/priv.h>
53f51e5803SRobert Watson #include <sys/sbuf.h>
5495fab37eSRobert Watson #include <sys/systm.h>
5595fab37eSRobert Watson #include <sys/mount.h>
5695fab37eSRobert Watson #include <sys/file.h>
5795fab37eSRobert Watson #include <sys/namei.h>
58a557af22SRobert Watson #include <sys/protosw.h>
5995fab37eSRobert Watson #include <sys/socket.h>
6095fab37eSRobert Watson #include <sys/socketvar.h>
6195fab37eSRobert Watson #include <sys/sysctl.h>
6295fab37eSRobert Watson 
6395fab37eSRobert Watson #include <net/bpfdesc.h>
6495fab37eSRobert Watson #include <net/if.h>
6595fab37eSRobert Watson #include <net/if_var.h>
6695fab37eSRobert Watson 
67aed55708SRobert Watson #include <security/mac/mac_framework.h>
6828e65e3dSRobert Watson #include <security/mac/mac_internal.h>
690efd6615SRobert Watson #include <security/mac/mac_policy.h>
70a3df768bSRobert Watson 
71c66b4d8dSRobert Watson /*
72e678cce9SRobert Watson  * XXXRW: struct ifnet locking is incomplete in the network code, so we use
73e678cce9SRobert Watson  * our own global mutex for struct ifnet.  Non-ideal, but should help in the
74e678cce9SRobert Watson  * SMP environment.
752220907bSRobert Watson  */
76b9b0dac3SRobert Watson struct mtx mac_ifnet_mtx;
772220907bSRobert Watson MTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF);
782220907bSRobert Watson 
79e678cce9SRobert Watson /*
80e678cce9SRobert Watson  * Retrieve the label associated with an mbuf by searching for the tag.
81e678cce9SRobert Watson  * Depending on the value of mac_labelmbufs, it's possible that a label will
82e678cce9SRobert Watson  * not be present, in which case NULL is returned.  Policies must handle the
83e678cce9SRobert Watson  * possibility of an mbuf not having label storage if they do not enforce
84e678cce9SRobert Watson  * early loading.
85e678cce9SRobert Watson  */
86c66b4d8dSRobert Watson struct label *
8726ae2b86SRobert Watson mac_mbuf_to_label(struct mbuf *m)
8810eeb10cSRobert Watson {
89225bff6fSRobert Watson 	struct m_tag *tag;
9010eeb10cSRobert Watson 	struct label *label;
9110eeb10cSRobert Watson 
9226ae2b86SRobert Watson 	if (m == NULL)
93583284e1SRobert Watson 		return (NULL);
9426ae2b86SRobert Watson 	tag = m_tag_find(m, PACKET_TAG_MACLABEL, NULL);
95583284e1SRobert Watson 	if (tag == NULL)
96583284e1SRobert Watson 		return (NULL);
97225bff6fSRobert Watson 	label = (struct label *)(tag+1);
9810eeb10cSRobert Watson 	return (label);
9910eeb10cSRobert Watson }
10010eeb10cSRobert Watson 
101eca8a663SRobert Watson static struct label *
102eca8a663SRobert Watson mac_bpfdesc_label_alloc(void)
103eca8a663SRobert Watson {
104eca8a663SRobert Watson 	struct label *label;
105eca8a663SRobert Watson 
106eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
10730d239bcSRobert Watson 	MAC_PERFORM(bpfdesc_init_label, label);
108eca8a663SRobert Watson 	return (label);
109eca8a663SRobert Watson }
110eca8a663SRobert Watson 
11108bcdc58SRobert Watson void
11230d239bcSRobert Watson mac_bpfdesc_init(struct bpf_d *d)
11308bcdc58SRobert Watson {
11408bcdc58SRobert Watson 
11526ae2b86SRobert Watson 	d->bd_label = mac_bpfdesc_label_alloc();
11608bcdc58SRobert Watson }
11708bcdc58SRobert Watson 
118eca8a663SRobert Watson static struct label *
119eca8a663SRobert Watson mac_ifnet_label_alloc(void)
120f7b951a8SRobert Watson {
121eca8a663SRobert Watson 	struct label *label;
122f7b951a8SRobert Watson 
123eca8a663SRobert Watson 	label = mac_labelzone_alloc(M_WAITOK);
12430d239bcSRobert Watson 	MAC_PERFORM(ifnet_init_label, label);
125eca8a663SRobert Watson 	return (label);
126f7b951a8SRobert Watson }
127f7b951a8SRobert Watson 
12808bcdc58SRobert Watson void
12930d239bcSRobert Watson mac_ifnet_init(struct ifnet *ifp)
13008bcdc58SRobert Watson {
13108bcdc58SRobert Watson 
132eca8a663SRobert Watson 	ifp->if_label = mac_ifnet_label_alloc();
133eca8a663SRobert Watson }
134eca8a663SRobert Watson 
13587807196SRobert Watson int
13630d239bcSRobert Watson mac_mbuf_tag_init(struct m_tag *tag, int flag)
13708bcdc58SRobert Watson {
138225bff6fSRobert Watson 	struct label *label;
1396d1a6a9aSRobert Watson 	int error;
14056c15412SRobert Watson 
141225bff6fSRobert Watson 	label = (struct label *) (tag + 1);
142225bff6fSRobert Watson 	mac_init_label(label);
14308bcdc58SRobert Watson 
14430d239bcSRobert Watson 	MAC_CHECK(mbuf_init_label, label, flag);
14556c15412SRobert Watson 	if (error) {
14630d239bcSRobert Watson 		MAC_PERFORM(mbuf_destroy_label, label);
147225bff6fSRobert Watson 		mac_destroy_label(label);
14856c15412SRobert Watson 	}
14956c15412SRobert Watson 	return (error);
15008bcdc58SRobert Watson }
15108bcdc58SRobert Watson 
152225bff6fSRobert Watson int
15330d239bcSRobert Watson mac_mbuf_init(struct mbuf *m, int flag)
154225bff6fSRobert Watson {
155225bff6fSRobert Watson 	struct m_tag *tag;
156225bff6fSRobert Watson 	int error;
157225bff6fSRobert Watson 
158225bff6fSRobert Watson 	M_ASSERTPKTHDR(m);
159225bff6fSRobert Watson 
160225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
161225bff6fSRobert Watson 	/*
16219c3e120SRobert Watson 	 * If conditionally allocating mbuf labels, don't allocate unless
16319c3e120SRobert Watson 	 * they are required.
164225bff6fSRobert Watson 	 */
16519c3e120SRobert Watson 	if (!mac_labelmbufs)
16619c3e120SRobert Watson 		return (0);
167225bff6fSRobert Watson #endif
168225bff6fSRobert Watson 	tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
169225bff6fSRobert Watson 	    flag);
170225bff6fSRobert Watson 	if (tag == NULL)
171225bff6fSRobert Watson 		return (ENOMEM);
17230d239bcSRobert Watson 	error = mac_mbuf_tag_init(tag, flag);
173225bff6fSRobert Watson 	if (error) {
174225bff6fSRobert Watson 		m_tag_free(tag);
175225bff6fSRobert Watson 		return (error);
176225bff6fSRobert Watson 	}
177225bff6fSRobert Watson 	m_tag_prepend(m, tag);
178225bff6fSRobert Watson 	return (0);
179225bff6fSRobert Watson }
180225bff6fSRobert Watson 
181eca8a663SRobert Watson static void
182eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label)
183eca8a663SRobert Watson {
18483985c26SRobert Watson 
18530d239bcSRobert Watson 	MAC_PERFORM(bpfdesc_destroy_label, label);
186eca8a663SRobert Watson 	mac_labelzone_free(label);
18787807196SRobert Watson }
18887807196SRobert Watson 
189763bbd2fSRobert Watson void
19030d239bcSRobert Watson mac_bpfdesc_destroy(struct bpf_d *d)
19108bcdc58SRobert Watson {
19208bcdc58SRobert Watson 
19326ae2b86SRobert Watson 	mac_bpfdesc_label_free(d->bd_label);
19426ae2b86SRobert Watson 	d->bd_label = NULL;
19508bcdc58SRobert Watson }
19608bcdc58SRobert Watson 
197f7b951a8SRobert Watson static void
198eca8a663SRobert Watson mac_ifnet_label_free(struct label *label)
199f7b951a8SRobert Watson {
200f7b951a8SRobert Watson 
20130d239bcSRobert Watson 	MAC_PERFORM(ifnet_destroy_label, label);
202eca8a663SRobert Watson 	mac_labelzone_free(label);
203f7b951a8SRobert Watson }
204f7b951a8SRobert Watson 
20587807196SRobert Watson void
20630d239bcSRobert Watson mac_ifnet_destroy(struct ifnet *ifp)
20787807196SRobert Watson {
20887807196SRobert Watson 
209eca8a663SRobert Watson 	mac_ifnet_label_free(ifp->if_label);
210eca8a663SRobert Watson 	ifp->if_label = NULL;
211eca8a663SRobert Watson }
212eca8a663SRobert Watson 
21387807196SRobert Watson void
21430d239bcSRobert Watson mac_mbuf_tag_destroy(struct m_tag *tag)
21587807196SRobert Watson {
216225bff6fSRobert Watson 	struct label *label;
21787807196SRobert Watson 
218225bff6fSRobert Watson 	label = (struct label *)(tag+1);
219225bff6fSRobert Watson 
22030d239bcSRobert Watson 	MAC_PERFORM(mbuf_destroy_label, label);
221225bff6fSRobert Watson 	mac_destroy_label(label);
22208bcdc58SRobert Watson }
22308bcdc58SRobert Watson 
224e678cce9SRobert Watson /*
22530d239bcSRobert Watson  * mac_mbuf_tag_copy is called when an mbuf header is duplicated, in which
226e678cce9SRobert Watson  * case the labels must also be duplicated.
227e678cce9SRobert Watson  */
228b0323ea3SRobert Watson void
22930d239bcSRobert Watson mac_mbuf_tag_copy(struct m_tag *src, struct m_tag *dest)
230225bff6fSRobert Watson {
231225bff6fSRobert Watson 	struct label *src_label, *dest_label;
232225bff6fSRobert Watson 
233225bff6fSRobert Watson 	src_label = (struct label *)(src+1);
234225bff6fSRobert Watson 	dest_label = (struct label *)(dest+1);
235225bff6fSRobert Watson 
236225bff6fSRobert Watson 	/*
23730d239bcSRobert Watson 	 * mac_mbuf_tag_init() is called on the target tag in m_tag_copy(),
238e678cce9SRobert Watson 	 * so we don't need to call it here.
239225bff6fSRobert Watson 	 */
24030d239bcSRobert Watson 	MAC_PERFORM(mbuf_copy_label, src_label, dest_label);
241225bff6fSRobert Watson }
242225bff6fSRobert Watson 
2433c308b09SRobert Watson void
24430d239bcSRobert Watson mac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to)
2453c308b09SRobert Watson {
2463c308b09SRobert Watson 	struct label *src_label, *dest_label;
2473c308b09SRobert Watson 
2483c308b09SRobert Watson 	src_label = mac_mbuf_to_label(m_from);
2493c308b09SRobert Watson 	dest_label = mac_mbuf_to_label(m_to);
2503c308b09SRobert Watson 
25130d239bcSRobert Watson 	MAC_PERFORM(mbuf_copy_label, src_label, dest_label);
2523c308b09SRobert Watson }
2533c308b09SRobert Watson 
2542220907bSRobert Watson static void
25530d239bcSRobert Watson mac_ifnet_copy_label(struct label *src, struct label *dest)
2562220907bSRobert Watson {
2572220907bSRobert Watson 
25830d239bcSRobert Watson 	MAC_PERFORM(ifnet_copy_label, src, dest);
2592220907bSRobert Watson }
2602220907bSRobert Watson 
26169bbb5b1SRobert Watson static int
26230d239bcSRobert Watson mac_ifnet_externalize_label(struct label *label, char *elements,
26383b7b0edSRobert Watson     char *outbuf, size_t outbuflen)
26469bbb5b1SRobert Watson {
26569bbb5b1SRobert Watson 	int error;
26669bbb5b1SRobert Watson 
267da77b2faSRobert Watson 	MAC_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
268f7b951a8SRobert Watson 
269f7b951a8SRobert Watson 	return (error);
270f7b951a8SRobert Watson }
271f7b951a8SRobert Watson 
272f7b951a8SRobert Watson static int
27330d239bcSRobert Watson mac_ifnet_internalize_label(struct label *label, char *string)
274f7b951a8SRobert Watson {
275f7b951a8SRobert Watson 	int error;
276f7b951a8SRobert Watson 
277da77b2faSRobert Watson 	MAC_INTERNALIZE(ifnet, label, string);
278f7b951a8SRobert Watson 
279f7b951a8SRobert Watson 	return (error);
280f7b951a8SRobert Watson }
281f7b951a8SRobert Watson 
28295fab37eSRobert Watson void
28330d239bcSRobert Watson mac_ifnet_create(struct ifnet *ifp)
28495fab37eSRobert Watson {
28595fab37eSRobert Watson 
28626ae2b86SRobert Watson 	MAC_IFNET_LOCK(ifp);
28730d239bcSRobert Watson 	MAC_PERFORM(ifnet_create, ifp, ifp->if_label);
28826ae2b86SRobert Watson 	MAC_IFNET_UNLOCK(ifp);
28995fab37eSRobert Watson }
29095fab37eSRobert Watson 
29195fab37eSRobert Watson void
29230d239bcSRobert Watson mac_bpfdesc_create(struct ucred *cred, struct bpf_d *d)
29395fab37eSRobert Watson {
29495fab37eSRobert Watson 
29530d239bcSRobert Watson 	MAC_PERFORM(bpfdesc_create, cred, d, d->bd_label);
29695fab37eSRobert Watson }
29795fab37eSRobert Watson 
29895fab37eSRobert Watson void
29930d239bcSRobert Watson mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m)
30095fab37eSRobert Watson {
30110eeb10cSRobert Watson 	struct label *label;
30210eeb10cSRobert Watson 
30326ae2b86SRobert Watson 	BPFD_LOCK_ASSERT(d);
304e33d9f29SRobert Watson 
30526ae2b86SRobert Watson 	label = mac_mbuf_to_label(m);
30695fab37eSRobert Watson 
30730d239bcSRobert Watson 	MAC_PERFORM(bpfdesc_create_mbuf, d, d->bd_label, m, label);
30895fab37eSRobert Watson }
30995fab37eSRobert Watson 
31095fab37eSRobert Watson void
31130d239bcSRobert Watson mac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m)
31295fab37eSRobert Watson {
31310eeb10cSRobert Watson 	struct label *label;
31410eeb10cSRobert Watson 
31526ae2b86SRobert Watson 	label = mac_mbuf_to_label(m);
31695fab37eSRobert Watson 
31726ae2b86SRobert Watson 	MAC_IFNET_LOCK(ifp);
31830d239bcSRobert Watson 	MAC_PERFORM(ifnet_create_mbuf, ifp, ifp->if_label, m, label);
31926ae2b86SRobert Watson 	MAC_IFNET_UNLOCK(ifp);
32095fab37eSRobert Watson }
32195fab37eSRobert Watson 
32295fab37eSRobert Watson void
32330d239bcSRobert Watson mac_mbuf_create_multicast_encap(struct mbuf *m, struct ifnet *ifp,
32426ae2b86SRobert Watson     struct mbuf *mnew)
32595fab37eSRobert Watson {
32626ae2b86SRobert Watson 	struct label *mlabel, *mnewlabel;
32795fab37eSRobert Watson 
32826ae2b86SRobert Watson 	mlabel = mac_mbuf_to_label(m);
32926ae2b86SRobert Watson 	mnewlabel = mac_mbuf_to_label(mnew);
33010eeb10cSRobert Watson 
33126ae2b86SRobert Watson 	MAC_IFNET_LOCK(ifp);
33230d239bcSRobert Watson 	MAC_PERFORM(mbuf_create_multicast_encap, m, mlabel, ifp,
33326ae2b86SRobert Watson 	    ifp->if_label, mnew, mnewlabel);
33426ae2b86SRobert Watson 	MAC_IFNET_UNLOCK(ifp);
33595fab37eSRobert Watson }
33695fab37eSRobert Watson 
33795fab37eSRobert Watson void
33830d239bcSRobert Watson mac_mbuf_create_netlayer(struct mbuf *m, struct mbuf *mnew)
33995fab37eSRobert Watson {
34026ae2b86SRobert Watson 	struct label *mlabel, *mnewlabel;
34195fab37eSRobert Watson 
34226ae2b86SRobert Watson 	mlabel = mac_mbuf_to_label(m);
34326ae2b86SRobert Watson 	mnewlabel = mac_mbuf_to_label(mnew);
34410eeb10cSRobert Watson 
34530d239bcSRobert Watson 	MAC_PERFORM(mbuf_create_netlayer, m, mlabel, mnew, mnewlabel);
34695fab37eSRobert Watson }
34795fab37eSRobert Watson 
34895fab37eSRobert Watson int
34930d239bcSRobert Watson mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp)
35095fab37eSRobert Watson {
35195fab37eSRobert Watson 	int error;
35295fab37eSRobert Watson 
35326ae2b86SRobert Watson 	BPFD_LOCK_ASSERT(d);
354e33d9f29SRobert Watson 
35526ae2b86SRobert Watson 	MAC_IFNET_LOCK(ifp);
35630d239bcSRobert Watson 	MAC_CHECK(bpfdesc_check_receive, d, d->bd_label, ifp, ifp->if_label);
35726ae2b86SRobert Watson 	MAC_IFNET_UNLOCK(ifp);
35895fab37eSRobert Watson 
35995fab37eSRobert Watson 	return (error);
36095fab37eSRobert Watson }
36195fab37eSRobert Watson 
36295fab37eSRobert Watson int
36330d239bcSRobert Watson mac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m)
36495fab37eSRobert Watson {
36510eeb10cSRobert Watson 	struct label *label;
36695fab37eSRobert Watson 	int error;
36795fab37eSRobert Watson 
36826ae2b86SRobert Watson 	M_ASSERTPKTHDR(m);
369225bff6fSRobert Watson 
37026ae2b86SRobert Watson 	label = mac_mbuf_to_label(m);
37195fab37eSRobert Watson 
37226ae2b86SRobert Watson 	MAC_IFNET_LOCK(ifp);
37330d239bcSRobert Watson 	MAC_CHECK(ifnet_check_transmit, ifp, ifp->if_label, m, label);
37426ae2b86SRobert Watson 	MAC_IFNET_UNLOCK(ifp);
37595fab37eSRobert Watson 
37695fab37eSRobert Watson 	return (error);
37795fab37eSRobert Watson }
37895fab37eSRobert Watson 
37995fab37eSRobert Watson int
38030d239bcSRobert Watson mac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr,
38126ae2b86SRobert Watson     struct ifnet *ifp)
38295fab37eSRobert Watson {
383f7b951a8SRobert Watson 	char *elements, *buffer;
3842220907bSRobert Watson 	struct label *intlabel;
385f7b951a8SRobert Watson 	struct mac mac;
38695fab37eSRobert Watson 	int error;
38795fab37eSRobert Watson 
388f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
38995fab37eSRobert Watson 	if (error)
39095fab37eSRobert Watson 		return (error);
39195fab37eSRobert Watson 
392f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
393f7b951a8SRobert Watson 	if (error)
394f7b951a8SRobert Watson 		return (error);
395f7b951a8SRobert Watson 
396a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
397f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
398f7b951a8SRobert Watson 	if (error) {
399f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
400f7b951a8SRobert Watson 		return (error);
401f7b951a8SRobert Watson 	}
402f7b951a8SRobert Watson 
403a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4042220907bSRobert Watson 	intlabel = mac_ifnet_label_alloc();
40526ae2b86SRobert Watson 	MAC_IFNET_LOCK(ifp);
40630d239bcSRobert Watson 	mac_ifnet_copy_label(ifp->if_label, intlabel);
40726ae2b86SRobert Watson 	MAC_IFNET_UNLOCK(ifp);
40830d239bcSRobert Watson 	error = mac_ifnet_externalize_label(intlabel, elements, buffer,
4098f3476b3SRobert Watson 	    mac.m_buflen);
4102220907bSRobert Watson 	mac_ifnet_label_free(intlabel);
411f7b951a8SRobert Watson 	if (error == 0)
412f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
413f7b951a8SRobert Watson 
414f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
415f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
416f7b951a8SRobert Watson 
417f7b951a8SRobert Watson 	return (error);
41895fab37eSRobert Watson }
41995fab37eSRobert Watson 
42095fab37eSRobert Watson int
42130d239bcSRobert Watson mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp)
42295fab37eSRobert Watson {
423eca8a663SRobert Watson 	struct label *intlabel;
424f7b951a8SRobert Watson 	struct mac mac;
425f7b951a8SRobert Watson 	char *buffer;
42695fab37eSRobert Watson 	int error;
42795fab37eSRobert Watson 
428f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
42995fab37eSRobert Watson 	if (error)
43095fab37eSRobert Watson 		return (error);
43195fab37eSRobert Watson 
432f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
43395fab37eSRobert Watson 	if (error)
43495fab37eSRobert Watson 		return (error);
43595fab37eSRobert Watson 
436a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
437f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
438f7b951a8SRobert Watson 	if (error) {
439f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
440f7b951a8SRobert Watson 		return (error);
441f7b951a8SRobert Watson 	}
442f7b951a8SRobert Watson 
443eca8a663SRobert Watson 	intlabel = mac_ifnet_label_alloc();
44430d239bcSRobert Watson 	error = mac_ifnet_internalize_label(intlabel, buffer);
445f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
446f7b951a8SRobert Watson 	if (error) {
447eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
448f7b951a8SRobert Watson 		return (error);
449f7b951a8SRobert Watson 	}
450f7b951a8SRobert Watson 
45195fab37eSRobert Watson 	/*
452acd3428bSRobert Watson 	 * XXX: Note that this is a redundant privilege check, since policies
453e678cce9SRobert Watson 	 * impose this check themselves if required by the policy
454acd3428bSRobert Watson 	 * Eventually, this should go away.
45595fab37eSRobert Watson 	 */
456acd3428bSRobert Watson 	error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
457f7b951a8SRobert Watson 	if (error) {
458eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
459f7b951a8SRobert Watson 		return (error);
460f7b951a8SRobert Watson 	}
46195fab37eSRobert Watson 
46226ae2b86SRobert Watson 	MAC_IFNET_LOCK(ifp);
46330d239bcSRobert Watson 	MAC_CHECK(ifnet_check_relabel, cred, ifp, ifp->if_label, intlabel);
464f7b951a8SRobert Watson 	if (error) {
46526ae2b86SRobert Watson 		MAC_IFNET_UNLOCK(ifp);
466eca8a663SRobert Watson 		mac_ifnet_label_free(intlabel);
467f7b951a8SRobert Watson 		return (error);
468f7b951a8SRobert Watson 	}
46995fab37eSRobert Watson 
47030d239bcSRobert Watson 	MAC_PERFORM(ifnet_relabel, cred, ifp, ifp->if_label, intlabel);
47126ae2b86SRobert Watson 	MAC_IFNET_UNLOCK(ifp);
47295fab37eSRobert Watson 
473eca8a663SRobert Watson 	mac_ifnet_label_free(intlabel);
474f7b951a8SRobert Watson 	return (0);
47595fab37eSRobert Watson }
476