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> 46677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 47677b542eSDavid E. O'Brien 487bc82500SRobert Watson #include "opt_mac.h" 49f9d0d524SRobert Watson 507bc82500SRobert Watson #include <sys/param.h> 5195fab37eSRobert Watson #include <sys/kernel.h> 5295fab37eSRobert Watson #include <sys/lock.h> 53b656366bSBruce Evans #include <sys/malloc.h> 5495fab37eSRobert Watson #include <sys/mutex.h> 5595fab37eSRobert Watson #include <sys/mac.h> 56acd3428bSRobert Watson #include <sys/priv.h> 57f51e5803SRobert Watson #include <sys/sbuf.h> 582087a58cSRobert Watson #include <sys/sdt.h> 5995fab37eSRobert Watson #include <sys/systm.h> 6095fab37eSRobert Watson #include <sys/mount.h> 6195fab37eSRobert Watson #include <sys/file.h> 6295fab37eSRobert Watson #include <sys/namei.h> 63a557af22SRobert Watson #include <sys/protosw.h> 6495fab37eSRobert Watson #include <sys/socket.h> 6595fab37eSRobert Watson #include <sys/socketvar.h> 6695fab37eSRobert Watson #include <sys/sysctl.h> 6795fab37eSRobert Watson 6895fab37eSRobert Watson #include <net/bpfdesc.h> 6995fab37eSRobert Watson #include <net/if.h> 7095fab37eSRobert Watson #include <net/if_var.h> 7195fab37eSRobert Watson 72aed55708SRobert Watson #include <security/mac/mac_framework.h> 7328e65e3dSRobert Watson #include <security/mac/mac_internal.h> 740efd6615SRobert Watson #include <security/mac/mac_policy.h> 75a3df768bSRobert Watson 76c66b4d8dSRobert Watson /* 77e678cce9SRobert Watson * XXXRW: struct ifnet locking is incomplete in the network code, so we use 78e678cce9SRobert Watson * our own global mutex for struct ifnet. Non-ideal, but should help in the 79e678cce9SRobert Watson * SMP environment. 805c95417dSRobert Watson * 815c95417dSRobert Watson * This lock is acquired only if a loaded policy is using ifnet labeling. 825c95417dSRobert Watson * This should not ever change during a MAC policy check, itself, but could 835c95417dSRobert Watson * change during setup/return from a check, so we have to condition unlock on 845c95417dSRobert Watson * previous lock. 852220907bSRobert Watson */ 86b9b0dac3SRobert Watson struct mtx mac_ifnet_mtx; 872220907bSRobert Watson MTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF); 882220907bSRobert Watson 89e678cce9SRobert Watson /* 90e678cce9SRobert Watson * Retrieve the label associated with an mbuf by searching for the tag. 91e678cce9SRobert Watson * Depending on the value of mac_labelmbufs, it's possible that a label will 92e678cce9SRobert Watson * not be present, in which case NULL is returned. Policies must handle the 93e678cce9SRobert Watson * possibility of an mbuf not having label storage if they do not enforce 94e678cce9SRobert Watson * early loading. 95e678cce9SRobert Watson */ 96c66b4d8dSRobert Watson struct label * 9726ae2b86SRobert Watson mac_mbuf_to_label(struct mbuf *m) 9810eeb10cSRobert Watson { 99225bff6fSRobert Watson struct m_tag *tag; 10010eeb10cSRobert Watson struct label *label; 10110eeb10cSRobert Watson 10226ae2b86SRobert Watson if (m == NULL) 103583284e1SRobert Watson return (NULL); 10426ae2b86SRobert Watson tag = m_tag_find(m, PACKET_TAG_MACLABEL, NULL); 105583284e1SRobert Watson if (tag == NULL) 106583284e1SRobert Watson return (NULL); 107225bff6fSRobert Watson label = (struct label *)(tag+1); 10810eeb10cSRobert Watson return (label); 10910eeb10cSRobert Watson } 11010eeb10cSRobert Watson 111eca8a663SRobert Watson static struct label * 112eca8a663SRobert Watson mac_bpfdesc_label_alloc(void) 113eca8a663SRobert Watson { 114eca8a663SRobert Watson struct label *label; 115eca8a663SRobert Watson 116eca8a663SRobert Watson label = mac_labelzone_alloc(M_WAITOK); 117fa765671SRobert Watson MAC_POLICY_PERFORM(bpfdesc_init_label, label); 118eca8a663SRobert Watson return (label); 119eca8a663SRobert Watson } 120eca8a663SRobert Watson 12108bcdc58SRobert Watson void 12230d239bcSRobert Watson mac_bpfdesc_init(struct bpf_d *d) 12308bcdc58SRobert Watson { 12408bcdc58SRobert Watson 1256356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_BPFDESC) 12626ae2b86SRobert Watson d->bd_label = mac_bpfdesc_label_alloc(); 1276356dba0SRobert Watson else 1286356dba0SRobert Watson d->bd_label = NULL; 12908bcdc58SRobert Watson } 13008bcdc58SRobert Watson 131eca8a663SRobert Watson static struct label * 132eca8a663SRobert Watson mac_ifnet_label_alloc(void) 133f7b951a8SRobert Watson { 134eca8a663SRobert Watson struct label *label; 135f7b951a8SRobert Watson 136eca8a663SRobert Watson label = mac_labelzone_alloc(M_WAITOK); 137fa765671SRobert Watson MAC_POLICY_PERFORM(ifnet_init_label, label); 138eca8a663SRobert Watson return (label); 139f7b951a8SRobert Watson } 140f7b951a8SRobert Watson 14108bcdc58SRobert Watson void 14230d239bcSRobert Watson mac_ifnet_init(struct ifnet *ifp) 14308bcdc58SRobert Watson { 14408bcdc58SRobert Watson 1456356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_IFNET) 146*30af2c13SJustin Hibbits if_setmaclabel(ifp, mac_ifnet_label_alloc()); 1476356dba0SRobert Watson else 148*30af2c13SJustin Hibbits if_setmaclabel(ifp, NULL); 149eca8a663SRobert Watson } 150eca8a663SRobert Watson 15187807196SRobert Watson int 15230d239bcSRobert Watson mac_mbuf_tag_init(struct m_tag *tag, int flag) 15308bcdc58SRobert Watson { 154225bff6fSRobert Watson struct label *label; 1556d1a6a9aSRobert Watson int error; 15656c15412SRobert Watson 157225bff6fSRobert Watson label = (struct label *) (tag + 1); 158225bff6fSRobert Watson mac_init_label(label); 15908bcdc58SRobert Watson 16040202729SRobert Watson if (flag & M_WAITOK) 161fa765671SRobert Watson MAC_POLICY_CHECK(mbuf_init_label, label, flag); 16240202729SRobert Watson else 163fa765671SRobert Watson MAC_POLICY_CHECK_NOSLEEP(mbuf_init_label, label, flag); 16456c15412SRobert Watson if (error) { 165fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label); 166225bff6fSRobert Watson mac_destroy_label(label); 16756c15412SRobert Watson } 16856c15412SRobert Watson return (error); 16908bcdc58SRobert Watson } 17008bcdc58SRobert Watson 171225bff6fSRobert Watson int 17230d239bcSRobert Watson mac_mbuf_init(struct mbuf *m, int flag) 173225bff6fSRobert Watson { 174225bff6fSRobert Watson struct m_tag *tag; 175225bff6fSRobert Watson int error; 176225bff6fSRobert Watson 177225bff6fSRobert Watson M_ASSERTPKTHDR(m); 178225bff6fSRobert Watson 1796356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_MBUF) { 180225bff6fSRobert Watson tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label), 181225bff6fSRobert Watson flag); 182225bff6fSRobert Watson if (tag == NULL) 183225bff6fSRobert Watson return (ENOMEM); 18430d239bcSRobert Watson error = mac_mbuf_tag_init(tag, flag); 185225bff6fSRobert Watson if (error) { 186225bff6fSRobert Watson m_tag_free(tag); 187225bff6fSRobert Watson return (error); 188225bff6fSRobert Watson } 189225bff6fSRobert Watson m_tag_prepend(m, tag); 1906356dba0SRobert Watson } 191225bff6fSRobert Watson return (0); 192225bff6fSRobert Watson } 193225bff6fSRobert Watson 194eca8a663SRobert Watson static void 195eca8a663SRobert Watson mac_bpfdesc_label_free(struct label *label) 196eca8a663SRobert Watson { 19783985c26SRobert Watson 198fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_destroy_label, label); 199eca8a663SRobert Watson mac_labelzone_free(label); 20087807196SRobert Watson } 20187807196SRobert Watson 202763bbd2fSRobert Watson void 20330d239bcSRobert Watson mac_bpfdesc_destroy(struct bpf_d *d) 20408bcdc58SRobert Watson { 20508bcdc58SRobert Watson 2066356dba0SRobert Watson if (d->bd_label != NULL) { 20726ae2b86SRobert Watson mac_bpfdesc_label_free(d->bd_label); 20826ae2b86SRobert Watson d->bd_label = NULL; 20908bcdc58SRobert Watson } 2106356dba0SRobert Watson } 21108bcdc58SRobert Watson 212f7b951a8SRobert Watson static void 213eca8a663SRobert Watson mac_ifnet_label_free(struct label *label) 214f7b951a8SRobert Watson { 215f7b951a8SRobert Watson 216fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(ifnet_destroy_label, label); 217eca8a663SRobert Watson mac_labelzone_free(label); 218f7b951a8SRobert Watson } 219f7b951a8SRobert Watson 22087807196SRobert Watson void 22130d239bcSRobert Watson mac_ifnet_destroy(struct ifnet *ifp) 22287807196SRobert Watson { 223*30af2c13SJustin Hibbits struct label *label = if_getmaclabel(ifp); 224*30af2c13SJustin Hibbits if (label != NULL) { 225*30af2c13SJustin Hibbits mac_ifnet_label_free(label); 226*30af2c13SJustin Hibbits if_setmaclabel(ifp, NULL); 227eca8a663SRobert Watson } 2286356dba0SRobert Watson } 229eca8a663SRobert Watson 23087807196SRobert Watson void 23130d239bcSRobert Watson mac_mbuf_tag_destroy(struct m_tag *tag) 23287807196SRobert Watson { 233225bff6fSRobert Watson struct label *label; 23487807196SRobert Watson 235225bff6fSRobert Watson label = (struct label *)(tag+1); 236225bff6fSRobert Watson 237fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label); 238225bff6fSRobert Watson mac_destroy_label(label); 23908bcdc58SRobert Watson } 24008bcdc58SRobert Watson 241e678cce9SRobert Watson /* 24230d239bcSRobert Watson * mac_mbuf_tag_copy is called when an mbuf header is duplicated, in which 243e678cce9SRobert Watson * case the labels must also be duplicated. 244e678cce9SRobert Watson */ 245b0323ea3SRobert Watson void 24630d239bcSRobert Watson mac_mbuf_tag_copy(struct m_tag *src, struct m_tag *dest) 247225bff6fSRobert Watson { 248225bff6fSRobert Watson struct label *src_label, *dest_label; 249225bff6fSRobert Watson 250225bff6fSRobert Watson src_label = (struct label *)(src+1); 251225bff6fSRobert Watson dest_label = (struct label *)(dest+1); 252225bff6fSRobert Watson 253225bff6fSRobert Watson /* 25430d239bcSRobert Watson * mac_mbuf_tag_init() is called on the target tag in m_tag_copy(), 255e678cce9SRobert Watson * so we don't need to call it here. 256225bff6fSRobert Watson */ 257fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label); 258225bff6fSRobert Watson } 259225bff6fSRobert Watson 2603c308b09SRobert Watson void 26130d239bcSRobert Watson mac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to) 2623c308b09SRobert Watson { 2633c308b09SRobert Watson struct label *src_label, *dest_label; 2643c308b09SRobert Watson 2653ad3d9c5SRobert Watson if (mac_policy_count == 0) 2663ad3d9c5SRobert Watson return; 2673ad3d9c5SRobert Watson 2683c308b09SRobert Watson src_label = mac_mbuf_to_label(m_from); 2693c308b09SRobert Watson dest_label = mac_mbuf_to_label(m_to); 2703c308b09SRobert Watson 271fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label); 2723c308b09SRobert Watson } 2733c308b09SRobert Watson 2742220907bSRobert Watson static void 27530d239bcSRobert Watson mac_ifnet_copy_label(struct label *src, struct label *dest) 2762220907bSRobert Watson { 2772220907bSRobert Watson 278fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(ifnet_copy_label, src, dest); 2792220907bSRobert Watson } 2802220907bSRobert Watson 28169bbb5b1SRobert Watson static int 28230d239bcSRobert Watson mac_ifnet_externalize_label(struct label *label, char *elements, 28383b7b0edSRobert Watson char *outbuf, size_t outbuflen) 28469bbb5b1SRobert Watson { 28569bbb5b1SRobert Watson int error; 28669bbb5b1SRobert Watson 287fa765671SRobert Watson MAC_POLICY_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen); 288f7b951a8SRobert Watson 289f7b951a8SRobert Watson return (error); 290f7b951a8SRobert Watson } 291f7b951a8SRobert Watson 292f7b951a8SRobert Watson static int 29330d239bcSRobert Watson mac_ifnet_internalize_label(struct label *label, char *string) 294f7b951a8SRobert Watson { 295f7b951a8SRobert Watson int error; 296f7b951a8SRobert Watson 297fa765671SRobert Watson MAC_POLICY_INTERNALIZE(ifnet, label, string); 298f7b951a8SRobert Watson 299f7b951a8SRobert Watson return (error); 300f7b951a8SRobert Watson } 301f7b951a8SRobert Watson 30295fab37eSRobert Watson void 30330d239bcSRobert Watson mac_ifnet_create(struct ifnet *ifp) 30495fab37eSRobert Watson { 3055c95417dSRobert Watson int locked; 30695fab37eSRobert Watson 3073de40469SRobert Watson if (mac_policy_count == 0) 3083de40469SRobert Watson return; 3093de40469SRobert Watson 3105c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked); 311*30af2c13SJustin Hibbits MAC_POLICY_PERFORM_NOSLEEP(ifnet_create, ifp, if_getmaclabel(ifp)); 3125c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked); 31395fab37eSRobert Watson } 31495fab37eSRobert Watson 31595fab37eSRobert Watson void 31630d239bcSRobert Watson mac_bpfdesc_create(struct ucred *cred, struct bpf_d *d) 31795fab37eSRobert Watson { 31895fab37eSRobert Watson 319fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create, cred, d, d->bd_label); 32095fab37eSRobert Watson } 32195fab37eSRobert Watson 32295fab37eSRobert Watson void 32330d239bcSRobert Watson mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m) 32495fab37eSRobert Watson { 32510eeb10cSRobert Watson struct label *label; 32610eeb10cSRobert Watson 327e4b3229aSAlexander V. Chernikov /* Assume reader lock is enough. */ 32826ae2b86SRobert Watson BPFD_LOCK_ASSERT(d); 329e33d9f29SRobert Watson 3303de40469SRobert Watson if (mac_policy_count == 0) 3313de40469SRobert Watson return; 3323de40469SRobert Watson 33326ae2b86SRobert Watson label = mac_mbuf_to_label(m); 33495fab37eSRobert Watson 335fa765671SRobert Watson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m, 336fa765671SRobert Watson label); 33795fab37eSRobert Watson } 33895fab37eSRobert Watson 33995fab37eSRobert Watson void 340f77697ddSMateusz Guzik mac_ifnet_create_mbuf_impl(struct ifnet *ifp, struct mbuf *m) 34195fab37eSRobert Watson { 34210eeb10cSRobert Watson struct label *label; 3435c95417dSRobert Watson int locked; 34410eeb10cSRobert Watson 34526ae2b86SRobert Watson label = mac_mbuf_to_label(m); 34695fab37eSRobert Watson 3475c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked); 348*30af2c13SJustin Hibbits MAC_POLICY_PERFORM_NOSLEEP(ifnet_create_mbuf, ifp, if_getmaclabel(ifp), m, 349fa765671SRobert Watson label); 3505c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked); 35195fab37eSRobert Watson } 35295fab37eSRobert Watson 3532087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(bpfdesc_check_receive, "struct bpf_d *", 3542087a58cSRobert Watson "struct ifnet *"); 3552087a58cSRobert Watson 35695fab37eSRobert Watson int 35730d239bcSRobert Watson mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp) 35895fab37eSRobert Watson { 3595c95417dSRobert Watson int error, locked; 36095fab37eSRobert Watson 361e4b3229aSAlexander V. Chernikov /* Assume reader lock is enough. */ 36226ae2b86SRobert Watson BPFD_LOCK_ASSERT(d); 363e33d9f29SRobert Watson 3643de40469SRobert Watson if (mac_policy_count == 0) 3653de40469SRobert Watson return (0); 3663de40469SRobert Watson 3675c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked); 368fa765671SRobert Watson MAC_POLICY_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp, 369*30af2c13SJustin Hibbits if_getmaclabel(ifp)); 3702087a58cSRobert Watson MAC_CHECK_PROBE2(bpfdesc_check_receive, error, d, ifp); 3715c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked); 37295fab37eSRobert Watson 37395fab37eSRobert Watson return (error); 37495fab37eSRobert Watson } 37595fab37eSRobert Watson 3762087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(ifnet_check_transmit, "struct ifnet *", 3772087a58cSRobert Watson "struct mbuf *"); 3782087a58cSRobert Watson 37995fab37eSRobert Watson int 380f77697ddSMateusz Guzik mac_ifnet_check_transmit_impl(struct ifnet *ifp, struct mbuf *m) 38195fab37eSRobert Watson { 38210eeb10cSRobert Watson struct label *label; 3835c95417dSRobert Watson int error, locked; 38495fab37eSRobert Watson 38526ae2b86SRobert Watson M_ASSERTPKTHDR(m); 386225bff6fSRobert Watson 38726ae2b86SRobert Watson label = mac_mbuf_to_label(m); 38895fab37eSRobert Watson 3895c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked); 390*30af2c13SJustin Hibbits MAC_POLICY_CHECK_NOSLEEP(ifnet_check_transmit, ifp, if_getmaclabel(ifp), m, 39140202729SRobert Watson label); 3922087a58cSRobert Watson MAC_CHECK_PROBE2(ifnet_check_transmit, error, ifp, m); 3935c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked); 39495fab37eSRobert Watson 39595fab37eSRobert Watson return (error); 39695fab37eSRobert Watson } 39795fab37eSRobert Watson 39895fab37eSRobert Watson int 39930d239bcSRobert Watson mac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr, 40026ae2b86SRobert Watson struct ifnet *ifp) 40195fab37eSRobert Watson { 402f7b951a8SRobert Watson char *elements, *buffer; 4032220907bSRobert Watson struct label *intlabel; 404f7b951a8SRobert Watson struct mac mac; 4055c95417dSRobert Watson int error, locked; 40695fab37eSRobert Watson 4076356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_IFNET)) 4086356dba0SRobert Watson return (EINVAL); 4096356dba0SRobert Watson 410541d96aaSBrooks Davis error = copyin(ifr_data_get_ptr(ifr), &mac, sizeof(mac)); 41195fab37eSRobert Watson if (error) 41295fab37eSRobert Watson return (error); 41395fab37eSRobert Watson 414f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 415f7b951a8SRobert Watson if (error) 416f7b951a8SRobert Watson return (error); 417f7b951a8SRobert Watson 418a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 419f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 420f7b951a8SRobert Watson if (error) { 421f7b951a8SRobert Watson free(elements, M_MACTEMP); 422f7b951a8SRobert Watson return (error); 423f7b951a8SRobert Watson } 424f7b951a8SRobert Watson 425a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 4262220907bSRobert Watson intlabel = mac_ifnet_label_alloc(); 4275c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked); 428*30af2c13SJustin Hibbits mac_ifnet_copy_label(if_getmaclabel(ifp), intlabel); 4295c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked); 43030d239bcSRobert Watson error = mac_ifnet_externalize_label(intlabel, elements, buffer, 4318f3476b3SRobert Watson mac.m_buflen); 4322220907bSRobert Watson mac_ifnet_label_free(intlabel); 433f7b951a8SRobert Watson if (error == 0) 434f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 435f7b951a8SRobert Watson 436f7b951a8SRobert Watson free(buffer, M_MACTEMP); 437f7b951a8SRobert Watson free(elements, M_MACTEMP); 438f7b951a8SRobert Watson 439f7b951a8SRobert Watson return (error); 44095fab37eSRobert Watson } 44195fab37eSRobert Watson 44295fab37eSRobert Watson int 44330d239bcSRobert Watson mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp) 44495fab37eSRobert Watson { 445eca8a663SRobert Watson struct label *intlabel; 446f7b951a8SRobert Watson struct mac mac; 447f7b951a8SRobert Watson char *buffer; 4485c95417dSRobert Watson int error, locked; 44995fab37eSRobert Watson 4506356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_IFNET)) 4516356dba0SRobert Watson return (EINVAL); 4526356dba0SRobert Watson 453541d96aaSBrooks Davis error = copyin(ifr_data_get_ptr(ifr), &mac, sizeof(mac)); 45495fab37eSRobert Watson if (error) 45595fab37eSRobert Watson return (error); 45695fab37eSRobert Watson 457f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 45895fab37eSRobert Watson if (error) 45995fab37eSRobert Watson return (error); 46095fab37eSRobert Watson 461a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 462f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 463f7b951a8SRobert Watson if (error) { 464f7b951a8SRobert Watson free(buffer, M_MACTEMP); 465f7b951a8SRobert Watson return (error); 466f7b951a8SRobert Watson } 467f7b951a8SRobert Watson 468eca8a663SRobert Watson intlabel = mac_ifnet_label_alloc(); 46930d239bcSRobert Watson error = mac_ifnet_internalize_label(intlabel, buffer); 470f7b951a8SRobert Watson free(buffer, M_MACTEMP); 471f7b951a8SRobert Watson if (error) { 472eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 473f7b951a8SRobert Watson return (error); 474f7b951a8SRobert Watson } 475f7b951a8SRobert Watson 47695fab37eSRobert Watson /* 477acd3428bSRobert Watson * XXX: Note that this is a redundant privilege check, since policies 478e678cce9SRobert Watson * impose this check themselves if required by the policy 479acd3428bSRobert Watson * Eventually, this should go away. 48095fab37eSRobert Watson */ 481cc426dd3SMateusz Guzik error = priv_check_cred(cred, PRIV_NET_SETIFMAC); 482f7b951a8SRobert Watson if (error) { 483eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 484f7b951a8SRobert Watson return (error); 485f7b951a8SRobert Watson } 48695fab37eSRobert Watson 4875c95417dSRobert Watson MAC_IFNET_LOCK(ifp, locked); 488fa765671SRobert Watson MAC_POLICY_CHECK_NOSLEEP(ifnet_check_relabel, cred, ifp, 489*30af2c13SJustin Hibbits if_getmaclabel(ifp), intlabel); 490f7b951a8SRobert Watson if (error) { 4915c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked); 492eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 493f7b951a8SRobert Watson return (error); 494f7b951a8SRobert Watson } 49595fab37eSRobert Watson 496*30af2c13SJustin Hibbits MAC_POLICY_PERFORM_NOSLEEP(ifnet_relabel, cred, ifp, if_getmaclabel(ifp), 49740202729SRobert Watson intlabel); 4985c95417dSRobert Watson MAC_IFNET_UNLOCK(ifp, locked); 49995fab37eSRobert Watson 500eca8a663SRobert Watson mac_ifnet_label_free(intlabel); 501f7b951a8SRobert Watson return (0); 50295fab37eSRobert Watson } 503