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. 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 * 207bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without 217bc82500SRobert Watson * modification, are permitted provided that the following conditions 227bc82500SRobert Watson * are met: 237bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright 247bc82500SRobert Watson * notice, this list of conditions and the following disclaimer. 257bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 267bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the 277bc82500SRobert Watson * documentation and/or other materials provided with the distribution. 287bc82500SRobert Watson * 297bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 307bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 317bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 327bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 337bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 347bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 357bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 367bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 377bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 387bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 397bc82500SRobert Watson * SUCH DAMAGE. 407bc82500SRobert Watson */ 41677b542eSDavid E. O'Brien 42677b542eSDavid E. O'Brien #include <sys/cdefs.h> 43677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 44677b542eSDavid E. O'Brien 457bc82500SRobert Watson #include "opt_mac.h" 46f9d0d524SRobert Watson 477bc82500SRobert Watson #include <sys/param.h> 4895fab37eSRobert Watson #include <sys/kernel.h> 4995fab37eSRobert Watson #include <sys/lock.h> 50b656366bSBruce Evans #include <sys/malloc.h> 5195fab37eSRobert Watson #include <sys/mutex.h> 5295fab37eSRobert Watson #include <sys/mac.h> 53acd3428bSRobert Watson #include <sys/priv.h> 54f51e5803SRobert Watson #include <sys/sbuf.h> 5595fab37eSRobert Watson #include <sys/systm.h> 5695fab37eSRobert Watson #include <sys/mount.h> 5795fab37eSRobert Watson #include <sys/file.h> 5895fab37eSRobert Watson #include <sys/namei.h> 59a557af22SRobert Watson #include <sys/protosw.h> 6095fab37eSRobert Watson #include <sys/socket.h> 6195fab37eSRobert Watson #include <sys/socketvar.h> 6295fab37eSRobert Watson #include <sys/sysctl.h> 6395fab37eSRobert Watson 6495fab37eSRobert Watson #include <net/bpfdesc.h> 6595fab37eSRobert Watson #include <net/if.h> 6695fab37eSRobert Watson #include <net/if_var.h> 6795fab37eSRobert Watson 68aed55708SRobert Watson #include <security/mac/mac_framework.h> 6928e65e3dSRobert Watson #include <security/mac/mac_internal.h> 700efd6615SRobert Watson #include <security/mac/mac_policy.h> 71a3df768bSRobert Watson 72c66b4d8dSRobert Watson /* 73e678cce9SRobert Watson * XXXRW: struct ifnet locking is incomplete in the network code, so we use 74e678cce9SRobert Watson * our own global mutex for struct ifnet. Non-ideal, but should help in the 75e678cce9SRobert Watson * SMP environment. 762220907bSRobert Watson */ 77b9b0dac3SRobert Watson struct mtx mac_ifnet_mtx; 782220907bSRobert Watson MTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF); 792220907bSRobert Watson 80e678cce9SRobert Watson /* 81e678cce9SRobert Watson * Retrieve the label associated with an mbuf by searching for the tag. 82e678cce9SRobert Watson * Depending on the value of mac_labelmbufs, it's possible that a label will 83e678cce9SRobert Watson * not be present, in which case NULL is returned. Policies must handle the 84e678cce9SRobert Watson * possibility of an mbuf not having label storage if they do not enforce 85e678cce9SRobert Watson * early loading. 86e678cce9SRobert Watson */ 87c66b4d8dSRobert Watson struct label * 8826ae2b86SRobert Watson mac_mbuf_to_label(struct mbuf *m) 8910eeb10cSRobert Watson { 90225bff6fSRobert Watson struct m_tag *tag; 9110eeb10cSRobert Watson struct label *label; 9210eeb10cSRobert Watson 9326ae2b86SRobert Watson if (m == NULL) 94583284e1SRobert Watson return (NULL); 9526ae2b86SRobert Watson tag = m_tag_find(m, PACKET_TAG_MACLABEL, NULL); 96583284e1SRobert Watson if (tag == NULL) 97583284e1SRobert Watson return (NULL); 98225bff6fSRobert Watson label = (struct label *)(tag+1); 9910eeb10cSRobert Watson return (label); 10010eeb10cSRobert Watson } 10110eeb10cSRobert Watson 102eca8a663SRobert Watson static struct label * 103eca8a663SRobert Watson mac_bpfdesc_label_alloc(void) 104eca8a663SRobert Watson { 105eca8a663SRobert Watson struct label *label; 106eca8a663SRobert Watson 107eca8a663SRobert Watson label = mac_labelzone_alloc(M_WAITOK); 10830d239bcSRobert Watson MAC_PERFORM(bpfdesc_init_label, label); 109eca8a663SRobert Watson return (label); 110eca8a663SRobert Watson } 111eca8a663SRobert Watson 11208bcdc58SRobert Watson void 11330d239bcSRobert Watson mac_bpfdesc_init(struct bpf_d *d) 11408bcdc58SRobert Watson { 11508bcdc58SRobert Watson 1166356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_BPFDESC) 11726ae2b86SRobert Watson d->bd_label = mac_bpfdesc_label_alloc(); 1186356dba0SRobert Watson else 1196356dba0SRobert Watson d->bd_label = NULL; 12008bcdc58SRobert Watson } 12108bcdc58SRobert Watson 122eca8a663SRobert Watson static struct label * 123eca8a663SRobert Watson mac_ifnet_label_alloc(void) 124f7b951a8SRobert Watson { 125eca8a663SRobert Watson struct label *label; 126f7b951a8SRobert Watson 127eca8a663SRobert Watson label = mac_labelzone_alloc(M_WAITOK); 12830d239bcSRobert Watson MAC_PERFORM(ifnet_init_label, label); 129eca8a663SRobert Watson return (label); 130f7b951a8SRobert Watson } 131f7b951a8SRobert Watson 13208bcdc58SRobert Watson void 13330d239bcSRobert Watson mac_ifnet_init(struct ifnet *ifp) 13408bcdc58SRobert Watson { 13508bcdc58SRobert Watson 1366356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_IFNET) 137eca8a663SRobert Watson ifp->if_label = mac_ifnet_label_alloc(); 1386356dba0SRobert Watson else 1396356dba0SRobert Watson ifp->if_label = NULL; 140eca8a663SRobert Watson } 141eca8a663SRobert Watson 14287807196SRobert Watson int 14330d239bcSRobert Watson mac_mbuf_tag_init(struct m_tag *tag, int flag) 14408bcdc58SRobert Watson { 145225bff6fSRobert Watson struct label *label; 1466d1a6a9aSRobert Watson int error; 14756c15412SRobert Watson 148225bff6fSRobert Watson label = (struct label *) (tag + 1); 149225bff6fSRobert Watson mac_init_label(label); 15008bcdc58SRobert Watson 15130d239bcSRobert Watson MAC_CHECK(mbuf_init_label, label, flag); 15256c15412SRobert Watson if (error) { 15330d239bcSRobert Watson MAC_PERFORM(mbuf_destroy_label, label); 154225bff6fSRobert Watson mac_destroy_label(label); 15556c15412SRobert Watson } 15656c15412SRobert Watson return (error); 15708bcdc58SRobert Watson } 15808bcdc58SRobert Watson 159225bff6fSRobert Watson int 16030d239bcSRobert Watson mac_mbuf_init(struct mbuf *m, int flag) 161225bff6fSRobert Watson { 162225bff6fSRobert Watson struct m_tag *tag; 163225bff6fSRobert Watson int error; 164225bff6fSRobert Watson 165225bff6fSRobert Watson M_ASSERTPKTHDR(m); 166225bff6fSRobert Watson 1676356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_MBUF) { 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); 1786356dba0SRobert Watson } 179225bff6fSRobert Watson return (0); 180225bff6fSRobert Watson } 181225bff6fSRobert Watson 182eca8a663SRobert Watson static void 183eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label) 184eca8a663SRobert Watson { 18583985c26SRobert Watson 18630d239bcSRobert Watson MAC_PERFORM(bpfdesc_destroy_label, label); 187eca8a663SRobert Watson mac_labelzone_free(label); 18887807196SRobert Watson } 18987807196SRobert Watson 190763bbd2fSRobert Watson void 19130d239bcSRobert Watson mac_bpfdesc_destroy(struct bpf_d *d) 19208bcdc58SRobert Watson { 19308bcdc58SRobert Watson 1946356dba0SRobert Watson if (d->bd_label != NULL) { 19526ae2b86SRobert Watson mac_bpfdesc_label_free(d->bd_label); 19626ae2b86SRobert Watson d->bd_label = NULL; 19708bcdc58SRobert Watson } 1986356dba0SRobert Watson } 19908bcdc58SRobert Watson 200f7b951a8SRobert Watson static void 201eca8a663SRobert Watson mac_ifnet_label_free(struct label *label) 202f7b951a8SRobert Watson { 203f7b951a8SRobert Watson 20430d239bcSRobert Watson MAC_PERFORM(ifnet_destroy_label, label); 205eca8a663SRobert Watson mac_labelzone_free(label); 206f7b951a8SRobert Watson } 207f7b951a8SRobert Watson 20887807196SRobert Watson void 20930d239bcSRobert Watson mac_ifnet_destroy(struct ifnet *ifp) 21087807196SRobert Watson { 21187807196SRobert Watson 2126356dba0SRobert Watson if (ifp->if_label != NULL) { 213eca8a663SRobert Watson mac_ifnet_label_free(ifp->if_label); 214eca8a663SRobert Watson ifp->if_label = NULL; 215eca8a663SRobert Watson } 2166356dba0SRobert Watson } 217eca8a663SRobert Watson 21887807196SRobert Watson void 21930d239bcSRobert Watson mac_mbuf_tag_destroy(struct m_tag *tag) 22087807196SRobert Watson { 221225bff6fSRobert Watson struct label *label; 22287807196SRobert Watson 223225bff6fSRobert Watson label = (struct label *)(tag+1); 224225bff6fSRobert Watson 22530d239bcSRobert Watson MAC_PERFORM(mbuf_destroy_label, label); 226225bff6fSRobert Watson mac_destroy_label(label); 22708bcdc58SRobert Watson } 22808bcdc58SRobert Watson 229e678cce9SRobert Watson /* 23030d239bcSRobert Watson * mac_mbuf_tag_copy is called when an mbuf header is duplicated, in which 231e678cce9SRobert Watson * case the labels must also be duplicated. 232e678cce9SRobert Watson */ 233b0323ea3SRobert Watson void 23430d239bcSRobert Watson mac_mbuf_tag_copy(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 /* 24230d239bcSRobert Watson * mac_mbuf_tag_init() is called on the target tag in m_tag_copy(), 243e678cce9SRobert Watson * so we don't need to call it here. 244225bff6fSRobert Watson */ 24530d239bcSRobert Watson MAC_PERFORM(mbuf_copy_label, src_label, dest_label); 246225bff6fSRobert Watson } 247225bff6fSRobert Watson 2483c308b09SRobert Watson void 24930d239bcSRobert Watson mac_mbuf_copy(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 25630d239bcSRobert Watson MAC_PERFORM(mbuf_copy_label, src_label, dest_label); 2573c308b09SRobert Watson } 2583c308b09SRobert Watson 2592220907bSRobert Watson static void 26030d239bcSRobert Watson mac_ifnet_copy_label(struct label *src, struct label *dest) 2612220907bSRobert Watson { 2622220907bSRobert Watson 26330d239bcSRobert Watson MAC_PERFORM(ifnet_copy_label, src, dest); 2642220907bSRobert Watson } 2652220907bSRobert Watson 26669bbb5b1SRobert Watson static int 26730d239bcSRobert Watson mac_ifnet_externalize_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 27830d239bcSRobert Watson mac_ifnet_internalize_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 28830d239bcSRobert Watson mac_ifnet_create(struct ifnet *ifp) 28995fab37eSRobert Watson { 29095fab37eSRobert Watson 29126ae2b86SRobert Watson MAC_IFNET_LOCK(ifp); 29230d239bcSRobert Watson MAC_PERFORM(ifnet_create, ifp, ifp->if_label); 29326ae2b86SRobert Watson MAC_IFNET_UNLOCK(ifp); 29495fab37eSRobert Watson } 29595fab37eSRobert Watson 29695fab37eSRobert Watson void 29730d239bcSRobert Watson mac_bpfdesc_create(struct ucred *cred, struct bpf_d *d) 29895fab37eSRobert Watson { 29995fab37eSRobert Watson 30030d239bcSRobert Watson MAC_PERFORM(bpfdesc_create, cred, d, d->bd_label); 30195fab37eSRobert Watson } 30295fab37eSRobert Watson 30395fab37eSRobert Watson void 30430d239bcSRobert Watson mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m) 30595fab37eSRobert Watson { 30610eeb10cSRobert Watson struct label *label; 30710eeb10cSRobert Watson 30826ae2b86SRobert Watson BPFD_LOCK_ASSERT(d); 309e33d9f29SRobert Watson 31026ae2b86SRobert Watson label = mac_mbuf_to_label(m); 31195fab37eSRobert Watson 31230d239bcSRobert Watson MAC_PERFORM(bpfdesc_create_mbuf, d, d->bd_label, m, label); 31395fab37eSRobert Watson } 31495fab37eSRobert Watson 31595fab37eSRobert Watson void 31630d239bcSRobert Watson mac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m) 31795fab37eSRobert Watson { 31810eeb10cSRobert Watson struct label *label; 31910eeb10cSRobert Watson 32026ae2b86SRobert Watson label = mac_mbuf_to_label(m); 32195fab37eSRobert Watson 32226ae2b86SRobert Watson MAC_IFNET_LOCK(ifp); 32330d239bcSRobert Watson MAC_PERFORM(ifnet_create_mbuf, ifp, ifp->if_label, m, label); 32426ae2b86SRobert Watson MAC_IFNET_UNLOCK(ifp); 32595fab37eSRobert Watson } 32695fab37eSRobert Watson 32795fab37eSRobert Watson int 32830d239bcSRobert Watson mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp) 32995fab37eSRobert Watson { 33095fab37eSRobert Watson int error; 33195fab37eSRobert Watson 33226ae2b86SRobert Watson BPFD_LOCK_ASSERT(d); 333e33d9f29SRobert Watson 33426ae2b86SRobert Watson MAC_IFNET_LOCK(ifp); 33530d239bcSRobert Watson MAC_CHECK(bpfdesc_check_receive, d, d->bd_label, ifp, ifp->if_label); 33626ae2b86SRobert Watson MAC_IFNET_UNLOCK(ifp); 33795fab37eSRobert Watson 33895fab37eSRobert Watson return (error); 33995fab37eSRobert Watson } 34095fab37eSRobert Watson 34195fab37eSRobert Watson int 34230d239bcSRobert Watson mac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m) 34395fab37eSRobert Watson { 34410eeb10cSRobert Watson struct label *label; 34595fab37eSRobert Watson int error; 34695fab37eSRobert Watson 34726ae2b86SRobert Watson M_ASSERTPKTHDR(m); 348225bff6fSRobert Watson 34926ae2b86SRobert Watson label = mac_mbuf_to_label(m); 35095fab37eSRobert Watson 35126ae2b86SRobert Watson MAC_IFNET_LOCK(ifp); 35230d239bcSRobert Watson MAC_CHECK(ifnet_check_transmit, ifp, ifp->if_label, m, label); 35326ae2b86SRobert Watson MAC_IFNET_UNLOCK(ifp); 35495fab37eSRobert Watson 35595fab37eSRobert Watson return (error); 35695fab37eSRobert Watson } 35795fab37eSRobert Watson 35895fab37eSRobert Watson int 35930d239bcSRobert Watson mac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr, 36026ae2b86SRobert Watson struct ifnet *ifp) 36195fab37eSRobert Watson { 362f7b951a8SRobert Watson char *elements, *buffer; 3632220907bSRobert Watson struct label *intlabel; 364f7b951a8SRobert Watson struct mac mac; 36595fab37eSRobert Watson int error; 36695fab37eSRobert Watson 3676356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_IFNET)) 3686356dba0SRobert Watson return (EINVAL); 3696356dba0SRobert Watson 370f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 37195fab37eSRobert Watson if (error) 37295fab37eSRobert Watson return (error); 37395fab37eSRobert Watson 374f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 375f7b951a8SRobert Watson if (error) 376f7b951a8SRobert Watson return (error); 377f7b951a8SRobert Watson 378a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 379f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 380f7b951a8SRobert Watson if (error) { 381f7b951a8SRobert Watson free(elements, M_MACTEMP); 382f7b951a8SRobert Watson return (error); 383f7b951a8SRobert Watson } 384f7b951a8SRobert Watson 385a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3862220907bSRobert Watson intlabel = mac_ifnet_label_alloc(); 38726ae2b86SRobert Watson MAC_IFNET_LOCK(ifp); 38830d239bcSRobert Watson mac_ifnet_copy_label(ifp->if_label, intlabel); 38926ae2b86SRobert Watson MAC_IFNET_UNLOCK(ifp); 39030d239bcSRobert Watson error = mac_ifnet_externalize_label(intlabel, elements, buffer, 3918f3476b3SRobert Watson mac.m_buflen); 3922220907bSRobert Watson mac_ifnet_label_free(intlabel); 393f7b951a8SRobert Watson if (error == 0) 394f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 395f7b951a8SRobert Watson 396f7b951a8SRobert Watson free(buffer, M_MACTEMP); 397f7b951a8SRobert Watson free(elements, M_MACTEMP); 398f7b951a8SRobert Watson 399f7b951a8SRobert Watson return (error); 40095fab37eSRobert Watson } 40195fab37eSRobert Watson 40295fab37eSRobert Watson int 40330d239bcSRobert Watson mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp) 40495fab37eSRobert Watson { 405eca8a663SRobert Watson struct label *intlabel; 406f7b951a8SRobert Watson struct mac mac; 407f7b951a8SRobert Watson char *buffer; 40895fab37eSRobert Watson int error; 40995fab37eSRobert Watson 4106356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_IFNET)) 4116356dba0SRobert Watson return (EINVAL); 4126356dba0SRobert Watson 413f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 41495fab37eSRobert Watson if (error) 41595fab37eSRobert Watson return (error); 41695fab37eSRobert Watson 417f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 41895fab37eSRobert Watson if (error) 41995fab37eSRobert Watson return (error); 42095fab37eSRobert Watson 421a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 422f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 423f7b951a8SRobert Watson if (error) { 424f7b951a8SRobert Watson free(buffer, M_MACTEMP); 425f7b951a8SRobert Watson return (error); 426f7b951a8SRobert Watson } 427f7b951a8SRobert Watson 428eca8a663SRobert Watson intlabel = mac_ifnet_label_alloc(); 42930d239bcSRobert Watson error = mac_ifnet_internalize_label(intlabel, buffer); 430f7b951a8SRobert Watson free(buffer, M_MACTEMP); 431f7b951a8SRobert Watson if (error) { 432eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 433f7b951a8SRobert Watson return (error); 434f7b951a8SRobert Watson } 435f7b951a8SRobert Watson 43695fab37eSRobert Watson /* 437acd3428bSRobert Watson * XXX: Note that this is a redundant privilege check, since policies 438e678cce9SRobert Watson * impose this check themselves if required by the policy 439acd3428bSRobert Watson * Eventually, this should go away. 44095fab37eSRobert Watson */ 441acd3428bSRobert Watson error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0); 442f7b951a8SRobert Watson if (error) { 443eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 444f7b951a8SRobert Watson return (error); 445f7b951a8SRobert Watson } 44695fab37eSRobert Watson 44726ae2b86SRobert Watson MAC_IFNET_LOCK(ifp); 44830d239bcSRobert Watson MAC_CHECK(ifnet_check_relabel, cred, ifp, ifp->if_label, intlabel); 449f7b951a8SRobert Watson if (error) { 45026ae2b86SRobert Watson MAC_IFNET_UNLOCK(ifp); 451eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 452f7b951a8SRobert Watson return (error); 453f7b951a8SRobert Watson } 45495fab37eSRobert Watson 45530d239bcSRobert Watson MAC_PERFORM(ifnet_relabel, cred, ifp, ifp->if_label, intlabel); 45626ae2b86SRobert Watson MAC_IFNET_UNLOCK(ifp); 45795fab37eSRobert Watson 458eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 459f7b951a8SRobert Watson return (0); 46095fab37eSRobert Watson } 461