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