17bc82500SRobert Watson /*-
25c95417dSRobert Watson * Copyright (c) 1999-2002, 2009, 2019 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.
66356dba0SRobert Watson * Copyright (c) 2008 Apple Inc.
77bc82500SRobert Watson * All rights reserved.
87bc82500SRobert Watson *
97bc82500SRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the
107bc82500SRobert Watson * TrustedBSD Project.
117bc82500SRobert Watson *
1230d239bcSRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract
1330d239bcSRobert Watson * N66001-04-C-6019 ("SEFOS").
1430d239bcSRobert Watson *
156201265bSRobert Watson * This software was developed for the FreeBSD Project in part by Network
166201265bSRobert Watson * Associates Laboratories, the Security Research Division of Network
176201265bSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
186201265bSRobert Watson * as part of the DARPA CHATS research program.
197bc82500SRobert Watson *
202087a58cSRobert Watson * This software was developed at the University of Cambridge Computer
212087a58cSRobert Watson * Laboratory with support from a grant from Google, Inc.
222087a58cSRobert Watson *
237bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without
247bc82500SRobert Watson * modification, are permitted provided that the following conditions
257bc82500SRobert Watson * are met:
267bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright
277bc82500SRobert Watson * notice, this list of conditions and the following disclaimer.
287bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
297bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the
307bc82500SRobert Watson * documentation and/or other materials provided with the distribution.
317bc82500SRobert Watson *
327bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
337bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
347bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
357bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
367bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
377bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
387bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
397bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
407bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
417bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
427bc82500SRobert Watson * SUCH DAMAGE.
437bc82500SRobert Watson */
44677b542eSDavid E. O'Brien
45677b542eSDavid E. O'Brien #include <sys/cdefs.h>
467bc82500SRobert Watson #include "opt_mac.h"
47f9d0d524SRobert Watson
487bc82500SRobert Watson #include <sys/param.h>
4995fab37eSRobert Watson #include <sys/kernel.h>
5095fab37eSRobert Watson #include <sys/lock.h>
51b656366bSBruce Evans #include <sys/malloc.h>
5295fab37eSRobert Watson #include <sys/mutex.h>
5395fab37eSRobert Watson #include <sys/mac.h>
54acd3428bSRobert Watson #include <sys/priv.h>
55f51e5803SRobert Watson #include <sys/sbuf.h>
562087a58cSRobert Watson #include <sys/sdt.h>
5795fab37eSRobert Watson #include <sys/systm.h>
5895fab37eSRobert Watson #include <sys/mount.h>
5995fab37eSRobert Watson #include <sys/file.h>
6095fab37eSRobert Watson #include <sys/namei.h>
61a557af22SRobert Watson #include <sys/protosw.h>
6295fab37eSRobert Watson #include <sys/socket.h>
6395fab37eSRobert Watson #include <sys/socketvar.h>
6495fab37eSRobert Watson #include <sys/sysctl.h>
6595fab37eSRobert Watson
6695fab37eSRobert Watson #include <net/bpfdesc.h>
6795fab37eSRobert Watson #include <net/if.h>
6895fab37eSRobert Watson #include <net/if_var.h>
6995fab37eSRobert Watson
70aed55708SRobert Watson #include <security/mac/mac_framework.h>
7128e65e3dSRobert Watson #include <security/mac/mac_internal.h>
720efd6615SRobert Watson #include <security/mac/mac_policy.h>
73a3df768bSRobert Watson
74c66b4d8dSRobert Watson /*
75e678cce9SRobert Watson * XXXRW: struct ifnet locking is incomplete in the network code, so we use
76e678cce9SRobert Watson * our own global mutex for struct ifnet. Non-ideal, but should help in the
77e678cce9SRobert Watson * SMP environment.
785c95417dSRobert Watson *
795c95417dSRobert Watson * This lock is acquired only if a loaded policy is using ifnet labeling.
805c95417dSRobert Watson * This should not ever change during a MAC policy check, itself, but could
815c95417dSRobert Watson * change during setup/return from a check, so we have to condition unlock on
825c95417dSRobert Watson * previous lock.
832220907bSRobert Watson */
84b9b0dac3SRobert Watson struct mtx mac_ifnet_mtx;
852220907bSRobert Watson MTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF);
862220907bSRobert Watson
87e678cce9SRobert Watson /*
88e678cce9SRobert Watson * Retrieve the label associated with an mbuf by searching for the tag.
89e678cce9SRobert Watson * Depending on the value of mac_labelmbufs, it's possible that a label will
90e678cce9SRobert Watson * not be present, in which case NULL is returned. Policies must handle the
91e678cce9SRobert Watson * possibility of an mbuf not having label storage if they do not enforce
92e678cce9SRobert Watson * early loading.
93e678cce9SRobert Watson */
94c66b4d8dSRobert Watson struct label *
mac_mbuf_to_label(struct mbuf * m)9526ae2b86SRobert Watson mac_mbuf_to_label(struct mbuf *m)
9610eeb10cSRobert Watson {
97225bff6fSRobert Watson struct m_tag *tag;
9810eeb10cSRobert Watson struct label *label;
9910eeb10cSRobert Watson
10026ae2b86SRobert Watson if (m == NULL)
101583284e1SRobert Watson return (NULL);
10226ae2b86SRobert Watson tag = m_tag_find(m, PACKET_TAG_MACLABEL, NULL);
103583284e1SRobert Watson if (tag == NULL)
104583284e1SRobert Watson return (NULL);
105225bff6fSRobert Watson label = (struct label *)(tag+1);
10610eeb10cSRobert Watson return (label);
10710eeb10cSRobert Watson }
10810eeb10cSRobert Watson
109eca8a663SRobert Watson static struct label *
mac_bpfdesc_label_alloc(void)110eca8a663SRobert Watson mac_bpfdesc_label_alloc(void)
111eca8a663SRobert Watson {
112eca8a663SRobert Watson struct label *label;
113eca8a663SRobert Watson
114eca8a663SRobert Watson label = mac_labelzone_alloc(M_WAITOK);
115fa765671SRobert Watson MAC_POLICY_PERFORM(bpfdesc_init_label, label);
116eca8a663SRobert Watson return (label);
117eca8a663SRobert Watson }
118eca8a663SRobert Watson
11908bcdc58SRobert Watson void
mac_bpfdesc_init(struct bpf_d * d)12030d239bcSRobert Watson mac_bpfdesc_init(struct bpf_d *d)
12108bcdc58SRobert Watson {
12208bcdc58SRobert Watson
1236356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_BPFDESC)
12426ae2b86SRobert Watson d->bd_label = mac_bpfdesc_label_alloc();
1256356dba0SRobert Watson else
1266356dba0SRobert Watson d->bd_label = NULL;
12708bcdc58SRobert Watson }
12808bcdc58SRobert Watson
129eca8a663SRobert Watson static struct label *
mac_ifnet_label_alloc(void)130eca8a663SRobert Watson mac_ifnet_label_alloc(void)
131f7b951a8SRobert Watson {
132eca8a663SRobert Watson struct label *label;
133f7b951a8SRobert Watson
134eca8a663SRobert Watson label = mac_labelzone_alloc(M_WAITOK);
135fa765671SRobert Watson MAC_POLICY_PERFORM(ifnet_init_label, label);
136eca8a663SRobert Watson return (label);
137f7b951a8SRobert Watson }
138f7b951a8SRobert Watson
13908bcdc58SRobert Watson void
mac_ifnet_init(struct ifnet * ifp)14030d239bcSRobert Watson mac_ifnet_init(struct ifnet *ifp)
14108bcdc58SRobert Watson {
14208bcdc58SRobert Watson
1436356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_IFNET)
144*30af2c13SJustin Hibbits if_setmaclabel(ifp, mac_ifnet_label_alloc());
1456356dba0SRobert Watson else
146*30af2c13SJustin Hibbits if_setmaclabel(ifp, NULL);
147eca8a663SRobert Watson }
148eca8a663SRobert Watson
14987807196SRobert Watson int
mac_mbuf_tag_init(struct m_tag * tag,int flag)15030d239bcSRobert Watson mac_mbuf_tag_init(struct m_tag *tag, int flag)
15108bcdc58SRobert Watson {
152225bff6fSRobert Watson struct label *label;
1536d1a6a9aSRobert Watson int error;
15456c15412SRobert Watson
155225bff6fSRobert Watson label = (struct label *) (tag + 1);
156225bff6fSRobert Watson mac_init_label(label);
15708bcdc58SRobert Watson
15840202729SRobert Watson if (flag & M_WAITOK)
159fa765671SRobert Watson MAC_POLICY_CHECK(mbuf_init_label, label, flag);
16040202729SRobert Watson else
161fa765671SRobert Watson MAC_POLICY_CHECK_NOSLEEP(mbuf_init_label, label, flag);
16256c15412SRobert Watson if (error) {
163fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label);
164225bff6fSRobert Watson mac_destroy_label(label);
16556c15412SRobert Watson }
16656c15412SRobert Watson return (error);
16708bcdc58SRobert Watson }
16808bcdc58SRobert Watson
169225bff6fSRobert Watson int
mac_mbuf_init(struct mbuf * m,int flag)17030d239bcSRobert Watson mac_mbuf_init(struct mbuf *m, int flag)
171225bff6fSRobert Watson {
172225bff6fSRobert Watson struct m_tag *tag;
173225bff6fSRobert Watson int error;
174225bff6fSRobert Watson
175225bff6fSRobert Watson M_ASSERTPKTHDR(m);
176225bff6fSRobert Watson
1776356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_MBUF) {
178225bff6fSRobert Watson tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
179225bff6fSRobert Watson flag);
180225bff6fSRobert Watson if (tag == NULL)
181225bff6fSRobert Watson return (ENOMEM);
18230d239bcSRobert Watson error = mac_mbuf_tag_init(tag, flag);
183225bff6fSRobert Watson if (error) {
184225bff6fSRobert Watson m_tag_free(tag);
185225bff6fSRobert Watson return (error);
186225bff6fSRobert Watson }
187225bff6fSRobert Watson m_tag_prepend(m, tag);
1886356dba0SRobert Watson }
189225bff6fSRobert Watson return (0);
190225bff6fSRobert Watson }
191225bff6fSRobert Watson
192eca8a663SRobert Watson static void
mac_bpfdesc_label_free(struct label * label)193eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label)
194eca8a663SRobert Watson {
19583985c26SRobert Watson
196fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_destroy_label, label);
197eca8a663SRobert Watson mac_labelzone_free(label);
19887807196SRobert Watson }
19987807196SRobert Watson
200763bbd2fSRobert Watson void
mac_bpfdesc_destroy(struct bpf_d * d)20130d239bcSRobert Watson mac_bpfdesc_destroy(struct bpf_d *d)
20208bcdc58SRobert Watson {
20308bcdc58SRobert Watson
2046356dba0SRobert Watson if (d->bd_label != NULL) {
20526ae2b86SRobert Watson mac_bpfdesc_label_free(d->bd_label);
20626ae2b86SRobert Watson d->bd_label = NULL;
20708bcdc58SRobert Watson }
2086356dba0SRobert Watson }
20908bcdc58SRobert Watson
210f7b951a8SRobert Watson static void
mac_ifnet_label_free(struct label * label)211eca8a663SRobert Watson mac_ifnet_label_free(struct label *label)
212f7b951a8SRobert Watson {
213f7b951a8SRobert Watson
214fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(ifnet_destroy_label, label);
215eca8a663SRobert Watson mac_labelzone_free(label);
216f7b951a8SRobert Watson }
217f7b951a8SRobert Watson
21887807196SRobert Watson void
mac_ifnet_destroy(struct ifnet * ifp)21930d239bcSRobert Watson mac_ifnet_destroy(struct ifnet *ifp)
22087807196SRobert Watson {
221*30af2c13SJustin Hibbits struct label *label = if_getmaclabel(ifp);
222*30af2c13SJustin Hibbits if (label != NULL) {
223*30af2c13SJustin Hibbits mac_ifnet_label_free(label);
224*30af2c13SJustin Hibbits if_setmaclabel(ifp, NULL);
225eca8a663SRobert Watson }
2266356dba0SRobert Watson }
227eca8a663SRobert Watson
22887807196SRobert Watson void
mac_mbuf_tag_destroy(struct m_tag * tag)22930d239bcSRobert Watson mac_mbuf_tag_destroy(struct m_tag *tag)
23087807196SRobert Watson {
231225bff6fSRobert Watson struct label *label;
23287807196SRobert Watson
233225bff6fSRobert Watson label = (struct label *)(tag+1);
234225bff6fSRobert Watson
235fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label);
236225bff6fSRobert Watson mac_destroy_label(label);
23708bcdc58SRobert Watson }
23808bcdc58SRobert Watson
239e678cce9SRobert Watson /*
24030d239bcSRobert Watson * mac_mbuf_tag_copy is called when an mbuf header is duplicated, in which
241e678cce9SRobert Watson * case the labels must also be duplicated.
242e678cce9SRobert Watson */
243b0323ea3SRobert Watson void
mac_mbuf_tag_copy(struct m_tag * src,struct m_tag * dest)24430d239bcSRobert Watson mac_mbuf_tag_copy(struct m_tag *src, struct m_tag *dest)
245225bff6fSRobert Watson {
246225bff6fSRobert Watson struct label *src_label, *dest_label;
247225bff6fSRobert Watson
248225bff6fSRobert Watson src_label = (struct label *)(src+1);
249225bff6fSRobert Watson dest_label = (struct label *)(dest+1);
250225bff6fSRobert Watson
251225bff6fSRobert Watson /*
25230d239bcSRobert Watson * mac_mbuf_tag_init() is called on the target tag in m_tag_copy(),
253e678cce9SRobert Watson * so we don't need to call it here.
254225bff6fSRobert Watson */
255fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
256225bff6fSRobert Watson }
257225bff6fSRobert Watson
2583c308b09SRobert Watson void
mac_mbuf_copy(struct mbuf * m_from,struct mbuf * m_to)25930d239bcSRobert Watson mac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to)
2603c308b09SRobert Watson {
2613c308b09SRobert Watson struct label *src_label, *dest_label;
2623c308b09SRobert Watson
2633ad3d9c5SRobert Watson if (mac_policy_count == 0)
2643ad3d9c5SRobert Watson return;
2653ad3d9c5SRobert Watson
2663c308b09SRobert Watson src_label = mac_mbuf_to_label(m_from);
2673c308b09SRobert Watson dest_label = mac_mbuf_to_label(m_to);
2683c308b09SRobert Watson
269fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
2703c308b09SRobert Watson }
2713c308b09SRobert Watson
2722220907bSRobert Watson static void
mac_ifnet_copy_label(struct label * src,struct label * dest)27330d239bcSRobert Watson mac_ifnet_copy_label(struct label *src, struct label *dest)
2742220907bSRobert Watson {
2752220907bSRobert Watson
276fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(ifnet_copy_label, src, dest);
2772220907bSRobert Watson }
2782220907bSRobert Watson
27969bbb5b1SRobert Watson static int
mac_ifnet_externalize_label(struct label * label,char * elements,char * outbuf,size_t outbuflen)28030d239bcSRobert Watson mac_ifnet_externalize_label(struct label *label, char *elements,
28183b7b0edSRobert Watson char *outbuf, size_t outbuflen)
28269bbb5b1SRobert Watson {
28369bbb5b1SRobert Watson int error;
28469bbb5b1SRobert Watson
285fa765671SRobert Watson MAC_POLICY_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
286f7b951a8SRobert Watson
287f7b951a8SRobert Watson return (error);
288f7b951a8SRobert Watson }
289f7b951a8SRobert Watson
290f7b951a8SRobert Watson static int
mac_ifnet_internalize_label(struct label * label,char * string)29130d239bcSRobert Watson mac_ifnet_internalize_label(struct label *label, char *string)
292f7b951a8SRobert Watson {
293f7b951a8SRobert Watson int error;
294f7b951a8SRobert Watson
295fa765671SRobert Watson MAC_POLICY_INTERNALIZE(ifnet, label, string);
296f7b951a8SRobert Watson
297f7b951a8SRobert Watson return (error);
298f7b951a8SRobert Watson }
299f7b951a8SRobert Watson
30095fab37eSRobert Watson void
mac_ifnet_create(struct ifnet * ifp)30130d239bcSRobert Watson mac_ifnet_create(struct ifnet *ifp)
30295fab37eSRobert Watson {
3035c95417dSRobert Watson int locked;
30495fab37eSRobert Watson
3053de40469SRobert Watson if (mac_policy_count == 0)
3063de40469SRobert Watson return;
3073de40469SRobert Watson
3085c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked);
309*30af2c13SJustin Hibbits MAC_POLICY_PERFORM_NOSLEEP(ifnet_create, ifp, if_getmaclabel(ifp));
3105c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked);
31195fab37eSRobert Watson }
31295fab37eSRobert Watson
31395fab37eSRobert Watson void
mac_bpfdesc_create(struct ucred * cred,struct bpf_d * d)31430d239bcSRobert Watson mac_bpfdesc_create(struct ucred *cred, struct bpf_d *d)
31595fab37eSRobert Watson {
31695fab37eSRobert Watson
317fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create, cred, d, d->bd_label);
31895fab37eSRobert Watson }
31995fab37eSRobert Watson
32095fab37eSRobert Watson void
mac_bpfdesc_create_mbuf(struct bpf_d * d,struct mbuf * m)32130d239bcSRobert Watson mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m)
32295fab37eSRobert Watson {
32310eeb10cSRobert Watson struct label *label;
32410eeb10cSRobert Watson
325e4b3229aSAlexander V. Chernikov /* Assume reader lock is enough. */
32626ae2b86SRobert Watson BPFD_LOCK_ASSERT(d);
327e33d9f29SRobert Watson
3283de40469SRobert Watson if (mac_policy_count == 0)
3293de40469SRobert Watson return;
3303de40469SRobert Watson
33126ae2b86SRobert Watson label = mac_mbuf_to_label(m);
33295fab37eSRobert Watson
333fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m,
334fa765671SRobert Watson label);
33595fab37eSRobert Watson }
33695fab37eSRobert Watson
33795fab37eSRobert Watson void
mac_ifnet_create_mbuf_impl(struct ifnet * ifp,struct mbuf * m)338f77697ddSMateusz Guzik mac_ifnet_create_mbuf_impl(struct ifnet *ifp, struct mbuf *m)
33995fab37eSRobert Watson {
34010eeb10cSRobert Watson struct label *label;
3415c95417dSRobert Watson int locked;
34210eeb10cSRobert Watson
34326ae2b86SRobert Watson label = mac_mbuf_to_label(m);
34495fab37eSRobert Watson
3455c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked);
346*30af2c13SJustin Hibbits MAC_POLICY_PERFORM_NOSLEEP(ifnet_create_mbuf, ifp, if_getmaclabel(ifp), m,
347fa765671SRobert Watson label);
3485c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked);
34995fab37eSRobert Watson }
35095fab37eSRobert Watson
3512087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(bpfdesc_check_receive, "struct bpf_d *",
3522087a58cSRobert Watson "struct ifnet *");
3532087a58cSRobert Watson
35495fab37eSRobert Watson int
mac_bpfdesc_check_receive(struct bpf_d * d,struct ifnet * ifp)35530d239bcSRobert Watson mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp)
35695fab37eSRobert Watson {
3575c95417dSRobert Watson int error, locked;
35895fab37eSRobert Watson
359e4b3229aSAlexander V. Chernikov /* Assume reader lock is enough. */
36026ae2b86SRobert Watson BPFD_LOCK_ASSERT(d);
361e33d9f29SRobert Watson
3623de40469SRobert Watson if (mac_policy_count == 0)
3633de40469SRobert Watson return (0);
3643de40469SRobert Watson
3655c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked);
366fa765671SRobert Watson MAC_POLICY_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp,
367*30af2c13SJustin Hibbits if_getmaclabel(ifp));
3682087a58cSRobert Watson MAC_CHECK_PROBE2(bpfdesc_check_receive, error, d, ifp);
3695c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked);
37095fab37eSRobert Watson
37195fab37eSRobert Watson return (error);
37295fab37eSRobert Watson }
37395fab37eSRobert Watson
3742087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(ifnet_check_transmit, "struct ifnet *",
3752087a58cSRobert Watson "struct mbuf *");
3762087a58cSRobert Watson
37795fab37eSRobert Watson int
mac_ifnet_check_transmit_impl(struct ifnet * ifp,struct mbuf * m)378f77697ddSMateusz Guzik mac_ifnet_check_transmit_impl(struct ifnet *ifp, struct mbuf *m)
37995fab37eSRobert Watson {
38010eeb10cSRobert Watson struct label *label;
3815c95417dSRobert Watson int error, locked;
38295fab37eSRobert Watson
38326ae2b86SRobert Watson M_ASSERTPKTHDR(m);
384225bff6fSRobert Watson
38526ae2b86SRobert Watson label = mac_mbuf_to_label(m);
38695fab37eSRobert Watson
3875c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked);
388*30af2c13SJustin Hibbits MAC_POLICY_CHECK_NOSLEEP(ifnet_check_transmit, ifp, if_getmaclabel(ifp), m,
38940202729SRobert Watson label);
3902087a58cSRobert Watson MAC_CHECK_PROBE2(ifnet_check_transmit, error, ifp, m);
3915c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked);
39295fab37eSRobert Watson
39395fab37eSRobert Watson return (error);
39495fab37eSRobert Watson }
39595fab37eSRobert Watson
39695fab37eSRobert Watson int
mac_ifnet_ioctl_get(struct ucred * cred,struct ifreq * ifr,struct ifnet * ifp)39730d239bcSRobert Watson mac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr,
39826ae2b86SRobert Watson struct ifnet *ifp)
39995fab37eSRobert Watson {
400f7b951a8SRobert Watson char *elements, *buffer;
4012220907bSRobert Watson struct label *intlabel;
402f7b951a8SRobert Watson struct mac mac;
4035c95417dSRobert Watson int error, locked;
40495fab37eSRobert Watson
4056356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_IFNET))
4066356dba0SRobert Watson return (EINVAL);
4076356dba0SRobert Watson
408541d96aaSBrooks Davis error = copyin(ifr_data_get_ptr(ifr), &mac, sizeof(mac));
40995fab37eSRobert Watson if (error)
41095fab37eSRobert Watson return (error);
41195fab37eSRobert Watson
412f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac);
413f7b951a8SRobert Watson if (error)
414f7b951a8SRobert Watson return (error);
415f7b951a8SRobert Watson
416a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
417f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
418f7b951a8SRobert Watson if (error) {
419f7b951a8SRobert Watson free(elements, M_MACTEMP);
420f7b951a8SRobert Watson return (error);
421f7b951a8SRobert Watson }
422f7b951a8SRobert Watson
423a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4242220907bSRobert Watson intlabel = mac_ifnet_label_alloc();
4255c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked);
426*30af2c13SJustin Hibbits mac_ifnet_copy_label(if_getmaclabel(ifp), intlabel);
4275c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked);
42830d239bcSRobert Watson error = mac_ifnet_externalize_label(intlabel, elements, buffer,
4298f3476b3SRobert Watson mac.m_buflen);
4302220907bSRobert Watson mac_ifnet_label_free(intlabel);
431f7b951a8SRobert Watson if (error == 0)
432f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1);
433f7b951a8SRobert Watson
434f7b951a8SRobert Watson free(buffer, M_MACTEMP);
435f7b951a8SRobert Watson free(elements, M_MACTEMP);
436f7b951a8SRobert Watson
437f7b951a8SRobert Watson return (error);
43895fab37eSRobert Watson }
43995fab37eSRobert Watson
44095fab37eSRobert Watson int
mac_ifnet_ioctl_set(struct ucred * cred,struct ifreq * ifr,struct ifnet * ifp)44130d239bcSRobert Watson mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp)
44295fab37eSRobert Watson {
443eca8a663SRobert Watson struct label *intlabel;
444f7b951a8SRobert Watson struct mac mac;
445f7b951a8SRobert Watson char *buffer;
4465c95417dSRobert Watson int error, locked;
44795fab37eSRobert Watson
4486356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_IFNET))
4496356dba0SRobert Watson return (EINVAL);
4506356dba0SRobert Watson
451541d96aaSBrooks Davis error = copyin(ifr_data_get_ptr(ifr), &mac, sizeof(mac));
45295fab37eSRobert Watson if (error)
45395fab37eSRobert Watson return (error);
45495fab37eSRobert Watson
455f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac);
45695fab37eSRobert Watson if (error)
45795fab37eSRobert Watson return (error);
45895fab37eSRobert Watson
459a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
460f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
461f7b951a8SRobert Watson if (error) {
462f7b951a8SRobert Watson free(buffer, M_MACTEMP);
463f7b951a8SRobert Watson return (error);
464f7b951a8SRobert Watson }
465f7b951a8SRobert Watson
466eca8a663SRobert Watson intlabel = mac_ifnet_label_alloc();
46730d239bcSRobert Watson error = mac_ifnet_internalize_label(intlabel, buffer);
468f7b951a8SRobert Watson free(buffer, M_MACTEMP);
469f7b951a8SRobert Watson if (error) {
470eca8a663SRobert Watson mac_ifnet_label_free(intlabel);
471f7b951a8SRobert Watson return (error);
472f7b951a8SRobert Watson }
473f7b951a8SRobert Watson
47495fab37eSRobert Watson /*
475acd3428bSRobert Watson * XXX: Note that this is a redundant privilege check, since policies
476e678cce9SRobert Watson * impose this check themselves if required by the policy
477acd3428bSRobert Watson * Eventually, this should go away.
47895fab37eSRobert Watson */
479cc426dd3SMateusz Guzik error = priv_check_cred(cred, PRIV_NET_SETIFMAC);
480f7b951a8SRobert Watson if (error) {
481eca8a663SRobert Watson mac_ifnet_label_free(intlabel);
482f7b951a8SRobert Watson return (error);
483f7b951a8SRobert Watson }
48495fab37eSRobert Watson
4855c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked);
486fa765671SRobert Watson MAC_POLICY_CHECK_NOSLEEP(ifnet_check_relabel, cred, ifp,
487*30af2c13SJustin Hibbits if_getmaclabel(ifp), intlabel);
488f7b951a8SRobert Watson if (error) {
4895c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked);
490eca8a663SRobert Watson mac_ifnet_label_free(intlabel);
491f7b951a8SRobert Watson return (error);
492f7b951a8SRobert Watson }
49395fab37eSRobert Watson
494*30af2c13SJustin Hibbits MAC_POLICY_PERFORM_NOSLEEP(ifnet_relabel, cred, ifp, if_getmaclabel(ifp),
49540202729SRobert Watson intlabel);
4965c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked);
49795fab37eSRobert Watson
498eca8a663SRobert Watson mac_ifnet_label_free(intlabel);
499f7b951a8SRobert Watson return (0);
50095fab37eSRobert Watson }
501