17bc82500SRobert Watson /*- 27bc82500SRobert Watson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 37bc82500SRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 47bc82500SRobert Watson * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 57bc82500SRobert Watson * All rights reserved. 67bc82500SRobert Watson * 77bc82500SRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 87bc82500SRobert Watson * TrustedBSD Project. 97bc82500SRobert Watson * 107bc82500SRobert Watson * This software was developed for the FreeBSD Project in part by NAI Labs, 117bc82500SRobert Watson * the Security Research Division of Network Associates, Inc. under 127bc82500SRobert Watson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 137bc82500SRobert Watson * CHATS research program. 147bc82500SRobert Watson * 157bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without 167bc82500SRobert Watson * modification, are permitted provided that the following conditions 177bc82500SRobert Watson * are met: 187bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright 197bc82500SRobert Watson * notice, this list of conditions and the following disclaimer. 207bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 217bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the 227bc82500SRobert Watson * documentation and/or other materials provided with the distribution. 237bc82500SRobert Watson * 3. The names of the authors may not be used to endorse or promote 247bc82500SRobert Watson * products derived from this software without specific prior written 257bc82500SRobert Watson * permission. 267bc82500SRobert Watson * 277bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 287bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 297bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 307bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 317bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 327bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 337bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 347bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 357bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 367bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 377bc82500SRobert Watson * SUCH DAMAGE. 387bc82500SRobert Watson * 397bc82500SRobert Watson * $FreeBSD$ 407bc82500SRobert Watson */ 417bc82500SRobert Watson /* 427bc82500SRobert Watson * Developed by the TrustedBSD Project. 437bc82500SRobert Watson * 447bc82500SRobert Watson * Framework for extensible kernel access control. Kernel and userland 457bc82500SRobert Watson * interface to the framework, policy registration and composition. 467bc82500SRobert Watson */ 477bc82500SRobert Watson 487bc82500SRobert Watson #include "opt_mac.h" 49328048bcSPoul-Henning Kamp #include "opt_devfs.h" 50f9d0d524SRobert Watson 517bc82500SRobert Watson #include <sys/param.h> 5295fab37eSRobert Watson #include <sys/extattr.h> 5395fab37eSRobert Watson #include <sys/kernel.h> 5495fab37eSRobert Watson #include <sys/lock.h> 55b656366bSBruce Evans #include <sys/malloc.h> 5695fab37eSRobert Watson #include <sys/mutex.h> 5795fab37eSRobert Watson #include <sys/mac.h> 587ba28492SRobert Watson #include <sys/module.h> 5995fab37eSRobert Watson #include <sys/proc.h> 6095fab37eSRobert Watson #include <sys/systm.h> 617bc82500SRobert Watson #include <sys/sysproto.h> 627bc82500SRobert Watson #include <sys/sysent.h> 6395fab37eSRobert Watson #include <sys/vnode.h> 6495fab37eSRobert Watson #include <sys/mount.h> 6595fab37eSRobert Watson #include <sys/file.h> 6695fab37eSRobert Watson #include <sys/namei.h> 6795fab37eSRobert Watson #include <sys/socket.h> 6895fab37eSRobert Watson #include <sys/pipe.h> 6995fab37eSRobert Watson #include <sys/socketvar.h> 7095fab37eSRobert Watson #include <sys/sysctl.h> 7195fab37eSRobert Watson 7295fab37eSRobert Watson #include <vm/vm.h> 7395fab37eSRobert Watson #include <vm/pmap.h> 7495fab37eSRobert Watson #include <vm/vm_map.h> 7595fab37eSRobert Watson #include <vm/vm_object.h> 7695fab37eSRobert Watson 7795fab37eSRobert Watson #include <sys/mac_policy.h> 7895fab37eSRobert Watson 7995fab37eSRobert Watson #include <fs/devfs/devfs.h> 8095fab37eSRobert Watson 8195fab37eSRobert Watson #include <net/bpfdesc.h> 8295fab37eSRobert Watson #include <net/if.h> 8395fab37eSRobert Watson #include <net/if_var.h> 8495fab37eSRobert Watson 8595fab37eSRobert Watson #include <netinet/in.h> 8695fab37eSRobert Watson #include <netinet/ip_var.h> 8795fab37eSRobert Watson 8895fab37eSRobert Watson #ifdef MAC 8995fab37eSRobert Watson 907ba28492SRobert Watson /* 917ba28492SRobert Watson * Declare that the kernel provides MAC support, version 1. This permits 927ba28492SRobert Watson * modules to refuse to be loaded if the necessary support isn't present, 937ba28492SRobert Watson * even if it's pre-boot. 947ba28492SRobert Watson */ 957ba28492SRobert Watson MODULE_VERSION(kernel_mac_support, 1); 967ba28492SRobert Watson 9795fab37eSRobert Watson SYSCTL_DECL(_security); 9895fab37eSRobert Watson 9995fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 10095fab37eSRobert Watson "TrustedBSD MAC policy controls"); 101b2f0927aSRobert Watson 10295fab37eSRobert Watson #if MAC_MAX_POLICIES > 32 10395fab37eSRobert Watson #error "MAC_MAX_POLICIES too large" 10495fab37eSRobert Watson #endif 105a13c67daSRobert Watson 10695fab37eSRobert Watson static unsigned int mac_max_policies = MAC_MAX_POLICIES; 10795fab37eSRobert Watson static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 10895fab37eSRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 10995fab37eSRobert Watson &mac_max_policies, 0, ""); 11095fab37eSRobert Watson 111a67fe518SRobert Watson /* 112a67fe518SRobert Watson * Has the kernel started generating labeled objects yet? All read/write 113a67fe518SRobert Watson * access to this variable is serialized during the boot process. Following 114a67fe518SRobert Watson * the end of serialization, we don't update this flag; no locking. 115a67fe518SRobert Watson */ 11695fab37eSRobert Watson static int mac_late = 0; 11795fab37eSRobert Watson 118763bbd2fSRobert Watson /* 119763bbd2fSRobert Watson * Warn about EA transactions only the first time they happen. 120763bbd2fSRobert Watson * Weak coherency, no locking. 121763bbd2fSRobert Watson */ 122763bbd2fSRobert Watson static int ea_warn_once = 0; 123763bbd2fSRobert Watson 12495fab37eSRobert Watson static int mac_enforce_fs = 1; 12595fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 12695fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 12795fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 12895fab37eSRobert Watson 12995fab37eSRobert Watson static int mac_enforce_network = 1; 13095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 13195fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 13295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 13395fab37eSRobert Watson 134b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 135b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 136b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 137c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 138b88c98f6SRobert Watson 13995fab37eSRobert Watson static int mac_enforce_process = 1; 14095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 14195fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 14295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 14395fab37eSRobert Watson 14495fab37eSRobert Watson static int mac_enforce_socket = 1; 14595fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 14695fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 14795fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 14895fab37eSRobert Watson 149ca7850c3SRobert Watson static int mac_enforce_vm = 1; 150ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 151ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 152c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 153ca7850c3SRobert Watson 15495fab37eSRobert Watson static int mac_cache_fslabel_in_vnode = 1; 15595fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, 15695fab37eSRobert Watson &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); 15795fab37eSRobert Watson TUNABLE_INT("security.mac.cache_fslabel_in_vnode", 15895fab37eSRobert Watson &mac_cache_fslabel_in_vnode); 15995fab37eSRobert Watson 160c0f39905SRobert Watson static int mac_mmap_revocation = 1; 161c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 162c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 163c0f39905SRobert Watson "relabel"); 16499fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 16595fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 16695fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 16795fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 16895fab37eSRobert Watson 169f050add5SRobert Watson #ifdef MAC_DEBUG 1706be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1716be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1726be0c25eSRobert Watson 1736be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1746be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1756be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1766be0c25eSRobert Watson "when label is corrupted."); 1776be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1786be0c25eSRobert Watson &mac_debug_label_fallback); 1796be0c25eSRobert Watson 180b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 181b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 182b2f0927aSRobert Watson 18395fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 18495fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 18595fab37eSRobert Watson nmacipqs, nmacpipes; 186b2f0927aSRobert Watson 187b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 18895fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 189b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 19095fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 191b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 19295fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 193b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 19495fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 195b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 19695fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 197b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 19895fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 199b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 20095fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 201b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 20295fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 203b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 20495fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 205b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 20695fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 207b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 20895fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 209f050add5SRobert Watson #endif 21095fab37eSRobert Watson 21195fab37eSRobert Watson static int error_select(int error1, int error2); 21295fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 21395fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 21495fab37eSRobert Watson 215e183f80eSRobert Watson static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 216e183f80eSRobert Watson struct vnode *vp, int *prot); 21795fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 21895fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 21995fab37eSRobert Watson 22083985c26SRobert Watson static void mac_destroy_socket_label(struct label *label); 22183985c26SRobert Watson 222763bbd2fSRobert Watson static int mac_setlabel_vnode_extattr(struct ucred *cred, 223763bbd2fSRobert Watson struct vnode *vp, struct label *intlabel); 224763bbd2fSRobert Watson 225763bbd2fSRobert Watson 22695fab37eSRobert Watson MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); 22795fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 228f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 22995fab37eSRobert Watson 23095fab37eSRobert Watson /* 23195fab37eSRobert Watson * mac_policy_list_lock protects the consistency of 'mac_policy_list', 23295fab37eSRobert Watson * the linked list of attached policy modules. Read-only consumers of 23395fab37eSRobert Watson * the list must acquire a shared lock for the duration of their use; 23495fab37eSRobert Watson * writers must acquire an exclusive lock. Note that for compound 23595fab37eSRobert Watson * operations, locks should be held for the entire compound operation, 23695fab37eSRobert Watson * and that this is not yet done for relabel requests. 23795fab37eSRobert Watson */ 23895fab37eSRobert Watson static struct mtx mac_policy_list_lock; 23995fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 24095fab37eSRobert Watson static int mac_policy_list_busy; 24195fab37eSRobert Watson #define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \ 24295fab37eSRobert Watson "mac_policy_list_lock", NULL, MTX_DEF); 24395fab37eSRobert Watson #define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock); 24495fab37eSRobert Watson #define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock); 24595fab37eSRobert Watson 24695fab37eSRobert Watson #define MAC_POLICY_LIST_BUSY() do { \ 24795fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 24895fab37eSRobert Watson mac_policy_list_busy++; \ 24995fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 25095fab37eSRobert Watson } while (0) 25195fab37eSRobert Watson 25295fab37eSRobert Watson #define MAC_POLICY_LIST_UNBUSY() do { \ 25395fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 25495fab37eSRobert Watson mac_policy_list_busy--; \ 25595fab37eSRobert Watson if (mac_policy_list_busy < 0) \ 25695fab37eSRobert Watson panic("Extra mac_policy_list_busy--"); \ 25795fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 25895fab37eSRobert Watson } while (0) 25995fab37eSRobert Watson 26095fab37eSRobert Watson /* 26195fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 26295fab37eSRobert Watson * module list and checking with each as to how it feels about the 26395fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 26495fab37eSRobert Watson * of the caller. 26595fab37eSRobert Watson */ 26695fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 26795fab37eSRobert Watson struct mac_policy_conf *mpc; \ 26895fab37eSRobert Watson \ 26995fab37eSRobert Watson error = 0; \ 27095fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 27195fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 27295fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 27395fab37eSRobert Watson error = error_select( \ 27495fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 27595fab37eSRobert Watson error); \ 27695fab37eSRobert Watson } \ 27795fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 27895fab37eSRobert Watson } while (0) 27995fab37eSRobert Watson 28095fab37eSRobert Watson /* 28195fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 28295fab37eSRobert Watson * the module list, invoking each instance of the operation, and 28395fab37eSRobert Watson * combining the results using the passed C operator. Note that it 28495fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 28595fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 28695fab37eSRobert Watson * a meaningful result. 28795fab37eSRobert Watson */ 28895fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 28995fab37eSRobert Watson struct mac_policy_conf *mpc; \ 29095fab37eSRobert Watson \ 29195fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 29295fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 29395fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 29495fab37eSRobert Watson result = result composition \ 29595fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 29695fab37eSRobert Watson } \ 29795fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 29895fab37eSRobert Watson } while (0) 29995fab37eSRobert Watson 300f7b951a8SRobert Watson #define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 301f7b951a8SRobert Watson outbuflen) do { \ 302f7b951a8SRobert Watson char *curptr, *curptr_start, *element_name, *element_temp; \ 303f7b951a8SRobert Watson size_t left, left_start, len; \ 304f7b951a8SRobert Watson int claimed, first, first_start, ignorenotfound; \ 305f7b951a8SRobert Watson \ 306f7b951a8SRobert Watson error = 0; \ 307f7b951a8SRobert Watson element_temp = elementlist; \ 308f7b951a8SRobert Watson curptr = outbuf; \ 309f7b951a8SRobert Watson curptr[0] = '\0'; \ 310f7b951a8SRobert Watson left = outbuflen; \ 311f7b951a8SRobert Watson first = 1; \ 312f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 313f7b951a8SRobert Watson curptr_start = curptr; \ 314f7b951a8SRobert Watson left_start = left; \ 315f7b951a8SRobert Watson first_start = first; \ 316f7b951a8SRobert Watson if (element_name[0] == '?') { \ 317f7b951a8SRobert Watson element_name++; \ 318f7b951a8SRobert Watson ignorenotfound = 1; \ 319f7b951a8SRobert Watson } else \ 320f7b951a8SRobert Watson ignorenotfound = 0; \ 321f7b951a8SRobert Watson claimed = 0; \ 322f7b951a8SRobert Watson if (first) { \ 323f7b951a8SRobert Watson len = snprintf(curptr, left, "%s/", \ 324f7b951a8SRobert Watson element_name); \ 325f7b951a8SRobert Watson first = 0; \ 326f7b951a8SRobert Watson } else \ 327f7b951a8SRobert Watson len = snprintf(curptr, left, ",%s/", \ 328f7b951a8SRobert Watson element_name); \ 329f7b951a8SRobert Watson if (len >= left) { \ 330f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 331f7b951a8SRobert Watson break; \ 332f7b951a8SRobert Watson } \ 333f7b951a8SRobert Watson curptr += len; \ 334f7b951a8SRobert Watson left -= len; \ 335f7b951a8SRobert Watson \ 336f7b951a8SRobert Watson MAC_CHECK(externalize_ ## type, label, element_name, \ 337f7b951a8SRobert Watson curptr, left, &len, &claimed); \ 338f7b951a8SRobert Watson if (error) \ 339f7b951a8SRobert Watson break; \ 340f7b951a8SRobert Watson if (claimed == 1) { \ 341f7b951a8SRobert Watson if (len >= outbuflen) { \ 342f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 343f7b951a8SRobert Watson break; \ 344f7b951a8SRobert Watson } \ 345f7b951a8SRobert Watson curptr += len; \ 346f7b951a8SRobert Watson left -= len; \ 347f7b951a8SRobert Watson } else if (claimed == 0 && ignorenotfound) { \ 348f7b951a8SRobert Watson /* \ 349f7b951a8SRobert Watson * Revert addition of the label element \ 350f7b951a8SRobert Watson * name. \ 351f7b951a8SRobert Watson */ \ 352f7b951a8SRobert Watson curptr = curptr_start; \ 353f7b951a8SRobert Watson *curptr = '\0'; \ 354f7b951a8SRobert Watson left = left_start; \ 355f7b951a8SRobert Watson first = first_start; \ 356f7b951a8SRobert Watson } else { \ 357f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: ENOLABEL */ \ 358f7b951a8SRobert Watson break; \ 359f7b951a8SRobert Watson } \ 360f7b951a8SRobert Watson } \ 361f7b951a8SRobert Watson } while (0) 362f7b951a8SRobert Watson 363f7b951a8SRobert Watson #define MAC_INTERNALIZE(type, label, instring) do { \ 364f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 365f7b951a8SRobert Watson int claimed; \ 366f7b951a8SRobert Watson \ 367f7b951a8SRobert Watson error = 0; \ 368f7b951a8SRobert Watson element = instring; \ 369f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 370f7b951a8SRobert Watson element_data = element_name; \ 371f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 372f7b951a8SRobert Watson if (element_data == NULL) { \ 373f7b951a8SRobert Watson error = EINVAL; \ 374f7b951a8SRobert Watson break; \ 375f7b951a8SRobert Watson } \ 376f7b951a8SRobert Watson claimed = 0; \ 377f7b951a8SRobert Watson MAC_CHECK(internalize_ ## type, label, element_name, \ 378f7b951a8SRobert Watson element_data, &claimed); \ 379f7b951a8SRobert Watson if (error) \ 380f7b951a8SRobert Watson break; \ 381f7b951a8SRobert Watson if (claimed != 1) { \ 382f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 383f7b951a8SRobert Watson error = EINVAL; \ 384f7b951a8SRobert Watson break; \ 385f7b951a8SRobert Watson } \ 386f7b951a8SRobert Watson } \ 387f7b951a8SRobert Watson } while (0) 388f7b951a8SRobert Watson 38995fab37eSRobert Watson /* 39095fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 39195fab37eSRobert Watson * module list and invoking that operation for each policy. 39295fab37eSRobert Watson */ 39395fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 39495fab37eSRobert Watson struct mac_policy_conf *mpc; \ 39595fab37eSRobert Watson \ 39695fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 39795fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 39895fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 39995fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 40095fab37eSRobert Watson } \ 40195fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 40295fab37eSRobert Watson } while (0) 40395fab37eSRobert Watson 40495fab37eSRobert Watson /* 40595fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 40695fab37eSRobert Watson */ 40795fab37eSRobert Watson static void 40895fab37eSRobert Watson mac_init(void) 40995fab37eSRobert Watson { 41095fab37eSRobert Watson 41195fab37eSRobert Watson LIST_INIT(&mac_policy_list); 41295fab37eSRobert Watson MAC_POLICY_LIST_LOCKINIT(); 41395fab37eSRobert Watson } 41495fab37eSRobert Watson 41595fab37eSRobert Watson /* 41695fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 41795fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 41895fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 41995fab37eSRobert Watson */ 42095fab37eSRobert Watson static void 42195fab37eSRobert Watson mac_late_init(void) 42295fab37eSRobert Watson { 42395fab37eSRobert Watson 42495fab37eSRobert Watson mac_late = 1; 42595fab37eSRobert Watson } 42695fab37eSRobert Watson 42795fab37eSRobert Watson /* 42895fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 42995fab37eSRobert Watson */ 43095fab37eSRobert Watson int 43195fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 43295fab37eSRobert Watson { 43395fab37eSRobert Watson struct mac_policy_conf *mpc; 43495fab37eSRobert Watson int error; 43595fab37eSRobert Watson 43695fab37eSRobert Watson error = 0; 43795fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 43895fab37eSRobert Watson 43995fab37eSRobert Watson switch (type) { 44095fab37eSRobert Watson case MOD_LOAD: 44195fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 44295fab37eSRobert Watson mac_late) { 44395fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 44495fab37eSRobert Watson "after booting\n", mpc->mpc_name); 44595fab37eSRobert Watson error = EBUSY; 44695fab37eSRobert Watson break; 44795fab37eSRobert Watson } 44895fab37eSRobert Watson error = mac_policy_register(mpc); 44995fab37eSRobert Watson break; 45095fab37eSRobert Watson case MOD_UNLOAD: 45195fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 45295fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 45395fab37eSRobert Watson != 0) 45495fab37eSRobert Watson error = mac_policy_unregister(mpc); 45595fab37eSRobert Watson else 45695fab37eSRobert Watson error = 0; 45795fab37eSRobert Watson break; 45895fab37eSRobert Watson default: 45995fab37eSRobert Watson break; 46095fab37eSRobert Watson } 46195fab37eSRobert Watson 46295fab37eSRobert Watson return (error); 46395fab37eSRobert Watson } 46495fab37eSRobert Watson 46595fab37eSRobert Watson static int 46695fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 46795fab37eSRobert Watson { 46895fab37eSRobert Watson struct mac_policy_conf *tmpc; 46995fab37eSRobert Watson struct mac_policy_op_entry *mpe; 47095fab37eSRobert Watson int slot; 47195fab37eSRobert Watson 472cc51a2b5SRobert Watson MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops), 473cc51a2b5SRobert Watson M_MACOPVEC, M_WAITOK | M_ZERO); 47495fab37eSRobert Watson for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) { 47595fab37eSRobert Watson switch (mpe->mpe_constant) { 47695fab37eSRobert Watson case MAC_OP_LAST: 47795fab37eSRobert Watson /* 47895fab37eSRobert Watson * Doesn't actually happen, but this allows checking 47995fab37eSRobert Watson * that all enumerated values are handled. 48095fab37eSRobert Watson */ 48195fab37eSRobert Watson break; 48295fab37eSRobert Watson case MAC_DESTROY: 48395fab37eSRobert Watson mpc->mpc_ops->mpo_destroy = 48495fab37eSRobert Watson mpe->mpe_function; 48595fab37eSRobert Watson break; 48695fab37eSRobert Watson case MAC_INIT: 48795fab37eSRobert Watson mpc->mpc_ops->mpo_init = 48895fab37eSRobert Watson mpe->mpe_function; 48995fab37eSRobert Watson break; 49027f2eac7SRobert Watson case MAC_SYSCALL: 49127f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall = 49227f2eac7SRobert Watson mpe->mpe_function; 49327f2eac7SRobert Watson break; 49496adb909SRobert Watson case MAC_INIT_BPFDESC_LABEL: 49596adb909SRobert Watson mpc->mpc_ops->mpo_init_bpfdesc_label = 49695fab37eSRobert Watson mpe->mpe_function; 49795fab37eSRobert Watson break; 49896adb909SRobert Watson case MAC_INIT_CRED_LABEL: 49996adb909SRobert Watson mpc->mpc_ops->mpo_init_cred_label = 50095fab37eSRobert Watson mpe->mpe_function; 50195fab37eSRobert Watson break; 50296adb909SRobert Watson case MAC_INIT_DEVFSDIRENT_LABEL: 50396adb909SRobert Watson mpc->mpc_ops->mpo_init_devfsdirent_label = 50495fab37eSRobert Watson mpe->mpe_function; 50595fab37eSRobert Watson break; 50696adb909SRobert Watson case MAC_INIT_IFNET_LABEL: 50796adb909SRobert Watson mpc->mpc_ops->mpo_init_ifnet_label = 50895fab37eSRobert Watson mpe->mpe_function; 50995fab37eSRobert Watson break; 51096adb909SRobert Watson case MAC_INIT_IPQ_LABEL: 51196adb909SRobert Watson mpc->mpc_ops->mpo_init_ipq_label = 51295fab37eSRobert Watson mpe->mpe_function; 51395fab37eSRobert Watson break; 51496adb909SRobert Watson case MAC_INIT_MBUF_LABEL: 51596adb909SRobert Watson mpc->mpc_ops->mpo_init_mbuf_label = 51695fab37eSRobert Watson mpe->mpe_function; 51795fab37eSRobert Watson break; 51896adb909SRobert Watson case MAC_INIT_MOUNT_LABEL: 51996adb909SRobert Watson mpc->mpc_ops->mpo_init_mount_label = 52095fab37eSRobert Watson mpe->mpe_function; 52195fab37eSRobert Watson break; 52296adb909SRobert Watson case MAC_INIT_MOUNT_FS_LABEL: 52396adb909SRobert Watson mpc->mpc_ops->mpo_init_mount_fs_label = 52495fab37eSRobert Watson mpe->mpe_function; 52595fab37eSRobert Watson break; 52696adb909SRobert Watson case MAC_INIT_PIPE_LABEL: 52796adb909SRobert Watson mpc->mpc_ops->mpo_init_pipe_label = 52895fab37eSRobert Watson mpe->mpe_function; 52995fab37eSRobert Watson break; 53096adb909SRobert Watson case MAC_INIT_SOCKET_LABEL: 53196adb909SRobert Watson mpc->mpc_ops->mpo_init_socket_label = 53295fab37eSRobert Watson mpe->mpe_function; 53395fab37eSRobert Watson break; 53496adb909SRobert Watson case MAC_INIT_SOCKET_PEER_LABEL: 53596adb909SRobert Watson mpc->mpc_ops->mpo_init_socket_peer_label = 53695fab37eSRobert Watson mpe->mpe_function; 53795fab37eSRobert Watson break; 53896adb909SRobert Watson case MAC_INIT_VNODE_LABEL: 53996adb909SRobert Watson mpc->mpc_ops->mpo_init_vnode_label = 54095fab37eSRobert Watson mpe->mpe_function; 54195fab37eSRobert Watson break; 54296adb909SRobert Watson case MAC_DESTROY_BPFDESC_LABEL: 54396adb909SRobert Watson mpc->mpc_ops->mpo_destroy_bpfdesc_label = 54495fab37eSRobert Watson mpe->mpe_function; 54595fab37eSRobert Watson break; 54696adb909SRobert Watson case MAC_DESTROY_CRED_LABEL: 54796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_cred_label = 54895fab37eSRobert Watson mpe->mpe_function; 54995fab37eSRobert Watson break; 55096adb909SRobert Watson case MAC_DESTROY_DEVFSDIRENT_LABEL: 55196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_devfsdirent_label = 55295fab37eSRobert Watson mpe->mpe_function; 55395fab37eSRobert Watson break; 55496adb909SRobert Watson case MAC_DESTROY_IFNET_LABEL: 55596adb909SRobert Watson mpc->mpc_ops->mpo_destroy_ifnet_label = 55695fab37eSRobert Watson mpe->mpe_function; 55795fab37eSRobert Watson break; 55896adb909SRobert Watson case MAC_DESTROY_IPQ_LABEL: 55996adb909SRobert Watson mpc->mpc_ops->mpo_destroy_ipq_label = 56095fab37eSRobert Watson mpe->mpe_function; 56195fab37eSRobert Watson break; 56296adb909SRobert Watson case MAC_DESTROY_MBUF_LABEL: 56396adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mbuf_label = 56495fab37eSRobert Watson mpe->mpe_function; 56595fab37eSRobert Watson break; 56696adb909SRobert Watson case MAC_DESTROY_MOUNT_LABEL: 56796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mount_label = 56895fab37eSRobert Watson mpe->mpe_function; 56995fab37eSRobert Watson break; 57096adb909SRobert Watson case MAC_DESTROY_MOUNT_FS_LABEL: 57196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mount_fs_label = 57295fab37eSRobert Watson mpe->mpe_function; 57395fab37eSRobert Watson break; 57496adb909SRobert Watson case MAC_DESTROY_PIPE_LABEL: 57596adb909SRobert Watson mpc->mpc_ops->mpo_destroy_pipe_label = 57696adb909SRobert Watson mpe->mpe_function; 57796adb909SRobert Watson break; 57896adb909SRobert Watson case MAC_DESTROY_SOCKET_LABEL: 57996adb909SRobert Watson mpc->mpc_ops->mpo_destroy_socket_label = 58096adb909SRobert Watson mpe->mpe_function; 58196adb909SRobert Watson break; 58296adb909SRobert Watson case MAC_DESTROY_SOCKET_PEER_LABEL: 58396adb909SRobert Watson mpc->mpc_ops->mpo_destroy_socket_peer_label = 58496adb909SRobert Watson mpe->mpe_function; 58596adb909SRobert Watson break; 58696adb909SRobert Watson case MAC_DESTROY_VNODE_LABEL: 58796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_vnode_label = 58895fab37eSRobert Watson mpe->mpe_function; 58995fab37eSRobert Watson break; 590f7b951a8SRobert Watson case MAC_COPY_PIPE_LABEL: 591f7b951a8SRobert Watson mpc->mpc_ops->mpo_copy_pipe_label = 59295fab37eSRobert Watson mpe->mpe_function; 59395fab37eSRobert Watson break; 594f7b951a8SRobert Watson case MAC_COPY_VNODE_LABEL: 595f7b951a8SRobert Watson mpc->mpc_ops->mpo_copy_vnode_label = 596f7b951a8SRobert Watson mpe->mpe_function; 597f7b951a8SRobert Watson break; 598f7b951a8SRobert Watson case MAC_EXTERNALIZE_CRED_LABEL: 599f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_cred_label = 600f7b951a8SRobert Watson mpe->mpe_function; 601f7b951a8SRobert Watson break; 602f7b951a8SRobert Watson case MAC_EXTERNALIZE_IFNET_LABEL: 603f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_ifnet_label = 604f7b951a8SRobert Watson mpe->mpe_function; 605f7b951a8SRobert Watson break; 606f7b951a8SRobert Watson case MAC_EXTERNALIZE_PIPE_LABEL: 607f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_pipe_label = 608f7b951a8SRobert Watson mpe->mpe_function; 609f7b951a8SRobert Watson break; 610f7b951a8SRobert Watson case MAC_EXTERNALIZE_SOCKET_LABEL: 611f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_socket_label = 612f7b951a8SRobert Watson mpe->mpe_function; 613f7b951a8SRobert Watson break; 614f7b951a8SRobert Watson case MAC_EXTERNALIZE_SOCKET_PEER_LABEL: 615f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_socket_peer_label = 616f7b951a8SRobert Watson mpe->mpe_function; 617f7b951a8SRobert Watson break; 618f7b951a8SRobert Watson case MAC_EXTERNALIZE_VNODE_LABEL: 619f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_vnode_label = 620f7b951a8SRobert Watson mpe->mpe_function; 621f7b951a8SRobert Watson break; 622f7b951a8SRobert Watson case MAC_INTERNALIZE_CRED_LABEL: 623f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_cred_label = 624f7b951a8SRobert Watson mpe->mpe_function; 625f7b951a8SRobert Watson break; 626f7b951a8SRobert Watson case MAC_INTERNALIZE_IFNET_LABEL: 627f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_ifnet_label = 628f7b951a8SRobert Watson mpe->mpe_function; 629f7b951a8SRobert Watson break; 630f7b951a8SRobert Watson case MAC_INTERNALIZE_PIPE_LABEL: 631f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_pipe_label = 632f7b951a8SRobert Watson mpe->mpe_function; 633f7b951a8SRobert Watson break; 634f7b951a8SRobert Watson case MAC_INTERNALIZE_SOCKET_LABEL: 635f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_socket_label = 636f7b951a8SRobert Watson mpe->mpe_function; 637f7b951a8SRobert Watson break; 638f7b951a8SRobert Watson case MAC_INTERNALIZE_VNODE_LABEL: 639f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_vnode_label = 64095fab37eSRobert Watson mpe->mpe_function; 64195fab37eSRobert Watson break; 64295fab37eSRobert Watson case MAC_CREATE_DEVFS_DEVICE: 64395fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_device = 64495fab37eSRobert Watson mpe->mpe_function; 64595fab37eSRobert Watson break; 64695fab37eSRobert Watson case MAC_CREATE_DEVFS_DIRECTORY: 64795fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_directory = 64895fab37eSRobert Watson mpe->mpe_function; 64995fab37eSRobert Watson break; 65074e62b1bSRobert Watson case MAC_CREATE_DEVFS_SYMLINK: 65174e62b1bSRobert Watson mpc->mpc_ops->mpo_create_devfs_symlink = 65274e62b1bSRobert Watson mpe->mpe_function; 65374e62b1bSRobert Watson break; 65495fab37eSRobert Watson case MAC_CREATE_DEVFS_VNODE: 65595fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_vnode = 65695fab37eSRobert Watson mpe->mpe_function; 65795fab37eSRobert Watson break; 65895fab37eSRobert Watson case MAC_CREATE_MOUNT: 65995fab37eSRobert Watson mpc->mpc_ops->mpo_create_mount = 66095fab37eSRobert Watson mpe->mpe_function; 66195fab37eSRobert Watson break; 66295fab37eSRobert Watson case MAC_CREATE_ROOT_MOUNT: 66395fab37eSRobert Watson mpc->mpc_ops->mpo_create_root_mount = 66495fab37eSRobert Watson mpe->mpe_function; 66595fab37eSRobert Watson break; 66695fab37eSRobert Watson case MAC_RELABEL_VNODE: 66795fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_vnode = 66895fab37eSRobert Watson mpe->mpe_function; 66995fab37eSRobert Watson break; 67095fab37eSRobert Watson case MAC_UPDATE_DEVFSDIRENT: 67195fab37eSRobert Watson mpc->mpc_ops->mpo_update_devfsdirent = 67295fab37eSRobert Watson mpe->mpe_function; 67395fab37eSRobert Watson break; 674763bbd2fSRobert Watson case MAC_ASSOCIATE_VNODE_DEVFS: 675763bbd2fSRobert Watson mpc->mpc_ops->mpo_associate_vnode_devfs = 67695fab37eSRobert Watson mpe->mpe_function; 67795fab37eSRobert Watson break; 678763bbd2fSRobert Watson case MAC_ASSOCIATE_VNODE_EXTATTR: 679763bbd2fSRobert Watson mpc->mpc_ops->mpo_associate_vnode_extattr = 68095fab37eSRobert Watson mpe->mpe_function; 68195fab37eSRobert Watson break; 682763bbd2fSRobert Watson case MAC_ASSOCIATE_VNODE_SINGLELABEL: 683763bbd2fSRobert Watson mpc->mpc_ops->mpo_associate_vnode_singlelabel = 68495fab37eSRobert Watson mpe->mpe_function; 68595fab37eSRobert Watson break; 686763bbd2fSRobert Watson case MAC_CREATE_VNODE_EXTATTR: 687763bbd2fSRobert Watson mpc->mpc_ops->mpo_create_vnode_extattr = 688763bbd2fSRobert Watson mpe->mpe_function; 689763bbd2fSRobert Watson break; 690763bbd2fSRobert Watson case MAC_SETLABEL_VNODE_EXTATTR: 691763bbd2fSRobert Watson mpc->mpc_ops->mpo_setlabel_vnode_extattr = 69295fab37eSRobert Watson mpe->mpe_function; 69395fab37eSRobert Watson break; 69495fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_SOCKET: 69595fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_socket = 69695fab37eSRobert Watson mpe->mpe_function; 69795fab37eSRobert Watson break; 69895fab37eSRobert Watson case MAC_CREATE_PIPE: 69995fab37eSRobert Watson mpc->mpc_ops->mpo_create_pipe = 70095fab37eSRobert Watson mpe->mpe_function; 70195fab37eSRobert Watson break; 70295fab37eSRobert Watson case MAC_CREATE_SOCKET: 70395fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket = 70495fab37eSRobert Watson mpe->mpe_function; 70595fab37eSRobert Watson break; 70695fab37eSRobert Watson case MAC_CREATE_SOCKET_FROM_SOCKET: 70795fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket_from_socket = 70895fab37eSRobert Watson mpe->mpe_function; 70995fab37eSRobert Watson break; 71095fab37eSRobert Watson case MAC_RELABEL_PIPE: 71195fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_pipe = 71295fab37eSRobert Watson mpe->mpe_function; 71395fab37eSRobert Watson break; 71495fab37eSRobert Watson case MAC_RELABEL_SOCKET: 71595fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_socket = 71695fab37eSRobert Watson mpe->mpe_function; 71795fab37eSRobert Watson break; 71895fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_MBUF: 71995fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_mbuf = 72095fab37eSRobert Watson mpe->mpe_function; 72195fab37eSRobert Watson break; 72295fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_SOCKET: 72395fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_socket = 72495fab37eSRobert Watson mpe->mpe_function; 72595fab37eSRobert Watson break; 72695fab37eSRobert Watson case MAC_CREATE_BPFDESC: 72795fab37eSRobert Watson mpc->mpc_ops->mpo_create_bpfdesc = 72895fab37eSRobert Watson mpe->mpe_function; 72995fab37eSRobert Watson break; 73095fab37eSRobert Watson case MAC_CREATE_DATAGRAM_FROM_IPQ: 73195fab37eSRobert Watson mpc->mpc_ops->mpo_create_datagram_from_ipq = 73295fab37eSRobert Watson mpe->mpe_function; 73395fab37eSRobert Watson break; 73495fab37eSRobert Watson case MAC_CREATE_FRAGMENT: 73595fab37eSRobert Watson mpc->mpc_ops->mpo_create_fragment = 73695fab37eSRobert Watson mpe->mpe_function; 73795fab37eSRobert Watson break; 73895fab37eSRobert Watson case MAC_CREATE_IFNET: 73995fab37eSRobert Watson mpc->mpc_ops->mpo_create_ifnet = 74095fab37eSRobert Watson mpe->mpe_function; 74195fab37eSRobert Watson break; 74295fab37eSRobert Watson case MAC_CREATE_IPQ: 74395fab37eSRobert Watson mpc->mpc_ops->mpo_create_ipq = 74495fab37eSRobert Watson mpe->mpe_function; 74595fab37eSRobert Watson break; 74695fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_MBUF: 74795fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_mbuf = 74895fab37eSRobert Watson mpe->mpe_function; 74995fab37eSRobert Watson break; 75095fab37eSRobert Watson case MAC_CREATE_MBUF_LINKLAYER: 75195fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_linklayer = 75295fab37eSRobert Watson mpe->mpe_function; 75395fab37eSRobert Watson break; 75495fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_BPFDESC: 75595fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc = 75695fab37eSRobert Watson mpe->mpe_function; 75795fab37eSRobert Watson break; 75895fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_IFNET: 75995fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_ifnet = 76095fab37eSRobert Watson mpe->mpe_function; 76195fab37eSRobert Watson break; 76295fab37eSRobert Watson case MAC_CREATE_MBUF_MULTICAST_ENCAP: 76395fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_multicast_encap = 76495fab37eSRobert Watson mpe->mpe_function; 76595fab37eSRobert Watson break; 76695fab37eSRobert Watson case MAC_CREATE_MBUF_NETLAYER: 76795fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_netlayer = 76895fab37eSRobert Watson mpe->mpe_function; 76995fab37eSRobert Watson break; 77095fab37eSRobert Watson case MAC_FRAGMENT_MATCH: 77195fab37eSRobert Watson mpc->mpc_ops->mpo_fragment_match = 77295fab37eSRobert Watson mpe->mpe_function; 77395fab37eSRobert Watson break; 77495fab37eSRobert Watson case MAC_RELABEL_IFNET: 77595fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_ifnet = 77695fab37eSRobert Watson mpe->mpe_function; 77795fab37eSRobert Watson break; 77895fab37eSRobert Watson case MAC_UPDATE_IPQ: 77995fab37eSRobert Watson mpc->mpc_ops->mpo_update_ipq = 78095fab37eSRobert Watson mpe->mpe_function; 78195fab37eSRobert Watson break; 78295fab37eSRobert Watson case MAC_CREATE_CRED: 78395fab37eSRobert Watson mpc->mpc_ops->mpo_create_cred = 78495fab37eSRobert Watson mpe->mpe_function; 78595fab37eSRobert Watson break; 78695fab37eSRobert Watson case MAC_EXECVE_TRANSITION: 78795fab37eSRobert Watson mpc->mpc_ops->mpo_execve_transition = 78895fab37eSRobert Watson mpe->mpe_function; 78995fab37eSRobert Watson break; 79095fab37eSRobert Watson case MAC_EXECVE_WILL_TRANSITION: 79195fab37eSRobert Watson mpc->mpc_ops->mpo_execve_will_transition = 79295fab37eSRobert Watson mpe->mpe_function; 79395fab37eSRobert Watson break; 79495fab37eSRobert Watson case MAC_CREATE_PROC0: 795226b96fbSRobert Watson mpc->mpc_ops->mpo_create_proc0 = 796226b96fbSRobert Watson mpe->mpe_function; 79795fab37eSRobert Watson break; 79895fab37eSRobert Watson case MAC_CREATE_PROC1: 799226b96fbSRobert Watson mpc->mpc_ops->mpo_create_proc1 = 800226b96fbSRobert Watson mpe->mpe_function; 80195fab37eSRobert Watson break; 80295fab37eSRobert Watson case MAC_RELABEL_CRED: 80395fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_cred = 80495fab37eSRobert Watson mpe->mpe_function; 80595fab37eSRobert Watson break; 80692dbb82aSRobert Watson case MAC_THREAD_USERRET: 80792dbb82aSRobert Watson mpc->mpc_ops->mpo_thread_userret = 80892dbb82aSRobert Watson mpe->mpe_function; 80992dbb82aSRobert Watson break; 81095fab37eSRobert Watson case MAC_CHECK_BPFDESC_RECEIVE: 81195fab37eSRobert Watson mpc->mpc_ops->mpo_check_bpfdesc_receive = 81295fab37eSRobert Watson mpe->mpe_function; 81395fab37eSRobert Watson break; 81495fab37eSRobert Watson case MAC_CHECK_CRED_RELABEL: 81595fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_relabel = 81695fab37eSRobert Watson mpe->mpe_function; 81795fab37eSRobert Watson break; 81895fab37eSRobert Watson case MAC_CHECK_CRED_VISIBLE: 81995fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_visible = 82095fab37eSRobert Watson mpe->mpe_function; 82195fab37eSRobert Watson break; 82295fab37eSRobert Watson case MAC_CHECK_IFNET_RELABEL: 82395fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_relabel = 82495fab37eSRobert Watson mpe->mpe_function; 82595fab37eSRobert Watson break; 82695fab37eSRobert Watson case MAC_CHECK_IFNET_TRANSMIT: 82795fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_transmit = 82895fab37eSRobert Watson mpe->mpe_function; 82995fab37eSRobert Watson break; 83095fab37eSRobert Watson case MAC_CHECK_MOUNT_STAT: 83195fab37eSRobert Watson mpc->mpc_ops->mpo_check_mount_stat = 83295fab37eSRobert Watson mpe->mpe_function; 83395fab37eSRobert Watson break; 83495fab37eSRobert Watson case MAC_CHECK_PIPE_IOCTL: 83595fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_ioctl = 83695fab37eSRobert Watson mpe->mpe_function; 83795fab37eSRobert Watson break; 838c024c3eeSRobert Watson case MAC_CHECK_PIPE_POLL: 839c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_poll = 840c024c3eeSRobert Watson mpe->mpe_function; 841c024c3eeSRobert Watson break; 842c024c3eeSRobert Watson case MAC_CHECK_PIPE_READ: 843c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_read = 84495fab37eSRobert Watson mpe->mpe_function; 84595fab37eSRobert Watson break; 84695fab37eSRobert Watson case MAC_CHECK_PIPE_RELABEL: 84795fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_relabel = 84895fab37eSRobert Watson mpe->mpe_function; 84995fab37eSRobert Watson break; 850c024c3eeSRobert Watson case MAC_CHECK_PIPE_STAT: 851c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_stat = 852c024c3eeSRobert Watson mpe->mpe_function; 853c024c3eeSRobert Watson break; 854c024c3eeSRobert Watson case MAC_CHECK_PIPE_WRITE: 855c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_write = 856c024c3eeSRobert Watson mpe->mpe_function; 857c024c3eeSRobert Watson break; 85895fab37eSRobert Watson case MAC_CHECK_PROC_DEBUG: 85995fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_debug = 86095fab37eSRobert Watson mpe->mpe_function; 86195fab37eSRobert Watson break; 86295fab37eSRobert Watson case MAC_CHECK_PROC_SCHED: 86395fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_sched = 86495fab37eSRobert Watson mpe->mpe_function; 86595fab37eSRobert Watson break; 86695fab37eSRobert Watson case MAC_CHECK_PROC_SIGNAL: 86795fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_signal = 86895fab37eSRobert Watson mpe->mpe_function; 86995fab37eSRobert Watson break; 87095fab37eSRobert Watson case MAC_CHECK_SOCKET_BIND: 87195fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_bind = 87295fab37eSRobert Watson mpe->mpe_function; 87395fab37eSRobert Watson break; 87495fab37eSRobert Watson case MAC_CHECK_SOCKET_CONNECT: 87595fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_connect = 87695fab37eSRobert Watson mpe->mpe_function; 87795fab37eSRobert Watson break; 878d61198e4SRobert Watson case MAC_CHECK_SOCKET_DELIVER: 879d61198e4SRobert Watson mpc->mpc_ops->mpo_check_socket_deliver = 88095fab37eSRobert Watson mpe->mpe_function; 88195fab37eSRobert Watson break; 882d61198e4SRobert Watson case MAC_CHECK_SOCKET_LISTEN: 883d61198e4SRobert Watson mpc->mpc_ops->mpo_check_socket_listen = 88495fab37eSRobert Watson mpe->mpe_function; 88595fab37eSRobert Watson break; 886b371c939SRobert Watson case MAC_CHECK_SOCKET_RECEIVE: 887b371c939SRobert Watson mpc->mpc_ops->mpo_check_socket_receive = 888b371c939SRobert Watson mpe->mpe_function; 889b371c939SRobert Watson break; 89095fab37eSRobert Watson case MAC_CHECK_SOCKET_RELABEL: 89195fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_relabel = 89295fab37eSRobert Watson mpe->mpe_function; 89395fab37eSRobert Watson break; 894b371c939SRobert Watson case MAC_CHECK_SOCKET_SEND: 895b371c939SRobert Watson mpc->mpc_ops->mpo_check_socket_send = 896b371c939SRobert Watson mpe->mpe_function; 897b371c939SRobert Watson break; 89895fab37eSRobert Watson case MAC_CHECK_SOCKET_VISIBLE: 89995fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_visible = 90095fab37eSRobert Watson mpe->mpe_function; 90195fab37eSRobert Watson break; 90203ce2c0cSRobert Watson case MAC_CHECK_SYSTEM_SWAPON: 90303ce2c0cSRobert Watson mpc->mpc_ops->mpo_check_system_swapon = 90403ce2c0cSRobert Watson mpe->mpe_function; 90503ce2c0cSRobert Watson break; 90695fab37eSRobert Watson case MAC_CHECK_VNODE_ACCESS: 90795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_access = 90895fab37eSRobert Watson mpe->mpe_function; 90995fab37eSRobert Watson break; 91095fab37eSRobert Watson case MAC_CHECK_VNODE_CHDIR: 91195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chdir = 91295fab37eSRobert Watson mpe->mpe_function; 91395fab37eSRobert Watson break; 91495fab37eSRobert Watson case MAC_CHECK_VNODE_CHROOT: 91595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chroot = 91695fab37eSRobert Watson mpe->mpe_function; 91795fab37eSRobert Watson break; 91895fab37eSRobert Watson case MAC_CHECK_VNODE_CREATE: 91995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_create = 92095fab37eSRobert Watson mpe->mpe_function; 92195fab37eSRobert Watson break; 92295fab37eSRobert Watson case MAC_CHECK_VNODE_DELETE: 92395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_delete = 92495fab37eSRobert Watson mpe->mpe_function; 92595fab37eSRobert Watson break; 92695fab37eSRobert Watson case MAC_CHECK_VNODE_DELETEACL: 92795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_deleteacl = 92895fab37eSRobert Watson mpe->mpe_function; 92995fab37eSRobert Watson break; 93095fab37eSRobert Watson case MAC_CHECK_VNODE_EXEC: 93195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_exec = 93295fab37eSRobert Watson mpe->mpe_function; 93395fab37eSRobert Watson break; 93495fab37eSRobert Watson case MAC_CHECK_VNODE_GETACL: 93595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getacl = 93695fab37eSRobert Watson mpe->mpe_function; 93795fab37eSRobert Watson break; 93895fab37eSRobert Watson case MAC_CHECK_VNODE_GETEXTATTR: 93995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getextattr = 94095fab37eSRobert Watson mpe->mpe_function; 94195fab37eSRobert Watson break; 9420a694196SRobert Watson case MAC_CHECK_VNODE_LINK: 9430a694196SRobert Watson mpc->mpc_ops->mpo_check_vnode_link = 9440a694196SRobert Watson mpe->mpe_function; 9450a694196SRobert Watson break; 94695fab37eSRobert Watson case MAC_CHECK_VNODE_LOOKUP: 94795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_lookup = 94895fab37eSRobert Watson mpe->mpe_function; 94995fab37eSRobert Watson break; 950e183f80eSRobert Watson case MAC_CHECK_VNODE_MMAP: 951e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mmap = 952e183f80eSRobert Watson mpe->mpe_function; 953e183f80eSRobert Watson break; 954e183f80eSRobert Watson case MAC_CHECK_VNODE_MMAP_DOWNGRADE: 955e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mmap_downgrade = 956e183f80eSRobert Watson mpe->mpe_function; 957e183f80eSRobert Watson break; 958e183f80eSRobert Watson case MAC_CHECK_VNODE_MPROTECT: 959e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mprotect = 96095fab37eSRobert Watson mpe->mpe_function; 96195fab37eSRobert Watson break; 96295fab37eSRobert Watson case MAC_CHECK_VNODE_OPEN: 96395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_open = 96495fab37eSRobert Watson mpe->mpe_function; 96595fab37eSRobert Watson break; 9667f724f8bSRobert Watson case MAC_CHECK_VNODE_POLL: 9677f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_poll = 9687f724f8bSRobert Watson mpe->mpe_function; 9697f724f8bSRobert Watson break; 9707f724f8bSRobert Watson case MAC_CHECK_VNODE_READ: 9717f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_read = 9727f724f8bSRobert Watson mpe->mpe_function; 9737f724f8bSRobert Watson break; 97495fab37eSRobert Watson case MAC_CHECK_VNODE_READDIR: 97595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readdir = 97695fab37eSRobert Watson mpe->mpe_function; 97795fab37eSRobert Watson break; 97895fab37eSRobert Watson case MAC_CHECK_VNODE_READLINK: 97995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readlink = 98095fab37eSRobert Watson mpe->mpe_function; 98195fab37eSRobert Watson break; 98295fab37eSRobert Watson case MAC_CHECK_VNODE_RELABEL: 98395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_relabel = 98495fab37eSRobert Watson mpe->mpe_function; 98595fab37eSRobert Watson break; 98695fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_FROM: 98795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_from = 98895fab37eSRobert Watson mpe->mpe_function; 98995fab37eSRobert Watson break; 99095fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_TO: 99195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_to = 99295fab37eSRobert Watson mpe->mpe_function; 99395fab37eSRobert Watson break; 99495fab37eSRobert Watson case MAC_CHECK_VNODE_REVOKE: 99595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_revoke = 99695fab37eSRobert Watson mpe->mpe_function; 99795fab37eSRobert Watson break; 99895fab37eSRobert Watson case MAC_CHECK_VNODE_SETACL: 99995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setacl = 100095fab37eSRobert Watson mpe->mpe_function; 100195fab37eSRobert Watson break; 100295fab37eSRobert Watson case MAC_CHECK_VNODE_SETEXTATTR: 100395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setextattr = 100495fab37eSRobert Watson mpe->mpe_function; 100595fab37eSRobert Watson break; 100695fab37eSRobert Watson case MAC_CHECK_VNODE_SETFLAGS: 100795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setflags = 100895fab37eSRobert Watson mpe->mpe_function; 100995fab37eSRobert Watson break; 101095fab37eSRobert Watson case MAC_CHECK_VNODE_SETMODE: 101195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setmode = 101295fab37eSRobert Watson mpe->mpe_function; 101395fab37eSRobert Watson break; 101495fab37eSRobert Watson case MAC_CHECK_VNODE_SETOWNER: 101595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setowner = 101695fab37eSRobert Watson mpe->mpe_function; 101795fab37eSRobert Watson break; 101895fab37eSRobert Watson case MAC_CHECK_VNODE_SETUTIMES: 101995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setutimes = 102095fab37eSRobert Watson mpe->mpe_function; 102195fab37eSRobert Watson break; 102295fab37eSRobert Watson case MAC_CHECK_VNODE_STAT: 102395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_stat = 102495fab37eSRobert Watson mpe->mpe_function; 102595fab37eSRobert Watson break; 10267f724f8bSRobert Watson case MAC_CHECK_VNODE_WRITE: 10277f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_write = 10287f724f8bSRobert Watson mpe->mpe_function; 10297f724f8bSRobert Watson break; 103095fab37eSRobert Watson /* 103195fab37eSRobert Watson default: 103295fab37eSRobert Watson printf("MAC policy `%s': unknown operation %d\n", 103395fab37eSRobert Watson mpc->mpc_name, mpe->mpe_constant); 103495fab37eSRobert Watson return (EINVAL); 103595fab37eSRobert Watson */ 103695fab37eSRobert Watson } 103795fab37eSRobert Watson } 103895fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); 103995fab37eSRobert Watson if (mac_policy_list_busy > 0) { 104095fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 104195fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 104295fab37eSRobert Watson mpc->mpc_ops = NULL; 104395fab37eSRobert Watson return (EBUSY); 104495fab37eSRobert Watson } 104595fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 104695fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 104795fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 104895fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 104995fab37eSRobert Watson mpc->mpc_ops = NULL; 105095fab37eSRobert Watson return (EEXIST); 105195fab37eSRobert Watson } 105295fab37eSRobert Watson } 105395fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 105495fab37eSRobert Watson slot = ffs(mac_policy_offsets_free); 105595fab37eSRobert Watson if (slot == 0) { 105695fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 105795fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 105895fab37eSRobert Watson mpc->mpc_ops = NULL; 105995fab37eSRobert Watson return (ENOMEM); 106095fab37eSRobert Watson } 106195fab37eSRobert Watson slot--; 106295fab37eSRobert Watson mac_policy_offsets_free &= ~(1 << slot); 106395fab37eSRobert Watson *mpc->mpc_field_off = slot; 106495fab37eSRobert Watson } 106595fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 106695fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 106795fab37eSRobert Watson 106895fab37eSRobert Watson /* Per-policy initialization. */ 106995fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 107095fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 107195fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 107295fab37eSRobert Watson 107395fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 107495fab37eSRobert Watson mpc->mpc_name); 107595fab37eSRobert Watson 107695fab37eSRobert Watson return (0); 107795fab37eSRobert Watson } 107895fab37eSRobert Watson 107995fab37eSRobert Watson static int 108095fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 108195fab37eSRobert Watson { 108295fab37eSRobert Watson 1083ea599aa0SRobert Watson /* 1084ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 1085ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 1086ea599aa0SRobert Watson * silently succeed. 1087ea599aa0SRobert Watson */ 1088ea599aa0SRobert Watson MAC_POLICY_LIST_LOCK(); 1089ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 1090ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 1091ea599aa0SRobert Watson return (0); 1092ea599aa0SRobert Watson } 109395fab37eSRobert Watson #if 0 109495fab37eSRobert Watson /* 109595fab37eSRobert Watson * Don't allow unloading modules with private data. 109695fab37eSRobert Watson */ 1097ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 1098ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 109995fab37eSRobert Watson return (EBUSY); 1100ea599aa0SRobert Watson } 110195fab37eSRobert Watson #endif 1102ea599aa0SRobert Watson /* 1103ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 1104ea599aa0SRobert Watson * by its own definition. 1105ea599aa0SRobert Watson */ 1106ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 1107ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 110895fab37eSRobert Watson return (EBUSY); 1109ea599aa0SRobert Watson } 1110ea599aa0SRobert Watson /* 1111ea599aa0SRobert Watson * Right now, we EBUSY if the list is in use. In the future, 1112ea599aa0SRobert Watson * for reliability reasons, we might want to sleep and wakeup 1113ea599aa0SRobert Watson * later to try again. 1114ea599aa0SRobert Watson */ 111595fab37eSRobert Watson if (mac_policy_list_busy > 0) { 111695fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 111795fab37eSRobert Watson return (EBUSY); 111895fab37eSRobert Watson } 111995fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 112095fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 112195fab37eSRobert Watson 112295fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 112395fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 112495fab37eSRobert Watson 112595fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 112695fab37eSRobert Watson mpc->mpc_ops = NULL; 11279aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 112895fab37eSRobert Watson 112995fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 113095fab37eSRobert Watson mpc->mpc_name); 113195fab37eSRobert Watson 113295fab37eSRobert Watson return (0); 113395fab37eSRobert Watson } 113495fab37eSRobert Watson 113595fab37eSRobert Watson /* 113695fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 113795fab37eSRobert Watson * value with the higher precedence. 113895fab37eSRobert Watson */ 113995fab37eSRobert Watson static int 114095fab37eSRobert Watson error_select(int error1, int error2) 114195fab37eSRobert Watson { 114295fab37eSRobert Watson 114395fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 114495fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 114595fab37eSRobert Watson return (EDEADLK); 114695fab37eSRobert Watson 114795fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 114895fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 114995fab37eSRobert Watson return (EINVAL); 115095fab37eSRobert Watson 115195fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 115295fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 115395fab37eSRobert Watson return (ESRCH); 115495fab37eSRobert Watson 115595fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 115695fab37eSRobert Watson return (ENOENT); 115795fab37eSRobert Watson 115895fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 115995fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 116095fab37eSRobert Watson return (EACCES); 116195fab37eSRobert Watson 116295fab37eSRobert Watson /* Precedence goes to privilege. */ 116395fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 116495fab37eSRobert Watson return (EPERM); 116595fab37eSRobert Watson 116695fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 116795fab37eSRobert Watson if (error1 != 0) 116895fab37eSRobert Watson return (error1); 116995fab37eSRobert Watson return (error2); 117095fab37eSRobert Watson } 117195fab37eSRobert Watson 117208bcdc58SRobert Watson static void 117308bcdc58SRobert Watson mac_init_label(struct label *label) 117408bcdc58SRobert Watson { 117508bcdc58SRobert Watson 117608bcdc58SRobert Watson bzero(label, sizeof(*label)); 117708bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 117808bcdc58SRobert Watson } 117908bcdc58SRobert Watson 118008bcdc58SRobert Watson static void 118108bcdc58SRobert Watson mac_destroy_label(struct label *label) 118208bcdc58SRobert Watson { 118308bcdc58SRobert Watson 118408bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 118508bcdc58SRobert Watson ("destroying uninitialized label")); 118608bcdc58SRobert Watson 118708bcdc58SRobert Watson bzero(label, sizeof(*label)); 118808bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 118908bcdc58SRobert Watson } 119008bcdc58SRobert Watson 119108bcdc58SRobert Watson void 119287807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 119308bcdc58SRobert Watson { 119408bcdc58SRobert Watson 119587807196SRobert Watson mac_init_label(&bpf_d->bd_label); 119687807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 119708bcdc58SRobert Watson #ifdef MAC_DEBUG 119887807196SRobert Watson atomic_add_int(&nmacbpfdescs, 1); 119908bcdc58SRobert Watson #endif 120008bcdc58SRobert Watson } 120108bcdc58SRobert Watson 1202f7b951a8SRobert Watson static void 1203f7b951a8SRobert Watson mac_init_cred_label(struct label *label) 120408bcdc58SRobert Watson { 120508bcdc58SRobert Watson 1206f7b951a8SRobert Watson mac_init_label(label); 1207f7b951a8SRobert Watson MAC_PERFORM(init_cred_label, label); 120808bcdc58SRobert Watson #ifdef MAC_DEBUG 120908bcdc58SRobert Watson atomic_add_int(&nmaccreds, 1); 121008bcdc58SRobert Watson #endif 121108bcdc58SRobert Watson } 121208bcdc58SRobert Watson 121308bcdc58SRobert Watson void 1214f7b951a8SRobert Watson mac_init_cred(struct ucred *cred) 1215f7b951a8SRobert Watson { 1216f7b951a8SRobert Watson 1217f7b951a8SRobert Watson mac_init_cred_label(&cred->cr_label); 1218f7b951a8SRobert Watson } 1219f7b951a8SRobert Watson 1220f7b951a8SRobert Watson void 122187807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 122208bcdc58SRobert Watson { 122308bcdc58SRobert Watson 122487807196SRobert Watson mac_init_label(&de->de_label); 122587807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 122608bcdc58SRobert Watson #ifdef MAC_DEBUG 122787807196SRobert Watson atomic_add_int(&nmacdevfsdirents, 1); 122808bcdc58SRobert Watson #endif 122908bcdc58SRobert Watson } 123008bcdc58SRobert Watson 1231f7b951a8SRobert Watson static void 1232f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label) 1233f7b951a8SRobert Watson { 1234f7b951a8SRobert Watson 1235f7b951a8SRobert Watson mac_init_label(label); 1236f7b951a8SRobert Watson MAC_PERFORM(init_ifnet_label, label); 1237f7b951a8SRobert Watson #ifdef MAC_DEBUG 1238f7b951a8SRobert Watson atomic_add_int(&nmacifnets, 1); 1239f7b951a8SRobert Watson #endif 1240f7b951a8SRobert Watson } 1241f7b951a8SRobert Watson 124208bcdc58SRobert Watson void 124308bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 124408bcdc58SRobert Watson { 124508bcdc58SRobert Watson 1246f7b951a8SRobert Watson mac_init_ifnet_label(&ifp->if_label); 124708bcdc58SRobert Watson } 124808bcdc58SRobert Watson 124908bcdc58SRobert Watson void 125008bcdc58SRobert Watson mac_init_ipq(struct ipq *ipq) 125108bcdc58SRobert Watson { 125208bcdc58SRobert Watson 125308bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 125408bcdc58SRobert Watson MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 125508bcdc58SRobert Watson #ifdef MAC_DEBUG 125608bcdc58SRobert Watson atomic_add_int(&nmacipqs, 1); 125708bcdc58SRobert Watson #endif 125808bcdc58SRobert Watson } 125908bcdc58SRobert Watson 126087807196SRobert Watson int 126187807196SRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 126208bcdc58SRobert Watson { 126356c15412SRobert Watson int error; 126456c15412SRobert Watson 126587807196SRobert Watson KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 126608bcdc58SRobert Watson 126787807196SRobert Watson mac_init_label(&m->m_pkthdr.label); 126887807196SRobert Watson 126956c15412SRobert Watson MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 127056c15412SRobert Watson if (error) { 127156c15412SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 127256c15412SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 127356c15412SRobert Watson } 127456c15412SRobert Watson 127508bcdc58SRobert Watson #ifdef MAC_DEBUG 127656c15412SRobert Watson if (error == 0) 127787807196SRobert Watson atomic_add_int(&nmacmbufs, 1); 127808bcdc58SRobert Watson #endif 127956c15412SRobert Watson return (error); 128008bcdc58SRobert Watson } 128108bcdc58SRobert Watson 128208bcdc58SRobert Watson void 128387807196SRobert Watson mac_init_mount(struct mount *mp) 128408bcdc58SRobert Watson { 128508bcdc58SRobert Watson 128687807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 128787807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 128887807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 128987807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 129008bcdc58SRobert Watson #ifdef MAC_DEBUG 129187807196SRobert Watson atomic_add_int(&nmacmounts, 1); 129208bcdc58SRobert Watson #endif 129308bcdc58SRobert Watson } 129408bcdc58SRobert Watson 1295f7b951a8SRobert Watson static void 1296f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 1297f7b951a8SRobert Watson { 1298f7b951a8SRobert Watson 1299f7b951a8SRobert Watson mac_init_label(label); 1300f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 1301f7b951a8SRobert Watson #ifdef MAC_DEBUG 1302f7b951a8SRobert Watson atomic_add_int(&nmacpipes, 1); 1303f7b951a8SRobert Watson #endif 1304f7b951a8SRobert Watson } 1305f7b951a8SRobert Watson 130608bcdc58SRobert Watson void 130708bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 130808bcdc58SRobert Watson { 130908bcdc58SRobert Watson struct label *label; 131008bcdc58SRobert Watson 131108bcdc58SRobert Watson label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 131208bcdc58SRobert Watson pipe->pipe_label = label; 131308bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 1314f7b951a8SRobert Watson mac_init_pipe_label(label); 131508bcdc58SRobert Watson } 131608bcdc58SRobert Watson 131783985c26SRobert Watson static int 131883985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 131908bcdc58SRobert Watson { 132083985c26SRobert Watson int error; 132108bcdc58SRobert Watson 132283985c26SRobert Watson mac_init_label(label); 132383985c26SRobert Watson 132483985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 132583985c26SRobert Watson if (error) { 132683985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 132783985c26SRobert Watson mac_destroy_label(label); 132883985c26SRobert Watson } 132983985c26SRobert Watson 133008bcdc58SRobert Watson #ifdef MAC_DEBUG 133183985c26SRobert Watson if (error == 0) 133287807196SRobert Watson atomic_add_int(&nmacsockets, 1); 133387807196SRobert Watson #endif 133483985c26SRobert Watson 133583985c26SRobert Watson return (error); 133683985c26SRobert Watson } 133783985c26SRobert Watson 133883985c26SRobert Watson static int 133983985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 134083985c26SRobert Watson { 134183985c26SRobert Watson int error; 134283985c26SRobert Watson 134383985c26SRobert Watson mac_init_label(label); 134483985c26SRobert Watson 134583985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 134683985c26SRobert Watson if (error) { 134783985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 134883985c26SRobert Watson mac_destroy_label(label); 134983985c26SRobert Watson } 135083985c26SRobert Watson 135183985c26SRobert Watson return (error); 135283985c26SRobert Watson } 135383985c26SRobert Watson 135483985c26SRobert Watson int 135583985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 135683985c26SRobert Watson { 135783985c26SRobert Watson int error; 135883985c26SRobert Watson 135983985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 136083985c26SRobert Watson if (error) 136183985c26SRobert Watson return (error); 136283985c26SRobert Watson 136383985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 136483985c26SRobert Watson if (error) 136583985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 136683985c26SRobert Watson 136783985c26SRobert Watson return (error); 136887807196SRobert Watson } 136987807196SRobert Watson 1370763bbd2fSRobert Watson void 1371f7b951a8SRobert Watson mac_init_vnode_label(struct label *label) 137287807196SRobert Watson { 137387807196SRobert Watson 137487807196SRobert Watson mac_init_label(label); 1375f7b951a8SRobert Watson MAC_PERFORM(init_vnode_label, label); 137687807196SRobert Watson #ifdef MAC_DEBUG 1377f7b951a8SRobert Watson atomic_add_int(&nmacvnodes, 1); 137808bcdc58SRobert Watson #endif 137908bcdc58SRobert Watson } 138008bcdc58SRobert Watson 138108bcdc58SRobert Watson void 138287807196SRobert Watson mac_init_vnode(struct vnode *vp) 138308bcdc58SRobert Watson { 138408bcdc58SRobert Watson 1385f7b951a8SRobert Watson mac_init_vnode_label(&vp->v_label); 138608bcdc58SRobert Watson } 138708bcdc58SRobert Watson 138808bcdc58SRobert Watson void 138908bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 139008bcdc58SRobert Watson { 139108bcdc58SRobert Watson 139208bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 139308bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 139408bcdc58SRobert Watson #ifdef MAC_DEBUG 139508bcdc58SRobert Watson atomic_subtract_int(&nmacbpfdescs, 1); 139608bcdc58SRobert Watson #endif 139708bcdc58SRobert Watson } 139808bcdc58SRobert Watson 1399f7b951a8SRobert Watson static void 1400f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label) 140108bcdc58SRobert Watson { 140208bcdc58SRobert Watson 1403f7b951a8SRobert Watson MAC_PERFORM(destroy_cred_label, label); 1404f7b951a8SRobert Watson mac_destroy_label(label); 140508bcdc58SRobert Watson #ifdef MAC_DEBUG 140687807196SRobert Watson atomic_subtract_int(&nmaccreds, 1); 140787807196SRobert Watson #endif 140887807196SRobert Watson } 140987807196SRobert Watson 141087807196SRobert Watson void 1411f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred) 1412f7b951a8SRobert Watson { 1413f7b951a8SRobert Watson 1414f7b951a8SRobert Watson mac_destroy_cred_label(&cred->cr_label); 1415f7b951a8SRobert Watson } 1416f7b951a8SRobert Watson 1417f7b951a8SRobert Watson void 141887807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 141987807196SRobert Watson { 142087807196SRobert Watson 142187807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 142287807196SRobert Watson mac_destroy_label(&de->de_label); 142387807196SRobert Watson #ifdef MAC_DEBUG 142487807196SRobert Watson atomic_subtract_int(&nmacdevfsdirents, 1); 142587807196SRobert Watson #endif 142687807196SRobert Watson } 142787807196SRobert Watson 1428f7b951a8SRobert Watson static void 1429f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label) 1430f7b951a8SRobert Watson { 1431f7b951a8SRobert Watson 1432f7b951a8SRobert Watson MAC_PERFORM(destroy_ifnet_label, label); 1433f7b951a8SRobert Watson mac_destroy_label(label); 1434f7b951a8SRobert Watson #ifdef MAC_DEBUG 1435f7b951a8SRobert Watson atomic_subtract_int(&nmacifnets, 1); 1436f7b951a8SRobert Watson #endif 1437f7b951a8SRobert Watson } 1438f7b951a8SRobert Watson 143987807196SRobert Watson void 144087807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 144187807196SRobert Watson { 144287807196SRobert Watson 1443f7b951a8SRobert Watson mac_destroy_ifnet_label(&ifp->if_label); 144487807196SRobert Watson } 144587807196SRobert Watson 144687807196SRobert Watson void 144787807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 144887807196SRobert Watson { 144987807196SRobert Watson 145087807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 145187807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 145287807196SRobert Watson #ifdef MAC_DEBUG 145387807196SRobert Watson atomic_subtract_int(&nmacipqs, 1); 145487807196SRobert Watson #endif 145587807196SRobert Watson } 145687807196SRobert Watson 145787807196SRobert Watson void 145887807196SRobert Watson mac_destroy_mbuf(struct mbuf *m) 145987807196SRobert Watson { 146087807196SRobert Watson 146187807196SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 146287807196SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 146387807196SRobert Watson #ifdef MAC_DEBUG 146487807196SRobert Watson atomic_subtract_int(&nmacmbufs, 1); 146508bcdc58SRobert Watson #endif 146608bcdc58SRobert Watson } 146708bcdc58SRobert Watson 146808bcdc58SRobert Watson void 146908bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 147008bcdc58SRobert Watson { 147108bcdc58SRobert Watson 147208bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 147308bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 147408bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 147508bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 147608bcdc58SRobert Watson #ifdef MAC_DEBUG 147708bcdc58SRobert Watson atomic_subtract_int(&nmacmounts, 1); 147808bcdc58SRobert Watson #endif 147908bcdc58SRobert Watson } 148008bcdc58SRobert Watson 1481f7b951a8SRobert Watson static void 1482f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 1483f7b951a8SRobert Watson { 1484f7b951a8SRobert Watson 1485f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 1486f7b951a8SRobert Watson mac_destroy_label(label); 1487f7b951a8SRobert Watson #ifdef MAC_DEBUG 1488f7b951a8SRobert Watson atomic_subtract_int(&nmacpipes, 1); 1489f7b951a8SRobert Watson #endif 1490f7b951a8SRobert Watson } 1491f7b951a8SRobert Watson 149287807196SRobert Watson void 149387807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 149408bcdc58SRobert Watson { 149508bcdc58SRobert Watson 1496f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 149787807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 149887807196SRobert Watson } 149987807196SRobert Watson 150083985c26SRobert Watson static void 150183985c26SRobert Watson mac_destroy_socket_label(struct label *label) 150283985c26SRobert Watson { 150383985c26SRobert Watson 150483985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 150583985c26SRobert Watson mac_destroy_label(label); 150683985c26SRobert Watson #ifdef MAC_DEBUG 150783985c26SRobert Watson atomic_subtract_int(&nmacsockets, 1); 150883985c26SRobert Watson #endif 150983985c26SRobert Watson } 151083985c26SRobert Watson 151183985c26SRobert Watson static void 151283985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 151383985c26SRobert Watson { 151483985c26SRobert Watson 151583985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 151683985c26SRobert Watson mac_destroy_label(label); 151783985c26SRobert Watson } 151883985c26SRobert Watson 151987807196SRobert Watson void 152087807196SRobert Watson mac_destroy_socket(struct socket *socket) 152187807196SRobert Watson { 152287807196SRobert Watson 152383985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 152483985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 152508bcdc58SRobert Watson } 152608bcdc58SRobert Watson 1527763bbd2fSRobert Watson void 1528f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label) 152908bcdc58SRobert Watson { 153008bcdc58SRobert Watson 1531f7b951a8SRobert Watson MAC_PERFORM(destroy_vnode_label, label); 153208bcdc58SRobert Watson mac_destroy_label(label); 153308bcdc58SRobert Watson #ifdef MAC_DEBUG 1534f7b951a8SRobert Watson atomic_subtract_int(&nmacvnodes, 1); 153508bcdc58SRobert Watson #endif 153608bcdc58SRobert Watson } 153708bcdc58SRobert Watson 153808bcdc58SRobert Watson void 153908bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 154008bcdc58SRobert Watson { 154108bcdc58SRobert Watson 1542f7b951a8SRobert Watson mac_destroy_vnode_label(&vp->v_label); 1543f7b951a8SRobert Watson } 1544f7b951a8SRobert Watson 1545f7b951a8SRobert Watson static void 1546f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 1547f7b951a8SRobert Watson { 1548f7b951a8SRobert Watson 1549f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 1550f7b951a8SRobert Watson } 1551f7b951a8SRobert Watson 1552763bbd2fSRobert Watson void 1553f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest) 1554f7b951a8SRobert Watson { 1555f7b951a8SRobert Watson 1556f7b951a8SRobert Watson MAC_PERFORM(copy_vnode_label, src, dest); 155708bcdc58SRobert Watson } 155808bcdc58SRobert Watson 155969bbb5b1SRobert Watson static int 1560f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 1561f7b951a8SRobert Watson { 1562f7b951a8SRobert Watson 1563f7b951a8SRobert Watson if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1564f7b951a8SRobert Watson return (EINVAL); 1565f7b951a8SRobert Watson 1566f7b951a8SRobert Watson return (0); 1567f7b951a8SRobert Watson } 1568f7b951a8SRobert Watson 1569f7b951a8SRobert Watson static int 1570f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements, 1571f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 157269bbb5b1SRobert Watson { 157369bbb5b1SRobert Watson int error; 157469bbb5b1SRobert Watson 1575f7b951a8SRobert Watson MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 157669bbb5b1SRobert Watson 157769bbb5b1SRobert Watson return (error); 157869bbb5b1SRobert Watson } 157969bbb5b1SRobert Watson 158069bbb5b1SRobert Watson static int 1581f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements, 1582f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 158369bbb5b1SRobert Watson { 158469bbb5b1SRobert Watson int error; 158569bbb5b1SRobert Watson 1586f7b951a8SRobert Watson MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1587f7b951a8SRobert Watson 1588f7b951a8SRobert Watson return (error); 1589f7b951a8SRobert Watson } 1590f7b951a8SRobert Watson 1591f7b951a8SRobert Watson static int 1592f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 1593f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1594f7b951a8SRobert Watson { 1595f7b951a8SRobert Watson int error; 1596f7b951a8SRobert Watson 1597f7b951a8SRobert Watson MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1598f7b951a8SRobert Watson 1599f7b951a8SRobert Watson return (error); 1600f7b951a8SRobert Watson } 1601f7b951a8SRobert Watson 1602f7b951a8SRobert Watson static int 1603f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 1604f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1605f7b951a8SRobert Watson { 1606f7b951a8SRobert Watson int error; 1607f7b951a8SRobert Watson 1608f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1609f7b951a8SRobert Watson 1610f7b951a8SRobert Watson return (error); 1611f7b951a8SRobert Watson } 1612f7b951a8SRobert Watson 1613f7b951a8SRobert Watson static int 1614f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 1615f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1616f7b951a8SRobert Watson { 1617f7b951a8SRobert Watson int error; 1618f7b951a8SRobert Watson 1619f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1620f7b951a8SRobert Watson 1621f7b951a8SRobert Watson return (error); 1622f7b951a8SRobert Watson } 1623f7b951a8SRobert Watson 1624f7b951a8SRobert Watson static int 1625f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements, 1626f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1627f7b951a8SRobert Watson { 1628f7b951a8SRobert Watson int error; 1629f7b951a8SRobert Watson 1630f7b951a8SRobert Watson MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1631f7b951a8SRobert Watson 1632f7b951a8SRobert Watson return (error); 1633f7b951a8SRobert Watson } 1634f7b951a8SRobert Watson 1635f7b951a8SRobert Watson static int 1636f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string) 1637f7b951a8SRobert Watson { 1638f7b951a8SRobert Watson int error; 1639f7b951a8SRobert Watson 1640f7b951a8SRobert Watson MAC_INTERNALIZE(cred_label, label, string); 1641f7b951a8SRobert Watson 1642f7b951a8SRobert Watson return (error); 1643f7b951a8SRobert Watson } 1644f7b951a8SRobert Watson 1645f7b951a8SRobert Watson static int 1646f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string) 1647f7b951a8SRobert Watson { 1648f7b951a8SRobert Watson int error; 1649f7b951a8SRobert Watson 1650f7b951a8SRobert Watson MAC_INTERNALIZE(ifnet_label, label, string); 1651f7b951a8SRobert Watson 1652f7b951a8SRobert Watson return (error); 1653f7b951a8SRobert Watson } 1654f7b951a8SRobert Watson 1655f7b951a8SRobert Watson static int 1656f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 1657f7b951a8SRobert Watson { 1658f7b951a8SRobert Watson int error; 1659f7b951a8SRobert Watson 1660f7b951a8SRobert Watson MAC_INTERNALIZE(pipe_label, label, string); 1661f7b951a8SRobert Watson 1662f7b951a8SRobert Watson return (error); 1663f7b951a8SRobert Watson } 1664f7b951a8SRobert Watson 1665f7b951a8SRobert Watson static int 1666f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string) 1667f7b951a8SRobert Watson { 1668f7b951a8SRobert Watson int error; 1669f7b951a8SRobert Watson 1670f7b951a8SRobert Watson MAC_INTERNALIZE(socket_label, label, string); 1671f7b951a8SRobert Watson 1672f7b951a8SRobert Watson return (error); 1673f7b951a8SRobert Watson } 1674f7b951a8SRobert Watson 1675f7b951a8SRobert Watson static int 1676f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string) 1677f7b951a8SRobert Watson { 1678f7b951a8SRobert Watson int error; 1679f7b951a8SRobert Watson 1680f7b951a8SRobert Watson MAC_INTERNALIZE(vnode_label, label, string); 168169bbb5b1SRobert Watson 168269bbb5b1SRobert Watson return (error); 168369bbb5b1SRobert Watson } 168469bbb5b1SRobert Watson 168569bbb5b1SRobert Watson /* 168669bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 168769bbb5b1SRobert Watson * kernel processes and threads are spawned. 168869bbb5b1SRobert Watson */ 168969bbb5b1SRobert Watson void 169069bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 169169bbb5b1SRobert Watson { 169269bbb5b1SRobert Watson 169369bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 169469bbb5b1SRobert Watson } 169569bbb5b1SRobert Watson 169669bbb5b1SRobert Watson /* 169769bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 169869bbb5b1SRobert Watson * userland processes and threads are spawned. 169969bbb5b1SRobert Watson */ 170069bbb5b1SRobert Watson void 170169bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 170269bbb5b1SRobert Watson { 170369bbb5b1SRobert Watson 170469bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 170569bbb5b1SRobert Watson } 170669bbb5b1SRobert Watson 170769bbb5b1SRobert Watson void 170869bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 170969bbb5b1SRobert Watson { 171069bbb5b1SRobert Watson 171169bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 171269bbb5b1SRobert Watson } 171369bbb5b1SRobert Watson 171469bbb5b1SRobert Watson /* 171569bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 171669bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 171769bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 171869bbb5b1SRobert Watson */ 171969bbb5b1SRobert Watson void 172069bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 172169bbb5b1SRobert Watson { 172269bbb5b1SRobert Watson 172369bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 172469bbb5b1SRobert Watson } 172569bbb5b1SRobert Watson 172695fab37eSRobert Watson void 172795fab37eSRobert Watson mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 172895fab37eSRobert Watson { 172995fab37eSRobert Watson 173095fab37eSRobert Watson MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 173195fab37eSRobert Watson } 173295fab37eSRobert Watson 173395fab37eSRobert Watson void 1734763bbd2fSRobert Watson mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1735763bbd2fSRobert Watson struct vnode *vp) 173695fab37eSRobert Watson { 173795fab37eSRobert Watson 1738763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1739763bbd2fSRobert Watson &de->de_label, vp, &vp->v_label); 174095fab37eSRobert Watson } 174195fab37eSRobert Watson 1742763bbd2fSRobert Watson int 1743763bbd2fSRobert Watson mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 174495fab37eSRobert Watson { 174595fab37eSRobert Watson int error; 174695fab37eSRobert Watson 1747763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1748763bbd2fSRobert Watson 1749763bbd2fSRobert Watson MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1750763bbd2fSRobert Watson &vp->v_label); 175195fab37eSRobert Watson 175295fab37eSRobert Watson return (error); 175395fab37eSRobert Watson } 175495fab37eSRobert Watson 175595fab37eSRobert Watson void 1756763bbd2fSRobert Watson mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 175795fab37eSRobert Watson { 175895fab37eSRobert Watson 1759763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1760763bbd2fSRobert Watson &vp->v_label); 176195fab37eSRobert Watson } 176295fab37eSRobert Watson 176395fab37eSRobert Watson int 1764763bbd2fSRobert Watson mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1765763bbd2fSRobert Watson struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 176695fab37eSRobert Watson { 1767763bbd2fSRobert Watson int error; 176895fab37eSRobert Watson 1769763bbd2fSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1770763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 177195fab37eSRobert Watson 1772763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1773763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1774763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1775763bbd2fSRobert Watson if (ea_warn_once == 0) { 1776763bbd2fSRobert Watson printf("Warning: transactions not supported " 1777763bbd2fSRobert Watson "in EA write.\n"); 1778763bbd2fSRobert Watson ea_warn_once = 1; 1779763bbd2fSRobert Watson } 1780763bbd2fSRobert Watson } else if (error) 178195fab37eSRobert Watson return (error); 178295fab37eSRobert Watson 1783763bbd2fSRobert Watson MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1784763bbd2fSRobert Watson dvp, &dvp->v_label, vp, &vp->v_label, cnp); 178595fab37eSRobert Watson 1786763bbd2fSRobert Watson if (error) { 1787763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 178895fab37eSRobert Watson return (error); 178995fab37eSRobert Watson } 179095fab37eSRobert Watson 1791763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 179295fab37eSRobert Watson 1793763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1794763bbd2fSRobert Watson error = 0; /* XXX */ 179595fab37eSRobert Watson 179695fab37eSRobert Watson return (error); 179795fab37eSRobert Watson } 179895fab37eSRobert Watson 179995fab37eSRobert Watson static int 1800763bbd2fSRobert Watson mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1801763bbd2fSRobert Watson struct label *intlabel) 180295fab37eSRobert Watson { 180395fab37eSRobert Watson int error; 180495fab37eSRobert Watson 1805763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 180695fab37eSRobert Watson 1807763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1808763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1809763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1810763bbd2fSRobert Watson if (ea_warn_once == 0) { 1811763bbd2fSRobert Watson printf("Warning: transactions not supported " 1812763bbd2fSRobert Watson "in EA write.\n"); 1813763bbd2fSRobert Watson ea_warn_once = 1; 181495fab37eSRobert Watson } 1815763bbd2fSRobert Watson } else if (error) 181695fab37eSRobert Watson return (error); 181795fab37eSRobert Watson 1818763bbd2fSRobert Watson MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 181995fab37eSRobert Watson 1820763bbd2fSRobert Watson if (error) { 1821763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 182295fab37eSRobert Watson return (error); 182395fab37eSRobert Watson } 182495fab37eSRobert Watson 1825763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1826763bbd2fSRobert Watson 1827763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1828763bbd2fSRobert Watson error = 0; /* XXX */ 1829763bbd2fSRobert Watson 1830763bbd2fSRobert Watson return (error); 183195fab37eSRobert Watson } 183295fab37eSRobert Watson 183395fab37eSRobert Watson void 183495fab37eSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 183595fab37eSRobert Watson { 183695fab37eSRobert Watson 183795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 183895fab37eSRobert Watson 183995fab37eSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 184095fab37eSRobert Watson } 184195fab37eSRobert Watson 184295fab37eSRobert Watson int 184395fab37eSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp) 184495fab37eSRobert Watson { 1845763bbd2fSRobert Watson int result; 184695fab37eSRobert Watson 184795fab37eSRobert Watson result = 0; 184895fab37eSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 184995fab37eSRobert Watson 185095fab37eSRobert Watson return (result); 185195fab37eSRobert Watson } 185295fab37eSRobert Watson 185395fab37eSRobert Watson int 185495fab37eSRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 185595fab37eSRobert Watson { 185695fab37eSRobert Watson int error; 185795fab37eSRobert Watson 185895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 185995fab37eSRobert Watson 186095fab37eSRobert Watson if (!mac_enforce_fs) 186195fab37eSRobert Watson return (0); 186295fab37eSRobert Watson 186395fab37eSRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 186495fab37eSRobert Watson return (error); 186595fab37eSRobert Watson } 186695fab37eSRobert Watson 186795fab37eSRobert Watson int 186895fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 186995fab37eSRobert Watson { 187095fab37eSRobert Watson int error; 187195fab37eSRobert Watson 187295fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 187395fab37eSRobert Watson 187495fab37eSRobert Watson if (!mac_enforce_fs) 187595fab37eSRobert Watson return (0); 187695fab37eSRobert Watson 187795fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 187895fab37eSRobert Watson return (error); 187995fab37eSRobert Watson } 188095fab37eSRobert Watson 188195fab37eSRobert Watson int 188295fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 188395fab37eSRobert Watson { 188495fab37eSRobert Watson int error; 188595fab37eSRobert Watson 188695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 188795fab37eSRobert Watson 188895fab37eSRobert Watson if (!mac_enforce_fs) 188995fab37eSRobert Watson return (0); 189095fab37eSRobert Watson 189195fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 189295fab37eSRobert Watson return (error); 189395fab37eSRobert Watson } 189495fab37eSRobert Watson 189595fab37eSRobert Watson int 189695fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 189795fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 189895fab37eSRobert Watson { 189995fab37eSRobert Watson int error; 190095fab37eSRobert Watson 190195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 190295fab37eSRobert Watson 190395fab37eSRobert Watson if (!mac_enforce_fs) 190495fab37eSRobert Watson return (0); 190595fab37eSRobert Watson 190695fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 190795fab37eSRobert Watson return (error); 190895fab37eSRobert Watson } 190995fab37eSRobert Watson 191095fab37eSRobert Watson int 191195fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 191295fab37eSRobert Watson struct componentname *cnp) 191395fab37eSRobert Watson { 191495fab37eSRobert Watson int error; 191595fab37eSRobert Watson 191695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 191795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 191895fab37eSRobert Watson 191995fab37eSRobert Watson if (!mac_enforce_fs) 192095fab37eSRobert Watson return (0); 192195fab37eSRobert Watson 192295fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 192395fab37eSRobert Watson &vp->v_label, cnp); 192495fab37eSRobert Watson return (error); 192595fab37eSRobert Watson } 192695fab37eSRobert Watson 192795fab37eSRobert Watson int 192895fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 192995fab37eSRobert Watson acl_type_t type) 193095fab37eSRobert Watson { 193195fab37eSRobert Watson int error; 193295fab37eSRobert Watson 193395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 193495fab37eSRobert Watson 193595fab37eSRobert Watson if (!mac_enforce_fs) 193695fab37eSRobert Watson return (0); 193795fab37eSRobert Watson 193895fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 193995fab37eSRobert Watson return (error); 194095fab37eSRobert Watson } 194195fab37eSRobert Watson 194295fab37eSRobert Watson int 194395fab37eSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 194495fab37eSRobert Watson { 194595fab37eSRobert Watson int error; 194695fab37eSRobert Watson 1947851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1948851704bbSRobert Watson 194995fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 195095fab37eSRobert Watson return (0); 195195fab37eSRobert Watson 195295fab37eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 195395fab37eSRobert Watson 195495fab37eSRobert Watson return (error); 195595fab37eSRobert Watson } 195695fab37eSRobert Watson 195795fab37eSRobert Watson int 195895fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 195995fab37eSRobert Watson { 196095fab37eSRobert Watson int error; 196195fab37eSRobert Watson 196295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 196395fab37eSRobert Watson 196495fab37eSRobert Watson if (!mac_enforce_fs) 196595fab37eSRobert Watson return (0); 196695fab37eSRobert Watson 196795fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 196895fab37eSRobert Watson return (error); 196995fab37eSRobert Watson } 197095fab37eSRobert Watson 197195fab37eSRobert Watson int 197295fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 197395fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 197495fab37eSRobert Watson { 197595fab37eSRobert Watson int error; 197695fab37eSRobert Watson 197795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 197895fab37eSRobert Watson 197995fab37eSRobert Watson if (!mac_enforce_fs) 198095fab37eSRobert Watson return (0); 198195fab37eSRobert Watson 198295fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 198395fab37eSRobert Watson attrnamespace, name, uio); 198495fab37eSRobert Watson return (error); 198595fab37eSRobert Watson } 198695fab37eSRobert Watson 198795fab37eSRobert Watson int 19880a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 19890a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 19900a694196SRobert Watson { 19910a694196SRobert Watson int error; 19920a694196SRobert Watson 19930a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 19940a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 19950a694196SRobert Watson 19960a694196SRobert Watson if (!mac_enforce_fs) 19970a694196SRobert Watson return (0); 19980a694196SRobert Watson 19990a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 20000a694196SRobert Watson &vp->v_label, cnp); 20010a694196SRobert Watson return (error); 20020a694196SRobert Watson } 20030a694196SRobert Watson 20040a694196SRobert Watson int 200595fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 200695fab37eSRobert Watson struct componentname *cnp) 200795fab37eSRobert Watson { 200895fab37eSRobert Watson int error; 200995fab37eSRobert Watson 201095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 201195fab37eSRobert Watson 201295fab37eSRobert Watson if (!mac_enforce_fs) 201395fab37eSRobert Watson return (0); 201495fab37eSRobert Watson 201595fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 201695fab37eSRobert Watson return (error); 201795fab37eSRobert Watson } 201895fab37eSRobert Watson 2019e183f80eSRobert Watson int 2020e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 202195fab37eSRobert Watson { 2022e183f80eSRobert Watson int error; 202395fab37eSRobert Watson 2024e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 2025ca7850c3SRobert Watson 2026e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 2027e183f80eSRobert Watson return (0); 2028e183f80eSRobert Watson 2029e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 2030e183f80eSRobert Watson return (error); 2031e183f80eSRobert Watson } 2032e183f80eSRobert Watson 2033e183f80eSRobert Watson void 2034e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 2035e183f80eSRobert Watson { 2036e183f80eSRobert Watson int result = *prot; 2037e183f80eSRobert Watson 2038e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 2039e183f80eSRobert Watson 2040e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 2041e183f80eSRobert Watson return; 2042e183f80eSRobert Watson 2043e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 2044e183f80eSRobert Watson &result); 2045e183f80eSRobert Watson 2046e183f80eSRobert Watson *prot = result; 2047e183f80eSRobert Watson } 2048e183f80eSRobert Watson 2049e183f80eSRobert Watson int 2050e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 2051e183f80eSRobert Watson { 2052e183f80eSRobert Watson int error; 2053e183f80eSRobert Watson 2054e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 2055e183f80eSRobert Watson 2056e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 2057e183f80eSRobert Watson return (0); 2058e183f80eSRobert Watson 2059e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 2060e183f80eSRobert Watson return (error); 206195fab37eSRobert Watson } 206295fab37eSRobert Watson 206395fab37eSRobert Watson int 206495fab37eSRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 206595fab37eSRobert Watson { 206695fab37eSRobert Watson int error; 206795fab37eSRobert Watson 206895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 206995fab37eSRobert Watson 207095fab37eSRobert Watson if (!mac_enforce_fs) 207195fab37eSRobert Watson return (0); 207295fab37eSRobert Watson 207395fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 207495fab37eSRobert Watson return (error); 207595fab37eSRobert Watson } 207695fab37eSRobert Watson 207795fab37eSRobert Watson int 2078177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 2079177142e4SRobert Watson struct vnode *vp) 20807f724f8bSRobert Watson { 20817f724f8bSRobert Watson int error; 20827f724f8bSRobert Watson 20837f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 20847f724f8bSRobert Watson 20857f724f8bSRobert Watson if (!mac_enforce_fs) 20867f724f8bSRobert Watson return (0); 20877f724f8bSRobert Watson 2088177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 2089177142e4SRobert Watson &vp->v_label); 20907f724f8bSRobert Watson 20917f724f8bSRobert Watson return (error); 20927f724f8bSRobert Watson } 20937f724f8bSRobert Watson 20947f724f8bSRobert Watson int 2095177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 2096177142e4SRobert Watson struct vnode *vp) 20977f724f8bSRobert Watson { 20987f724f8bSRobert Watson int error; 20997f724f8bSRobert Watson 21007f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 21017f724f8bSRobert Watson 21027f724f8bSRobert Watson if (!mac_enforce_fs) 21037f724f8bSRobert Watson return (0); 21047f724f8bSRobert Watson 2105177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 2106177142e4SRobert Watson &vp->v_label); 21077f724f8bSRobert Watson 21087f724f8bSRobert Watson return (error); 21097f724f8bSRobert Watson } 21107f724f8bSRobert Watson 21117f724f8bSRobert Watson int 211295fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 211395fab37eSRobert Watson { 211495fab37eSRobert Watson int error; 211595fab37eSRobert Watson 211695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 211795fab37eSRobert Watson 211895fab37eSRobert Watson if (!mac_enforce_fs) 211995fab37eSRobert Watson return (0); 212095fab37eSRobert Watson 212195fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 212295fab37eSRobert Watson return (error); 212395fab37eSRobert Watson } 212495fab37eSRobert Watson 212595fab37eSRobert Watson int 212695fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 212795fab37eSRobert Watson { 212895fab37eSRobert Watson int error; 212995fab37eSRobert Watson 213095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 213195fab37eSRobert Watson 213295fab37eSRobert Watson if (!mac_enforce_fs) 213395fab37eSRobert Watson return (0); 213495fab37eSRobert Watson 213595fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 213695fab37eSRobert Watson return (error); 213795fab37eSRobert Watson } 213895fab37eSRobert Watson 213995fab37eSRobert Watson static int 214095fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 214195fab37eSRobert Watson struct label *newlabel) 214295fab37eSRobert Watson { 214395fab37eSRobert Watson int error; 214495fab37eSRobert Watson 214595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 214695fab37eSRobert Watson 214795fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 214895fab37eSRobert Watson 214995fab37eSRobert Watson return (error); 215095fab37eSRobert Watson } 215195fab37eSRobert Watson 215295fab37eSRobert Watson int 215395fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 215495fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 215595fab37eSRobert Watson { 215695fab37eSRobert Watson int error; 215795fab37eSRobert Watson 215895fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 215995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 216095fab37eSRobert Watson 216195fab37eSRobert Watson if (!mac_enforce_fs) 216295fab37eSRobert Watson return (0); 216395fab37eSRobert Watson 216495fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 216595fab37eSRobert Watson &vp->v_label, cnp); 216695fab37eSRobert Watson return (error); 216795fab37eSRobert Watson } 216895fab37eSRobert Watson 216995fab37eSRobert Watson int 217095fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 217195fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 217295fab37eSRobert Watson { 217395fab37eSRobert Watson int error; 217495fab37eSRobert Watson 217595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 217695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 217795fab37eSRobert Watson 217895fab37eSRobert Watson if (!mac_enforce_fs) 217995fab37eSRobert Watson return (0); 218095fab37eSRobert Watson 218195fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 218295fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 218395fab37eSRobert Watson return (error); 218495fab37eSRobert Watson } 218595fab37eSRobert Watson 218695fab37eSRobert Watson int 218795fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 218895fab37eSRobert Watson { 218995fab37eSRobert Watson int error; 219095fab37eSRobert Watson 219195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 219295fab37eSRobert Watson 219395fab37eSRobert Watson if (!mac_enforce_fs) 219495fab37eSRobert Watson return (0); 219595fab37eSRobert Watson 219695fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 219795fab37eSRobert Watson return (error); 219895fab37eSRobert Watson } 219995fab37eSRobert Watson 220095fab37eSRobert Watson int 220195fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 220295fab37eSRobert Watson struct acl *acl) 220395fab37eSRobert Watson { 220495fab37eSRobert Watson int error; 220595fab37eSRobert Watson 220695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 220795fab37eSRobert Watson 220895fab37eSRobert Watson if (!mac_enforce_fs) 220995fab37eSRobert Watson return (0); 221095fab37eSRobert Watson 221195fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 221295fab37eSRobert Watson return (error); 221395fab37eSRobert Watson } 221495fab37eSRobert Watson 221595fab37eSRobert Watson int 221695fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 221795fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 221895fab37eSRobert Watson { 221995fab37eSRobert Watson int error; 222095fab37eSRobert Watson 222195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 222295fab37eSRobert Watson 222395fab37eSRobert Watson if (!mac_enforce_fs) 222495fab37eSRobert Watson return (0); 222595fab37eSRobert Watson 222695fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 222795fab37eSRobert Watson attrnamespace, name, uio); 222895fab37eSRobert Watson return (error); 222995fab37eSRobert Watson } 223095fab37eSRobert Watson 223195fab37eSRobert Watson int 223295fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 223395fab37eSRobert Watson { 223495fab37eSRobert Watson int error; 223595fab37eSRobert Watson 223695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 223795fab37eSRobert Watson 223895fab37eSRobert Watson if (!mac_enforce_fs) 223995fab37eSRobert Watson return (0); 224095fab37eSRobert Watson 224195fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 224295fab37eSRobert Watson return (error); 224395fab37eSRobert Watson } 224495fab37eSRobert Watson 224595fab37eSRobert Watson int 224695fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 224795fab37eSRobert Watson { 224895fab37eSRobert Watson int error; 224995fab37eSRobert Watson 225095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 225195fab37eSRobert Watson 225295fab37eSRobert Watson if (!mac_enforce_fs) 225395fab37eSRobert Watson return (0); 225495fab37eSRobert Watson 225595fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 225695fab37eSRobert Watson return (error); 225795fab37eSRobert Watson } 225895fab37eSRobert Watson 225995fab37eSRobert Watson int 226095fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 226195fab37eSRobert Watson gid_t gid) 226295fab37eSRobert Watson { 226395fab37eSRobert Watson int error; 226495fab37eSRobert Watson 226595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 226695fab37eSRobert Watson 226795fab37eSRobert Watson if (!mac_enforce_fs) 226895fab37eSRobert Watson return (0); 226995fab37eSRobert Watson 227095fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 227195fab37eSRobert Watson return (error); 227295fab37eSRobert Watson } 227395fab37eSRobert Watson 227495fab37eSRobert Watson int 227595fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 227695fab37eSRobert Watson struct timespec atime, struct timespec mtime) 227795fab37eSRobert Watson { 227895fab37eSRobert Watson int error; 227995fab37eSRobert Watson 228095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 228195fab37eSRobert Watson 228295fab37eSRobert Watson if (!mac_enforce_fs) 228395fab37eSRobert Watson return (0); 228495fab37eSRobert Watson 228595fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 228695fab37eSRobert Watson mtime); 228795fab37eSRobert Watson return (error); 228895fab37eSRobert Watson } 228995fab37eSRobert Watson 229095fab37eSRobert Watson int 2291177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2292177142e4SRobert Watson struct vnode *vp) 229395fab37eSRobert Watson { 229495fab37eSRobert Watson int error; 229595fab37eSRobert Watson 229695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 229795fab37eSRobert Watson 229895fab37eSRobert Watson if (!mac_enforce_fs) 229995fab37eSRobert Watson return (0); 230095fab37eSRobert Watson 2301177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2302177142e4SRobert Watson &vp->v_label); 230395fab37eSRobert Watson return (error); 230495fab37eSRobert Watson } 230595fab37eSRobert Watson 23067f724f8bSRobert Watson int 2307177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2308177142e4SRobert Watson struct vnode *vp) 23097f724f8bSRobert Watson { 23107f724f8bSRobert Watson int error; 23117f724f8bSRobert Watson 23127f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 23137f724f8bSRobert Watson 23147f724f8bSRobert Watson if (!mac_enforce_fs) 23157f724f8bSRobert Watson return (0); 23167f724f8bSRobert Watson 2317177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2318177142e4SRobert Watson &vp->v_label); 23197f724f8bSRobert Watson 23207f724f8bSRobert Watson return (error); 23217f724f8bSRobert Watson } 23227f724f8bSRobert Watson 232395fab37eSRobert Watson /* 232495fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 232595fab37eSRobert Watson * permission allowed for each object type we know about in its 232695fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 232795fab37eSRobert Watson * know) when necessary. The process lock is not held here. 232895fab37eSRobert Watson */ 232995fab37eSRobert Watson static void 233095fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 233195fab37eSRobert Watson { 233295fab37eSRobert Watson 233395fab37eSRobert Watson /* XXX freeze all other threads */ 233495fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 233595fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 233695fab37eSRobert Watson /* XXX allow other threads to continue */ 233795fab37eSRobert Watson } 233895fab37eSRobert Watson 233995fab37eSRobert Watson static __inline const char * 234095fab37eSRobert Watson prot2str(vm_prot_t prot) 234195fab37eSRobert Watson { 234295fab37eSRobert Watson 234395fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 234495fab37eSRobert Watson case VM_PROT_READ: 234595fab37eSRobert Watson return ("r--"); 234695fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 234795fab37eSRobert Watson return ("rw-"); 234895fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 234995fab37eSRobert Watson return ("r-x"); 235095fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 235195fab37eSRobert Watson return ("rwx"); 235295fab37eSRobert Watson case VM_PROT_WRITE: 235395fab37eSRobert Watson return ("-w-"); 235495fab37eSRobert Watson case VM_PROT_EXECUTE: 235595fab37eSRobert Watson return ("--x"); 235695fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 235795fab37eSRobert Watson return ("-wx"); 235895fab37eSRobert Watson default: 235995fab37eSRobert Watson return ("---"); 236095fab37eSRobert Watson } 236195fab37eSRobert Watson } 236295fab37eSRobert Watson 236395fab37eSRobert Watson static void 236495fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 236595fab37eSRobert Watson struct vm_map *map) 236695fab37eSRobert Watson { 236795fab37eSRobert Watson struct vm_map_entry *vme; 2368e183f80eSRobert Watson int result; 2369e183f80eSRobert Watson vm_prot_t revokeperms; 237095fab37eSRobert Watson vm_object_t object; 237195fab37eSRobert Watson vm_ooffset_t offset; 237295fab37eSRobert Watson struct vnode *vp; 237395fab37eSRobert Watson 2374c0f39905SRobert Watson if (!mac_mmap_revocation) 2375c0f39905SRobert Watson return; 2376c0f39905SRobert Watson 237795fab37eSRobert Watson vm_map_lock_read(map); 237895fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 237995fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 238095fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 238195fab37eSRobert Watson vme->object.sub_map); 238295fab37eSRobert Watson continue; 238395fab37eSRobert Watson } 238495fab37eSRobert Watson /* 238595fab37eSRobert Watson * Skip over entries that obviously are not shared. 238695fab37eSRobert Watson */ 238795fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 238895fab37eSRobert Watson !vme->max_protection) 238995fab37eSRobert Watson continue; 239095fab37eSRobert Watson /* 239195fab37eSRobert Watson * Drill down to the deepest backing object. 239295fab37eSRobert Watson */ 239395fab37eSRobert Watson offset = vme->offset; 239495fab37eSRobert Watson object = vme->object.vm_object; 239595fab37eSRobert Watson if (object == NULL) 239695fab37eSRobert Watson continue; 239795fab37eSRobert Watson while (object->backing_object != NULL) { 239895fab37eSRobert Watson object = object->backing_object; 239995fab37eSRobert Watson offset += object->backing_object_offset; 240095fab37eSRobert Watson } 240195fab37eSRobert Watson /* 240295fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 240395fab37eSRobert Watson * by the MAC system, so only things with backing by a 240495fab37eSRobert Watson * normal object (read: vnodes) are checked. 240595fab37eSRobert Watson */ 240695fab37eSRobert Watson if (object->type != OBJT_VNODE) 240795fab37eSRobert Watson continue; 240895fab37eSRobert Watson vp = (struct vnode *)object->handle; 240995fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2410e183f80eSRobert Watson result = vme->max_protection; 2411e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 241295fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 241395fab37eSRobert Watson /* 241495fab37eSRobert Watson * Find out what maximum protection we may be allowing 241595fab37eSRobert Watson * now but a policy needs to get removed. 241695fab37eSRobert Watson */ 241795fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 241895fab37eSRobert Watson if (!revokeperms) 241995fab37eSRobert Watson continue; 2420b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 2421b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2422b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 2423b656366bSBruce Evans (long)(vme->end - vme->start), 242495fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 242595fab37eSRobert Watson vm_map_lock_upgrade(map); 242695fab37eSRobert Watson /* 242795fab37eSRobert Watson * This is the really simple case: if a map has more 242895fab37eSRobert Watson * max_protection than is allowed, but it's not being 242995fab37eSRobert Watson * actually used (that is, the current protection is 243095fab37eSRobert Watson * still allowed), we can just wipe it out and do 243195fab37eSRobert Watson * nothing more. 243295fab37eSRobert Watson */ 243395fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 243495fab37eSRobert Watson vme->max_protection -= revokeperms; 243595fab37eSRobert Watson } else { 243695fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 243795fab37eSRobert Watson /* 243895fab37eSRobert Watson * In the more complicated case, flush out all 243995fab37eSRobert Watson * pending changes to the object then turn it 244095fab37eSRobert Watson * copy-on-write. 244195fab37eSRobert Watson */ 244295fab37eSRobert Watson vm_object_reference(object); 244395fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 244495fab37eSRobert Watson vm_object_page_clean(object, 244595fab37eSRobert Watson OFF_TO_IDX(offset), 244695fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 244795fab37eSRobert Watson PAGE_MASK), 244895fab37eSRobert Watson OBJPC_SYNC); 244995fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 245095fab37eSRobert Watson vm_object_deallocate(object); 245195fab37eSRobert Watson /* 245295fab37eSRobert Watson * Why bother if there's no read permissions 245395fab37eSRobert Watson * anymore? For the rest, we need to leave 245495fab37eSRobert Watson * the write permissions on for COW, or 245595fab37eSRobert Watson * remove them entirely if configured to. 245695fab37eSRobert Watson */ 245795fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 245895fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 245995fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 246095fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 246195fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 246295fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 246395fab37eSRobert Watson } 246495fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 246595fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 246695fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 246795fab37eSRobert Watson } 246895fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 246995fab37eSRobert Watson vme->max_protection = 0; 247095fab37eSRobert Watson vme->protection = 0; 247195fab37eSRobert Watson } 247295fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 247395fab37eSRobert Watson vme->protection & ~revokeperms); 247495fab37eSRobert Watson vm_map_simplify_entry(map, vme); 247595fab37eSRobert Watson } 247695fab37eSRobert Watson vm_map_lock_downgrade(map); 247795fab37eSRobert Watson } 247895fab37eSRobert Watson vm_map_unlock_read(map); 247995fab37eSRobert Watson } 248095fab37eSRobert Watson 248195fab37eSRobert Watson /* 248295fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 248395fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 248495fab37eSRobert Watson * buffer cache. 248595fab37eSRobert Watson */ 248695fab37eSRobert Watson static void 248795fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 248895fab37eSRobert Watson { 248995fab37eSRobert Watson 249095fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 249195fab37eSRobert Watson } 249295fab37eSRobert Watson 249395fab37eSRobert Watson void 249495fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 249595fab37eSRobert Watson { 249695fab37eSRobert Watson 249795fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 249895fab37eSRobert Watson } 249995fab37eSRobert Watson 250095fab37eSRobert Watson void 250195fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 250295fab37eSRobert Watson { 250395fab37eSRobert Watson 250495fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 250595fab37eSRobert Watson } 250695fab37eSRobert Watson 250795fab37eSRobert Watson void 250895fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 250995fab37eSRobert Watson { 251095fab37eSRobert Watson 251195fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 251295fab37eSRobert Watson } 251395fab37eSRobert Watson 251495fab37eSRobert Watson void 251595fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 251695fab37eSRobert Watson { 251795fab37eSRobert Watson 251895fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 251995fab37eSRobert Watson } 252095fab37eSRobert Watson 252195fab37eSRobert Watson void 252295fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 252395fab37eSRobert Watson { 252495fab37eSRobert Watson 252595fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 252695fab37eSRobert Watson } 252795fab37eSRobert Watson 252895fab37eSRobert Watson void 252995fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 253095fab37eSRobert Watson struct socket *newsocket) 253195fab37eSRobert Watson { 253295fab37eSRobert Watson 253395fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 253495fab37eSRobert Watson newsocket, &newsocket->so_label); 253595fab37eSRobert Watson } 253695fab37eSRobert Watson 253795fab37eSRobert Watson static void 253895fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 253995fab37eSRobert Watson struct label *newlabel) 254095fab37eSRobert Watson { 254195fab37eSRobert Watson 254295fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 254395fab37eSRobert Watson } 254495fab37eSRobert Watson 254595fab37eSRobert Watson static void 254695fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 254795fab37eSRobert Watson { 254895fab37eSRobert Watson 254995fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 255095fab37eSRobert Watson } 255195fab37eSRobert Watson 255295fab37eSRobert Watson void 255395fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 255495fab37eSRobert Watson { 255595fab37eSRobert Watson 255695fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 255795fab37eSRobert Watson socket, &socket->so_peerlabel); 255895fab37eSRobert Watson } 255995fab37eSRobert Watson 256095fab37eSRobert Watson void 256195fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 256295fab37eSRobert Watson struct socket *newsocket) 256395fab37eSRobert Watson { 256495fab37eSRobert Watson 256595fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 256695fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 256795fab37eSRobert Watson } 256895fab37eSRobert Watson 256995fab37eSRobert Watson void 257095fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 257195fab37eSRobert Watson { 257295fab37eSRobert Watson 257395fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 257495fab37eSRobert Watson datagram, &datagram->m_pkthdr.label); 257595fab37eSRobert Watson } 257695fab37eSRobert Watson 257795fab37eSRobert Watson void 257895fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 257995fab37eSRobert Watson { 258095fab37eSRobert Watson 258195fab37eSRobert Watson MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 258295fab37eSRobert Watson fragment, &fragment->m_pkthdr.label); 258395fab37eSRobert Watson } 258495fab37eSRobert Watson 258595fab37eSRobert Watson void 258695fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 258795fab37eSRobert Watson { 258895fab37eSRobert Watson 258995fab37eSRobert Watson MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 259095fab37eSRobert Watson &ipq->ipq_label); 259195fab37eSRobert Watson } 259295fab37eSRobert Watson 259395fab37eSRobert Watson void 259495fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 259595fab37eSRobert Watson { 259695fab37eSRobert Watson 259795fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 259895fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 259995fab37eSRobert Watson } 260095fab37eSRobert Watson 260195fab37eSRobert Watson void 260295fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 260395fab37eSRobert Watson { 260495fab37eSRobert Watson 260595fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 260695fab37eSRobert Watson &mbuf->m_pkthdr.label); 260795fab37eSRobert Watson } 260895fab37eSRobert Watson 260995fab37eSRobert Watson void 261095fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 261195fab37eSRobert Watson { 261295fab37eSRobert Watson 261395fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 261495fab37eSRobert Watson &mbuf->m_pkthdr.label); 261595fab37eSRobert Watson } 261695fab37eSRobert Watson 261795fab37eSRobert Watson void 261895fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 261995fab37eSRobert Watson { 262095fab37eSRobert Watson 262195fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 262295fab37eSRobert Watson &mbuf->m_pkthdr.label); 262395fab37eSRobert Watson } 262495fab37eSRobert Watson 262595fab37eSRobert Watson void 262695fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 262795fab37eSRobert Watson struct mbuf *newmbuf) 262895fab37eSRobert Watson { 262995fab37eSRobert Watson 263095fab37eSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 263195fab37eSRobert Watson &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 263295fab37eSRobert Watson &newmbuf->m_pkthdr.label); 263395fab37eSRobert Watson } 263495fab37eSRobert Watson 263595fab37eSRobert Watson void 263695fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 263795fab37eSRobert Watson { 263895fab37eSRobert Watson 263995fab37eSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 264095fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 264195fab37eSRobert Watson } 264295fab37eSRobert Watson 264395fab37eSRobert Watson int 264495fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 264595fab37eSRobert Watson { 264695fab37eSRobert Watson int result; 264795fab37eSRobert Watson 264895fab37eSRobert Watson result = 1; 264995fab37eSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 265095fab37eSRobert Watson ipq, &ipq->ipq_label); 265195fab37eSRobert Watson 265295fab37eSRobert Watson return (result); 265395fab37eSRobert Watson } 265495fab37eSRobert Watson 265595fab37eSRobert Watson void 265695fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 265795fab37eSRobert Watson { 265895fab37eSRobert Watson 265995fab37eSRobert Watson MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 266095fab37eSRobert Watson &ipq->ipq_label); 266195fab37eSRobert Watson } 266295fab37eSRobert Watson 266395fab37eSRobert Watson void 266495fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 266595fab37eSRobert Watson { 266695fab37eSRobert Watson 266795fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 266895fab37eSRobert Watson &mbuf->m_pkthdr.label); 266995fab37eSRobert Watson } 267095fab37eSRobert Watson 267195fab37eSRobert Watson void 267295fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 267395fab37eSRobert Watson { 267495fab37eSRobert Watson 267595fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 267695fab37eSRobert Watson &mp->mnt_fslabel); 267795fab37eSRobert Watson } 267895fab37eSRobert Watson 267995fab37eSRobert Watson void 268095fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 268195fab37eSRobert Watson { 268295fab37eSRobert Watson 268395fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 268495fab37eSRobert Watson &mp->mnt_fslabel); 268595fab37eSRobert Watson } 268695fab37eSRobert Watson 268795fab37eSRobert Watson int 268895fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 268995fab37eSRobert Watson { 269095fab37eSRobert Watson int error; 269195fab37eSRobert Watson 269295fab37eSRobert Watson if (!mac_enforce_network) 269395fab37eSRobert Watson return (0); 269495fab37eSRobert Watson 269595fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 269695fab37eSRobert Watson &ifnet->if_label); 269795fab37eSRobert Watson 269895fab37eSRobert Watson return (error); 269995fab37eSRobert Watson } 270095fab37eSRobert Watson 270195fab37eSRobert Watson static int 270295fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 270395fab37eSRobert Watson { 270495fab37eSRobert Watson int error; 270595fab37eSRobert Watson 270695fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 270795fab37eSRobert Watson 270895fab37eSRobert Watson return (error); 270995fab37eSRobert Watson } 271095fab37eSRobert Watson 271195fab37eSRobert Watson int 271295fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 271395fab37eSRobert Watson { 271495fab37eSRobert Watson int error; 271595fab37eSRobert Watson 271695fab37eSRobert Watson if (!mac_enforce_process) 271795fab37eSRobert Watson return (0); 271895fab37eSRobert Watson 271995fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 272095fab37eSRobert Watson 272195fab37eSRobert Watson return (error); 272295fab37eSRobert Watson } 272395fab37eSRobert Watson 272495fab37eSRobert Watson int 272595fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 272695fab37eSRobert Watson { 272795fab37eSRobert Watson int error; 272895fab37eSRobert Watson 272995fab37eSRobert Watson if (!mac_enforce_network) 273095fab37eSRobert Watson return (0); 273195fab37eSRobert Watson 273295fab37eSRobert Watson KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 273395fab37eSRobert Watson if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 273429e1b85fSBrooks Davis if_printf(ifnet, "not initialized\n"); 273595fab37eSRobert Watson 273695fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 273795fab37eSRobert Watson &mbuf->m_pkthdr.label); 273895fab37eSRobert Watson 273995fab37eSRobert Watson return (error); 274095fab37eSRobert Watson } 274195fab37eSRobert Watson 274295fab37eSRobert Watson int 274395fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 274495fab37eSRobert Watson { 274595fab37eSRobert Watson int error; 274695fab37eSRobert Watson 274795fab37eSRobert Watson if (!mac_enforce_fs) 274895fab37eSRobert Watson return (0); 274995fab37eSRobert Watson 275095fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 275195fab37eSRobert Watson 275295fab37eSRobert Watson return (error); 275395fab37eSRobert Watson } 275495fab37eSRobert Watson 275595fab37eSRobert Watson int 275695fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 275795fab37eSRobert Watson void *data) 275895fab37eSRobert Watson { 275995fab37eSRobert Watson int error; 276095fab37eSRobert Watson 27611aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 27621aa37f53SRobert Watson 27631aa37f53SRobert Watson if (!mac_enforce_pipe) 27641aa37f53SRobert Watson return (0); 27651aa37f53SRobert Watson 276695fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 276795fab37eSRobert Watson 276895fab37eSRobert Watson return (error); 276995fab37eSRobert Watson } 277095fab37eSRobert Watson 277195fab37eSRobert Watson int 2772c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 277395fab37eSRobert Watson { 277495fab37eSRobert Watson int error; 277595fab37eSRobert Watson 27761aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 27771aa37f53SRobert Watson 27781aa37f53SRobert Watson if (!mac_enforce_pipe) 27791aa37f53SRobert Watson return (0); 27801aa37f53SRobert Watson 2781c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2782c024c3eeSRobert Watson 2783c024c3eeSRobert Watson return (error); 2784c024c3eeSRobert Watson } 2785c024c3eeSRobert Watson 2786c024c3eeSRobert Watson int 2787c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2788c024c3eeSRobert Watson { 2789c024c3eeSRobert Watson int error; 2790c024c3eeSRobert Watson 27911aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 27921aa37f53SRobert Watson 27931aa37f53SRobert Watson if (!mac_enforce_pipe) 27941aa37f53SRobert Watson return (0); 27951aa37f53SRobert Watson 2796c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 279795fab37eSRobert Watson 279895fab37eSRobert Watson return (error); 279995fab37eSRobert Watson } 280095fab37eSRobert Watson 280195fab37eSRobert Watson static int 280295fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 280395fab37eSRobert Watson struct label *newlabel) 280495fab37eSRobert Watson { 280595fab37eSRobert Watson int error; 280695fab37eSRobert Watson 28071aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28081aa37f53SRobert Watson 28091aa37f53SRobert Watson if (!mac_enforce_pipe) 28101aa37f53SRobert Watson return (0); 28111aa37f53SRobert Watson 281295fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 281395fab37eSRobert Watson 281495fab37eSRobert Watson return (error); 281595fab37eSRobert Watson } 281695fab37eSRobert Watson 281795fab37eSRobert Watson int 2818c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2819c024c3eeSRobert Watson { 2820c024c3eeSRobert Watson int error; 2821c024c3eeSRobert Watson 28221aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28231aa37f53SRobert Watson 28241aa37f53SRobert Watson if (!mac_enforce_pipe) 28251aa37f53SRobert Watson return (0); 28261aa37f53SRobert Watson 2827c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2828c024c3eeSRobert Watson 2829c024c3eeSRobert Watson return (error); 2830c024c3eeSRobert Watson } 2831c024c3eeSRobert Watson 2832c024c3eeSRobert Watson int 2833c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2834c024c3eeSRobert Watson { 2835c024c3eeSRobert Watson int error; 2836c024c3eeSRobert Watson 28371aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28381aa37f53SRobert Watson 28391aa37f53SRobert Watson if (!mac_enforce_pipe) 28401aa37f53SRobert Watson return (0); 28411aa37f53SRobert Watson 2842c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2843c024c3eeSRobert Watson 2844c024c3eeSRobert Watson return (error); 2845c024c3eeSRobert Watson } 2846c024c3eeSRobert Watson 2847c024c3eeSRobert Watson int 284895fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 284995fab37eSRobert Watson { 285095fab37eSRobert Watson int error; 285195fab37eSRobert Watson 2852b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2853b12baf55SRobert Watson 285495fab37eSRobert Watson if (!mac_enforce_process) 285595fab37eSRobert Watson return (0); 285695fab37eSRobert Watson 285795fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 285895fab37eSRobert Watson 285995fab37eSRobert Watson return (error); 286095fab37eSRobert Watson } 286195fab37eSRobert Watson 286295fab37eSRobert Watson int 286395fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 286495fab37eSRobert Watson { 286595fab37eSRobert Watson int error; 286695fab37eSRobert Watson 2867b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2868b12baf55SRobert Watson 286995fab37eSRobert Watson if (!mac_enforce_process) 287095fab37eSRobert Watson return (0); 287195fab37eSRobert Watson 287295fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 287395fab37eSRobert Watson 287495fab37eSRobert Watson return (error); 287595fab37eSRobert Watson } 287695fab37eSRobert Watson 287795fab37eSRobert Watson int 287895fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 287995fab37eSRobert Watson { 288095fab37eSRobert Watson int error; 288195fab37eSRobert Watson 2882b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2883b12baf55SRobert Watson 288495fab37eSRobert Watson if (!mac_enforce_process) 288595fab37eSRobert Watson return (0); 288695fab37eSRobert Watson 288795fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 288895fab37eSRobert Watson 288995fab37eSRobert Watson return (error); 289095fab37eSRobert Watson } 289195fab37eSRobert Watson 289295fab37eSRobert Watson int 289395fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 289495fab37eSRobert Watson struct sockaddr *sockaddr) 289595fab37eSRobert Watson { 289695fab37eSRobert Watson int error; 289795fab37eSRobert Watson 289895fab37eSRobert Watson if (!mac_enforce_socket) 289995fab37eSRobert Watson return (0); 290095fab37eSRobert Watson 290195fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 290295fab37eSRobert Watson sockaddr); 290395fab37eSRobert Watson 290495fab37eSRobert Watson return (error); 290595fab37eSRobert Watson } 290695fab37eSRobert Watson 290795fab37eSRobert Watson int 290895fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 290995fab37eSRobert Watson struct sockaddr *sockaddr) 291095fab37eSRobert Watson { 291195fab37eSRobert Watson int error; 291295fab37eSRobert Watson 291395fab37eSRobert Watson if (!mac_enforce_socket) 291495fab37eSRobert Watson return (0); 291595fab37eSRobert Watson 291695fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 291795fab37eSRobert Watson sockaddr); 291895fab37eSRobert Watson 291995fab37eSRobert Watson return (error); 292095fab37eSRobert Watson } 292195fab37eSRobert Watson 292295fab37eSRobert Watson int 2923d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2924d61198e4SRobert Watson { 2925d61198e4SRobert Watson int error; 2926d61198e4SRobert Watson 2927d61198e4SRobert Watson if (!mac_enforce_socket) 2928d61198e4SRobert Watson return (0); 2929d61198e4SRobert Watson 2930d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2931d61198e4SRobert Watson &mbuf->m_pkthdr.label); 2932d61198e4SRobert Watson 2933d61198e4SRobert Watson return (error); 2934d61198e4SRobert Watson } 2935d61198e4SRobert Watson 2936d61198e4SRobert Watson int 293795fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 293895fab37eSRobert Watson { 293995fab37eSRobert Watson int error; 294095fab37eSRobert Watson 294195fab37eSRobert Watson if (!mac_enforce_socket) 294295fab37eSRobert Watson return (0); 294395fab37eSRobert Watson 294495fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 294595fab37eSRobert Watson return (error); 294695fab37eSRobert Watson } 294795fab37eSRobert Watson 2948b371c939SRobert Watson int 2949b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 2950b371c939SRobert Watson { 2951b371c939SRobert Watson int error; 2952b371c939SRobert Watson 2953b371c939SRobert Watson if (!mac_enforce_socket) 2954b371c939SRobert Watson return (0); 2955b371c939SRobert Watson 2956b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2957b371c939SRobert Watson 2958b371c939SRobert Watson return (error); 2959b371c939SRobert Watson } 2960b371c939SRobert Watson 296195fab37eSRobert Watson static int 296295fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 296395fab37eSRobert Watson struct label *newlabel) 296495fab37eSRobert Watson { 296595fab37eSRobert Watson int error; 296695fab37eSRobert Watson 296795fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 296895fab37eSRobert Watson newlabel); 296995fab37eSRobert Watson 297095fab37eSRobert Watson return (error); 297195fab37eSRobert Watson } 297295fab37eSRobert Watson 297395fab37eSRobert Watson int 2974b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 2975b371c939SRobert Watson { 2976b371c939SRobert Watson int error; 2977b371c939SRobert Watson 2978b371c939SRobert Watson if (!mac_enforce_socket) 2979b371c939SRobert Watson return (0); 2980b371c939SRobert Watson 2981b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2982b371c939SRobert Watson 2983b371c939SRobert Watson return (error); 2984b371c939SRobert Watson } 2985b371c939SRobert Watson 2986b371c939SRobert Watson int 298795fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 298895fab37eSRobert Watson { 298995fab37eSRobert Watson int error; 299095fab37eSRobert Watson 299195fab37eSRobert Watson if (!mac_enforce_socket) 299295fab37eSRobert Watson return (0); 299395fab37eSRobert Watson 299495fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 299595fab37eSRobert Watson 299695fab37eSRobert Watson return (error); 299795fab37eSRobert Watson } 299895fab37eSRobert Watson 299995fab37eSRobert Watson int 300003ce2c0cSRobert Watson mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 300103ce2c0cSRobert Watson { 300203ce2c0cSRobert Watson int error; 300303ce2c0cSRobert Watson 300403ce2c0cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 300503ce2c0cSRobert Watson 300603ce2c0cSRobert Watson if (!mac_enforce_fs) 300703ce2c0cSRobert Watson return (0); 300803ce2c0cSRobert Watson 300903ce2c0cSRobert Watson MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 301003ce2c0cSRobert Watson return (error); 301103ce2c0cSRobert Watson } 301203ce2c0cSRobert Watson 301303ce2c0cSRobert Watson int 301495fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 301595fab37eSRobert Watson struct ifnet *ifnet) 301695fab37eSRobert Watson { 3017f7b951a8SRobert Watson char *elements, *buffer; 3018f7b951a8SRobert Watson struct mac mac; 301995fab37eSRobert Watson int error; 302095fab37eSRobert Watson 3021f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 302295fab37eSRobert Watson if (error) 302395fab37eSRobert Watson return (error); 302495fab37eSRobert Watson 3025f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3026f7b951a8SRobert Watson if (error) 3027f7b951a8SRobert Watson return (error); 3028f7b951a8SRobert Watson 3029f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3030f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3031f7b951a8SRobert Watson if (error) { 3032f7b951a8SRobert Watson free(elements, M_MACTEMP); 3033f7b951a8SRobert Watson return (error); 3034f7b951a8SRobert Watson } 3035f7b951a8SRobert Watson 3036f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3037f7b951a8SRobert Watson error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 3038f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3039f7b951a8SRobert Watson if (error == 0) 3040f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3041f7b951a8SRobert Watson 3042f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3043f7b951a8SRobert Watson free(elements, M_MACTEMP); 3044f7b951a8SRobert Watson 3045f7b951a8SRobert Watson return (error); 304695fab37eSRobert Watson } 304795fab37eSRobert Watson 304895fab37eSRobert Watson int 304995fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 305095fab37eSRobert Watson struct ifnet *ifnet) 305195fab37eSRobert Watson { 305295fab37eSRobert Watson struct label intlabel; 3053f7b951a8SRobert Watson struct mac mac; 3054f7b951a8SRobert Watson char *buffer; 305595fab37eSRobert Watson int error; 305695fab37eSRobert Watson 3057f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 305895fab37eSRobert Watson if (error) 305995fab37eSRobert Watson return (error); 306095fab37eSRobert Watson 3061f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 306295fab37eSRobert Watson if (error) 306395fab37eSRobert Watson return (error); 306495fab37eSRobert Watson 3065f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3066f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3067f7b951a8SRobert Watson if (error) { 3068f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3069f7b951a8SRobert Watson return (error); 3070f7b951a8SRobert Watson } 3071f7b951a8SRobert Watson 3072f7b951a8SRobert Watson mac_init_ifnet_label(&intlabel); 3073f7b951a8SRobert Watson error = mac_internalize_ifnet_label(&intlabel, buffer); 3074f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3075f7b951a8SRobert Watson if (error) { 3076f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3077f7b951a8SRobert Watson return (error); 3078f7b951a8SRobert Watson } 3079f7b951a8SRobert Watson 308095fab37eSRobert Watson /* 308195fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 308295fab37eSRobert Watson * policies impose this check themselves if required by the 308395fab37eSRobert Watson * policy. Eventually, this should go away. 308495fab37eSRobert Watson */ 308595fab37eSRobert Watson error = suser_cred(cred, 0); 3086f7b951a8SRobert Watson if (error) { 3087f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3088f7b951a8SRobert Watson return (error); 3089f7b951a8SRobert Watson } 309095fab37eSRobert Watson 309195fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 309295fab37eSRobert Watson &intlabel); 3093f7b951a8SRobert Watson if (error) { 3094f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3095f7b951a8SRobert Watson return (error); 3096f7b951a8SRobert Watson } 309795fab37eSRobert Watson 309895fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 309995fab37eSRobert Watson 3100f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3101f7b951a8SRobert Watson return (0); 310295fab37eSRobert Watson } 310395fab37eSRobert Watson 310495fab37eSRobert Watson void 310595fab37eSRobert Watson mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 310695fab37eSRobert Watson { 310795fab37eSRobert Watson 310895fab37eSRobert Watson MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 310995fab37eSRobert Watson } 311095fab37eSRobert Watson 311195fab37eSRobert Watson void 311295fab37eSRobert Watson mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 311395fab37eSRobert Watson { 311495fab37eSRobert Watson 311595fab37eSRobert Watson MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 311695fab37eSRobert Watson } 311795fab37eSRobert Watson 311874e62b1bSRobert Watson void 311974e62b1bSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 312074e62b1bSRobert Watson struct devfs_dirent *de) 312174e62b1bSRobert Watson { 312274e62b1bSRobert Watson 312374e62b1bSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 312474e62b1bSRobert Watson &de->de_label); 312574e62b1bSRobert Watson } 312674e62b1bSRobert Watson 312795fab37eSRobert Watson void 312895fab37eSRobert Watson mac_create_devfs_directory(char *dirname, int dirnamelen, 312995fab37eSRobert Watson struct devfs_dirent *de) 313095fab37eSRobert Watson { 313195fab37eSRobert Watson 313295fab37eSRobert Watson MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 313395fab37eSRobert Watson &de->de_label); 313495fab37eSRobert Watson } 313595fab37eSRobert Watson 313695fab37eSRobert Watson int 313795fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 3138f7b951a8SRobert Watson struct mac *mac) 313995fab37eSRobert Watson { 314095fab37eSRobert Watson struct label intlabel; 3141f7b951a8SRobert Watson char *buffer; 314295fab37eSRobert Watson int error; 314395fab37eSRobert Watson 3144f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 314595fab37eSRobert Watson if (error) 314695fab37eSRobert Watson return (error); 314795fab37eSRobert Watson 3148f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3149f7b951a8SRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 3150f7b951a8SRobert Watson if (error) { 3151f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3152f7b951a8SRobert Watson return (error); 3153f7b951a8SRobert Watson } 3154f7b951a8SRobert Watson 3155f7b951a8SRobert Watson mac_init_socket_label(&intlabel, M_WAITOK); 3156f7b951a8SRobert Watson error = mac_internalize_socket_label(&intlabel, buffer); 3157f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3158f7b951a8SRobert Watson if (error) { 3159f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 3160f7b951a8SRobert Watson return (error); 3161f7b951a8SRobert Watson } 3162f7b951a8SRobert Watson 316395fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 316495fab37eSRobert Watson if (error) { 3165f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 316695fab37eSRobert Watson return (error); 316795fab37eSRobert Watson } 316895fab37eSRobert Watson 316995fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 317095fab37eSRobert Watson 3171f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 317295fab37eSRobert Watson return (0); 317395fab37eSRobert Watson } 317495fab37eSRobert Watson 317595fab37eSRobert Watson int 317695fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 317795fab37eSRobert Watson { 317895fab37eSRobert Watson int error; 317995fab37eSRobert Watson 31801aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31811aa37f53SRobert Watson 318295fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 318395fab37eSRobert Watson if (error) 318495fab37eSRobert Watson return (error); 318595fab37eSRobert Watson 318695fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 318795fab37eSRobert Watson 318895fab37eSRobert Watson return (0); 318995fab37eSRobert Watson } 319095fab37eSRobert Watson 319195fab37eSRobert Watson int 319295fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 3193f7b951a8SRobert Watson struct mac *mac) 319495fab37eSRobert Watson { 3195f7b951a8SRobert Watson char *buffer, *elements; 3196f7b951a8SRobert Watson int error; 319795fab37eSRobert Watson 3198f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3199f7b951a8SRobert Watson if (error) 3200f7b951a8SRobert Watson return (error); 3201f7b951a8SRobert Watson 3202f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3203f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3204f7b951a8SRobert Watson if (error) { 3205f7b951a8SRobert Watson free(elements, M_MACTEMP); 3206f7b951a8SRobert Watson return (error); 3207f7b951a8SRobert Watson } 3208f7b951a8SRobert Watson 3209f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3210f7b951a8SRobert Watson error = mac_externalize_socket_label(&so->so_label, elements, 3211f7b951a8SRobert Watson buffer, mac->m_buflen, M_WAITOK); 3212f7b951a8SRobert Watson if (error == 0) 3213f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3214f7b951a8SRobert Watson 3215f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3216f7b951a8SRobert Watson free(elements, M_MACTEMP); 3217f7b951a8SRobert Watson 3218f7b951a8SRobert Watson return (error); 321995fab37eSRobert Watson } 322095fab37eSRobert Watson 322195fab37eSRobert Watson int 322295fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 3223f7b951a8SRobert Watson struct mac *mac) 322495fab37eSRobert Watson { 3225f7b951a8SRobert Watson char *elements, *buffer; 3226f7b951a8SRobert Watson int error; 322795fab37eSRobert Watson 3228f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3229f7b951a8SRobert Watson if (error) 3230f7b951a8SRobert Watson return (error); 3231f7b951a8SRobert Watson 3232f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3233f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3234f7b951a8SRobert Watson if (error) { 3235f7b951a8SRobert Watson free(elements, M_MACTEMP); 3236f7b951a8SRobert Watson return (error); 3237f7b951a8SRobert Watson } 3238f7b951a8SRobert Watson 3239f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3240f7b951a8SRobert Watson error = mac_externalize_socket_peer_label(&so->so_peerlabel, 3241f7b951a8SRobert Watson elements, buffer, mac->m_buflen, M_WAITOK); 3242f7b951a8SRobert Watson if (error == 0) 3243f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3244f7b951a8SRobert Watson 3245f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3246f7b951a8SRobert Watson free(elements, M_MACTEMP); 3247f7b951a8SRobert Watson 3248f7b951a8SRobert Watson return (error); 324995fab37eSRobert Watson } 325095fab37eSRobert Watson 325195fab37eSRobert Watson /* 325295fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 325395fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 325495fab37eSRobert Watson * extended attributes. 325595fab37eSRobert Watson */ 325695fab37eSRobert Watson int 325795fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 325895fab37eSRobert Watson { 325995fab37eSRobert Watson struct vnode *vp = ap->a_vp; 326095fab37eSRobert Watson struct label *intlabel = ap->a_label; 326195fab37eSRobert Watson int error; 326295fab37eSRobert Watson 326395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 326495fab37eSRobert Watson 3265763bbd2fSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 3266763bbd2fSRobert Watson return (EOPNOTSUPP); 326795fab37eSRobert Watson 3268763bbd2fSRobert Watson error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 326995fab37eSRobert Watson if (error) 327095fab37eSRobert Watson return (error); 327195fab37eSRobert Watson 327295fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 327395fab37eSRobert Watson 327495fab37eSRobert Watson return (0); 327595fab37eSRobert Watson } 327695fab37eSRobert Watson 327795fab37eSRobert Watson static int 327895fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 327995fab37eSRobert Watson { 328095fab37eSRobert Watson int error; 328195fab37eSRobert Watson 328295fab37eSRobert Watson if (vp->v_mount == NULL) { 328395fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 328406be2aaaSNate Lawson if (vp->v_type != VNON) 328506be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 328695fab37eSRobert Watson return (EBADF); 328795fab37eSRobert Watson } 328895fab37eSRobert Watson 328995fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 329095fab37eSRobert Watson return (EOPNOTSUPP); 329195fab37eSRobert Watson 329295fab37eSRobert Watson /* 329395fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 329495fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 329595fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 329695fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 329795fab37eSRobert Watson */ 329895fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 329995fab37eSRobert Watson if (error) 330095fab37eSRobert Watson return (error); 330195fab37eSRobert Watson 330295fab37eSRobert Watson /* 330395fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 330495fab37eSRobert Watson * decisions about who is and is not able to modify labels 330595fab37eSRobert Watson * and protections on files. This might not be right. We can't 330695fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 330795fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 330895fab37eSRobert Watson */ 330995fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 331095fab37eSRobert Watson if (error) 331195fab37eSRobert Watson return (error); 331295fab37eSRobert Watson 331395fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 331495fab37eSRobert Watson if (error) 331595fab37eSRobert Watson return (error); 331695fab37eSRobert Watson 331795fab37eSRobert Watson return (0); 331895fab37eSRobert Watson } 331995fab37eSRobert Watson 3320f7b951a8SRobert Watson int 3321f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3322f7b951a8SRobert Watson { 3323f7b951a8SRobert Watson char *elements, *buffer; 3324f7b951a8SRobert Watson struct mac mac; 3325f7b951a8SRobert Watson struct proc *tproc; 3326f7b951a8SRobert Watson struct ucred *tcred; 3327f7b951a8SRobert Watson int error; 3328f7b951a8SRobert Watson 3329f7b951a8SRobert Watson error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 3330f7b951a8SRobert Watson if (error) 3331f7b951a8SRobert Watson return (error); 3332f7b951a8SRobert Watson 3333f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3334f7b951a8SRobert Watson if (error) 3335f7b951a8SRobert Watson return (error); 3336f7b951a8SRobert Watson 3337f7b951a8SRobert Watson tproc = pfind(uap->pid); 3338f7b951a8SRobert Watson if (tproc == NULL) 3339f7b951a8SRobert Watson return (ESRCH); 3340f7b951a8SRobert Watson 3341f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 3342f7b951a8SRobert Watson error = p_cansee(td, tproc); 3343f7b951a8SRobert Watson if (error == 0) 3344f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 3345f7b951a8SRobert Watson PROC_UNLOCK(tproc); 3346f7b951a8SRobert Watson if (error) 3347f7b951a8SRobert Watson return (error); 3348f7b951a8SRobert Watson 3349f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3350f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3351f7b951a8SRobert Watson if (error) { 3352f7b951a8SRobert Watson free(elements, M_MACTEMP); 3353f7b951a8SRobert Watson crfree(tcred); 3354f7b951a8SRobert Watson return (error); 3355f7b951a8SRobert Watson } 3356f7b951a8SRobert Watson 3357f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3358f7b951a8SRobert Watson error = mac_externalize_cred_label(&tcred->cr_label, elements, 3359f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3360f7b951a8SRobert Watson if (error == 0) 3361f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3362f7b951a8SRobert Watson 3363f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3364f7b951a8SRobert Watson free(elements, M_MACTEMP); 3365f7b951a8SRobert Watson crfree(tcred); 3366f7b951a8SRobert Watson return (error); 3367f7b951a8SRobert Watson } 3368f7b951a8SRobert Watson 336995fab37eSRobert Watson /* 337095fab37eSRobert Watson * MPSAFE 337195fab37eSRobert Watson */ 337295fab37eSRobert Watson int 337395fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 337495fab37eSRobert Watson { 3375f7b951a8SRobert Watson char *elements, *buffer; 3376f7b951a8SRobert Watson struct mac mac; 337795fab37eSRobert Watson int error; 337895fab37eSRobert Watson 3379f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3380f7b951a8SRobert Watson if (error) 3381f7b951a8SRobert Watson return (error); 338295fab37eSRobert Watson 3383f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3384f7b951a8SRobert Watson if (error) 3385f7b951a8SRobert Watson return (error); 3386f7b951a8SRobert Watson 3387f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3388f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3389f7b951a8SRobert Watson if (error) { 3390f7b951a8SRobert Watson free(elements, M_MACTEMP); 3391f7b951a8SRobert Watson return (error); 3392f7b951a8SRobert Watson } 3393f7b951a8SRobert Watson 3394f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3395f7b951a8SRobert Watson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3396f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3397f7b951a8SRobert Watson if (error == 0) 3398f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3399f7b951a8SRobert Watson 3400f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3401f7b951a8SRobert Watson free(elements, M_MACTEMP); 340295fab37eSRobert Watson return (error); 340395fab37eSRobert Watson } 340495fab37eSRobert Watson 340595fab37eSRobert Watson /* 340695fab37eSRobert Watson * MPSAFE 340795fab37eSRobert Watson */ 340895fab37eSRobert Watson int 340995fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 341095fab37eSRobert Watson { 341195fab37eSRobert Watson struct ucred *newcred, *oldcred; 341295fab37eSRobert Watson struct label intlabel; 3413f7b951a8SRobert Watson struct proc *p; 3414f7b951a8SRobert Watson struct mac mac; 3415f7b951a8SRobert Watson char *buffer; 341695fab37eSRobert Watson int error; 341795fab37eSRobert Watson 3418f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 341995fab37eSRobert Watson if (error) 342095fab37eSRobert Watson return (error); 342195fab37eSRobert Watson 3422f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 342395fab37eSRobert Watson if (error) 342495fab37eSRobert Watson return (error); 342595fab37eSRobert Watson 3426f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3427f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3428f7b951a8SRobert Watson if (error) { 3429f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3430f7b951a8SRobert Watson return (error); 3431f7b951a8SRobert Watson } 3432f7b951a8SRobert Watson 3433f7b951a8SRobert Watson mac_init_cred_label(&intlabel); 3434f7b951a8SRobert Watson error = mac_internalize_cred_label(&intlabel, buffer); 3435f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3436f7b951a8SRobert Watson if (error) { 3437f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3438f7b951a8SRobert Watson return (error); 3439f7b951a8SRobert Watson } 3440f7b951a8SRobert Watson 344195fab37eSRobert Watson newcred = crget(); 344295fab37eSRobert Watson 344395fab37eSRobert Watson p = td->td_proc; 344495fab37eSRobert Watson PROC_LOCK(p); 344595fab37eSRobert Watson oldcred = p->p_ucred; 344695fab37eSRobert Watson 344795fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 344895fab37eSRobert Watson if (error) { 344995fab37eSRobert Watson PROC_UNLOCK(p); 345095fab37eSRobert Watson crfree(newcred); 3451f7b951a8SRobert Watson goto out; 345295fab37eSRobert Watson } 345395fab37eSRobert Watson 345495fab37eSRobert Watson setsugid(p); 345595fab37eSRobert Watson crcopy(newcred, oldcred); 345695fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 345795fab37eSRobert Watson p->p_ucred = newcred; 3458e5cb5e37SRobert Watson 3459e5cb5e37SRobert Watson /* 3460e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3461e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3462e5cb5e37SRobert Watson */ 3463e5cb5e37SRobert Watson crhold(newcred); 346495fab37eSRobert Watson PROC_UNLOCK(p); 3465e5cb5e37SRobert Watson 3466f7b951a8SRobert Watson if (mac_enforce_vm) { 346716140035SRobert Watson mtx_lock(&Giant); 3468e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 346916140035SRobert Watson mtx_unlock(&Giant); 3470f7b951a8SRobert Watson } 3471e5cb5e37SRobert Watson 3472e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 347395fab37eSRobert Watson crfree(oldcred); 3474f7b951a8SRobert Watson 3475f7b951a8SRobert Watson out: 3476f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3477f7b951a8SRobert Watson return (error); 347895fab37eSRobert Watson } 347995fab37eSRobert Watson 348095fab37eSRobert Watson /* 348195fab37eSRobert Watson * MPSAFE 348295fab37eSRobert Watson */ 348395fab37eSRobert Watson int 348495fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 348595fab37eSRobert Watson { 3486f7b951a8SRobert Watson char *elements, *buffer; 3487f7b951a8SRobert Watson struct label intlabel; 348895fab37eSRobert Watson struct file *fp; 3489f7b951a8SRobert Watson struct mac mac; 349095fab37eSRobert Watson struct vnode *vp; 349195fab37eSRobert Watson struct pipe *pipe; 3492f7b951a8SRobert Watson short label_type; 349395fab37eSRobert Watson int error; 349495fab37eSRobert Watson 3495f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3496f7b951a8SRobert Watson if (error) 3497f7b951a8SRobert Watson return (error); 349895fab37eSRobert Watson 3499f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3500f7b951a8SRobert Watson if (error) 3501f7b951a8SRobert Watson return (error); 3502f7b951a8SRobert Watson 3503f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3504f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3505f7b951a8SRobert Watson if (error) { 3506f7b951a8SRobert Watson free(elements, M_MACTEMP); 3507f7b951a8SRobert Watson return (error); 3508f7b951a8SRobert Watson } 3509f7b951a8SRobert Watson 3510f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3511f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 351295fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 351395fab37eSRobert Watson if (error) 351495fab37eSRobert Watson goto out; 351595fab37eSRobert Watson 3516f7b951a8SRobert Watson label_type = fp->f_type; 351795fab37eSRobert Watson switch (fp->f_type) { 351895fab37eSRobert Watson case DTYPE_FIFO: 351995fab37eSRobert Watson case DTYPE_VNODE: 352095fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 352195fab37eSRobert Watson 3522f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3523f7b951a8SRobert Watson 352495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3525f7b951a8SRobert Watson mac_copy_vnode_label(&vp->v_label, &intlabel); 352695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 3527f7b951a8SRobert Watson 352895fab37eSRobert Watson break; 352995fab37eSRobert Watson case DTYPE_PIPE: 353095fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 3531f7b951a8SRobert Watson 3532f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3533f7b951a8SRobert Watson 3534f7b951a8SRobert Watson PIPE_LOCK(pipe); 3535f7b951a8SRobert Watson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3536f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 353795fab37eSRobert Watson break; 353895fab37eSRobert Watson default: 353995fab37eSRobert Watson error = EINVAL; 3540f7b951a8SRobert Watson fdrop(fp, td); 3541f7b951a8SRobert Watson goto out; 3542f7b951a8SRobert Watson } 3543f7b951a8SRobert Watson fdrop(fp, td); 3544f7b951a8SRobert Watson 3545f7b951a8SRobert Watson switch (label_type) { 3546f7b951a8SRobert Watson case DTYPE_FIFO: 3547f7b951a8SRobert Watson case DTYPE_VNODE: 3548f7b951a8SRobert Watson if (error == 0) 3549f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, 3550f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3551f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3552f7b951a8SRobert Watson break; 3553f7b951a8SRobert Watson case DTYPE_PIPE: 3554f7b951a8SRobert Watson error = mac_externalize_pipe_label(&intlabel, elements, 3555f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3556f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 3557f7b951a8SRobert Watson break; 3558f7b951a8SRobert Watson default: 3559f7b951a8SRobert Watson panic("__mac_get_fd: corrupted label_type"); 356095fab37eSRobert Watson } 356195fab37eSRobert Watson 356295fab37eSRobert Watson if (error == 0) 3563f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 356495fab37eSRobert Watson 356595fab37eSRobert Watson out: 3566f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3567f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3568f7b951a8SRobert Watson free(elements, M_MACTEMP); 3569f7b951a8SRobert Watson 357095fab37eSRobert Watson return (error); 357195fab37eSRobert Watson } 357295fab37eSRobert Watson 357395fab37eSRobert Watson /* 357495fab37eSRobert Watson * MPSAFE 357595fab37eSRobert Watson */ 357695fab37eSRobert Watson int 357795fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 357895fab37eSRobert Watson { 3579f7b951a8SRobert Watson char *elements, *buffer; 358095fab37eSRobert Watson struct nameidata nd; 3581f7b951a8SRobert Watson struct label intlabel; 3582f7b951a8SRobert Watson struct mac mac; 358395fab37eSRobert Watson int error; 358495fab37eSRobert Watson 3585f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3586f7b951a8SRobert Watson if (error) 3587f7b951a8SRobert Watson return (error); 3588f7b951a8SRobert Watson 3589f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3590f7b951a8SRobert Watson if (error) 3591f7b951a8SRobert Watson return (error); 3592f7b951a8SRobert Watson 3593f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3594f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3595f7b951a8SRobert Watson if (error) { 3596f7b951a8SRobert Watson free(elements, M_MACTEMP); 3597f7b951a8SRobert Watson return (error); 3598f7b951a8SRobert Watson } 3599f7b951a8SRobert Watson 3600f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3601f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3602f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3603f7b951a8SRobert Watson td); 360495fab37eSRobert Watson error = namei(&nd); 360595fab37eSRobert Watson if (error) 360695fab37eSRobert Watson goto out; 360795fab37eSRobert Watson 3608f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3609f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3610763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3611763bbd2fSRobert Watson mac.m_buflen, M_WAITOK); 3612f7b951a8SRobert Watson 361395fab37eSRobert Watson NDFREE(&nd, 0); 3614f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3615f7b951a8SRobert Watson 3616f7b951a8SRobert Watson if (error == 0) 3617f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3618f7b951a8SRobert Watson 3619f7b951a8SRobert Watson out: 3620f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3621f7b951a8SRobert Watson 3622f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3623f7b951a8SRobert Watson free(elements, M_MACTEMP); 3624f7b951a8SRobert Watson 3625f7b951a8SRobert Watson return (error); 3626f7b951a8SRobert Watson } 3627f7b951a8SRobert Watson 3628f7b951a8SRobert Watson /* 3629f7b951a8SRobert Watson * MPSAFE 3630f7b951a8SRobert Watson */ 3631f7b951a8SRobert Watson int 3632f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3633f7b951a8SRobert Watson { 3634f7b951a8SRobert Watson char *elements, *buffer; 3635f7b951a8SRobert Watson struct nameidata nd; 3636f7b951a8SRobert Watson struct label intlabel; 3637f7b951a8SRobert Watson struct mac mac; 3638f7b951a8SRobert Watson int error; 3639f7b951a8SRobert Watson 3640f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3641f7b951a8SRobert Watson if (error) 3642f7b951a8SRobert Watson return (error); 3643f7b951a8SRobert Watson 3644f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3645f7b951a8SRobert Watson if (error) 3646f7b951a8SRobert Watson return (error); 3647f7b951a8SRobert Watson 3648f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3649f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3650f7b951a8SRobert Watson if (error) { 3651f7b951a8SRobert Watson free(elements, M_MACTEMP); 3652f7b951a8SRobert Watson return (error); 3653f7b951a8SRobert Watson } 3654f7b951a8SRobert Watson 3655f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3656f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3657f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3658f7b951a8SRobert Watson td); 3659f7b951a8SRobert Watson error = namei(&nd); 366095fab37eSRobert Watson if (error) 366195fab37eSRobert Watson goto out; 366295fab37eSRobert Watson 3663f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3664f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3665763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3666763bbd2fSRobert Watson mac.m_buflen, M_WAITOK); 3667f7b951a8SRobert Watson NDFREE(&nd, 0); 3668f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3669f7b951a8SRobert Watson 3670f7b951a8SRobert Watson if (error == 0) 3671f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 367295fab37eSRobert Watson 367395fab37eSRobert Watson out: 3674f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3675f7b951a8SRobert Watson 3676f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3677f7b951a8SRobert Watson free(elements, M_MACTEMP); 3678f7b951a8SRobert Watson 367995fab37eSRobert Watson return (error); 368095fab37eSRobert Watson } 368195fab37eSRobert Watson 368295fab37eSRobert Watson /* 368395fab37eSRobert Watson * MPSAFE 368495fab37eSRobert Watson */ 368595fab37eSRobert Watson int 368695fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 368795fab37eSRobert Watson { 368895fab37eSRobert Watson struct label intlabel; 3689f7b951a8SRobert Watson struct pipe *pipe; 3690f7b951a8SRobert Watson struct file *fp; 369195fab37eSRobert Watson struct mount *mp; 369295fab37eSRobert Watson struct vnode *vp; 3693f7b951a8SRobert Watson struct mac mac; 3694f7b951a8SRobert Watson char *buffer; 369595fab37eSRobert Watson int error; 369695fab37eSRobert Watson 3697f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3698f7b951a8SRobert Watson if (error) 3699f7b951a8SRobert Watson return (error); 3700f7b951a8SRobert Watson 3701f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3702f7b951a8SRobert Watson if (error) 3703f7b951a8SRobert Watson return (error); 3704f7b951a8SRobert Watson 3705f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3706f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3707f7b951a8SRobert Watson if (error) { 3708f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3709f7b951a8SRobert Watson return (error); 3710f7b951a8SRobert Watson } 3711f7b951a8SRobert Watson 3712f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3713f7b951a8SRobert Watson 371495fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 371595fab37eSRobert Watson if (error) 3716f7b951a8SRobert Watson goto out; 371795fab37eSRobert Watson 371895fab37eSRobert Watson switch (fp->f_type) { 371995fab37eSRobert Watson case DTYPE_FIFO: 372095fab37eSRobert Watson case DTYPE_VNODE: 3721f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3722f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3723f7b951a8SRobert Watson if (error) { 3724f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3725f7b951a8SRobert Watson break; 3726f7b951a8SRobert Watson } 3727f7b951a8SRobert Watson 372895fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 372995fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3730f7b951a8SRobert Watson if (error != 0) { 3731f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 373295fab37eSRobert Watson break; 3733f7b951a8SRobert Watson } 373495fab37eSRobert Watson 373595fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 373695fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 373795fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 373895fab37eSRobert Watson vn_finished_write(mp); 3739f7b951a8SRobert Watson 3740f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 374195fab37eSRobert Watson break; 3742f7b951a8SRobert Watson 374395fab37eSRobert Watson case DTYPE_PIPE: 3744f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3745f7b951a8SRobert Watson error = mac_internalize_pipe_label(&intlabel, buffer); 3746f7b951a8SRobert Watson if (error == 0) { 374795fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 37481aa37f53SRobert Watson PIPE_LOCK(pipe); 3749f7b951a8SRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, 3750f7b951a8SRobert Watson &intlabel); 37511aa37f53SRobert Watson PIPE_UNLOCK(pipe); 3752f7b951a8SRobert Watson } 3753f7b951a8SRobert Watson 3754f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 375595fab37eSRobert Watson break; 3756f7b951a8SRobert Watson 375795fab37eSRobert Watson default: 375895fab37eSRobert Watson error = EINVAL; 375995fab37eSRobert Watson } 376095fab37eSRobert Watson 376195fab37eSRobert Watson fdrop(fp, td); 3762f7b951a8SRobert Watson out: 3763f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3764f7b951a8SRobert Watson 3765f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3766f7b951a8SRobert Watson 376795fab37eSRobert Watson return (error); 376895fab37eSRobert Watson } 376995fab37eSRobert Watson 377095fab37eSRobert Watson /* 377195fab37eSRobert Watson * MPSAFE 377295fab37eSRobert Watson */ 377395fab37eSRobert Watson int 377495fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 377595fab37eSRobert Watson { 377695fab37eSRobert Watson struct label intlabel; 3777f7b951a8SRobert Watson struct nameidata nd; 377895fab37eSRobert Watson struct mount *mp; 3779f7b951a8SRobert Watson struct mac mac; 3780f7b951a8SRobert Watson char *buffer; 378195fab37eSRobert Watson int error; 378295fab37eSRobert Watson 3783f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 378495fab37eSRobert Watson if (error) 3785f7b951a8SRobert Watson return (error); 378695fab37eSRobert Watson 3787f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 378895fab37eSRobert Watson if (error) 3789f7b951a8SRobert Watson return (error); 379095fab37eSRobert Watson 3791f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3792f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3793f7b951a8SRobert Watson if (error) { 3794f7b951a8SRobert Watson free(buffer, M_MACTEMP); 379595fab37eSRobert Watson return (error); 379695fab37eSRobert Watson } 379795fab37eSRobert Watson 3798f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3799f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3800f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3801f7b951a8SRobert Watson if (error) { 3802f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3803f7b951a8SRobert Watson return (error); 3804f7b951a8SRobert Watson } 3805f7b951a8SRobert Watson 3806f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3807f7b951a8SRobert Watson 3808f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3809f7b951a8SRobert Watson td); 3810f7b951a8SRobert Watson error = namei(&nd); 3811f7b951a8SRobert Watson if (error == 0) { 3812f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3813f7b951a8SRobert Watson if (error == 0) 3814f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3815f7b951a8SRobert Watson td->td_ucred); 3816f7b951a8SRobert Watson vn_finished_write(mp); 3817f7b951a8SRobert Watson } 3818f7b951a8SRobert Watson 3819f7b951a8SRobert Watson NDFREE(&nd, 0); 3820f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3821f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3822f7b951a8SRobert Watson 3823f7b951a8SRobert Watson return (error); 3824f7b951a8SRobert Watson } 3825f7b951a8SRobert Watson 3826f7b951a8SRobert Watson /* 3827f7b951a8SRobert Watson * MPSAFE 3828f7b951a8SRobert Watson */ 3829f7b951a8SRobert Watson int 3830f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3831f7b951a8SRobert Watson { 3832f7b951a8SRobert Watson struct label intlabel; 3833f7b951a8SRobert Watson struct nameidata nd; 3834f7b951a8SRobert Watson struct mount *mp; 3835f7b951a8SRobert Watson struct mac mac; 3836f7b951a8SRobert Watson char *buffer; 3837f7b951a8SRobert Watson int error; 3838f7b951a8SRobert Watson 3839f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3840f7b951a8SRobert Watson if (error) 3841f7b951a8SRobert Watson return (error); 3842f7b951a8SRobert Watson 3843f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3844f7b951a8SRobert Watson if (error) 3845f7b951a8SRobert Watson return (error); 3846f7b951a8SRobert Watson 3847f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3848f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3849f7b951a8SRobert Watson if (error) { 3850f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3851f7b951a8SRobert Watson return (error); 3852f7b951a8SRobert Watson } 3853f7b951a8SRobert Watson 3854f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3855f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3856f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3857f7b951a8SRobert Watson if (error) { 3858f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3859f7b951a8SRobert Watson return (error); 3860f7b951a8SRobert Watson } 3861f7b951a8SRobert Watson 3862f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3863f7b951a8SRobert Watson 3864f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3865f7b951a8SRobert Watson td); 3866f7b951a8SRobert Watson error = namei(&nd); 3867f7b951a8SRobert Watson if (error == 0) { 3868f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3869f7b951a8SRobert Watson if (error == 0) 3870f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3871f7b951a8SRobert Watson td->td_ucred); 3872f7b951a8SRobert Watson vn_finished_write(mp); 3873f7b951a8SRobert Watson } 3874f7b951a8SRobert Watson 3875f7b951a8SRobert Watson NDFREE(&nd, 0); 3876f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3877f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3878f7b951a8SRobert Watson 3879f7b951a8SRobert Watson return (error); 3880f7b951a8SRobert Watson } 3881f7b951a8SRobert Watson 3882f7b951a8SRobert Watson /* 3883f7b951a8SRobert Watson * MPSAFE 3884f7b951a8SRobert Watson */ 388527f2eac7SRobert Watson int 388627f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 388727f2eac7SRobert Watson { 388827f2eac7SRobert Watson struct mac_policy_conf *mpc; 388927f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 389027f2eac7SRobert Watson int error; 389127f2eac7SRobert Watson 389227f2eac7SRobert Watson error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 389327f2eac7SRobert Watson if (error) 389427f2eac7SRobert Watson return (error); 389527f2eac7SRobert Watson 389627f2eac7SRobert Watson error = ENOSYS; 389727f2eac7SRobert Watson MAC_POLICY_LIST_BUSY(); 389827f2eac7SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 389927f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 390027f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 390127f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 390227f2eac7SRobert Watson SCARG(uap, call), SCARG(uap, arg)); 390327f2eac7SRobert Watson goto out; 390427f2eac7SRobert Watson } 390527f2eac7SRobert Watson } 390627f2eac7SRobert Watson 390727f2eac7SRobert Watson out: 390827f2eac7SRobert Watson MAC_POLICY_LIST_UNBUSY(); 390927f2eac7SRobert Watson return (error); 391027f2eac7SRobert Watson } 391127f2eac7SRobert Watson 391295fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 391395fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 391495fab37eSRobert Watson 391595fab37eSRobert Watson #else /* !MAC */ 39167bc82500SRobert Watson 39177bc82500SRobert Watson int 3918f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3919f7b951a8SRobert Watson { 3920f7b951a8SRobert Watson 3921f7b951a8SRobert Watson return (ENOSYS); 3922f7b951a8SRobert Watson } 3923f7b951a8SRobert Watson 3924f7b951a8SRobert Watson int 39257bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 39267bc82500SRobert Watson { 39277bc82500SRobert Watson 39287bc82500SRobert Watson return (ENOSYS); 39297bc82500SRobert Watson } 39307bc82500SRobert Watson 39317bc82500SRobert Watson int 39327bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 39337bc82500SRobert Watson { 39347bc82500SRobert Watson 39357bc82500SRobert Watson return (ENOSYS); 39367bc82500SRobert Watson } 39377bc82500SRobert Watson 39387bc82500SRobert Watson int 39397bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 39407bc82500SRobert Watson { 39417bc82500SRobert Watson 39427bc82500SRobert Watson return (ENOSYS); 39437bc82500SRobert Watson } 39447bc82500SRobert Watson 39457bc82500SRobert Watson int 39467bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 39477bc82500SRobert Watson { 39487bc82500SRobert Watson 39497bc82500SRobert Watson return (ENOSYS); 39507bc82500SRobert Watson } 39517bc82500SRobert Watson 39527bc82500SRobert Watson int 3953f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3954f7b951a8SRobert Watson { 3955f7b951a8SRobert Watson 3956f7b951a8SRobert Watson return (ENOSYS); 3957f7b951a8SRobert Watson } 3958f7b951a8SRobert Watson 3959f7b951a8SRobert Watson int 39607bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 39617bc82500SRobert Watson { 39627bc82500SRobert Watson 39637bc82500SRobert Watson return (ENOSYS); 39647bc82500SRobert Watson } 39657bc82500SRobert Watson 39667bc82500SRobert Watson int 39677bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 39687bc82500SRobert Watson { 39697bc82500SRobert Watson 39707bc82500SRobert Watson return (ENOSYS); 39717bc82500SRobert Watson } 397295fab37eSRobert Watson 397327f2eac7SRobert Watson int 3974f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3975f7b951a8SRobert Watson { 3976f7b951a8SRobert Watson 3977f7b951a8SRobert Watson return (ENOSYS); 3978f7b951a8SRobert Watson } 3979f7b951a8SRobert Watson 3980f7b951a8SRobert Watson int 398127f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 398227f2eac7SRobert Watson { 398327f2eac7SRobert Watson 398427f2eac7SRobert Watson return (ENOSYS); 398527f2eac7SRobert Watson } 398627f2eac7SRobert Watson 3987f7b951a8SRobert Watson #endif 3988