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 11895fab37eSRobert Watson static int mac_enforce_fs = 1; 11995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 12095fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 12195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 12295fab37eSRobert Watson 12395fab37eSRobert Watson static int mac_enforce_network = 1; 12495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 12595fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 12695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 12795fab37eSRobert Watson 128b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 129b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 130b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 131c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 132b88c98f6SRobert Watson 13395fab37eSRobert Watson static int mac_enforce_process = 1; 13495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 13595fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 13695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 13795fab37eSRobert Watson 13895fab37eSRobert Watson static int mac_enforce_socket = 1; 13995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 14095fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 14195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 14295fab37eSRobert Watson 143ca7850c3SRobert Watson static int mac_enforce_vm = 1; 144ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 145ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 146c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 147ca7850c3SRobert Watson 1482789e47eSRobert Watson static int mac_label_size = sizeof(struct oldmac); 14995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, 15095fab37eSRobert Watson &mac_label_size, 0, "Pre-compiled MAC label size"); 15195fab37eSRobert Watson 15295fab37eSRobert Watson static int mac_cache_fslabel_in_vnode = 1; 15395fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, 15495fab37eSRobert Watson &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); 15595fab37eSRobert Watson TUNABLE_INT("security.mac.cache_fslabel_in_vnode", 15695fab37eSRobert Watson &mac_cache_fslabel_in_vnode); 15795fab37eSRobert Watson 15895fab37eSRobert Watson static int mac_vnode_label_cache_hits = 0; 15995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, 16095fab37eSRobert Watson &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); 16195fab37eSRobert Watson static int mac_vnode_label_cache_misses = 0; 16295fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, 16395fab37eSRobert Watson &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); 164c0f39905SRobert Watson 165c0f39905SRobert Watson static int mac_mmap_revocation = 1; 166c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 167c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 168c0f39905SRobert Watson "relabel"); 16999fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 17095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 17195fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 17295fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 17395fab37eSRobert Watson 174f050add5SRobert Watson #ifdef MAC_DEBUG 1756be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1766be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1776be0c25eSRobert Watson 1786be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1796be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1806be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1816be0c25eSRobert Watson "when label is corrupted."); 1826be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1836be0c25eSRobert Watson &mac_debug_label_fallback); 1846be0c25eSRobert Watson 185b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 186b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 187b2f0927aSRobert Watson 18895fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 18995fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 19095fab37eSRobert Watson nmacipqs, nmacpipes; 191b2f0927aSRobert Watson 192b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 19395fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 194b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 19595fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 196b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 19795fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 198b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 19995fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 200b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 20195fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 202b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 20395fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 204b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 20595fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 206b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 20795fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 208b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 20995fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 210b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 21195fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 212b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 21395fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 214f050add5SRobert Watson #endif 21595fab37eSRobert Watson 21695fab37eSRobert Watson static int error_select(int error1, int error2); 217f7b951a8SRobert Watson static int mac_externalize_vnode_oldmac(struct label *label, 218f7b951a8SRobert Watson struct oldmac *extmac); 21995fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 22095fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 22195fab37eSRobert Watson 22295fab37eSRobert Watson static int mac_stdcreatevnode_ea(struct vnode *vp); 223e183f80eSRobert Watson static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 224e183f80eSRobert Watson struct vnode *vp, int *prot); 22595fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 22695fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 22795fab37eSRobert Watson 22883985c26SRobert Watson static void mac_destroy_socket_label(struct label *label); 22983985c26SRobert Watson 23095fab37eSRobert Watson MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); 23195fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 232f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 23395fab37eSRobert Watson 23495fab37eSRobert Watson /* 23595fab37eSRobert Watson * mac_policy_list_lock protects the consistency of 'mac_policy_list', 23695fab37eSRobert Watson * the linked list of attached policy modules. Read-only consumers of 23795fab37eSRobert Watson * the list must acquire a shared lock for the duration of their use; 23895fab37eSRobert Watson * writers must acquire an exclusive lock. Note that for compound 23995fab37eSRobert Watson * operations, locks should be held for the entire compound operation, 24095fab37eSRobert Watson * and that this is not yet done for relabel requests. 24195fab37eSRobert Watson */ 24295fab37eSRobert Watson static struct mtx mac_policy_list_lock; 24395fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 24495fab37eSRobert Watson static int mac_policy_list_busy; 24595fab37eSRobert Watson #define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \ 24695fab37eSRobert Watson "mac_policy_list_lock", NULL, MTX_DEF); 24795fab37eSRobert Watson #define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock); 24895fab37eSRobert Watson #define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock); 24995fab37eSRobert Watson 25095fab37eSRobert Watson #define MAC_POLICY_LIST_BUSY() do { \ 25195fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 25295fab37eSRobert Watson mac_policy_list_busy++; \ 25395fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 25495fab37eSRobert Watson } while (0) 25595fab37eSRobert Watson 25695fab37eSRobert Watson #define MAC_POLICY_LIST_UNBUSY() do { \ 25795fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 25895fab37eSRobert Watson mac_policy_list_busy--; \ 25995fab37eSRobert Watson if (mac_policy_list_busy < 0) \ 26095fab37eSRobert Watson panic("Extra mac_policy_list_busy--"); \ 26195fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 26295fab37eSRobert Watson } while (0) 26395fab37eSRobert Watson 26495fab37eSRobert Watson /* 26595fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 26695fab37eSRobert Watson * module list and checking with each as to how it feels about the 26795fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 26895fab37eSRobert Watson * of the caller. 26995fab37eSRobert Watson */ 27095fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 27195fab37eSRobert Watson struct mac_policy_conf *mpc; \ 27295fab37eSRobert Watson \ 27395fab37eSRobert Watson error = 0; \ 27495fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 27595fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 27695fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 27795fab37eSRobert Watson error = error_select( \ 27895fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 27995fab37eSRobert Watson error); \ 28095fab37eSRobert Watson } \ 28195fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 28295fab37eSRobert Watson } while (0) 28395fab37eSRobert Watson 28495fab37eSRobert Watson /* 28595fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 28695fab37eSRobert Watson * the module list, invoking each instance of the operation, and 28795fab37eSRobert Watson * combining the results using the passed C operator. Note that it 28895fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 28995fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 29095fab37eSRobert Watson * a meaningful result. 29195fab37eSRobert Watson */ 29295fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 29395fab37eSRobert Watson struct mac_policy_conf *mpc; \ 29495fab37eSRobert Watson \ 29595fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 29695fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 29795fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 29895fab37eSRobert Watson result = result composition \ 29995fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 30095fab37eSRobert Watson } \ 30195fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 30295fab37eSRobert Watson } while (0) 30395fab37eSRobert Watson 304f7b951a8SRobert Watson #define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 305f7b951a8SRobert Watson outbuflen) do { \ 306f7b951a8SRobert Watson char *curptr, *curptr_start, *element_name, *element_temp; \ 307f7b951a8SRobert Watson size_t left, left_start, len; \ 308f7b951a8SRobert Watson int claimed, first, first_start, ignorenotfound; \ 309f7b951a8SRobert Watson \ 310f7b951a8SRobert Watson error = 0; \ 311f7b951a8SRobert Watson element_temp = elementlist; \ 312f7b951a8SRobert Watson curptr = outbuf; \ 313f7b951a8SRobert Watson curptr[0] = '\0'; \ 314f7b951a8SRobert Watson left = outbuflen; \ 315f7b951a8SRobert Watson first = 1; \ 316f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 317f7b951a8SRobert Watson curptr_start = curptr; \ 318f7b951a8SRobert Watson left_start = left; \ 319f7b951a8SRobert Watson first_start = first; \ 320f7b951a8SRobert Watson if (element_name[0] == '?') { \ 321f7b951a8SRobert Watson element_name++; \ 322f7b951a8SRobert Watson ignorenotfound = 1; \ 323f7b951a8SRobert Watson } else \ 324f7b951a8SRobert Watson ignorenotfound = 0; \ 325f7b951a8SRobert Watson claimed = 0; \ 326f7b951a8SRobert Watson if (first) { \ 327f7b951a8SRobert Watson len = snprintf(curptr, left, "%s/", \ 328f7b951a8SRobert Watson element_name); \ 329f7b951a8SRobert Watson first = 0; \ 330f7b951a8SRobert Watson } else \ 331f7b951a8SRobert Watson len = snprintf(curptr, left, ",%s/", \ 332f7b951a8SRobert Watson element_name); \ 333f7b951a8SRobert Watson if (len >= left) { \ 334f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 335f7b951a8SRobert Watson break; \ 336f7b951a8SRobert Watson } \ 337f7b951a8SRobert Watson curptr += len; \ 338f7b951a8SRobert Watson left -= len; \ 339f7b951a8SRobert Watson \ 340f7b951a8SRobert Watson MAC_CHECK(externalize_ ## type, label, element_name, \ 341f7b951a8SRobert Watson curptr, left, &len, &claimed); \ 342f7b951a8SRobert Watson if (error) \ 343f7b951a8SRobert Watson break; \ 344f7b951a8SRobert Watson if (claimed == 1) { \ 345f7b951a8SRobert Watson if (len >= outbuflen) { \ 346f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 347f7b951a8SRobert Watson break; \ 348f7b951a8SRobert Watson } \ 349f7b951a8SRobert Watson curptr += len; \ 350f7b951a8SRobert Watson left -= len; \ 351f7b951a8SRobert Watson } else if (claimed == 0 && ignorenotfound) { \ 352f7b951a8SRobert Watson /* \ 353f7b951a8SRobert Watson * Revert addition of the label element \ 354f7b951a8SRobert Watson * name. \ 355f7b951a8SRobert Watson */ \ 356f7b951a8SRobert Watson curptr = curptr_start; \ 357f7b951a8SRobert Watson *curptr = '\0'; \ 358f7b951a8SRobert Watson left = left_start; \ 359f7b951a8SRobert Watson first = first_start; \ 360f7b951a8SRobert Watson } else { \ 361f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: ENOLABEL */ \ 362f7b951a8SRobert Watson break; \ 363f7b951a8SRobert Watson } \ 364f7b951a8SRobert Watson } \ 365f7b951a8SRobert Watson } while (0) 366f7b951a8SRobert Watson 367f7b951a8SRobert Watson #define MAC_INTERNALIZE(type, label, instring) do { \ 368f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 369f7b951a8SRobert Watson int claimed; \ 370f7b951a8SRobert Watson \ 371f7b951a8SRobert Watson error = 0; \ 372f7b951a8SRobert Watson element = instring; \ 373f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 374f7b951a8SRobert Watson element_data = element_name; \ 375f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 376f7b951a8SRobert Watson if (element_data == NULL) { \ 377f7b951a8SRobert Watson error = EINVAL; \ 378f7b951a8SRobert Watson break; \ 379f7b951a8SRobert Watson } \ 380f7b951a8SRobert Watson claimed = 0; \ 381f7b951a8SRobert Watson MAC_CHECK(internalize_ ## type, label, element_name, \ 382f7b951a8SRobert Watson element_data, &claimed); \ 383f7b951a8SRobert Watson if (error) \ 384f7b951a8SRobert Watson break; \ 385f7b951a8SRobert Watson if (claimed != 1) { \ 386f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 387f7b951a8SRobert Watson error = EINVAL; \ 388f7b951a8SRobert Watson break; \ 389f7b951a8SRobert Watson } \ 390f7b951a8SRobert Watson } \ 391f7b951a8SRobert Watson } while (0) 392f7b951a8SRobert Watson 39395fab37eSRobert Watson /* 39495fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 39595fab37eSRobert Watson * module list and invoking that operation for each policy. 39695fab37eSRobert Watson */ 39795fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 39895fab37eSRobert Watson struct mac_policy_conf *mpc; \ 39995fab37eSRobert Watson \ 40095fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 40195fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 40295fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 40395fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 40495fab37eSRobert Watson } \ 40595fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 40695fab37eSRobert Watson } while (0) 40795fab37eSRobert Watson 40895fab37eSRobert Watson /* 40995fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 41095fab37eSRobert Watson */ 41195fab37eSRobert Watson static void 41295fab37eSRobert Watson mac_init(void) 41395fab37eSRobert Watson { 41495fab37eSRobert Watson 41595fab37eSRobert Watson LIST_INIT(&mac_policy_list); 41695fab37eSRobert Watson MAC_POLICY_LIST_LOCKINIT(); 41795fab37eSRobert Watson } 41895fab37eSRobert Watson 41995fab37eSRobert Watson /* 42095fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 42195fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 42295fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 42395fab37eSRobert Watson */ 42495fab37eSRobert Watson static void 42595fab37eSRobert Watson mac_late_init(void) 42695fab37eSRobert Watson { 42795fab37eSRobert Watson 42895fab37eSRobert Watson mac_late = 1; 42995fab37eSRobert Watson } 43095fab37eSRobert Watson 43195fab37eSRobert Watson /* 43295fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 43395fab37eSRobert Watson */ 43495fab37eSRobert Watson int 43595fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 43695fab37eSRobert Watson { 43795fab37eSRobert Watson struct mac_policy_conf *mpc; 43895fab37eSRobert Watson int error; 43995fab37eSRobert Watson 44095fab37eSRobert Watson error = 0; 44195fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 44295fab37eSRobert Watson 44395fab37eSRobert Watson switch (type) { 44495fab37eSRobert Watson case MOD_LOAD: 44595fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 44695fab37eSRobert Watson mac_late) { 44795fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 44895fab37eSRobert Watson "after booting\n", mpc->mpc_name); 44995fab37eSRobert Watson error = EBUSY; 45095fab37eSRobert Watson break; 45195fab37eSRobert Watson } 45295fab37eSRobert Watson error = mac_policy_register(mpc); 45395fab37eSRobert Watson break; 45495fab37eSRobert Watson case MOD_UNLOAD: 45595fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 45695fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 45795fab37eSRobert Watson != 0) 45895fab37eSRobert Watson error = mac_policy_unregister(mpc); 45995fab37eSRobert Watson else 46095fab37eSRobert Watson error = 0; 46195fab37eSRobert Watson break; 46295fab37eSRobert Watson default: 46395fab37eSRobert Watson break; 46495fab37eSRobert Watson } 46595fab37eSRobert Watson 46695fab37eSRobert Watson return (error); 46795fab37eSRobert Watson } 46895fab37eSRobert Watson 46995fab37eSRobert Watson static int 47095fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 47195fab37eSRobert Watson { 47295fab37eSRobert Watson struct mac_policy_conf *tmpc; 47395fab37eSRobert Watson struct mac_policy_op_entry *mpe; 47495fab37eSRobert Watson int slot; 47595fab37eSRobert Watson 476cc51a2b5SRobert Watson MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops), 477cc51a2b5SRobert Watson M_MACOPVEC, M_WAITOK | M_ZERO); 47895fab37eSRobert Watson for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) { 47995fab37eSRobert Watson switch (mpe->mpe_constant) { 48095fab37eSRobert Watson case MAC_OP_LAST: 48195fab37eSRobert Watson /* 48295fab37eSRobert Watson * Doesn't actually happen, but this allows checking 48395fab37eSRobert Watson * that all enumerated values are handled. 48495fab37eSRobert Watson */ 48595fab37eSRobert Watson break; 48695fab37eSRobert Watson case MAC_DESTROY: 48795fab37eSRobert Watson mpc->mpc_ops->mpo_destroy = 48895fab37eSRobert Watson mpe->mpe_function; 48995fab37eSRobert Watson break; 49095fab37eSRobert Watson case MAC_INIT: 49195fab37eSRobert Watson mpc->mpc_ops->mpo_init = 49295fab37eSRobert Watson mpe->mpe_function; 49395fab37eSRobert Watson break; 49427f2eac7SRobert Watson case MAC_SYSCALL: 49527f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall = 49627f2eac7SRobert Watson mpe->mpe_function; 49727f2eac7SRobert Watson break; 49896adb909SRobert Watson case MAC_INIT_BPFDESC_LABEL: 49996adb909SRobert Watson mpc->mpc_ops->mpo_init_bpfdesc_label = 50095fab37eSRobert Watson mpe->mpe_function; 50195fab37eSRobert Watson break; 50296adb909SRobert Watson case MAC_INIT_CRED_LABEL: 50396adb909SRobert Watson mpc->mpc_ops->mpo_init_cred_label = 50495fab37eSRobert Watson mpe->mpe_function; 50595fab37eSRobert Watson break; 50696adb909SRobert Watson case MAC_INIT_DEVFSDIRENT_LABEL: 50796adb909SRobert Watson mpc->mpc_ops->mpo_init_devfsdirent_label = 50895fab37eSRobert Watson mpe->mpe_function; 50995fab37eSRobert Watson break; 51096adb909SRobert Watson case MAC_INIT_IFNET_LABEL: 51196adb909SRobert Watson mpc->mpc_ops->mpo_init_ifnet_label = 51295fab37eSRobert Watson mpe->mpe_function; 51395fab37eSRobert Watson break; 51496adb909SRobert Watson case MAC_INIT_IPQ_LABEL: 51596adb909SRobert Watson mpc->mpc_ops->mpo_init_ipq_label = 51695fab37eSRobert Watson mpe->mpe_function; 51795fab37eSRobert Watson break; 51896adb909SRobert Watson case MAC_INIT_MBUF_LABEL: 51996adb909SRobert Watson mpc->mpc_ops->mpo_init_mbuf_label = 52095fab37eSRobert Watson mpe->mpe_function; 52195fab37eSRobert Watson break; 52296adb909SRobert Watson case MAC_INIT_MOUNT_LABEL: 52396adb909SRobert Watson mpc->mpc_ops->mpo_init_mount_label = 52495fab37eSRobert Watson mpe->mpe_function; 52595fab37eSRobert Watson break; 52696adb909SRobert Watson case MAC_INIT_MOUNT_FS_LABEL: 52796adb909SRobert Watson mpc->mpc_ops->mpo_init_mount_fs_label = 52895fab37eSRobert Watson mpe->mpe_function; 52995fab37eSRobert Watson break; 53096adb909SRobert Watson case MAC_INIT_PIPE_LABEL: 53196adb909SRobert Watson mpc->mpc_ops->mpo_init_pipe_label = 53295fab37eSRobert Watson mpe->mpe_function; 53395fab37eSRobert Watson break; 53496adb909SRobert Watson case MAC_INIT_SOCKET_LABEL: 53596adb909SRobert Watson mpc->mpc_ops->mpo_init_socket_label = 53695fab37eSRobert Watson mpe->mpe_function; 53795fab37eSRobert Watson break; 53896adb909SRobert Watson case MAC_INIT_SOCKET_PEER_LABEL: 53996adb909SRobert Watson mpc->mpc_ops->mpo_init_socket_peer_label = 54095fab37eSRobert Watson mpe->mpe_function; 54195fab37eSRobert Watson break; 54296adb909SRobert Watson case MAC_INIT_VNODE_LABEL: 54396adb909SRobert Watson mpc->mpc_ops->mpo_init_vnode_label = 54495fab37eSRobert Watson mpe->mpe_function; 54595fab37eSRobert Watson break; 54696adb909SRobert Watson case MAC_DESTROY_BPFDESC_LABEL: 54796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_bpfdesc_label = 54895fab37eSRobert Watson mpe->mpe_function; 54995fab37eSRobert Watson break; 55096adb909SRobert Watson case MAC_DESTROY_CRED_LABEL: 55196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_cred_label = 55295fab37eSRobert Watson mpe->mpe_function; 55395fab37eSRobert Watson break; 55496adb909SRobert Watson case MAC_DESTROY_DEVFSDIRENT_LABEL: 55596adb909SRobert Watson mpc->mpc_ops->mpo_destroy_devfsdirent_label = 55695fab37eSRobert Watson mpe->mpe_function; 55795fab37eSRobert Watson break; 55896adb909SRobert Watson case MAC_DESTROY_IFNET_LABEL: 55996adb909SRobert Watson mpc->mpc_ops->mpo_destroy_ifnet_label = 56095fab37eSRobert Watson mpe->mpe_function; 56195fab37eSRobert Watson break; 56296adb909SRobert Watson case MAC_DESTROY_IPQ_LABEL: 56396adb909SRobert Watson mpc->mpc_ops->mpo_destroy_ipq_label = 56495fab37eSRobert Watson mpe->mpe_function; 56595fab37eSRobert Watson break; 56696adb909SRobert Watson case MAC_DESTROY_MBUF_LABEL: 56796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mbuf_label = 56895fab37eSRobert Watson mpe->mpe_function; 56995fab37eSRobert Watson break; 57096adb909SRobert Watson case MAC_DESTROY_MOUNT_LABEL: 57196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mount_label = 57295fab37eSRobert Watson mpe->mpe_function; 57395fab37eSRobert Watson break; 57496adb909SRobert Watson case MAC_DESTROY_MOUNT_FS_LABEL: 57596adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mount_fs_label = 57695fab37eSRobert Watson mpe->mpe_function; 57795fab37eSRobert Watson break; 57896adb909SRobert Watson case MAC_DESTROY_PIPE_LABEL: 57996adb909SRobert Watson mpc->mpc_ops->mpo_destroy_pipe_label = 58096adb909SRobert Watson mpe->mpe_function; 58196adb909SRobert Watson break; 58296adb909SRobert Watson case MAC_DESTROY_SOCKET_LABEL: 58396adb909SRobert Watson mpc->mpc_ops->mpo_destroy_socket_label = 58496adb909SRobert Watson mpe->mpe_function; 58596adb909SRobert Watson break; 58696adb909SRobert Watson case MAC_DESTROY_SOCKET_PEER_LABEL: 58796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_socket_peer_label = 58896adb909SRobert Watson mpe->mpe_function; 58996adb909SRobert Watson break; 59096adb909SRobert Watson case MAC_DESTROY_VNODE_LABEL: 59196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_vnode_label = 59295fab37eSRobert Watson mpe->mpe_function; 59395fab37eSRobert Watson break; 594f7b951a8SRobert Watson case MAC_COPY_PIPE_LABEL: 595f7b951a8SRobert Watson mpc->mpc_ops->mpo_copy_pipe_label = 59695fab37eSRobert Watson mpe->mpe_function; 59795fab37eSRobert Watson break; 598f7b951a8SRobert Watson case MAC_COPY_VNODE_LABEL: 599f7b951a8SRobert Watson mpc->mpc_ops->mpo_copy_vnode_label = 600f7b951a8SRobert Watson mpe->mpe_function; 601f7b951a8SRobert Watson break; 602f7b951a8SRobert Watson case MAC_EXTERNALIZE_CRED_LABEL: 603f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_cred_label = 604f7b951a8SRobert Watson mpe->mpe_function; 605f7b951a8SRobert Watson break; 606f7b951a8SRobert Watson case MAC_EXTERNALIZE_IFNET_LABEL: 607f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_ifnet_label = 608f7b951a8SRobert Watson mpe->mpe_function; 609f7b951a8SRobert Watson break; 610f7b951a8SRobert Watson case MAC_EXTERNALIZE_PIPE_LABEL: 611f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_pipe_label = 612f7b951a8SRobert Watson mpe->mpe_function; 613f7b951a8SRobert Watson break; 614f7b951a8SRobert Watson case MAC_EXTERNALIZE_SOCKET_LABEL: 615f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_socket_label = 616f7b951a8SRobert Watson mpe->mpe_function; 617f7b951a8SRobert Watson break; 618f7b951a8SRobert Watson case MAC_EXTERNALIZE_SOCKET_PEER_LABEL: 619f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_socket_peer_label = 620f7b951a8SRobert Watson mpe->mpe_function; 621f7b951a8SRobert Watson break; 622f7b951a8SRobert Watson case MAC_EXTERNALIZE_VNODE_LABEL: 623f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_vnode_label = 624f7b951a8SRobert Watson mpe->mpe_function; 625f7b951a8SRobert Watson break; 626f7b951a8SRobert Watson case MAC_EXTERNALIZE_VNODE_OLDMAC: 627f7b951a8SRobert Watson mpc->mpc_ops->mpo_externalize_vnode_oldmac = 628f7b951a8SRobert Watson mpe->mpe_function; 629f7b951a8SRobert Watson break; 630f7b951a8SRobert Watson case MAC_INTERNALIZE_CRED_LABEL: 631f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_cred_label = 632f7b951a8SRobert Watson mpe->mpe_function; 633f7b951a8SRobert Watson break; 634f7b951a8SRobert Watson case MAC_INTERNALIZE_IFNET_LABEL: 635f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_ifnet_label = 636f7b951a8SRobert Watson mpe->mpe_function; 637f7b951a8SRobert Watson break; 638f7b951a8SRobert Watson case MAC_INTERNALIZE_PIPE_LABEL: 639f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_pipe_label = 640f7b951a8SRobert Watson mpe->mpe_function; 641f7b951a8SRobert Watson break; 642f7b951a8SRobert Watson case MAC_INTERNALIZE_SOCKET_LABEL: 643f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_socket_label = 644f7b951a8SRobert Watson mpe->mpe_function; 645f7b951a8SRobert Watson break; 646f7b951a8SRobert Watson case MAC_INTERNALIZE_VNODE_LABEL: 647f7b951a8SRobert Watson mpc->mpc_ops->mpo_internalize_vnode_label = 64895fab37eSRobert Watson mpe->mpe_function; 64995fab37eSRobert Watson break; 65095fab37eSRobert Watson case MAC_CREATE_DEVFS_DEVICE: 65195fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_device = 65295fab37eSRobert Watson mpe->mpe_function; 65395fab37eSRobert Watson break; 65495fab37eSRobert Watson case MAC_CREATE_DEVFS_DIRECTORY: 65595fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_directory = 65695fab37eSRobert Watson mpe->mpe_function; 65795fab37eSRobert Watson break; 65874e62b1bSRobert Watson case MAC_CREATE_DEVFS_SYMLINK: 65974e62b1bSRobert Watson mpc->mpc_ops->mpo_create_devfs_symlink = 66074e62b1bSRobert Watson mpe->mpe_function; 66174e62b1bSRobert Watson break; 66295fab37eSRobert Watson case MAC_CREATE_DEVFS_VNODE: 66395fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_vnode = 66495fab37eSRobert Watson mpe->mpe_function; 66595fab37eSRobert Watson break; 66695fab37eSRobert Watson case MAC_STDCREATEVNODE_EA: 66795fab37eSRobert Watson mpc->mpc_ops->mpo_stdcreatevnode_ea = 66895fab37eSRobert Watson mpe->mpe_function; 66995fab37eSRobert Watson break; 67095fab37eSRobert Watson case MAC_CREATE_VNODE: 67195fab37eSRobert Watson mpc->mpc_ops->mpo_create_vnode = 67295fab37eSRobert Watson mpe->mpe_function; 67395fab37eSRobert Watson break; 67495fab37eSRobert Watson case MAC_CREATE_MOUNT: 67595fab37eSRobert Watson mpc->mpc_ops->mpo_create_mount = 67695fab37eSRobert Watson mpe->mpe_function; 67795fab37eSRobert Watson break; 67895fab37eSRobert Watson case MAC_CREATE_ROOT_MOUNT: 67995fab37eSRobert Watson mpc->mpc_ops->mpo_create_root_mount = 68095fab37eSRobert Watson mpe->mpe_function; 68195fab37eSRobert Watson break; 68295fab37eSRobert Watson case MAC_RELABEL_VNODE: 68395fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_vnode = 68495fab37eSRobert Watson mpe->mpe_function; 68595fab37eSRobert Watson break; 68695fab37eSRobert Watson case MAC_UPDATE_DEVFSDIRENT: 68795fab37eSRobert Watson mpc->mpc_ops->mpo_update_devfsdirent = 68895fab37eSRobert Watson mpe->mpe_function; 68995fab37eSRobert Watson break; 69095fab37eSRobert Watson case MAC_UPDATE_PROCFSVNODE: 69195fab37eSRobert Watson mpc->mpc_ops->mpo_update_procfsvnode = 69295fab37eSRobert Watson mpe->mpe_function; 69395fab37eSRobert Watson break; 69495fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_EXTATTR: 69595fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_extattr = 69695fab37eSRobert Watson mpe->mpe_function; 69795fab37eSRobert Watson break; 69895fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: 69995fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_externalized = 70095fab37eSRobert Watson mpe->mpe_function; 70195fab37eSRobert Watson break; 70295fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_MOUNT: 70395fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_mount = 70495fab37eSRobert Watson mpe->mpe_function; 70595fab37eSRobert Watson break; 70695fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_SOCKET: 70795fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_socket = 70895fab37eSRobert Watson mpe->mpe_function; 70995fab37eSRobert Watson break; 71095fab37eSRobert Watson case MAC_CREATE_PIPE: 71195fab37eSRobert Watson mpc->mpc_ops->mpo_create_pipe = 71295fab37eSRobert Watson mpe->mpe_function; 71395fab37eSRobert Watson break; 71495fab37eSRobert Watson case MAC_CREATE_SOCKET: 71595fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket = 71695fab37eSRobert Watson mpe->mpe_function; 71795fab37eSRobert Watson break; 71895fab37eSRobert Watson case MAC_CREATE_SOCKET_FROM_SOCKET: 71995fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket_from_socket = 72095fab37eSRobert Watson mpe->mpe_function; 72195fab37eSRobert Watson break; 72295fab37eSRobert Watson case MAC_RELABEL_PIPE: 72395fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_pipe = 72495fab37eSRobert Watson mpe->mpe_function; 72595fab37eSRobert Watson break; 72695fab37eSRobert Watson case MAC_RELABEL_SOCKET: 72795fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_socket = 72895fab37eSRobert Watson mpe->mpe_function; 72995fab37eSRobert Watson break; 73095fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_MBUF: 73195fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_mbuf = 73295fab37eSRobert Watson mpe->mpe_function; 73395fab37eSRobert Watson break; 73495fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_SOCKET: 73595fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_socket = 73695fab37eSRobert Watson mpe->mpe_function; 73795fab37eSRobert Watson break; 73895fab37eSRobert Watson case MAC_CREATE_BPFDESC: 73995fab37eSRobert Watson mpc->mpc_ops->mpo_create_bpfdesc = 74095fab37eSRobert Watson mpe->mpe_function; 74195fab37eSRobert Watson break; 74295fab37eSRobert Watson case MAC_CREATE_DATAGRAM_FROM_IPQ: 74395fab37eSRobert Watson mpc->mpc_ops->mpo_create_datagram_from_ipq = 74495fab37eSRobert Watson mpe->mpe_function; 74595fab37eSRobert Watson break; 74695fab37eSRobert Watson case MAC_CREATE_FRAGMENT: 74795fab37eSRobert Watson mpc->mpc_ops->mpo_create_fragment = 74895fab37eSRobert Watson mpe->mpe_function; 74995fab37eSRobert Watson break; 75095fab37eSRobert Watson case MAC_CREATE_IFNET: 75195fab37eSRobert Watson mpc->mpc_ops->mpo_create_ifnet = 75295fab37eSRobert Watson mpe->mpe_function; 75395fab37eSRobert Watson break; 75495fab37eSRobert Watson case MAC_CREATE_IPQ: 75595fab37eSRobert Watson mpc->mpc_ops->mpo_create_ipq = 75695fab37eSRobert Watson mpe->mpe_function; 75795fab37eSRobert Watson break; 75895fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_MBUF: 75995fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_mbuf = 76095fab37eSRobert Watson mpe->mpe_function; 76195fab37eSRobert Watson break; 76295fab37eSRobert Watson case MAC_CREATE_MBUF_LINKLAYER: 76395fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_linklayer = 76495fab37eSRobert Watson mpe->mpe_function; 76595fab37eSRobert Watson break; 76695fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_BPFDESC: 76795fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc = 76895fab37eSRobert Watson mpe->mpe_function; 76995fab37eSRobert Watson break; 77095fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_IFNET: 77195fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_ifnet = 77295fab37eSRobert Watson mpe->mpe_function; 77395fab37eSRobert Watson break; 77495fab37eSRobert Watson case MAC_CREATE_MBUF_MULTICAST_ENCAP: 77595fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_multicast_encap = 77695fab37eSRobert Watson mpe->mpe_function; 77795fab37eSRobert Watson break; 77895fab37eSRobert Watson case MAC_CREATE_MBUF_NETLAYER: 77995fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_netlayer = 78095fab37eSRobert Watson mpe->mpe_function; 78195fab37eSRobert Watson break; 78295fab37eSRobert Watson case MAC_FRAGMENT_MATCH: 78395fab37eSRobert Watson mpc->mpc_ops->mpo_fragment_match = 78495fab37eSRobert Watson mpe->mpe_function; 78595fab37eSRobert Watson break; 78695fab37eSRobert Watson case MAC_RELABEL_IFNET: 78795fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_ifnet = 78895fab37eSRobert Watson mpe->mpe_function; 78995fab37eSRobert Watson break; 79095fab37eSRobert Watson case MAC_UPDATE_IPQ: 79195fab37eSRobert Watson mpc->mpc_ops->mpo_update_ipq = 79295fab37eSRobert Watson mpe->mpe_function; 79395fab37eSRobert Watson break; 79495fab37eSRobert Watson case MAC_CREATE_CRED: 79595fab37eSRobert Watson mpc->mpc_ops->mpo_create_cred = 79695fab37eSRobert Watson mpe->mpe_function; 79795fab37eSRobert Watson break; 79895fab37eSRobert Watson case MAC_EXECVE_TRANSITION: 79995fab37eSRobert Watson mpc->mpc_ops->mpo_execve_transition = 80095fab37eSRobert Watson mpe->mpe_function; 80195fab37eSRobert Watson break; 80295fab37eSRobert Watson case MAC_EXECVE_WILL_TRANSITION: 80395fab37eSRobert Watson mpc->mpc_ops->mpo_execve_will_transition = 80495fab37eSRobert Watson mpe->mpe_function; 80595fab37eSRobert Watson break; 80695fab37eSRobert Watson case MAC_CREATE_PROC0: 807226b96fbSRobert Watson mpc->mpc_ops->mpo_create_proc0 = 808226b96fbSRobert Watson mpe->mpe_function; 80995fab37eSRobert Watson break; 81095fab37eSRobert Watson case MAC_CREATE_PROC1: 811226b96fbSRobert Watson mpc->mpc_ops->mpo_create_proc1 = 812226b96fbSRobert Watson mpe->mpe_function; 81395fab37eSRobert Watson break; 81495fab37eSRobert Watson case MAC_RELABEL_CRED: 81595fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_cred = 81695fab37eSRobert Watson mpe->mpe_function; 81795fab37eSRobert Watson break; 81892dbb82aSRobert Watson case MAC_THREAD_USERRET: 81992dbb82aSRobert Watson mpc->mpc_ops->mpo_thread_userret = 82092dbb82aSRobert Watson mpe->mpe_function; 82192dbb82aSRobert Watson break; 82295fab37eSRobert Watson case MAC_CHECK_BPFDESC_RECEIVE: 82395fab37eSRobert Watson mpc->mpc_ops->mpo_check_bpfdesc_receive = 82495fab37eSRobert Watson mpe->mpe_function; 82595fab37eSRobert Watson break; 82695fab37eSRobert Watson case MAC_CHECK_CRED_RELABEL: 82795fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_relabel = 82895fab37eSRobert Watson mpe->mpe_function; 82995fab37eSRobert Watson break; 83095fab37eSRobert Watson case MAC_CHECK_CRED_VISIBLE: 83195fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_visible = 83295fab37eSRobert Watson mpe->mpe_function; 83395fab37eSRobert Watson break; 83495fab37eSRobert Watson case MAC_CHECK_IFNET_RELABEL: 83595fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_relabel = 83695fab37eSRobert Watson mpe->mpe_function; 83795fab37eSRobert Watson break; 83895fab37eSRobert Watson case MAC_CHECK_IFNET_TRANSMIT: 83995fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_transmit = 84095fab37eSRobert Watson mpe->mpe_function; 84195fab37eSRobert Watson break; 84295fab37eSRobert Watson case MAC_CHECK_MOUNT_STAT: 84395fab37eSRobert Watson mpc->mpc_ops->mpo_check_mount_stat = 84495fab37eSRobert Watson mpe->mpe_function; 84595fab37eSRobert Watson break; 84695fab37eSRobert Watson case MAC_CHECK_PIPE_IOCTL: 84795fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_ioctl = 84895fab37eSRobert Watson mpe->mpe_function; 84995fab37eSRobert Watson break; 850c024c3eeSRobert Watson case MAC_CHECK_PIPE_POLL: 851c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_poll = 852c024c3eeSRobert Watson mpe->mpe_function; 853c024c3eeSRobert Watson break; 854c024c3eeSRobert Watson case MAC_CHECK_PIPE_READ: 855c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_read = 85695fab37eSRobert Watson mpe->mpe_function; 85795fab37eSRobert Watson break; 85895fab37eSRobert Watson case MAC_CHECK_PIPE_RELABEL: 85995fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_relabel = 86095fab37eSRobert Watson mpe->mpe_function; 86195fab37eSRobert Watson break; 862c024c3eeSRobert Watson case MAC_CHECK_PIPE_STAT: 863c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_stat = 864c024c3eeSRobert Watson mpe->mpe_function; 865c024c3eeSRobert Watson break; 866c024c3eeSRobert Watson case MAC_CHECK_PIPE_WRITE: 867c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_write = 868c024c3eeSRobert Watson mpe->mpe_function; 869c024c3eeSRobert Watson break; 87095fab37eSRobert Watson case MAC_CHECK_PROC_DEBUG: 87195fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_debug = 87295fab37eSRobert Watson mpe->mpe_function; 87395fab37eSRobert Watson break; 87495fab37eSRobert Watson case MAC_CHECK_PROC_SCHED: 87595fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_sched = 87695fab37eSRobert Watson mpe->mpe_function; 87795fab37eSRobert Watson break; 87895fab37eSRobert Watson case MAC_CHECK_PROC_SIGNAL: 87995fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_signal = 88095fab37eSRobert Watson mpe->mpe_function; 88195fab37eSRobert Watson break; 88295fab37eSRobert Watson case MAC_CHECK_SOCKET_BIND: 88395fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_bind = 88495fab37eSRobert Watson mpe->mpe_function; 88595fab37eSRobert Watson break; 88695fab37eSRobert Watson case MAC_CHECK_SOCKET_CONNECT: 88795fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_connect = 88895fab37eSRobert Watson mpe->mpe_function; 88995fab37eSRobert Watson break; 890d61198e4SRobert Watson case MAC_CHECK_SOCKET_DELIVER: 891d61198e4SRobert Watson mpc->mpc_ops->mpo_check_socket_deliver = 89295fab37eSRobert Watson mpe->mpe_function; 89395fab37eSRobert Watson break; 894d61198e4SRobert Watson case MAC_CHECK_SOCKET_LISTEN: 895d61198e4SRobert Watson mpc->mpc_ops->mpo_check_socket_listen = 89695fab37eSRobert Watson mpe->mpe_function; 89795fab37eSRobert Watson break; 898b371c939SRobert Watson case MAC_CHECK_SOCKET_RECEIVE: 899b371c939SRobert Watson mpc->mpc_ops->mpo_check_socket_receive = 900b371c939SRobert Watson mpe->mpe_function; 901b371c939SRobert Watson break; 90295fab37eSRobert Watson case MAC_CHECK_SOCKET_RELABEL: 90395fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_relabel = 90495fab37eSRobert Watson mpe->mpe_function; 90595fab37eSRobert Watson break; 906b371c939SRobert Watson case MAC_CHECK_SOCKET_SEND: 907b371c939SRobert Watson mpc->mpc_ops->mpo_check_socket_send = 908b371c939SRobert Watson mpe->mpe_function; 909b371c939SRobert Watson break; 91095fab37eSRobert Watson case MAC_CHECK_SOCKET_VISIBLE: 91195fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_visible = 91295fab37eSRobert Watson mpe->mpe_function; 91395fab37eSRobert Watson break; 91495fab37eSRobert Watson case MAC_CHECK_VNODE_ACCESS: 91595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_access = 91695fab37eSRobert Watson mpe->mpe_function; 91795fab37eSRobert Watson break; 91895fab37eSRobert Watson case MAC_CHECK_VNODE_CHDIR: 91995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chdir = 92095fab37eSRobert Watson mpe->mpe_function; 92195fab37eSRobert Watson break; 92295fab37eSRobert Watson case MAC_CHECK_VNODE_CHROOT: 92395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chroot = 92495fab37eSRobert Watson mpe->mpe_function; 92595fab37eSRobert Watson break; 92695fab37eSRobert Watson case MAC_CHECK_VNODE_CREATE: 92795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_create = 92895fab37eSRobert Watson mpe->mpe_function; 92995fab37eSRobert Watson break; 93095fab37eSRobert Watson case MAC_CHECK_VNODE_DELETE: 93195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_delete = 93295fab37eSRobert Watson mpe->mpe_function; 93395fab37eSRobert Watson break; 93495fab37eSRobert Watson case MAC_CHECK_VNODE_DELETEACL: 93595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_deleteacl = 93695fab37eSRobert Watson mpe->mpe_function; 93795fab37eSRobert Watson break; 93895fab37eSRobert Watson case MAC_CHECK_VNODE_EXEC: 93995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_exec = 94095fab37eSRobert Watson mpe->mpe_function; 94195fab37eSRobert Watson break; 94295fab37eSRobert Watson case MAC_CHECK_VNODE_GETACL: 94395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getacl = 94495fab37eSRobert Watson mpe->mpe_function; 94595fab37eSRobert Watson break; 94695fab37eSRobert Watson case MAC_CHECK_VNODE_GETEXTATTR: 94795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getextattr = 94895fab37eSRobert Watson mpe->mpe_function; 94995fab37eSRobert Watson break; 9500a694196SRobert Watson case MAC_CHECK_VNODE_LINK: 9510a694196SRobert Watson mpc->mpc_ops->mpo_check_vnode_link = 9520a694196SRobert Watson mpe->mpe_function; 9530a694196SRobert Watson break; 95495fab37eSRobert Watson case MAC_CHECK_VNODE_LOOKUP: 95595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_lookup = 95695fab37eSRobert Watson mpe->mpe_function; 95795fab37eSRobert Watson break; 958e183f80eSRobert Watson case MAC_CHECK_VNODE_MMAP: 959e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mmap = 960e183f80eSRobert Watson mpe->mpe_function; 961e183f80eSRobert Watson break; 962e183f80eSRobert Watson case MAC_CHECK_VNODE_MMAP_DOWNGRADE: 963e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mmap_downgrade = 964e183f80eSRobert Watson mpe->mpe_function; 965e183f80eSRobert Watson break; 966e183f80eSRobert Watson case MAC_CHECK_VNODE_MPROTECT: 967e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mprotect = 96895fab37eSRobert Watson mpe->mpe_function; 96995fab37eSRobert Watson break; 97095fab37eSRobert Watson case MAC_CHECK_VNODE_OPEN: 97195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_open = 97295fab37eSRobert Watson mpe->mpe_function; 97395fab37eSRobert Watson break; 9747f724f8bSRobert Watson case MAC_CHECK_VNODE_POLL: 9757f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_poll = 9767f724f8bSRobert Watson mpe->mpe_function; 9777f724f8bSRobert Watson break; 9787f724f8bSRobert Watson case MAC_CHECK_VNODE_READ: 9797f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_read = 9807f724f8bSRobert Watson mpe->mpe_function; 9817f724f8bSRobert Watson break; 98295fab37eSRobert Watson case MAC_CHECK_VNODE_READDIR: 98395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readdir = 98495fab37eSRobert Watson mpe->mpe_function; 98595fab37eSRobert Watson break; 98695fab37eSRobert Watson case MAC_CHECK_VNODE_READLINK: 98795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readlink = 98895fab37eSRobert Watson mpe->mpe_function; 98995fab37eSRobert Watson break; 99095fab37eSRobert Watson case MAC_CHECK_VNODE_RELABEL: 99195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_relabel = 99295fab37eSRobert Watson mpe->mpe_function; 99395fab37eSRobert Watson break; 99495fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_FROM: 99595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_from = 99695fab37eSRobert Watson mpe->mpe_function; 99795fab37eSRobert Watson break; 99895fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_TO: 99995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_to = 100095fab37eSRobert Watson mpe->mpe_function; 100195fab37eSRobert Watson break; 100295fab37eSRobert Watson case MAC_CHECK_VNODE_REVOKE: 100395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_revoke = 100495fab37eSRobert Watson mpe->mpe_function; 100595fab37eSRobert Watson break; 100695fab37eSRobert Watson case MAC_CHECK_VNODE_SETACL: 100795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setacl = 100895fab37eSRobert Watson mpe->mpe_function; 100995fab37eSRobert Watson break; 101095fab37eSRobert Watson case MAC_CHECK_VNODE_SETEXTATTR: 101195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setextattr = 101295fab37eSRobert Watson mpe->mpe_function; 101395fab37eSRobert Watson break; 101495fab37eSRobert Watson case MAC_CHECK_VNODE_SETFLAGS: 101595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setflags = 101695fab37eSRobert Watson mpe->mpe_function; 101795fab37eSRobert Watson break; 101895fab37eSRobert Watson case MAC_CHECK_VNODE_SETMODE: 101995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setmode = 102095fab37eSRobert Watson mpe->mpe_function; 102195fab37eSRobert Watson break; 102295fab37eSRobert Watson case MAC_CHECK_VNODE_SETOWNER: 102395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setowner = 102495fab37eSRobert Watson mpe->mpe_function; 102595fab37eSRobert Watson break; 102695fab37eSRobert Watson case MAC_CHECK_VNODE_SETUTIMES: 102795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setutimes = 102895fab37eSRobert Watson mpe->mpe_function; 102995fab37eSRobert Watson break; 103095fab37eSRobert Watson case MAC_CHECK_VNODE_STAT: 103195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_stat = 103295fab37eSRobert Watson mpe->mpe_function; 103395fab37eSRobert Watson break; 10341cbfd977SRobert Watson case MAC_CHECK_VNODE_SWAPON: 10351cbfd977SRobert Watson mpc->mpc_ops->mpo_check_vnode_swapon = 10361cbfd977SRobert Watson mpe->mpe_function; 10371cbfd977SRobert Watson break; 10387f724f8bSRobert Watson case MAC_CHECK_VNODE_WRITE: 10397f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_write = 10407f724f8bSRobert Watson mpe->mpe_function; 10417f724f8bSRobert Watson break; 104295fab37eSRobert Watson /* 104395fab37eSRobert Watson default: 104495fab37eSRobert Watson printf("MAC policy `%s': unknown operation %d\n", 104595fab37eSRobert Watson mpc->mpc_name, mpe->mpe_constant); 104695fab37eSRobert Watson return (EINVAL); 104795fab37eSRobert Watson */ 104895fab37eSRobert Watson } 104995fab37eSRobert Watson } 105095fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); 105195fab37eSRobert Watson if (mac_policy_list_busy > 0) { 105295fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 105395fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 105495fab37eSRobert Watson mpc->mpc_ops = NULL; 105595fab37eSRobert Watson return (EBUSY); 105695fab37eSRobert Watson } 105795fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 105895fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 105995fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 106095fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 106195fab37eSRobert Watson mpc->mpc_ops = NULL; 106295fab37eSRobert Watson return (EEXIST); 106395fab37eSRobert Watson } 106495fab37eSRobert Watson } 106595fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 106695fab37eSRobert Watson slot = ffs(mac_policy_offsets_free); 106795fab37eSRobert Watson if (slot == 0) { 106895fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 106995fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 107095fab37eSRobert Watson mpc->mpc_ops = NULL; 107195fab37eSRobert Watson return (ENOMEM); 107295fab37eSRobert Watson } 107395fab37eSRobert Watson slot--; 107495fab37eSRobert Watson mac_policy_offsets_free &= ~(1 << slot); 107595fab37eSRobert Watson *mpc->mpc_field_off = slot; 107695fab37eSRobert Watson } 107795fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 107895fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 107995fab37eSRobert Watson 108095fab37eSRobert Watson /* Per-policy initialization. */ 108195fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 108295fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 108395fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 108495fab37eSRobert Watson 108595fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 108695fab37eSRobert Watson mpc->mpc_name); 108795fab37eSRobert Watson 108895fab37eSRobert Watson return (0); 108995fab37eSRobert Watson } 109095fab37eSRobert Watson 109195fab37eSRobert Watson static int 109295fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 109395fab37eSRobert Watson { 109495fab37eSRobert Watson 1095ea599aa0SRobert Watson /* 1096ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 1097ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 1098ea599aa0SRobert Watson * silently succeed. 1099ea599aa0SRobert Watson */ 1100ea599aa0SRobert Watson MAC_POLICY_LIST_LOCK(); 1101ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 1102ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 1103ea599aa0SRobert Watson return (0); 1104ea599aa0SRobert Watson } 110595fab37eSRobert Watson #if 0 110695fab37eSRobert Watson /* 110795fab37eSRobert Watson * Don't allow unloading modules with private data. 110895fab37eSRobert Watson */ 1109ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 1110ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 111195fab37eSRobert Watson return (EBUSY); 1112ea599aa0SRobert Watson } 111395fab37eSRobert Watson #endif 1114ea599aa0SRobert Watson /* 1115ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 1116ea599aa0SRobert Watson * by its own definition. 1117ea599aa0SRobert Watson */ 1118ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 1119ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 112095fab37eSRobert Watson return (EBUSY); 1121ea599aa0SRobert Watson } 1122ea599aa0SRobert Watson /* 1123ea599aa0SRobert Watson * Right now, we EBUSY if the list is in use. In the future, 1124ea599aa0SRobert Watson * for reliability reasons, we might want to sleep and wakeup 1125ea599aa0SRobert Watson * later to try again. 1126ea599aa0SRobert Watson */ 112795fab37eSRobert Watson if (mac_policy_list_busy > 0) { 112895fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 112995fab37eSRobert Watson return (EBUSY); 113095fab37eSRobert Watson } 113195fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 113295fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 113395fab37eSRobert Watson 113495fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 113595fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 113695fab37eSRobert Watson 113795fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 113895fab37eSRobert Watson mpc->mpc_ops = NULL; 11399aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 114095fab37eSRobert Watson 114195fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 114295fab37eSRobert Watson mpc->mpc_name); 114395fab37eSRobert Watson 114495fab37eSRobert Watson return (0); 114595fab37eSRobert Watson } 114695fab37eSRobert Watson 114795fab37eSRobert Watson /* 114895fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 114995fab37eSRobert Watson * value with the higher precedence. 115095fab37eSRobert Watson */ 115195fab37eSRobert Watson static int 115295fab37eSRobert Watson error_select(int error1, int error2) 115395fab37eSRobert Watson { 115495fab37eSRobert Watson 115595fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 115695fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 115795fab37eSRobert Watson return (EDEADLK); 115895fab37eSRobert Watson 115995fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 116095fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 116195fab37eSRobert Watson return (EINVAL); 116295fab37eSRobert Watson 116395fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 116495fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 116595fab37eSRobert Watson return (ESRCH); 116695fab37eSRobert Watson 116795fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 116895fab37eSRobert Watson return (ENOENT); 116995fab37eSRobert Watson 117095fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 117195fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 117295fab37eSRobert Watson return (EACCES); 117395fab37eSRobert Watson 117495fab37eSRobert Watson /* Precedence goes to privilege. */ 117595fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 117695fab37eSRobert Watson return (EPERM); 117795fab37eSRobert Watson 117895fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 117995fab37eSRobert Watson if (error1 != 0) 118095fab37eSRobert Watson return (error1); 118195fab37eSRobert Watson return (error2); 118295fab37eSRobert Watson } 118395fab37eSRobert Watson 118408bcdc58SRobert Watson static void 118508bcdc58SRobert Watson mac_init_label(struct label *label) 118608bcdc58SRobert Watson { 118708bcdc58SRobert Watson 118808bcdc58SRobert Watson bzero(label, sizeof(*label)); 118908bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 119008bcdc58SRobert Watson } 119108bcdc58SRobert Watson 119208bcdc58SRobert Watson static void 119308bcdc58SRobert Watson mac_destroy_label(struct label *label) 119408bcdc58SRobert Watson { 119508bcdc58SRobert Watson 119608bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 119708bcdc58SRobert Watson ("destroying uninitialized label")); 119808bcdc58SRobert Watson 119908bcdc58SRobert Watson bzero(label, sizeof(*label)); 120008bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 120108bcdc58SRobert Watson } 120208bcdc58SRobert Watson 120308bcdc58SRobert Watson void 120487807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 120508bcdc58SRobert Watson { 120608bcdc58SRobert Watson 120787807196SRobert Watson mac_init_label(&bpf_d->bd_label); 120887807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 120908bcdc58SRobert Watson #ifdef MAC_DEBUG 121087807196SRobert Watson atomic_add_int(&nmacbpfdescs, 1); 121108bcdc58SRobert Watson #endif 121208bcdc58SRobert Watson } 121308bcdc58SRobert Watson 1214f7b951a8SRobert Watson static void 1215f7b951a8SRobert Watson mac_init_cred_label(struct label *label) 121608bcdc58SRobert Watson { 121708bcdc58SRobert Watson 1218f7b951a8SRobert Watson mac_init_label(label); 1219f7b951a8SRobert Watson MAC_PERFORM(init_cred_label, label); 122008bcdc58SRobert Watson #ifdef MAC_DEBUG 122108bcdc58SRobert Watson atomic_add_int(&nmaccreds, 1); 122208bcdc58SRobert Watson #endif 122308bcdc58SRobert Watson } 122408bcdc58SRobert Watson 122508bcdc58SRobert Watson void 1226f7b951a8SRobert Watson mac_init_cred(struct ucred *cred) 1227f7b951a8SRobert Watson { 1228f7b951a8SRobert Watson 1229f7b951a8SRobert Watson mac_init_cred_label(&cred->cr_label); 1230f7b951a8SRobert Watson } 1231f7b951a8SRobert Watson 1232f7b951a8SRobert Watson void 123387807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 123408bcdc58SRobert Watson { 123508bcdc58SRobert Watson 123687807196SRobert Watson mac_init_label(&de->de_label); 123787807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 123808bcdc58SRobert Watson #ifdef MAC_DEBUG 123987807196SRobert Watson atomic_add_int(&nmacdevfsdirents, 1); 124008bcdc58SRobert Watson #endif 124108bcdc58SRobert Watson } 124208bcdc58SRobert Watson 1243f7b951a8SRobert Watson static void 1244f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label) 1245f7b951a8SRobert Watson { 1246f7b951a8SRobert Watson 1247f7b951a8SRobert Watson mac_init_label(label); 1248f7b951a8SRobert Watson MAC_PERFORM(init_ifnet_label, label); 1249f7b951a8SRobert Watson #ifdef MAC_DEBUG 1250f7b951a8SRobert Watson atomic_add_int(&nmacifnets, 1); 1251f7b951a8SRobert Watson #endif 1252f7b951a8SRobert Watson } 1253f7b951a8SRobert Watson 125408bcdc58SRobert Watson void 125508bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 125608bcdc58SRobert Watson { 125708bcdc58SRobert Watson 1258f7b951a8SRobert Watson mac_init_ifnet_label(&ifp->if_label); 125908bcdc58SRobert Watson } 126008bcdc58SRobert Watson 126108bcdc58SRobert Watson void 126208bcdc58SRobert Watson mac_init_ipq(struct ipq *ipq) 126308bcdc58SRobert Watson { 126408bcdc58SRobert Watson 126508bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 126608bcdc58SRobert Watson MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 126708bcdc58SRobert Watson #ifdef MAC_DEBUG 126808bcdc58SRobert Watson atomic_add_int(&nmacipqs, 1); 126908bcdc58SRobert Watson #endif 127008bcdc58SRobert Watson } 127108bcdc58SRobert Watson 127287807196SRobert Watson int 127387807196SRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 127408bcdc58SRobert Watson { 127556c15412SRobert Watson int error; 127656c15412SRobert Watson 127787807196SRobert Watson KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 127808bcdc58SRobert Watson 127987807196SRobert Watson mac_init_label(&m->m_pkthdr.label); 128087807196SRobert Watson 128156c15412SRobert Watson MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 128256c15412SRobert Watson if (error) { 128356c15412SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 128456c15412SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 128556c15412SRobert Watson } 128656c15412SRobert Watson 128708bcdc58SRobert Watson #ifdef MAC_DEBUG 128856c15412SRobert Watson if (error == 0) 128987807196SRobert Watson atomic_add_int(&nmacmbufs, 1); 129008bcdc58SRobert Watson #endif 129156c15412SRobert Watson return (error); 129208bcdc58SRobert Watson } 129308bcdc58SRobert Watson 129408bcdc58SRobert Watson void 129587807196SRobert Watson mac_init_mount(struct mount *mp) 129608bcdc58SRobert Watson { 129708bcdc58SRobert Watson 129887807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 129987807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 130087807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 130187807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 130208bcdc58SRobert Watson #ifdef MAC_DEBUG 130387807196SRobert Watson atomic_add_int(&nmacmounts, 1); 130408bcdc58SRobert Watson #endif 130508bcdc58SRobert Watson } 130608bcdc58SRobert Watson 1307f7b951a8SRobert Watson static void 1308f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 1309f7b951a8SRobert Watson { 1310f7b951a8SRobert Watson 1311f7b951a8SRobert Watson mac_init_label(label); 1312f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 1313f7b951a8SRobert Watson #ifdef MAC_DEBUG 1314f7b951a8SRobert Watson atomic_add_int(&nmacpipes, 1); 1315f7b951a8SRobert Watson #endif 1316f7b951a8SRobert Watson } 1317f7b951a8SRobert Watson 131808bcdc58SRobert Watson void 131908bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 132008bcdc58SRobert Watson { 132108bcdc58SRobert Watson struct label *label; 132208bcdc58SRobert Watson 132308bcdc58SRobert Watson label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 132408bcdc58SRobert Watson pipe->pipe_label = label; 132508bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 1326f7b951a8SRobert Watson mac_init_pipe_label(label); 132708bcdc58SRobert Watson } 132808bcdc58SRobert Watson 132983985c26SRobert Watson static int 133083985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 133108bcdc58SRobert Watson { 133283985c26SRobert Watson int error; 133308bcdc58SRobert Watson 133483985c26SRobert Watson mac_init_label(label); 133583985c26SRobert Watson 133683985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 133783985c26SRobert Watson if (error) { 133883985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 133983985c26SRobert Watson mac_destroy_label(label); 134083985c26SRobert Watson } 134183985c26SRobert Watson 134208bcdc58SRobert Watson #ifdef MAC_DEBUG 134383985c26SRobert Watson if (error == 0) 134487807196SRobert Watson atomic_add_int(&nmacsockets, 1); 134587807196SRobert Watson #endif 134683985c26SRobert Watson 134783985c26SRobert Watson return (error); 134883985c26SRobert Watson } 134983985c26SRobert Watson 135083985c26SRobert Watson static int 135183985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 135283985c26SRobert Watson { 135383985c26SRobert Watson int error; 135483985c26SRobert Watson 135583985c26SRobert Watson mac_init_label(label); 135683985c26SRobert Watson 135783985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 135883985c26SRobert Watson if (error) { 135983985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 136083985c26SRobert Watson mac_destroy_label(label); 136183985c26SRobert Watson } 136283985c26SRobert Watson 136383985c26SRobert Watson return (error); 136483985c26SRobert Watson } 136583985c26SRobert Watson 136683985c26SRobert Watson int 136783985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 136883985c26SRobert Watson { 136983985c26SRobert Watson int error; 137083985c26SRobert Watson 137183985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 137283985c26SRobert Watson if (error) 137383985c26SRobert Watson return (error); 137483985c26SRobert Watson 137583985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 137683985c26SRobert Watson if (error) 137783985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 137883985c26SRobert Watson 137983985c26SRobert Watson return (error); 138087807196SRobert Watson } 138187807196SRobert Watson 138287807196SRobert Watson static void 1383f7b951a8SRobert Watson mac_init_vnode_label(struct label *label) 138487807196SRobert Watson { 138587807196SRobert Watson 138687807196SRobert Watson mac_init_label(label); 1387f7b951a8SRobert Watson MAC_PERFORM(init_vnode_label, label); 138887807196SRobert Watson #ifdef MAC_DEBUG 1389f7b951a8SRobert Watson atomic_add_int(&nmacvnodes, 1); 139008bcdc58SRobert Watson #endif 139108bcdc58SRobert Watson } 139208bcdc58SRobert Watson 139308bcdc58SRobert Watson void 139487807196SRobert Watson mac_init_vnode(struct vnode *vp) 139508bcdc58SRobert Watson { 139608bcdc58SRobert Watson 1397f7b951a8SRobert Watson mac_init_vnode_label(&vp->v_label); 139808bcdc58SRobert Watson } 139908bcdc58SRobert Watson 140008bcdc58SRobert Watson void 140108bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 140208bcdc58SRobert Watson { 140308bcdc58SRobert Watson 140408bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 140508bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 140608bcdc58SRobert Watson #ifdef MAC_DEBUG 140708bcdc58SRobert Watson atomic_subtract_int(&nmacbpfdescs, 1); 140808bcdc58SRobert Watson #endif 140908bcdc58SRobert Watson } 141008bcdc58SRobert Watson 1411f7b951a8SRobert Watson static void 1412f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label) 141308bcdc58SRobert Watson { 141408bcdc58SRobert Watson 1415f7b951a8SRobert Watson MAC_PERFORM(destroy_cred_label, label); 1416f7b951a8SRobert Watson mac_destroy_label(label); 141708bcdc58SRobert Watson #ifdef MAC_DEBUG 141887807196SRobert Watson atomic_subtract_int(&nmaccreds, 1); 141987807196SRobert Watson #endif 142087807196SRobert Watson } 142187807196SRobert Watson 142287807196SRobert Watson void 1423f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred) 1424f7b951a8SRobert Watson { 1425f7b951a8SRobert Watson 1426f7b951a8SRobert Watson mac_destroy_cred_label(&cred->cr_label); 1427f7b951a8SRobert Watson } 1428f7b951a8SRobert Watson 1429f7b951a8SRobert Watson void 143087807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 143187807196SRobert Watson { 143287807196SRobert Watson 143387807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 143487807196SRobert Watson mac_destroy_label(&de->de_label); 143587807196SRobert Watson #ifdef MAC_DEBUG 143687807196SRobert Watson atomic_subtract_int(&nmacdevfsdirents, 1); 143787807196SRobert Watson #endif 143887807196SRobert Watson } 143987807196SRobert Watson 1440f7b951a8SRobert Watson static void 1441f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label) 1442f7b951a8SRobert Watson { 1443f7b951a8SRobert Watson 1444f7b951a8SRobert Watson MAC_PERFORM(destroy_ifnet_label, label); 1445f7b951a8SRobert Watson mac_destroy_label(label); 1446f7b951a8SRobert Watson #ifdef MAC_DEBUG 1447f7b951a8SRobert Watson atomic_subtract_int(&nmacifnets, 1); 1448f7b951a8SRobert Watson #endif 1449f7b951a8SRobert Watson } 1450f7b951a8SRobert Watson 145187807196SRobert Watson void 145287807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 145387807196SRobert Watson { 145487807196SRobert Watson 1455f7b951a8SRobert Watson mac_destroy_ifnet_label(&ifp->if_label); 145687807196SRobert Watson } 145787807196SRobert Watson 145887807196SRobert Watson void 145987807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 146087807196SRobert Watson { 146187807196SRobert Watson 146287807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 146387807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 146487807196SRobert Watson #ifdef MAC_DEBUG 146587807196SRobert Watson atomic_subtract_int(&nmacipqs, 1); 146687807196SRobert Watson #endif 146787807196SRobert Watson } 146887807196SRobert Watson 146987807196SRobert Watson void 147087807196SRobert Watson mac_destroy_mbuf(struct mbuf *m) 147187807196SRobert Watson { 147287807196SRobert Watson 147387807196SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 147487807196SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 147587807196SRobert Watson #ifdef MAC_DEBUG 147687807196SRobert Watson atomic_subtract_int(&nmacmbufs, 1); 147708bcdc58SRobert Watson #endif 147808bcdc58SRobert Watson } 147908bcdc58SRobert Watson 148008bcdc58SRobert Watson void 148108bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 148208bcdc58SRobert Watson { 148308bcdc58SRobert Watson 148408bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 148508bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 148608bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 148708bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 148808bcdc58SRobert Watson #ifdef MAC_DEBUG 148908bcdc58SRobert Watson atomic_subtract_int(&nmacmounts, 1); 149008bcdc58SRobert Watson #endif 149108bcdc58SRobert Watson } 149208bcdc58SRobert Watson 1493f7b951a8SRobert Watson static void 1494f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 1495f7b951a8SRobert Watson { 1496f7b951a8SRobert Watson 1497f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 1498f7b951a8SRobert Watson mac_destroy_label(label); 1499f7b951a8SRobert Watson #ifdef MAC_DEBUG 1500f7b951a8SRobert Watson atomic_subtract_int(&nmacpipes, 1); 1501f7b951a8SRobert Watson #endif 1502f7b951a8SRobert Watson } 1503f7b951a8SRobert Watson 150487807196SRobert Watson void 150587807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 150608bcdc58SRobert Watson { 150708bcdc58SRobert Watson 1508f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 150987807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 151087807196SRobert Watson } 151187807196SRobert Watson 151283985c26SRobert Watson static void 151383985c26SRobert Watson mac_destroy_socket_label(struct label *label) 151483985c26SRobert Watson { 151583985c26SRobert Watson 151683985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 151783985c26SRobert Watson mac_destroy_label(label); 151883985c26SRobert Watson #ifdef MAC_DEBUG 151983985c26SRobert Watson atomic_subtract_int(&nmacsockets, 1); 152083985c26SRobert Watson #endif 152183985c26SRobert Watson } 152283985c26SRobert Watson 152383985c26SRobert Watson static void 152483985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 152583985c26SRobert Watson { 152683985c26SRobert Watson 152783985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 152883985c26SRobert Watson mac_destroy_label(label); 152983985c26SRobert Watson } 153083985c26SRobert Watson 153187807196SRobert Watson void 153287807196SRobert Watson mac_destroy_socket(struct socket *socket) 153387807196SRobert Watson { 153487807196SRobert Watson 153583985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 153683985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 153708bcdc58SRobert Watson } 153808bcdc58SRobert Watson 153908bcdc58SRobert Watson static void 1540f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label) 154108bcdc58SRobert Watson { 154208bcdc58SRobert Watson 1543f7b951a8SRobert Watson MAC_PERFORM(destroy_vnode_label, label); 154408bcdc58SRobert Watson mac_destroy_label(label); 154508bcdc58SRobert Watson #ifdef MAC_DEBUG 1546f7b951a8SRobert Watson atomic_subtract_int(&nmacvnodes, 1); 154708bcdc58SRobert Watson #endif 154808bcdc58SRobert Watson } 154908bcdc58SRobert Watson 155008bcdc58SRobert Watson void 155108bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 155208bcdc58SRobert Watson { 155308bcdc58SRobert Watson 1554f7b951a8SRobert Watson mac_destroy_vnode_label(&vp->v_label); 1555f7b951a8SRobert Watson } 1556f7b951a8SRobert Watson 1557f7b951a8SRobert Watson static void 1558f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 1559f7b951a8SRobert Watson { 1560f7b951a8SRobert Watson 1561f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 1562f7b951a8SRobert Watson } 1563f7b951a8SRobert Watson 1564f7b951a8SRobert Watson static void 1565f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest) 1566f7b951a8SRobert Watson { 1567f7b951a8SRobert Watson 1568f7b951a8SRobert Watson MAC_PERFORM(copy_vnode_label, src, dest); 156908bcdc58SRobert Watson } 157008bcdc58SRobert Watson 157169bbb5b1SRobert Watson static int 1572f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 1573f7b951a8SRobert Watson { 1574f7b951a8SRobert Watson 1575f7b951a8SRobert Watson if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1576f7b951a8SRobert Watson return (EINVAL); 1577f7b951a8SRobert Watson 1578f7b951a8SRobert Watson return (0); 1579f7b951a8SRobert Watson } 1580f7b951a8SRobert Watson 1581f7b951a8SRobert Watson static int 1582f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements, 1583f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 158469bbb5b1SRobert Watson { 158569bbb5b1SRobert Watson int error; 158669bbb5b1SRobert Watson 1587f7b951a8SRobert Watson MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 158869bbb5b1SRobert Watson 158969bbb5b1SRobert Watson return (error); 159069bbb5b1SRobert Watson } 159169bbb5b1SRobert Watson 159269bbb5b1SRobert Watson static int 1593f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements, 1594f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 159569bbb5b1SRobert Watson { 159669bbb5b1SRobert Watson int error; 159769bbb5b1SRobert Watson 1598f7b951a8SRobert Watson MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1599f7b951a8SRobert Watson 1600f7b951a8SRobert Watson return (error); 1601f7b951a8SRobert Watson } 1602f7b951a8SRobert Watson 1603f7b951a8SRobert Watson static int 1604f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 1605f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1606f7b951a8SRobert Watson { 1607f7b951a8SRobert Watson int error; 1608f7b951a8SRobert Watson 1609f7b951a8SRobert Watson MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1610f7b951a8SRobert Watson 1611f7b951a8SRobert Watson return (error); 1612f7b951a8SRobert Watson } 1613f7b951a8SRobert Watson 1614f7b951a8SRobert Watson static int 1615f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 1616f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1617f7b951a8SRobert Watson { 1618f7b951a8SRobert Watson int error; 1619f7b951a8SRobert Watson 1620f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1621f7b951a8SRobert Watson 1622f7b951a8SRobert Watson return (error); 1623f7b951a8SRobert Watson } 1624f7b951a8SRobert Watson 1625f7b951a8SRobert Watson static int 1626f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 1627f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1628f7b951a8SRobert Watson { 1629f7b951a8SRobert Watson int error; 1630f7b951a8SRobert Watson 1631f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1632f7b951a8SRobert Watson 1633f7b951a8SRobert Watson return (error); 1634f7b951a8SRobert Watson } 1635f7b951a8SRobert Watson 1636f7b951a8SRobert Watson static int 1637f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements, 1638f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1639f7b951a8SRobert Watson { 1640f7b951a8SRobert Watson int error; 1641f7b951a8SRobert Watson 1642f7b951a8SRobert Watson MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1643f7b951a8SRobert Watson 1644f7b951a8SRobert Watson return (error); 1645f7b951a8SRobert Watson } 1646f7b951a8SRobert Watson 1647f7b951a8SRobert Watson static int 1648f7b951a8SRobert Watson mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) 1649f7b951a8SRobert Watson { 1650f7b951a8SRobert Watson int error; 1651f7b951a8SRobert Watson 1652f7b951a8SRobert Watson MAC_CHECK(externalize_vnode_oldmac, label, extmac); 1653f7b951a8SRobert Watson 1654f7b951a8SRobert Watson return (error); 1655f7b951a8SRobert Watson } 1656f7b951a8SRobert Watson 1657f7b951a8SRobert Watson static int 1658f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string) 1659f7b951a8SRobert Watson { 1660f7b951a8SRobert Watson int error; 1661f7b951a8SRobert Watson 1662f7b951a8SRobert Watson MAC_INTERNALIZE(cred_label, label, string); 1663f7b951a8SRobert Watson 1664f7b951a8SRobert Watson return (error); 1665f7b951a8SRobert Watson } 1666f7b951a8SRobert Watson 1667f7b951a8SRobert Watson static int 1668f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string) 1669f7b951a8SRobert Watson { 1670f7b951a8SRobert Watson int error; 1671f7b951a8SRobert Watson 1672f7b951a8SRobert Watson MAC_INTERNALIZE(ifnet_label, label, string); 1673f7b951a8SRobert Watson 1674f7b951a8SRobert Watson return (error); 1675f7b951a8SRobert Watson } 1676f7b951a8SRobert Watson 1677f7b951a8SRobert Watson static int 1678f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 1679f7b951a8SRobert Watson { 1680f7b951a8SRobert Watson int error; 1681f7b951a8SRobert Watson 1682f7b951a8SRobert Watson MAC_INTERNALIZE(pipe_label, label, string); 1683f7b951a8SRobert Watson 1684f7b951a8SRobert Watson return (error); 1685f7b951a8SRobert Watson } 1686f7b951a8SRobert Watson 1687f7b951a8SRobert Watson static int 1688f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string) 1689f7b951a8SRobert Watson { 1690f7b951a8SRobert Watson int error; 1691f7b951a8SRobert Watson 1692f7b951a8SRobert Watson MAC_INTERNALIZE(socket_label, label, string); 1693f7b951a8SRobert Watson 1694f7b951a8SRobert Watson return (error); 1695f7b951a8SRobert Watson } 1696f7b951a8SRobert Watson 1697f7b951a8SRobert Watson static int 1698f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string) 1699f7b951a8SRobert Watson { 1700f7b951a8SRobert Watson int error; 1701f7b951a8SRobert Watson 1702f7b951a8SRobert Watson MAC_INTERNALIZE(vnode_label, label, string); 170369bbb5b1SRobert Watson 170469bbb5b1SRobert Watson return (error); 170569bbb5b1SRobert Watson } 170669bbb5b1SRobert Watson 170769bbb5b1SRobert Watson /* 170869bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 170969bbb5b1SRobert Watson * kernel processes and threads are spawned. 171069bbb5b1SRobert Watson */ 171169bbb5b1SRobert Watson void 171269bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 171369bbb5b1SRobert Watson { 171469bbb5b1SRobert Watson 171569bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 171669bbb5b1SRobert Watson } 171769bbb5b1SRobert Watson 171869bbb5b1SRobert Watson /* 171969bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 172069bbb5b1SRobert Watson * userland processes and threads are spawned. 172169bbb5b1SRobert Watson */ 172269bbb5b1SRobert Watson void 172369bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 172469bbb5b1SRobert Watson { 172569bbb5b1SRobert Watson 172669bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 172769bbb5b1SRobert Watson } 172869bbb5b1SRobert Watson 172969bbb5b1SRobert Watson void 173069bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 173169bbb5b1SRobert Watson { 173269bbb5b1SRobert Watson 173369bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 173469bbb5b1SRobert Watson } 173569bbb5b1SRobert Watson 173669bbb5b1SRobert Watson /* 173769bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 173869bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 173969bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 174069bbb5b1SRobert Watson */ 174169bbb5b1SRobert Watson void 174269bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 174369bbb5b1SRobert Watson { 174469bbb5b1SRobert Watson 174569bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 174669bbb5b1SRobert Watson } 174769bbb5b1SRobert Watson 174895fab37eSRobert Watson void 174995fab37eSRobert Watson mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 175095fab37eSRobert Watson { 175195fab37eSRobert Watson 175295fab37eSRobert Watson MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 175395fab37eSRobert Watson } 175495fab37eSRobert Watson 175595fab37eSRobert Watson void 175695fab37eSRobert Watson mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) 175795fab37eSRobert Watson { 175895fab37eSRobert Watson 175995fab37eSRobert Watson MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); 176095fab37eSRobert Watson } 176195fab37eSRobert Watson 176295fab37eSRobert Watson /* 176395fab37eSRobert Watson * Support callout for policies that manage their own externalization 176495fab37eSRobert Watson * using extended attributes. 176595fab37eSRobert Watson */ 176695fab37eSRobert Watson static int 176795fab37eSRobert Watson mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) 176895fab37eSRobert Watson { 176995fab37eSRobert Watson int error; 177095fab37eSRobert Watson 177195fab37eSRobert Watson MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, 177295fab37eSRobert Watson &mp->mnt_fslabel); 177395fab37eSRobert Watson 177495fab37eSRobert Watson return (error); 177595fab37eSRobert Watson } 177695fab37eSRobert Watson 177795fab37eSRobert Watson /* 177895fab37eSRobert Watson * Given an externalized mac label, internalize it and stamp it on a 177995fab37eSRobert Watson * vnode. 178095fab37eSRobert Watson */ 178195fab37eSRobert Watson static int 1782f7b951a8SRobert Watson mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) 178395fab37eSRobert Watson { 178495fab37eSRobert Watson int error; 178595fab37eSRobert Watson 178695fab37eSRobert Watson MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); 178795fab37eSRobert Watson 178895fab37eSRobert Watson return (error); 178995fab37eSRobert Watson } 179095fab37eSRobert Watson 179195fab37eSRobert Watson /* 179295fab37eSRobert Watson * Call out to individual policies to update the label in a vnode from 179395fab37eSRobert Watson * the mountpoint. 179495fab37eSRobert Watson */ 179595fab37eSRobert Watson void 179695fab37eSRobert Watson mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) 179795fab37eSRobert Watson { 179895fab37eSRobert Watson 179995fab37eSRobert Watson MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, 180095fab37eSRobert Watson &mp->mnt_fslabel); 180195fab37eSRobert Watson 1802e6e370a7SJeff Roberson ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); 180395fab37eSRobert Watson if (mac_cache_fslabel_in_vnode) 1804e6e370a7SJeff Roberson vp->v_vflag |= VV_CACHEDLABEL; 180595fab37eSRobert Watson } 180695fab37eSRobert Watson 180795fab37eSRobert Watson /* 180895fab37eSRobert Watson * Implementation of VOP_REFRESHLABEL() that relies on extended attributes 180995fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 181095fab37eSRobert Watson * extended attributes. 181195fab37eSRobert Watson */ 181295fab37eSRobert Watson int 181395fab37eSRobert Watson vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) 181495fab37eSRobert Watson { 181595fab37eSRobert Watson struct vnode *vp = ap->a_vp; 1816f7b951a8SRobert Watson struct oldmac extmac; 181795fab37eSRobert Watson int buflen, error; 181895fab37eSRobert Watson 181995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); 182095fab37eSRobert Watson 182195fab37eSRobert Watson /* 182295fab37eSRobert Watson * Call out to external policies first. Order doesn't really 182395fab37eSRobert Watson * matter, as long as failure of one assures failure of all. 182495fab37eSRobert Watson */ 182595fab37eSRobert Watson error = mac_update_vnode_from_extattr(vp, vp->v_mount); 182695fab37eSRobert Watson if (error) 182795fab37eSRobert Watson return (error); 182895fab37eSRobert Watson 182995fab37eSRobert Watson buflen = sizeof(extmac); 183095fab37eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, 183195fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, 183295fab37eSRobert Watson (char *)&extmac, curthread); 183395fab37eSRobert Watson switch (error) { 183495fab37eSRobert Watson case 0: 183595fab37eSRobert Watson /* Got it */ 183695fab37eSRobert Watson break; 183795fab37eSRobert Watson 183895fab37eSRobert Watson case ENOATTR: 183995fab37eSRobert Watson /* 184095fab37eSRobert Watson * Use the label from the mount point. 184195fab37eSRobert Watson */ 184295fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 184395fab37eSRobert Watson return (0); 184495fab37eSRobert Watson 184595fab37eSRobert Watson case EOPNOTSUPP: 184695fab37eSRobert Watson default: 184795fab37eSRobert Watson /* Fail horribly. */ 184895fab37eSRobert Watson return (error); 184995fab37eSRobert Watson } 185095fab37eSRobert Watson 185195fab37eSRobert Watson if (buflen != sizeof(extmac)) 185295fab37eSRobert Watson error = EPERM; /* Fail very closed. */ 185395fab37eSRobert Watson if (error == 0) 185495fab37eSRobert Watson error = mac_update_vnode_from_externalized(vp, &extmac); 185595fab37eSRobert Watson if (error == 0) 1856e6e370a7SJeff Roberson vp->v_vflag |= VV_CACHEDLABEL; 185795fab37eSRobert Watson else { 185895fab37eSRobert Watson struct vattr va; 185995fab37eSRobert Watson 186095fab37eSRobert Watson printf("Corrupted label on %s", 186195fab37eSRobert Watson vp->v_mount->mnt_stat.f_mntonname); 186295fab37eSRobert Watson if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) 186395fab37eSRobert Watson printf(" inum %ld", va.va_fileid); 18646be0c25eSRobert Watson #ifdef MAC_DEBUG 186595fab37eSRobert Watson if (mac_debug_label_fallback) { 186695fab37eSRobert Watson printf(", falling back.\n"); 186795fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 186895fab37eSRobert Watson error = 0; 186995fab37eSRobert Watson } else { 18706be0c25eSRobert Watson #endif 187195fab37eSRobert Watson printf(".\n"); 187295fab37eSRobert Watson error = EPERM; 18736be0c25eSRobert Watson #ifdef MAC_DEBUG 187495fab37eSRobert Watson } 18756be0c25eSRobert Watson #endif 187695fab37eSRobert Watson } 187795fab37eSRobert Watson 187895fab37eSRobert Watson return (error); 187995fab37eSRobert Watson } 188095fab37eSRobert Watson 188195fab37eSRobert Watson /* 188295fab37eSRobert Watson * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle 188395fab37eSRobert Watson * the labeling activity outselves. Filesystems should be careful not 188495fab37eSRobert Watson * to change their minds regarding whether they support vop_refreshlabel() 188595fab37eSRobert Watson * for a vnode or not. Don't cache the vnode here, allow the file 188695fab37eSRobert Watson * system code to determine if it's safe to cache. If we update from 188795fab37eSRobert Watson * the mount, don't cache since a change to the mount label should affect 188895fab37eSRobert Watson * all vnodes. 188995fab37eSRobert Watson */ 189095fab37eSRobert Watson static int 189195fab37eSRobert Watson vn_refreshlabel(struct vnode *vp, struct ucred *cred) 189295fab37eSRobert Watson { 189395fab37eSRobert Watson int error; 189495fab37eSRobert Watson 189595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); 189695fab37eSRobert Watson 189795fab37eSRobert Watson if (vp->v_mount == NULL) { 189895fab37eSRobert Watson /* 189995fab37eSRobert Watson Eventually, we probably want to special-case refreshing 190095fab37eSRobert Watson of deadfs vnodes, and if there's a lock-free race somewhere, 190195fab37eSRobert Watson that case might be handled here. 190295fab37eSRobert Watson 190395fab37eSRobert Watson mac_update_vnode_deadfs(vp); 190495fab37eSRobert Watson return (0); 190595fab37eSRobert Watson */ 190695fab37eSRobert Watson /* printf("vn_refreshlabel: null v_mount\n"); */ 190706be2aaaSNate Lawson if (vp->v_type != VNON) 190895fab37eSRobert Watson printf( 190906be2aaaSNate Lawson "vn_refreshlabel: null v_mount with non-VNON\n"); 191095fab37eSRobert Watson return (EBADF); 191195fab37eSRobert Watson } 191295fab37eSRobert Watson 1913e6e370a7SJeff Roberson if (vp->v_vflag & VV_CACHEDLABEL) { 191495fab37eSRobert Watson mac_vnode_label_cache_hits++; 191595fab37eSRobert Watson return (0); 191695fab37eSRobert Watson } else 191795fab37eSRobert Watson mac_vnode_label_cache_misses++; 191895fab37eSRobert Watson 191995fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 192095fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 192195fab37eSRobert Watson return (0); 192295fab37eSRobert Watson } 192395fab37eSRobert Watson 192495fab37eSRobert Watson error = VOP_REFRESHLABEL(vp, cred, curthread); 192595fab37eSRobert Watson switch (error) { 192695fab37eSRobert Watson case EOPNOTSUPP: 192795fab37eSRobert Watson /* 192895fab37eSRobert Watson * If labels are not supported on this vnode, fall back to 192995fab37eSRobert Watson * the label in the mount and propagate it to the vnode. 193095fab37eSRobert Watson * There should probably be some sort of policy/flag/decision 193195fab37eSRobert Watson * about doing this. 193295fab37eSRobert Watson */ 193395fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 193495fab37eSRobert Watson error = 0; 193595fab37eSRobert Watson default: 193695fab37eSRobert Watson return (error); 193795fab37eSRobert Watson } 193895fab37eSRobert Watson } 193995fab37eSRobert Watson 194095fab37eSRobert Watson /* 194195fab37eSRobert Watson * Helper function for file systems using the vop_std*_ea() calls. This 194295fab37eSRobert Watson * function must be called after EA service is available for the vnode, 194395fab37eSRobert Watson * but before it's hooked up to the namespace so that the node persists 194495fab37eSRobert Watson * if there's a crash, or before it can be accessed. On successful 194595fab37eSRobert Watson * commit of the label to disk (etc), do cache the label. 194695fab37eSRobert Watson */ 194795fab37eSRobert Watson int 194895fab37eSRobert Watson vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) 194995fab37eSRobert Watson { 1950f7b951a8SRobert Watson struct oldmac extmac; 195195fab37eSRobert Watson int error; 195295fab37eSRobert Watson 1953e6e370a7SJeff Roberson ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); 195495fab37eSRobert Watson if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 195595fab37eSRobert Watson mac_update_vnode_from_mount(tvp, tvp->v_mount); 195695fab37eSRobert Watson } else { 195795fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 195895fab37eSRobert Watson if (error) 195995fab37eSRobert Watson return (error); 196095fab37eSRobert Watson 196195fab37eSRobert Watson /* 196295fab37eSRobert Watson * Stick the label in the vnode. Then try to write to 196395fab37eSRobert Watson * disk. If we fail, return a failure to abort the 196495fab37eSRobert Watson * create operation. Really, this failure shouldn't 196595fab37eSRobert Watson * happen except in fairly unusual circumstances (out 196695fab37eSRobert Watson * of disk, etc). 196795fab37eSRobert Watson */ 196895fab37eSRobert Watson mac_create_vnode(cred, dvp, tvp); 196995fab37eSRobert Watson 197095fab37eSRobert Watson error = mac_stdcreatevnode_ea(tvp); 197195fab37eSRobert Watson if (error) 197295fab37eSRobert Watson return (error); 197395fab37eSRobert Watson 197495fab37eSRobert Watson /* 197595fab37eSRobert Watson * XXX: Eventually this will go away and all policies will 197695fab37eSRobert Watson * directly manage their extended attributes. 197795fab37eSRobert Watson */ 1978f7b951a8SRobert Watson error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); 197995fab37eSRobert Watson if (error) 198095fab37eSRobert Watson return (error); 198195fab37eSRobert Watson 198295fab37eSRobert Watson error = vn_extattr_set(tvp, IO_NODELOCKED, 198395fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 198495fab37eSRobert Watson sizeof(extmac), (char *)&extmac, curthread); 198595fab37eSRobert Watson if (error == 0) 1986e6e370a7SJeff Roberson tvp->v_vflag |= VV_CACHEDLABEL; 198795fab37eSRobert Watson else { 198895fab37eSRobert Watson #if 0 198995fab37eSRobert Watson /* 199095fab37eSRobert Watson * In theory, we could have fall-back behavior here. 199195fab37eSRobert Watson * It would probably be incorrect. 199295fab37eSRobert Watson */ 199395fab37eSRobert Watson #endif 199495fab37eSRobert Watson return (error); 199595fab37eSRobert Watson } 199695fab37eSRobert Watson } 199795fab37eSRobert Watson 199895fab37eSRobert Watson return (0); 199995fab37eSRobert Watson } 200095fab37eSRobert Watson 200195fab37eSRobert Watson void 200295fab37eSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 200395fab37eSRobert Watson { 200495fab37eSRobert Watson int error; 200595fab37eSRobert Watson 200695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 200795fab37eSRobert Watson 200895fab37eSRobert Watson error = vn_refreshlabel(vp, old); 200995fab37eSRobert Watson if (error) { 201095fab37eSRobert Watson printf("mac_execve_transition: vn_refreshlabel returned %d\n", 201195fab37eSRobert Watson error); 201295fab37eSRobert Watson printf("mac_execve_transition: using old vnode label\n"); 201395fab37eSRobert Watson } 201495fab37eSRobert Watson 201595fab37eSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 201695fab37eSRobert Watson } 201795fab37eSRobert Watson 201895fab37eSRobert Watson int 201995fab37eSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp) 202095fab37eSRobert Watson { 202195fab37eSRobert Watson int error, result; 202295fab37eSRobert Watson 202395fab37eSRobert Watson error = vn_refreshlabel(vp, old); 202495fab37eSRobert Watson if (error) 202595fab37eSRobert Watson return (error); 202695fab37eSRobert Watson 202795fab37eSRobert Watson result = 0; 202895fab37eSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 202995fab37eSRobert Watson 203095fab37eSRobert Watson return (result); 203195fab37eSRobert Watson } 203295fab37eSRobert Watson 203395fab37eSRobert Watson int 203495fab37eSRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 203595fab37eSRobert Watson { 203695fab37eSRobert Watson int error; 203795fab37eSRobert Watson 203895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 203995fab37eSRobert Watson 204095fab37eSRobert Watson if (!mac_enforce_fs) 204195fab37eSRobert Watson return (0); 204295fab37eSRobert Watson 204395fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 204495fab37eSRobert Watson if (error) 204595fab37eSRobert Watson return (error); 204695fab37eSRobert Watson 204795fab37eSRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 204895fab37eSRobert Watson return (error); 204995fab37eSRobert Watson } 205095fab37eSRobert Watson 205195fab37eSRobert Watson int 205295fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 205395fab37eSRobert Watson { 205495fab37eSRobert Watson int error; 205595fab37eSRobert Watson 205695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 205795fab37eSRobert Watson 205895fab37eSRobert Watson if (!mac_enforce_fs) 205995fab37eSRobert Watson return (0); 206095fab37eSRobert Watson 206195fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 206295fab37eSRobert Watson if (error) 206395fab37eSRobert Watson return (error); 206495fab37eSRobert Watson 206595fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 206695fab37eSRobert Watson return (error); 206795fab37eSRobert Watson } 206895fab37eSRobert Watson 206995fab37eSRobert Watson int 207095fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 207195fab37eSRobert Watson { 207295fab37eSRobert Watson int error; 207395fab37eSRobert Watson 207495fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 207595fab37eSRobert Watson 207695fab37eSRobert Watson if (!mac_enforce_fs) 207795fab37eSRobert Watson return (0); 207895fab37eSRobert Watson 207995fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 208095fab37eSRobert Watson if (error) 208195fab37eSRobert Watson return (error); 208295fab37eSRobert Watson 208395fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 208495fab37eSRobert Watson return (error); 208595fab37eSRobert Watson } 208695fab37eSRobert Watson 208795fab37eSRobert Watson int 208895fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 208995fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 209095fab37eSRobert Watson { 209195fab37eSRobert Watson int error; 209295fab37eSRobert Watson 209395fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 209495fab37eSRobert Watson 209595fab37eSRobert Watson if (!mac_enforce_fs) 209695fab37eSRobert Watson return (0); 209795fab37eSRobert Watson 209895fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 209995fab37eSRobert Watson if (error) 210095fab37eSRobert Watson return (error); 210195fab37eSRobert Watson 210295fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 210395fab37eSRobert Watson return (error); 210495fab37eSRobert Watson } 210595fab37eSRobert Watson 210695fab37eSRobert Watson int 210795fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 210895fab37eSRobert Watson struct componentname *cnp) 210995fab37eSRobert Watson { 211095fab37eSRobert Watson int error; 211195fab37eSRobert Watson 211295fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 211395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 211495fab37eSRobert Watson 211595fab37eSRobert Watson if (!mac_enforce_fs) 211695fab37eSRobert Watson return (0); 211795fab37eSRobert Watson 211895fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 211995fab37eSRobert Watson if (error) 212095fab37eSRobert Watson return (error); 212195fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 212295fab37eSRobert Watson if (error) 212395fab37eSRobert Watson return (error); 212495fab37eSRobert Watson 212595fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 212695fab37eSRobert Watson &vp->v_label, cnp); 212795fab37eSRobert Watson return (error); 212895fab37eSRobert Watson } 212995fab37eSRobert Watson 213095fab37eSRobert Watson int 213195fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 213295fab37eSRobert Watson acl_type_t type) 213395fab37eSRobert Watson { 213495fab37eSRobert Watson int error; 213595fab37eSRobert Watson 213695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 213795fab37eSRobert Watson 213895fab37eSRobert Watson if (!mac_enforce_fs) 213995fab37eSRobert Watson return (0); 214095fab37eSRobert Watson 214195fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 214295fab37eSRobert Watson if (error) 214395fab37eSRobert Watson return (error); 214495fab37eSRobert Watson 214595fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 214695fab37eSRobert Watson return (error); 214795fab37eSRobert Watson } 214895fab37eSRobert Watson 214995fab37eSRobert Watson int 215095fab37eSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 215195fab37eSRobert Watson { 215295fab37eSRobert Watson int error; 215395fab37eSRobert Watson 2154851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 2155851704bbSRobert Watson 215695fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 215795fab37eSRobert Watson return (0); 215895fab37eSRobert Watson 215995fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 216095fab37eSRobert Watson if (error) 216195fab37eSRobert Watson return (error); 216295fab37eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 216395fab37eSRobert Watson 216495fab37eSRobert Watson return (error); 216595fab37eSRobert Watson } 216695fab37eSRobert Watson 216795fab37eSRobert Watson int 216895fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 216995fab37eSRobert Watson { 217095fab37eSRobert Watson int error; 217195fab37eSRobert Watson 217295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 217395fab37eSRobert Watson 217495fab37eSRobert Watson if (!mac_enforce_fs) 217595fab37eSRobert Watson return (0); 217695fab37eSRobert Watson 217795fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 217895fab37eSRobert Watson if (error) 217995fab37eSRobert Watson return (error); 218095fab37eSRobert Watson 218195fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 218295fab37eSRobert Watson return (error); 218395fab37eSRobert Watson } 218495fab37eSRobert Watson 218595fab37eSRobert Watson int 218695fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 218795fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 218895fab37eSRobert Watson { 218995fab37eSRobert Watson int error; 219095fab37eSRobert Watson 219195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 219295fab37eSRobert Watson 219395fab37eSRobert Watson if (!mac_enforce_fs) 219495fab37eSRobert Watson return (0); 219595fab37eSRobert Watson 219695fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 219795fab37eSRobert Watson if (error) 219895fab37eSRobert Watson return (error); 219995fab37eSRobert Watson 220095fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 220195fab37eSRobert Watson attrnamespace, name, uio); 220295fab37eSRobert Watson return (error); 220395fab37eSRobert Watson } 220495fab37eSRobert Watson 220595fab37eSRobert Watson int 22060a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 22070a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 22080a694196SRobert Watson { 22090a694196SRobert Watson int error; 22100a694196SRobert Watson 22110a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 22120a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 22130a694196SRobert Watson 22140a694196SRobert Watson if (!mac_enforce_fs) 22150a694196SRobert Watson return (0); 22160a694196SRobert Watson 22170a694196SRobert Watson error = vn_refreshlabel(dvp, cred); 22180a694196SRobert Watson if (error) 22190a694196SRobert Watson return (error); 22200a694196SRobert Watson 22210a694196SRobert Watson error = vn_refreshlabel(vp, cred); 22220a694196SRobert Watson if (error) 22230a694196SRobert Watson return (error); 22240a694196SRobert Watson 22250a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 22260a694196SRobert Watson &vp->v_label, cnp); 22270a694196SRobert Watson return (error); 22280a694196SRobert Watson } 22290a694196SRobert Watson 22300a694196SRobert Watson int 223195fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 223295fab37eSRobert Watson struct componentname *cnp) 223395fab37eSRobert Watson { 223495fab37eSRobert Watson int error; 223595fab37eSRobert Watson 223695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 223795fab37eSRobert Watson 223895fab37eSRobert Watson if (!mac_enforce_fs) 223995fab37eSRobert Watson return (0); 224095fab37eSRobert Watson 224195fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 224295fab37eSRobert Watson if (error) 224395fab37eSRobert Watson return (error); 224495fab37eSRobert Watson 224595fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 224695fab37eSRobert Watson return (error); 224795fab37eSRobert Watson } 224895fab37eSRobert Watson 2249e183f80eSRobert Watson int 2250e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 225195fab37eSRobert Watson { 2252e183f80eSRobert Watson int error; 225395fab37eSRobert Watson 2254e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 2255ca7850c3SRobert Watson 2256e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 2257e183f80eSRobert Watson return (0); 2258e183f80eSRobert Watson 2259e183f80eSRobert Watson error = vn_refreshlabel(vp, cred); 2260e183f80eSRobert Watson if (error) 2261e183f80eSRobert Watson return (error); 2262e183f80eSRobert Watson 2263e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 2264e183f80eSRobert Watson return (error); 2265e183f80eSRobert Watson } 2266e183f80eSRobert Watson 2267e183f80eSRobert Watson void 2268e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 2269e183f80eSRobert Watson { 2270e183f80eSRobert Watson int result = *prot; 2271e183f80eSRobert Watson 2272e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 2273e183f80eSRobert Watson 2274e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 2275e183f80eSRobert Watson return; 2276e183f80eSRobert Watson 2277e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 2278e183f80eSRobert Watson &result); 2279e183f80eSRobert Watson 2280e183f80eSRobert Watson *prot = result; 2281e183f80eSRobert Watson } 2282e183f80eSRobert Watson 2283e183f80eSRobert Watson int 2284e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 2285e183f80eSRobert Watson { 2286e183f80eSRobert Watson int error; 2287e183f80eSRobert Watson 2288e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 2289e183f80eSRobert Watson 2290e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 2291e183f80eSRobert Watson return (0); 2292e183f80eSRobert Watson 2293e183f80eSRobert Watson error = vn_refreshlabel(vp, cred); 2294e183f80eSRobert Watson if (error) 2295e183f80eSRobert Watson return (error); 2296e183f80eSRobert Watson 2297e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 2298e183f80eSRobert Watson return (error); 229995fab37eSRobert Watson } 230095fab37eSRobert Watson 230195fab37eSRobert Watson int 230295fab37eSRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 230395fab37eSRobert Watson { 230495fab37eSRobert Watson int error; 230595fab37eSRobert Watson 230695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 230795fab37eSRobert Watson 230895fab37eSRobert Watson if (!mac_enforce_fs) 230995fab37eSRobert Watson return (0); 231095fab37eSRobert Watson 231195fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 231295fab37eSRobert Watson if (error) 231395fab37eSRobert Watson return (error); 231495fab37eSRobert Watson 231595fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 231695fab37eSRobert Watson return (error); 231795fab37eSRobert Watson } 231895fab37eSRobert Watson 231995fab37eSRobert Watson int 2320177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 2321177142e4SRobert Watson struct vnode *vp) 23227f724f8bSRobert Watson { 23237f724f8bSRobert Watson int error; 23247f724f8bSRobert Watson 23257f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 23267f724f8bSRobert Watson 23277f724f8bSRobert Watson if (!mac_enforce_fs) 23287f724f8bSRobert Watson return (0); 23297f724f8bSRobert Watson 2330177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 23317f724f8bSRobert Watson if (error) 23327f724f8bSRobert Watson return (error); 23337f724f8bSRobert Watson 2334177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 2335177142e4SRobert Watson &vp->v_label); 23367f724f8bSRobert Watson 23377f724f8bSRobert Watson return (error); 23387f724f8bSRobert Watson } 23397f724f8bSRobert Watson 23407f724f8bSRobert Watson int 2341177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 2342177142e4SRobert Watson struct vnode *vp) 23437f724f8bSRobert Watson { 23447f724f8bSRobert Watson int error; 23457f724f8bSRobert Watson 23467f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 23477f724f8bSRobert Watson 23487f724f8bSRobert Watson if (!mac_enforce_fs) 23497f724f8bSRobert Watson return (0); 23507f724f8bSRobert Watson 2351177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 23527f724f8bSRobert Watson if (error) 23537f724f8bSRobert Watson return (error); 23547f724f8bSRobert Watson 2355177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 2356177142e4SRobert Watson &vp->v_label); 23577f724f8bSRobert Watson 23587f724f8bSRobert Watson return (error); 23597f724f8bSRobert Watson } 23607f724f8bSRobert Watson 23617f724f8bSRobert Watson int 236295fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 236395fab37eSRobert Watson { 236495fab37eSRobert Watson int error; 236595fab37eSRobert Watson 236695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 236795fab37eSRobert Watson 236895fab37eSRobert Watson if (!mac_enforce_fs) 236995fab37eSRobert Watson return (0); 237095fab37eSRobert Watson 237195fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 237295fab37eSRobert Watson if (error) 237395fab37eSRobert Watson return (error); 237495fab37eSRobert Watson 237595fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 237695fab37eSRobert Watson return (error); 237795fab37eSRobert Watson } 237895fab37eSRobert Watson 237995fab37eSRobert Watson int 238095fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 238195fab37eSRobert Watson { 238295fab37eSRobert Watson int error; 238395fab37eSRobert Watson 238495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 238595fab37eSRobert Watson 238695fab37eSRobert Watson if (!mac_enforce_fs) 238795fab37eSRobert Watson return (0); 238895fab37eSRobert Watson 238995fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 239095fab37eSRobert Watson if (error) 239195fab37eSRobert Watson return (error); 239295fab37eSRobert Watson 239395fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 239495fab37eSRobert Watson return (error); 239595fab37eSRobert Watson } 239695fab37eSRobert Watson 239795fab37eSRobert Watson static int 239895fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 239995fab37eSRobert Watson struct label *newlabel) 240095fab37eSRobert Watson { 240195fab37eSRobert Watson int error; 240295fab37eSRobert Watson 240395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 240495fab37eSRobert Watson 240595fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 240695fab37eSRobert Watson if (error) 240795fab37eSRobert Watson return (error); 240895fab37eSRobert Watson 240995fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 241095fab37eSRobert Watson 241195fab37eSRobert Watson return (error); 241295fab37eSRobert Watson } 241395fab37eSRobert Watson 241495fab37eSRobert Watson int 241595fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 241695fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 241795fab37eSRobert Watson { 241895fab37eSRobert Watson int error; 241995fab37eSRobert Watson 242095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 242195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 242295fab37eSRobert Watson 242395fab37eSRobert Watson if (!mac_enforce_fs) 242495fab37eSRobert Watson return (0); 242595fab37eSRobert Watson 242695fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 242795fab37eSRobert Watson if (error) 242895fab37eSRobert Watson return (error); 242995fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 243095fab37eSRobert Watson if (error) 243195fab37eSRobert Watson return (error); 243295fab37eSRobert Watson 243395fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 243495fab37eSRobert Watson &vp->v_label, cnp); 243595fab37eSRobert Watson return (error); 243695fab37eSRobert Watson } 243795fab37eSRobert Watson 243895fab37eSRobert Watson int 243995fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 244095fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 244195fab37eSRobert Watson { 244295fab37eSRobert Watson int error; 244395fab37eSRobert Watson 244495fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 244595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 244695fab37eSRobert Watson 244795fab37eSRobert Watson if (!mac_enforce_fs) 244895fab37eSRobert Watson return (0); 244995fab37eSRobert Watson 245095fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 245195fab37eSRobert Watson if (error) 245295fab37eSRobert Watson return (error); 245395fab37eSRobert Watson if (vp != NULL) { 245495fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 245595fab37eSRobert Watson if (error) 245695fab37eSRobert Watson return (error); 245795fab37eSRobert Watson } 245895fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 245995fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 246095fab37eSRobert Watson return (error); 246195fab37eSRobert Watson } 246295fab37eSRobert Watson 246395fab37eSRobert Watson int 246495fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 246595fab37eSRobert Watson { 246695fab37eSRobert Watson int error; 246795fab37eSRobert Watson 246895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 246995fab37eSRobert Watson 247095fab37eSRobert Watson if (!mac_enforce_fs) 247195fab37eSRobert Watson return (0); 247295fab37eSRobert Watson 247395fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 247495fab37eSRobert Watson if (error) 247595fab37eSRobert Watson return (error); 247695fab37eSRobert Watson 247795fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 247895fab37eSRobert Watson return (error); 247995fab37eSRobert Watson } 248095fab37eSRobert Watson 248195fab37eSRobert Watson int 248295fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 248395fab37eSRobert Watson struct acl *acl) 248495fab37eSRobert Watson { 248595fab37eSRobert Watson int error; 248695fab37eSRobert Watson 248795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 248895fab37eSRobert Watson 248995fab37eSRobert Watson if (!mac_enforce_fs) 249095fab37eSRobert Watson return (0); 249195fab37eSRobert Watson 249295fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 249395fab37eSRobert Watson if (error) 249495fab37eSRobert Watson return (error); 249595fab37eSRobert Watson 249695fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 249795fab37eSRobert Watson return (error); 249895fab37eSRobert Watson } 249995fab37eSRobert Watson 250095fab37eSRobert Watson int 250195fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 250295fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 250395fab37eSRobert Watson { 250495fab37eSRobert Watson int error; 250595fab37eSRobert Watson 250695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 250795fab37eSRobert Watson 250895fab37eSRobert Watson if (!mac_enforce_fs) 250995fab37eSRobert Watson return (0); 251095fab37eSRobert Watson 251195fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 251295fab37eSRobert Watson if (error) 251395fab37eSRobert Watson return (error); 251495fab37eSRobert Watson 251595fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 251695fab37eSRobert Watson attrnamespace, name, uio); 251795fab37eSRobert Watson return (error); 251895fab37eSRobert Watson } 251995fab37eSRobert Watson 252095fab37eSRobert Watson int 252195fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 252295fab37eSRobert Watson { 252395fab37eSRobert Watson int error; 252495fab37eSRobert Watson 252595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 252695fab37eSRobert Watson 252795fab37eSRobert Watson if (!mac_enforce_fs) 252895fab37eSRobert Watson return (0); 252995fab37eSRobert Watson 253095fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 253195fab37eSRobert Watson if (error) 253295fab37eSRobert Watson return (error); 253395fab37eSRobert Watson 253495fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 253595fab37eSRobert Watson return (error); 253695fab37eSRobert Watson } 253795fab37eSRobert Watson 253895fab37eSRobert Watson int 253995fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 254095fab37eSRobert Watson { 254195fab37eSRobert Watson int error; 254295fab37eSRobert Watson 254395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 254495fab37eSRobert Watson 254595fab37eSRobert Watson if (!mac_enforce_fs) 254695fab37eSRobert Watson return (0); 254795fab37eSRobert Watson 254895fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 254995fab37eSRobert Watson if (error) 255095fab37eSRobert Watson return (error); 255195fab37eSRobert Watson 255295fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 255395fab37eSRobert Watson return (error); 255495fab37eSRobert Watson } 255595fab37eSRobert Watson 255695fab37eSRobert Watson int 255795fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 255895fab37eSRobert Watson gid_t gid) 255995fab37eSRobert Watson { 256095fab37eSRobert Watson int error; 256195fab37eSRobert Watson 256295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 256395fab37eSRobert Watson 256495fab37eSRobert Watson if (!mac_enforce_fs) 256595fab37eSRobert Watson return (0); 256695fab37eSRobert Watson 256795fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 256895fab37eSRobert Watson if (error) 256995fab37eSRobert Watson return (error); 257095fab37eSRobert Watson 257195fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 257295fab37eSRobert Watson return (error); 257395fab37eSRobert Watson } 257495fab37eSRobert Watson 257595fab37eSRobert Watson int 257695fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 257795fab37eSRobert Watson struct timespec atime, struct timespec mtime) 257895fab37eSRobert Watson { 257995fab37eSRobert Watson int error; 258095fab37eSRobert Watson 258195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 258295fab37eSRobert Watson 258395fab37eSRobert Watson if (!mac_enforce_fs) 258495fab37eSRobert Watson return (0); 258595fab37eSRobert Watson 258695fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 258795fab37eSRobert Watson if (error) 258895fab37eSRobert Watson return (error); 258995fab37eSRobert Watson 259095fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 259195fab37eSRobert Watson mtime); 259295fab37eSRobert Watson return (error); 259395fab37eSRobert Watson } 259495fab37eSRobert Watson 259595fab37eSRobert Watson int 2596177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2597177142e4SRobert Watson struct vnode *vp) 259895fab37eSRobert Watson { 259995fab37eSRobert Watson int error; 260095fab37eSRobert Watson 260195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 260295fab37eSRobert Watson 260395fab37eSRobert Watson if (!mac_enforce_fs) 260495fab37eSRobert Watson return (0); 260595fab37eSRobert Watson 2606177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 260795fab37eSRobert Watson if (error) 260895fab37eSRobert Watson return (error); 260995fab37eSRobert Watson 2610177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2611177142e4SRobert Watson &vp->v_label); 261295fab37eSRobert Watson return (error); 261395fab37eSRobert Watson } 261495fab37eSRobert Watson 26157f724f8bSRobert Watson int 26161cbfd977SRobert Watson mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) 26171cbfd977SRobert Watson { 26181cbfd977SRobert Watson int error; 26191cbfd977SRobert Watson 26201cbfd977SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_swapon"); 26211cbfd977SRobert Watson 26221cbfd977SRobert Watson if (!mac_enforce_fs) 26231cbfd977SRobert Watson return (0); 26241cbfd977SRobert Watson 26251cbfd977SRobert Watson error = vn_refreshlabel(vp, cred); 26261cbfd977SRobert Watson if (error) 26271cbfd977SRobert Watson return (error); 26281cbfd977SRobert Watson 26291cbfd977SRobert Watson MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); 26301cbfd977SRobert Watson return (error); 26311cbfd977SRobert Watson } 26321cbfd977SRobert Watson 26331cbfd977SRobert Watson int 2634177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2635177142e4SRobert Watson struct vnode *vp) 26367f724f8bSRobert Watson { 26377f724f8bSRobert Watson int error; 26387f724f8bSRobert Watson 26397f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 26407f724f8bSRobert Watson 26417f724f8bSRobert Watson if (!mac_enforce_fs) 26427f724f8bSRobert Watson return (0); 26437f724f8bSRobert Watson 2644177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 26457f724f8bSRobert Watson if (error) 26467f724f8bSRobert Watson return (error); 26477f724f8bSRobert Watson 2648177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2649177142e4SRobert Watson &vp->v_label); 26507f724f8bSRobert Watson 26517f724f8bSRobert Watson return (error); 26527f724f8bSRobert Watson } 26537f724f8bSRobert Watson 265495fab37eSRobert Watson /* 265595fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 265695fab37eSRobert Watson * permission allowed for each object type we know about in its 265795fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 265895fab37eSRobert Watson * know) when necessary. The process lock is not held here. 265995fab37eSRobert Watson */ 266095fab37eSRobert Watson static void 266195fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 266295fab37eSRobert Watson { 266395fab37eSRobert Watson 266495fab37eSRobert Watson /* XXX freeze all other threads */ 266595fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 266695fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 266795fab37eSRobert Watson /* XXX allow other threads to continue */ 266895fab37eSRobert Watson } 266995fab37eSRobert Watson 267095fab37eSRobert Watson static __inline const char * 267195fab37eSRobert Watson prot2str(vm_prot_t prot) 267295fab37eSRobert Watson { 267395fab37eSRobert Watson 267495fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 267595fab37eSRobert Watson case VM_PROT_READ: 267695fab37eSRobert Watson return ("r--"); 267795fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 267895fab37eSRobert Watson return ("rw-"); 267995fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 268095fab37eSRobert Watson return ("r-x"); 268195fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 268295fab37eSRobert Watson return ("rwx"); 268395fab37eSRobert Watson case VM_PROT_WRITE: 268495fab37eSRobert Watson return ("-w-"); 268595fab37eSRobert Watson case VM_PROT_EXECUTE: 268695fab37eSRobert Watson return ("--x"); 268795fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 268895fab37eSRobert Watson return ("-wx"); 268995fab37eSRobert Watson default: 269095fab37eSRobert Watson return ("---"); 269195fab37eSRobert Watson } 269295fab37eSRobert Watson } 269395fab37eSRobert Watson 269495fab37eSRobert Watson static void 269595fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 269695fab37eSRobert Watson struct vm_map *map) 269795fab37eSRobert Watson { 269895fab37eSRobert Watson struct vm_map_entry *vme; 2699e183f80eSRobert Watson int result; 2700e183f80eSRobert Watson vm_prot_t revokeperms; 270195fab37eSRobert Watson vm_object_t object; 270295fab37eSRobert Watson vm_ooffset_t offset; 270395fab37eSRobert Watson struct vnode *vp; 270495fab37eSRobert Watson 2705c0f39905SRobert Watson if (!mac_mmap_revocation) 2706c0f39905SRobert Watson return; 2707c0f39905SRobert Watson 270895fab37eSRobert Watson vm_map_lock_read(map); 270995fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 271095fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 271195fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 271295fab37eSRobert Watson vme->object.sub_map); 271395fab37eSRobert Watson continue; 271495fab37eSRobert Watson } 271595fab37eSRobert Watson /* 271695fab37eSRobert Watson * Skip over entries that obviously are not shared. 271795fab37eSRobert Watson */ 271895fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 271995fab37eSRobert Watson !vme->max_protection) 272095fab37eSRobert Watson continue; 272195fab37eSRobert Watson /* 272295fab37eSRobert Watson * Drill down to the deepest backing object. 272395fab37eSRobert Watson */ 272495fab37eSRobert Watson offset = vme->offset; 272595fab37eSRobert Watson object = vme->object.vm_object; 272695fab37eSRobert Watson if (object == NULL) 272795fab37eSRobert Watson continue; 272895fab37eSRobert Watson while (object->backing_object != NULL) { 272995fab37eSRobert Watson object = object->backing_object; 273095fab37eSRobert Watson offset += object->backing_object_offset; 273195fab37eSRobert Watson } 273295fab37eSRobert Watson /* 273395fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 273495fab37eSRobert Watson * by the MAC system, so only things with backing by a 273595fab37eSRobert Watson * normal object (read: vnodes) are checked. 273695fab37eSRobert Watson */ 273795fab37eSRobert Watson if (object->type != OBJT_VNODE) 273895fab37eSRobert Watson continue; 273995fab37eSRobert Watson vp = (struct vnode *)object->handle; 274095fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2741e183f80eSRobert Watson result = vme->max_protection; 2742e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 274395fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 274495fab37eSRobert Watson /* 274595fab37eSRobert Watson * Find out what maximum protection we may be allowing 274695fab37eSRobert Watson * now but a policy needs to get removed. 274795fab37eSRobert Watson */ 274895fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 274995fab37eSRobert Watson if (!revokeperms) 275095fab37eSRobert Watson continue; 2751b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 2752b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2753b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 2754b656366bSBruce Evans (long)(vme->end - vme->start), 275595fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 275695fab37eSRobert Watson vm_map_lock_upgrade(map); 275795fab37eSRobert Watson /* 275895fab37eSRobert Watson * This is the really simple case: if a map has more 275995fab37eSRobert Watson * max_protection than is allowed, but it's not being 276095fab37eSRobert Watson * actually used (that is, the current protection is 276195fab37eSRobert Watson * still allowed), we can just wipe it out and do 276295fab37eSRobert Watson * nothing more. 276395fab37eSRobert Watson */ 276495fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 276595fab37eSRobert Watson vme->max_protection -= revokeperms; 276695fab37eSRobert Watson } else { 276795fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 276895fab37eSRobert Watson /* 276995fab37eSRobert Watson * In the more complicated case, flush out all 277095fab37eSRobert Watson * pending changes to the object then turn it 277195fab37eSRobert Watson * copy-on-write. 277295fab37eSRobert Watson */ 277395fab37eSRobert Watson vm_object_reference(object); 277495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 277595fab37eSRobert Watson vm_object_page_clean(object, 277695fab37eSRobert Watson OFF_TO_IDX(offset), 277795fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 277895fab37eSRobert Watson PAGE_MASK), 277995fab37eSRobert Watson OBJPC_SYNC); 278095fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 278195fab37eSRobert Watson vm_object_deallocate(object); 278295fab37eSRobert Watson /* 278395fab37eSRobert Watson * Why bother if there's no read permissions 278495fab37eSRobert Watson * anymore? For the rest, we need to leave 278595fab37eSRobert Watson * the write permissions on for COW, or 278695fab37eSRobert Watson * remove them entirely if configured to. 278795fab37eSRobert Watson */ 278895fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 278995fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 279095fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 279195fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 279295fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 279395fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 279495fab37eSRobert Watson } 279595fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 279695fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 279795fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 279895fab37eSRobert Watson } 279995fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 280095fab37eSRobert Watson vme->max_protection = 0; 280195fab37eSRobert Watson vme->protection = 0; 280295fab37eSRobert Watson } 280395fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 280495fab37eSRobert Watson vme->protection & ~revokeperms); 280595fab37eSRobert Watson vm_map_simplify_entry(map, vme); 280695fab37eSRobert Watson } 280795fab37eSRobert Watson vm_map_lock_downgrade(map); 280895fab37eSRobert Watson } 280995fab37eSRobert Watson vm_map_unlock_read(map); 281095fab37eSRobert Watson } 281195fab37eSRobert Watson 281295fab37eSRobert Watson /* 281395fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 281495fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 281595fab37eSRobert Watson * buffer cache. 281695fab37eSRobert Watson */ 281795fab37eSRobert Watson static void 281895fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 281995fab37eSRobert Watson { 282095fab37eSRobert Watson 282195fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 282295fab37eSRobert Watson } 282395fab37eSRobert Watson 282495fab37eSRobert Watson void 282595fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 282695fab37eSRobert Watson { 282795fab37eSRobert Watson 282895fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 282995fab37eSRobert Watson } 283095fab37eSRobert Watson 283195fab37eSRobert Watson void 283295fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 283395fab37eSRobert Watson { 283495fab37eSRobert Watson 283595fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 283695fab37eSRobert Watson } 283795fab37eSRobert Watson 283895fab37eSRobert Watson void 283995fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 284095fab37eSRobert Watson { 284195fab37eSRobert Watson 284295fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 284395fab37eSRobert Watson } 284495fab37eSRobert Watson 284595fab37eSRobert Watson void 284695fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 284795fab37eSRobert Watson { 284895fab37eSRobert Watson 284995fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 285095fab37eSRobert Watson } 285195fab37eSRobert Watson 285295fab37eSRobert Watson void 285395fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 285495fab37eSRobert Watson { 285595fab37eSRobert Watson 285695fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 285795fab37eSRobert Watson } 285895fab37eSRobert Watson 285995fab37eSRobert Watson void 286095fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 286195fab37eSRobert Watson struct socket *newsocket) 286295fab37eSRobert Watson { 286395fab37eSRobert Watson 286495fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 286595fab37eSRobert Watson newsocket, &newsocket->so_label); 286695fab37eSRobert Watson } 286795fab37eSRobert Watson 286895fab37eSRobert Watson static void 286995fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 287095fab37eSRobert Watson struct label *newlabel) 287195fab37eSRobert Watson { 287295fab37eSRobert Watson 287395fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 287495fab37eSRobert Watson } 287595fab37eSRobert Watson 287695fab37eSRobert Watson static void 287795fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 287895fab37eSRobert Watson { 287995fab37eSRobert Watson 288095fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 288195fab37eSRobert Watson } 288295fab37eSRobert Watson 288395fab37eSRobert Watson void 288495fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 288595fab37eSRobert Watson { 288695fab37eSRobert Watson 288795fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 288895fab37eSRobert Watson socket, &socket->so_peerlabel); 288995fab37eSRobert Watson } 289095fab37eSRobert Watson 289195fab37eSRobert Watson void 289295fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 289395fab37eSRobert Watson struct socket *newsocket) 289495fab37eSRobert Watson { 289595fab37eSRobert Watson 289695fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 289795fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 289895fab37eSRobert Watson } 289995fab37eSRobert Watson 290095fab37eSRobert Watson void 290195fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 290295fab37eSRobert Watson { 290395fab37eSRobert Watson 290495fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 290595fab37eSRobert Watson datagram, &datagram->m_pkthdr.label); 290695fab37eSRobert Watson } 290795fab37eSRobert Watson 290895fab37eSRobert Watson void 290995fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 291095fab37eSRobert Watson { 291195fab37eSRobert Watson 291295fab37eSRobert Watson MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 291395fab37eSRobert Watson fragment, &fragment->m_pkthdr.label); 291495fab37eSRobert Watson } 291595fab37eSRobert Watson 291695fab37eSRobert Watson void 291795fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 291895fab37eSRobert Watson { 291995fab37eSRobert Watson 292095fab37eSRobert Watson MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 292195fab37eSRobert Watson &ipq->ipq_label); 292295fab37eSRobert Watson } 292395fab37eSRobert Watson 292495fab37eSRobert Watson void 292595fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 292695fab37eSRobert Watson { 292795fab37eSRobert Watson 292895fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 292995fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 293095fab37eSRobert Watson } 293195fab37eSRobert Watson 293295fab37eSRobert Watson void 293395fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 293495fab37eSRobert Watson { 293595fab37eSRobert Watson 293695fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 293795fab37eSRobert Watson &mbuf->m_pkthdr.label); 293895fab37eSRobert Watson } 293995fab37eSRobert Watson 294095fab37eSRobert Watson void 294195fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 294295fab37eSRobert Watson { 294395fab37eSRobert Watson 294495fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 294595fab37eSRobert Watson &mbuf->m_pkthdr.label); 294695fab37eSRobert Watson } 294795fab37eSRobert Watson 294895fab37eSRobert Watson void 294995fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 295095fab37eSRobert Watson { 295195fab37eSRobert Watson 295295fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 295395fab37eSRobert Watson &mbuf->m_pkthdr.label); 295495fab37eSRobert Watson } 295595fab37eSRobert Watson 295695fab37eSRobert Watson void 295795fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 295895fab37eSRobert Watson struct mbuf *newmbuf) 295995fab37eSRobert Watson { 296095fab37eSRobert Watson 296195fab37eSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 296295fab37eSRobert Watson &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 296395fab37eSRobert Watson &newmbuf->m_pkthdr.label); 296495fab37eSRobert Watson } 296595fab37eSRobert Watson 296695fab37eSRobert Watson void 296795fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 296895fab37eSRobert Watson { 296995fab37eSRobert Watson 297095fab37eSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 297195fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 297295fab37eSRobert Watson } 297395fab37eSRobert Watson 297495fab37eSRobert Watson int 297595fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 297695fab37eSRobert Watson { 297795fab37eSRobert Watson int result; 297895fab37eSRobert Watson 297995fab37eSRobert Watson result = 1; 298095fab37eSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 298195fab37eSRobert Watson ipq, &ipq->ipq_label); 298295fab37eSRobert Watson 298395fab37eSRobert Watson return (result); 298495fab37eSRobert Watson } 298595fab37eSRobert Watson 298695fab37eSRobert Watson void 298795fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 298895fab37eSRobert Watson { 298995fab37eSRobert Watson 299095fab37eSRobert Watson MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 299195fab37eSRobert Watson &ipq->ipq_label); 299295fab37eSRobert Watson } 299395fab37eSRobert Watson 299495fab37eSRobert Watson void 299595fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 299695fab37eSRobert Watson { 299795fab37eSRobert Watson 299895fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 299995fab37eSRobert Watson &mbuf->m_pkthdr.label); 300095fab37eSRobert Watson } 300195fab37eSRobert Watson 300295fab37eSRobert Watson void 300395fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 300495fab37eSRobert Watson { 300595fab37eSRobert Watson 300695fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 300795fab37eSRobert Watson &mp->mnt_fslabel); 300895fab37eSRobert Watson } 300995fab37eSRobert Watson 301095fab37eSRobert Watson void 301195fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 301295fab37eSRobert Watson { 301395fab37eSRobert Watson 301495fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 301595fab37eSRobert Watson &mp->mnt_fslabel); 301695fab37eSRobert Watson } 301795fab37eSRobert Watson 301895fab37eSRobert Watson int 301995fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 302095fab37eSRobert Watson { 302195fab37eSRobert Watson int error; 302295fab37eSRobert Watson 302395fab37eSRobert Watson if (!mac_enforce_network) 302495fab37eSRobert Watson return (0); 302595fab37eSRobert Watson 302695fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 302795fab37eSRobert Watson &ifnet->if_label); 302895fab37eSRobert Watson 302995fab37eSRobert Watson return (error); 303095fab37eSRobert Watson } 303195fab37eSRobert Watson 303295fab37eSRobert Watson static int 303395fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 303495fab37eSRobert Watson { 303595fab37eSRobert Watson int error; 303695fab37eSRobert Watson 303795fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 303895fab37eSRobert Watson 303995fab37eSRobert Watson return (error); 304095fab37eSRobert Watson } 304195fab37eSRobert Watson 304295fab37eSRobert Watson int 304395fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 304495fab37eSRobert Watson { 304595fab37eSRobert Watson int error; 304695fab37eSRobert Watson 304795fab37eSRobert Watson if (!mac_enforce_process) 304895fab37eSRobert Watson return (0); 304995fab37eSRobert Watson 305095fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 305195fab37eSRobert Watson 305295fab37eSRobert Watson return (error); 305395fab37eSRobert Watson } 305495fab37eSRobert Watson 305595fab37eSRobert Watson int 305695fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 305795fab37eSRobert Watson { 305895fab37eSRobert Watson int error; 305995fab37eSRobert Watson 306095fab37eSRobert Watson if (!mac_enforce_network) 306195fab37eSRobert Watson return (0); 306295fab37eSRobert Watson 306395fab37eSRobert Watson KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 306495fab37eSRobert Watson if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 306529e1b85fSBrooks Davis if_printf(ifnet, "not initialized\n"); 306695fab37eSRobert Watson 306795fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 306895fab37eSRobert Watson &mbuf->m_pkthdr.label); 306995fab37eSRobert Watson 307095fab37eSRobert Watson return (error); 307195fab37eSRobert Watson } 307295fab37eSRobert Watson 307395fab37eSRobert Watson int 307495fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 307595fab37eSRobert Watson { 307695fab37eSRobert Watson int error; 307795fab37eSRobert Watson 307895fab37eSRobert Watson if (!mac_enforce_fs) 307995fab37eSRobert Watson return (0); 308095fab37eSRobert Watson 308195fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 308295fab37eSRobert Watson 308395fab37eSRobert Watson return (error); 308495fab37eSRobert Watson } 308595fab37eSRobert Watson 308695fab37eSRobert Watson int 308795fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 308895fab37eSRobert Watson void *data) 308995fab37eSRobert Watson { 309095fab37eSRobert Watson int error; 309195fab37eSRobert Watson 30921aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 30931aa37f53SRobert Watson 30941aa37f53SRobert Watson if (!mac_enforce_pipe) 30951aa37f53SRobert Watson return (0); 30961aa37f53SRobert Watson 309795fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 309895fab37eSRobert Watson 309995fab37eSRobert Watson return (error); 310095fab37eSRobert Watson } 310195fab37eSRobert Watson 310295fab37eSRobert Watson int 3103c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 310495fab37eSRobert Watson { 310595fab37eSRobert Watson int error; 310695fab37eSRobert Watson 31071aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31081aa37f53SRobert Watson 31091aa37f53SRobert Watson if (!mac_enforce_pipe) 31101aa37f53SRobert Watson return (0); 31111aa37f53SRobert Watson 3112c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 3113c024c3eeSRobert Watson 3114c024c3eeSRobert Watson return (error); 3115c024c3eeSRobert Watson } 3116c024c3eeSRobert Watson 3117c024c3eeSRobert Watson int 3118c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 3119c024c3eeSRobert Watson { 3120c024c3eeSRobert Watson int error; 3121c024c3eeSRobert Watson 31221aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31231aa37f53SRobert Watson 31241aa37f53SRobert Watson if (!mac_enforce_pipe) 31251aa37f53SRobert Watson return (0); 31261aa37f53SRobert Watson 3127c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 312895fab37eSRobert Watson 312995fab37eSRobert Watson return (error); 313095fab37eSRobert Watson } 313195fab37eSRobert Watson 313295fab37eSRobert Watson static int 313395fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 313495fab37eSRobert Watson struct label *newlabel) 313595fab37eSRobert Watson { 313695fab37eSRobert Watson int error; 313795fab37eSRobert Watson 31381aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31391aa37f53SRobert Watson 31401aa37f53SRobert Watson if (!mac_enforce_pipe) 31411aa37f53SRobert Watson return (0); 31421aa37f53SRobert Watson 314395fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 314495fab37eSRobert Watson 314595fab37eSRobert Watson return (error); 314695fab37eSRobert Watson } 314795fab37eSRobert Watson 314895fab37eSRobert Watson int 3149c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 3150c024c3eeSRobert Watson { 3151c024c3eeSRobert Watson int error; 3152c024c3eeSRobert Watson 31531aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31541aa37f53SRobert Watson 31551aa37f53SRobert Watson if (!mac_enforce_pipe) 31561aa37f53SRobert Watson return (0); 31571aa37f53SRobert Watson 3158c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 3159c024c3eeSRobert Watson 3160c024c3eeSRobert Watson return (error); 3161c024c3eeSRobert Watson } 3162c024c3eeSRobert Watson 3163c024c3eeSRobert Watson int 3164c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 3165c024c3eeSRobert Watson { 3166c024c3eeSRobert Watson int error; 3167c024c3eeSRobert Watson 31681aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31691aa37f53SRobert Watson 31701aa37f53SRobert Watson if (!mac_enforce_pipe) 31711aa37f53SRobert Watson return (0); 31721aa37f53SRobert Watson 3173c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 3174c024c3eeSRobert Watson 3175c024c3eeSRobert Watson return (error); 3176c024c3eeSRobert Watson } 3177c024c3eeSRobert Watson 3178c024c3eeSRobert Watson int 317995fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 318095fab37eSRobert Watson { 318195fab37eSRobert Watson int error; 318295fab37eSRobert Watson 3183b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 3184b12baf55SRobert Watson 318595fab37eSRobert Watson if (!mac_enforce_process) 318695fab37eSRobert Watson return (0); 318795fab37eSRobert Watson 318895fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 318995fab37eSRobert Watson 319095fab37eSRobert Watson return (error); 319195fab37eSRobert Watson } 319295fab37eSRobert Watson 319395fab37eSRobert Watson int 319495fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 319595fab37eSRobert Watson { 319695fab37eSRobert Watson int error; 319795fab37eSRobert Watson 3198b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 3199b12baf55SRobert Watson 320095fab37eSRobert Watson if (!mac_enforce_process) 320195fab37eSRobert Watson return (0); 320295fab37eSRobert Watson 320395fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 320495fab37eSRobert Watson 320595fab37eSRobert Watson return (error); 320695fab37eSRobert Watson } 320795fab37eSRobert Watson 320895fab37eSRobert Watson int 320995fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 321095fab37eSRobert Watson { 321195fab37eSRobert Watson int error; 321295fab37eSRobert Watson 3213b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 3214b12baf55SRobert Watson 321595fab37eSRobert Watson if (!mac_enforce_process) 321695fab37eSRobert Watson return (0); 321795fab37eSRobert Watson 321895fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 321995fab37eSRobert Watson 322095fab37eSRobert Watson return (error); 322195fab37eSRobert Watson } 322295fab37eSRobert Watson 322395fab37eSRobert Watson int 322495fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 322595fab37eSRobert Watson struct sockaddr *sockaddr) 322695fab37eSRobert Watson { 322795fab37eSRobert Watson int error; 322895fab37eSRobert Watson 322995fab37eSRobert Watson if (!mac_enforce_socket) 323095fab37eSRobert Watson return (0); 323195fab37eSRobert Watson 323295fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 323395fab37eSRobert Watson sockaddr); 323495fab37eSRobert Watson 323595fab37eSRobert Watson return (error); 323695fab37eSRobert Watson } 323795fab37eSRobert Watson 323895fab37eSRobert Watson int 323995fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 324095fab37eSRobert Watson struct sockaddr *sockaddr) 324195fab37eSRobert Watson { 324295fab37eSRobert Watson int error; 324395fab37eSRobert Watson 324495fab37eSRobert Watson if (!mac_enforce_socket) 324595fab37eSRobert Watson return (0); 324695fab37eSRobert Watson 324795fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 324895fab37eSRobert Watson sockaddr); 324995fab37eSRobert Watson 325095fab37eSRobert Watson return (error); 325195fab37eSRobert Watson } 325295fab37eSRobert Watson 325395fab37eSRobert Watson int 3254d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 3255d61198e4SRobert Watson { 3256d61198e4SRobert Watson int error; 3257d61198e4SRobert Watson 3258d61198e4SRobert Watson if (!mac_enforce_socket) 3259d61198e4SRobert Watson return (0); 3260d61198e4SRobert Watson 3261d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 3262d61198e4SRobert Watson &mbuf->m_pkthdr.label); 3263d61198e4SRobert Watson 3264d61198e4SRobert Watson return (error); 3265d61198e4SRobert Watson } 3266d61198e4SRobert Watson 3267d61198e4SRobert Watson int 326895fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 326995fab37eSRobert Watson { 327095fab37eSRobert Watson int error; 327195fab37eSRobert Watson 327295fab37eSRobert Watson if (!mac_enforce_socket) 327395fab37eSRobert Watson return (0); 327495fab37eSRobert Watson 327595fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 327695fab37eSRobert Watson return (error); 327795fab37eSRobert Watson } 327895fab37eSRobert Watson 3279b371c939SRobert Watson int 3280b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 3281b371c939SRobert Watson { 3282b371c939SRobert Watson int error; 3283b371c939SRobert Watson 3284b371c939SRobert Watson if (!mac_enforce_socket) 3285b371c939SRobert Watson return (0); 3286b371c939SRobert Watson 3287b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 3288b371c939SRobert Watson 3289b371c939SRobert Watson return (error); 3290b371c939SRobert Watson } 3291b371c939SRobert Watson 329295fab37eSRobert Watson static int 329395fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 329495fab37eSRobert Watson struct label *newlabel) 329595fab37eSRobert Watson { 329695fab37eSRobert Watson int error; 329795fab37eSRobert Watson 329895fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 329995fab37eSRobert Watson newlabel); 330095fab37eSRobert Watson 330195fab37eSRobert Watson return (error); 330295fab37eSRobert Watson } 330395fab37eSRobert Watson 330495fab37eSRobert Watson int 3305b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 3306b371c939SRobert Watson { 3307b371c939SRobert Watson int error; 3308b371c939SRobert Watson 3309b371c939SRobert Watson if (!mac_enforce_socket) 3310b371c939SRobert Watson return (0); 3311b371c939SRobert Watson 3312b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 3313b371c939SRobert Watson 3314b371c939SRobert Watson return (error); 3315b371c939SRobert Watson } 3316b371c939SRobert Watson 3317b371c939SRobert Watson int 331895fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 331995fab37eSRobert Watson { 332095fab37eSRobert Watson int error; 332195fab37eSRobert Watson 332295fab37eSRobert Watson if (!mac_enforce_socket) 332395fab37eSRobert Watson return (0); 332495fab37eSRobert Watson 332595fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 332695fab37eSRobert Watson 332795fab37eSRobert Watson return (error); 332895fab37eSRobert Watson } 332995fab37eSRobert Watson 333095fab37eSRobert Watson int 333195fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 333295fab37eSRobert Watson struct ifnet *ifnet) 333395fab37eSRobert Watson { 3334f7b951a8SRobert Watson char *elements, *buffer; 3335f7b951a8SRobert Watson struct mac mac; 333695fab37eSRobert Watson int error; 333795fab37eSRobert Watson 3338f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 333995fab37eSRobert Watson if (error) 334095fab37eSRobert Watson return (error); 334195fab37eSRobert Watson 3342f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3343f7b951a8SRobert Watson if (error) 3344f7b951a8SRobert Watson return (error); 3345f7b951a8SRobert Watson 3346f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3347f7b951a8SRobert Watson 3348f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3349f7b951a8SRobert Watson if (error) { 3350f7b951a8SRobert Watson free(elements, M_MACTEMP); 3351f7b951a8SRobert Watson return (error); 3352f7b951a8SRobert Watson } 3353f7b951a8SRobert Watson 3354f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3355f7b951a8SRobert Watson 3356f7b951a8SRobert Watson error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 3357f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3358f7b951a8SRobert Watson if (error == 0) 3359f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3360f7b951a8SRobert Watson 3361f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3362f7b951a8SRobert Watson free(elements, M_MACTEMP); 3363f7b951a8SRobert Watson 3364f7b951a8SRobert Watson return (error); 336595fab37eSRobert Watson } 336695fab37eSRobert Watson 336795fab37eSRobert Watson int 336895fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 336995fab37eSRobert Watson struct ifnet *ifnet) 337095fab37eSRobert Watson { 337195fab37eSRobert Watson struct label intlabel; 3372f7b951a8SRobert Watson struct mac mac; 3373f7b951a8SRobert Watson char *buffer; 337495fab37eSRobert Watson int error; 337595fab37eSRobert Watson 3376f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 337795fab37eSRobert Watson if (error) 337895fab37eSRobert Watson return (error); 337995fab37eSRobert Watson 3380f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 338195fab37eSRobert Watson if (error) 338295fab37eSRobert Watson return (error); 338395fab37eSRobert Watson 3384f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3385f7b951a8SRobert Watson 3386f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3387f7b951a8SRobert Watson if (error) { 3388f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3389f7b951a8SRobert Watson return (error); 3390f7b951a8SRobert Watson } 3391f7b951a8SRobert Watson 3392f7b951a8SRobert Watson mac_init_ifnet_label(&intlabel); 3393f7b951a8SRobert Watson error = mac_internalize_ifnet_label(&intlabel, buffer); 3394f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3395f7b951a8SRobert Watson if (error) { 3396f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3397f7b951a8SRobert Watson return (error); 3398f7b951a8SRobert Watson } 3399f7b951a8SRobert Watson 340095fab37eSRobert Watson /* 340195fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 340295fab37eSRobert Watson * policies impose this check themselves if required by the 340395fab37eSRobert Watson * policy. Eventually, this should go away. 340495fab37eSRobert Watson */ 340595fab37eSRobert Watson error = suser_cred(cred, 0); 3406f7b951a8SRobert Watson if (error) { 3407f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3408f7b951a8SRobert Watson return (error); 3409f7b951a8SRobert Watson } 341095fab37eSRobert Watson 341195fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 341295fab37eSRobert Watson &intlabel); 3413f7b951a8SRobert Watson if (error) { 3414f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3415f7b951a8SRobert Watson return (error); 3416f7b951a8SRobert Watson } 341795fab37eSRobert Watson 341895fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 341995fab37eSRobert Watson 3420f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3421f7b951a8SRobert Watson return (0); 342295fab37eSRobert Watson } 342395fab37eSRobert Watson 342495fab37eSRobert Watson void 342595fab37eSRobert Watson mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 342695fab37eSRobert Watson { 342795fab37eSRobert Watson 342895fab37eSRobert Watson MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 342995fab37eSRobert Watson } 343095fab37eSRobert Watson 343195fab37eSRobert Watson void 343295fab37eSRobert Watson mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 343395fab37eSRobert Watson { 343495fab37eSRobert Watson 343595fab37eSRobert Watson MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 343695fab37eSRobert Watson } 343795fab37eSRobert Watson 343874e62b1bSRobert Watson void 343974e62b1bSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 344074e62b1bSRobert Watson struct devfs_dirent *de) 344174e62b1bSRobert Watson { 344274e62b1bSRobert Watson 344374e62b1bSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 344474e62b1bSRobert Watson &de->de_label); 344574e62b1bSRobert Watson } 344674e62b1bSRobert Watson 344795fab37eSRobert Watson static int 344895fab37eSRobert Watson mac_stdcreatevnode_ea(struct vnode *vp) 344995fab37eSRobert Watson { 345095fab37eSRobert Watson int error; 345195fab37eSRobert Watson 345295fab37eSRobert Watson MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); 345395fab37eSRobert Watson 345495fab37eSRobert Watson return (error); 345595fab37eSRobert Watson } 345695fab37eSRobert Watson 345795fab37eSRobert Watson void 345895fab37eSRobert Watson mac_create_devfs_directory(char *dirname, int dirnamelen, 345995fab37eSRobert Watson struct devfs_dirent *de) 346095fab37eSRobert Watson { 346195fab37eSRobert Watson 346295fab37eSRobert Watson MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 346395fab37eSRobert Watson &de->de_label); 346495fab37eSRobert Watson } 346595fab37eSRobert Watson 346695fab37eSRobert Watson /* 346795fab37eSRobert Watson * When a new vnode is created, this call will initialize its label. 346895fab37eSRobert Watson */ 346995fab37eSRobert Watson void 347095fab37eSRobert Watson mac_create_vnode(struct ucred *cred, struct vnode *parent, 347195fab37eSRobert Watson struct vnode *child) 347295fab37eSRobert Watson { 347395fab37eSRobert Watson int error; 347495fab37eSRobert Watson 347595fab37eSRobert Watson ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); 347695fab37eSRobert Watson ASSERT_VOP_LOCKED(child, "mac_create_vnode"); 347795fab37eSRobert Watson 347895fab37eSRobert Watson error = vn_refreshlabel(parent, cred); 347995fab37eSRobert Watson if (error) { 348095fab37eSRobert Watson printf("mac_create_vnode: vn_refreshlabel returned %d\n", 348195fab37eSRobert Watson error); 348295fab37eSRobert Watson printf("mac_create_vnode: using old vnode label\n"); 348395fab37eSRobert Watson } 348495fab37eSRobert Watson 348595fab37eSRobert Watson MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, 348695fab37eSRobert Watson &child->v_label); 348795fab37eSRobert Watson } 348895fab37eSRobert Watson 348995fab37eSRobert Watson int 349095fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 3491f7b951a8SRobert Watson struct mac *mac) 349295fab37eSRobert Watson { 349395fab37eSRobert Watson struct label intlabel; 3494f7b951a8SRobert Watson char *buffer; 349595fab37eSRobert Watson int error; 349695fab37eSRobert Watson 3497f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 349895fab37eSRobert Watson if (error) 349995fab37eSRobert Watson return (error); 350095fab37eSRobert Watson 3501f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3502f7b951a8SRobert Watson 3503f7b951a8SRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 3504f7b951a8SRobert Watson if (error) { 3505f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3506f7b951a8SRobert Watson return (error); 3507f7b951a8SRobert Watson } 3508f7b951a8SRobert Watson 3509f7b951a8SRobert Watson mac_init_socket_label(&intlabel, M_WAITOK); 3510f7b951a8SRobert Watson error = mac_internalize_socket_label(&intlabel, buffer); 3511f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3512f7b951a8SRobert Watson if (error) { 3513f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 3514f7b951a8SRobert Watson return (error); 3515f7b951a8SRobert Watson } 3516f7b951a8SRobert Watson 351795fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 351895fab37eSRobert Watson if (error) { 3519f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 352095fab37eSRobert Watson return (error); 352195fab37eSRobert Watson } 352295fab37eSRobert Watson 352395fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 352495fab37eSRobert Watson 3525f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 352695fab37eSRobert Watson return (0); 352795fab37eSRobert Watson } 352895fab37eSRobert Watson 352995fab37eSRobert Watson int 353095fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 353195fab37eSRobert Watson { 353295fab37eSRobert Watson int error; 353395fab37eSRobert Watson 35341aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 35351aa37f53SRobert Watson 353695fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 353795fab37eSRobert Watson if (error) 353895fab37eSRobert Watson return (error); 353995fab37eSRobert Watson 354095fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 354195fab37eSRobert Watson 354295fab37eSRobert Watson return (0); 354395fab37eSRobert Watson } 354495fab37eSRobert Watson 354595fab37eSRobert Watson int 354695fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 3547f7b951a8SRobert Watson struct mac *mac) 354895fab37eSRobert Watson { 3549f7b951a8SRobert Watson char *buffer, *elements; 3550f7b951a8SRobert Watson int error; 355195fab37eSRobert Watson 3552f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3553f7b951a8SRobert Watson if (error) 3554f7b951a8SRobert Watson return (error); 3555f7b951a8SRobert Watson 3556f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3557f7b951a8SRobert Watson 3558f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3559f7b951a8SRobert Watson if (error) { 3560f7b951a8SRobert Watson free(elements, M_MACTEMP); 3561f7b951a8SRobert Watson return (error); 3562f7b951a8SRobert Watson } 3563f7b951a8SRobert Watson 3564f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3565f7b951a8SRobert Watson 3566f7b951a8SRobert Watson error = mac_externalize_socket_label(&so->so_label, elements, 3567f7b951a8SRobert Watson buffer, mac->m_buflen, M_WAITOK); 3568f7b951a8SRobert Watson if (error == 0) 3569f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3570f7b951a8SRobert Watson 3571f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3572f7b951a8SRobert Watson free(elements, M_MACTEMP); 3573f7b951a8SRobert Watson 3574f7b951a8SRobert Watson return (error); 357595fab37eSRobert Watson } 357695fab37eSRobert Watson 357795fab37eSRobert Watson int 357895fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 3579f7b951a8SRobert Watson struct mac *mac) 358095fab37eSRobert Watson { 3581f7b951a8SRobert Watson char *elements, *buffer; 3582f7b951a8SRobert Watson int error; 358395fab37eSRobert Watson 3584f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3585f7b951a8SRobert Watson if (error) 3586f7b951a8SRobert Watson return (error); 3587f7b951a8SRobert Watson 3588f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3589f7b951a8SRobert Watson 3590f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3591f7b951a8SRobert Watson if (error) { 3592f7b951a8SRobert Watson free(elements, M_MACTEMP); 3593f7b951a8SRobert Watson return (error); 3594f7b951a8SRobert Watson } 3595f7b951a8SRobert Watson 3596f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3597f7b951a8SRobert Watson 3598f7b951a8SRobert Watson error = mac_externalize_socket_peer_label(&so->so_peerlabel, 3599f7b951a8SRobert Watson elements, buffer, mac->m_buflen, M_WAITOK); 3600f7b951a8SRobert Watson if (error == 0) 3601f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3602f7b951a8SRobert Watson 3603f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3604f7b951a8SRobert Watson free(elements, M_MACTEMP); 3605f7b951a8SRobert Watson 3606f7b951a8SRobert Watson return (error); 360795fab37eSRobert Watson } 360895fab37eSRobert Watson 360995fab37eSRobert Watson /* 361095fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 361195fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 361295fab37eSRobert Watson * extended attributes. 361395fab37eSRobert Watson */ 361495fab37eSRobert Watson int 361595fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 361695fab37eSRobert Watson { 361795fab37eSRobert Watson struct vnode *vp = ap->a_vp; 361895fab37eSRobert Watson struct label *intlabel = ap->a_label; 3619f7b951a8SRobert Watson struct oldmac extmac; 362095fab37eSRobert Watson int error; 362195fab37eSRobert Watson 362295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 362395fab37eSRobert Watson 362495fab37eSRobert Watson /* 362595fab37eSRobert Watson * XXX: Eventually call out to EA check/set calls here. 362695fab37eSRobert Watson * Be particularly careful to avoid race conditions, 362795fab37eSRobert Watson * consistency problems, and stability problems when 362895fab37eSRobert Watson * dealing with multiple EAs. In particular, we require 362995fab37eSRobert Watson * the ability to write multiple EAs on the same file in 363095fab37eSRobert Watson * a single transaction, which the current EA interface 363195fab37eSRobert Watson * does not provide. 363295fab37eSRobert Watson */ 363395fab37eSRobert Watson 3634f7b951a8SRobert Watson error = mac_externalize_vnode_oldmac(intlabel, &extmac); 363595fab37eSRobert Watson if (error) 363695fab37eSRobert Watson return (error); 363795fab37eSRobert Watson 363895fab37eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, 363995fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 364095fab37eSRobert Watson sizeof(extmac), (char *)&extmac, curthread); 364195fab37eSRobert Watson if (error) 364295fab37eSRobert Watson return (error); 364395fab37eSRobert Watson 364495fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 364595fab37eSRobert Watson 3646e6e370a7SJeff Roberson vp->v_vflag |= VV_CACHEDLABEL; 364795fab37eSRobert Watson 364895fab37eSRobert Watson return (0); 364995fab37eSRobert Watson } 365095fab37eSRobert Watson 365195fab37eSRobert Watson static int 365295fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 365395fab37eSRobert Watson { 365495fab37eSRobert Watson int error; 365595fab37eSRobert Watson 365695fab37eSRobert Watson if (vp->v_mount == NULL) { 365795fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 365806be2aaaSNate Lawson if (vp->v_type != VNON) 365906be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 366095fab37eSRobert Watson return (EBADF); 366195fab37eSRobert Watson } 366295fab37eSRobert Watson 366395fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 366495fab37eSRobert Watson return (EOPNOTSUPP); 366595fab37eSRobert Watson 366695fab37eSRobert Watson /* 366795fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 366895fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 366995fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 367095fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 367195fab37eSRobert Watson */ 367295fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 367395fab37eSRobert Watson if (error) 367495fab37eSRobert Watson return (error); 367595fab37eSRobert Watson 367695fab37eSRobert Watson /* 367795fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 367895fab37eSRobert Watson * decisions about who is and is not able to modify labels 367995fab37eSRobert Watson * and protections on files. This might not be right. We can't 368095fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 368195fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 368295fab37eSRobert Watson */ 368395fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 368495fab37eSRobert Watson if (error) 368595fab37eSRobert Watson return (error); 368695fab37eSRobert Watson 368795fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 368895fab37eSRobert Watson if (error) 368995fab37eSRobert Watson return (error); 369095fab37eSRobert Watson 369195fab37eSRobert Watson return (0); 369295fab37eSRobert Watson } 369395fab37eSRobert Watson 3694f7b951a8SRobert Watson int 3695f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3696f7b951a8SRobert Watson { 3697f7b951a8SRobert Watson char *elements, *buffer; 3698f7b951a8SRobert Watson struct mac mac; 3699f7b951a8SRobert Watson struct proc *tproc; 3700f7b951a8SRobert Watson struct ucred *tcred; 3701f7b951a8SRobert Watson int error; 3702f7b951a8SRobert Watson 3703f7b951a8SRobert Watson error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 3704f7b951a8SRobert Watson if (error) 3705f7b951a8SRobert Watson return (error); 3706f7b951a8SRobert Watson 3707f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3708f7b951a8SRobert Watson if (error) 3709f7b951a8SRobert Watson return (error); 3710f7b951a8SRobert Watson 3711f7b951a8SRobert Watson tproc = pfind(uap->pid); 3712f7b951a8SRobert Watson if (tproc == NULL) 3713f7b951a8SRobert Watson return (ESRCH); 3714f7b951a8SRobert Watson 3715f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 3716f7b951a8SRobert Watson error = p_cansee(td, tproc); 3717f7b951a8SRobert Watson if (error == 0) 3718f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 3719f7b951a8SRobert Watson PROC_UNLOCK(tproc); 3720f7b951a8SRobert Watson if (error) 3721f7b951a8SRobert Watson return (error); 3722f7b951a8SRobert Watson 3723f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3724f7b951a8SRobert Watson 3725f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3726f7b951a8SRobert Watson if (error) { 3727f7b951a8SRobert Watson free(elements, M_MACTEMP); 3728f7b951a8SRobert Watson crfree(tcred); 3729f7b951a8SRobert Watson return (error); 3730f7b951a8SRobert Watson } 3731f7b951a8SRobert Watson 3732f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3733f7b951a8SRobert Watson 3734f7b951a8SRobert Watson error = mac_externalize_cred_label(&tcred->cr_label, elements, 3735f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3736f7b951a8SRobert Watson if (error == 0) 3737f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3738f7b951a8SRobert Watson 3739f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3740f7b951a8SRobert Watson free(elements, M_MACTEMP); 3741f7b951a8SRobert Watson crfree(tcred); 3742f7b951a8SRobert Watson return (error); 3743f7b951a8SRobert Watson } 3744f7b951a8SRobert Watson 374595fab37eSRobert Watson /* 374695fab37eSRobert Watson * MPSAFE 374795fab37eSRobert Watson */ 374895fab37eSRobert Watson int 374995fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 375095fab37eSRobert Watson { 3751f7b951a8SRobert Watson char *elements, *buffer; 3752f7b951a8SRobert Watson struct mac mac; 375395fab37eSRobert Watson int error; 375495fab37eSRobert Watson 3755f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3756f7b951a8SRobert Watson if (error) 3757f7b951a8SRobert Watson return (error); 375895fab37eSRobert Watson 3759f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3760f7b951a8SRobert Watson if (error) 3761f7b951a8SRobert Watson return (error); 3762f7b951a8SRobert Watson 3763f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3764f7b951a8SRobert Watson 3765f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3766f7b951a8SRobert Watson if (error) { 3767f7b951a8SRobert Watson free(elements, M_MACTEMP); 3768f7b951a8SRobert Watson return (error); 3769f7b951a8SRobert Watson } 3770f7b951a8SRobert Watson 3771f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3772f7b951a8SRobert Watson 3773f7b951a8SRobert Watson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3774f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3775f7b951a8SRobert Watson if (error == 0) 3776f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3777f7b951a8SRobert Watson 3778f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3779f7b951a8SRobert Watson free(elements, M_MACTEMP); 378095fab37eSRobert Watson return (error); 378195fab37eSRobert Watson } 378295fab37eSRobert Watson 378395fab37eSRobert Watson /* 378495fab37eSRobert Watson * MPSAFE 378595fab37eSRobert Watson */ 378695fab37eSRobert Watson int 378795fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 378895fab37eSRobert Watson { 378995fab37eSRobert Watson struct ucred *newcred, *oldcred; 379095fab37eSRobert Watson struct label intlabel; 3791f7b951a8SRobert Watson struct proc *p; 3792f7b951a8SRobert Watson struct mac mac; 3793f7b951a8SRobert Watson char *buffer; 379495fab37eSRobert Watson int error; 379595fab37eSRobert Watson 3796f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 379795fab37eSRobert Watson if (error) 379895fab37eSRobert Watson return (error); 379995fab37eSRobert Watson 3800f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 380195fab37eSRobert Watson if (error) 380295fab37eSRobert Watson return (error); 380395fab37eSRobert Watson 3804f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3805f7b951a8SRobert Watson 3806f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3807f7b951a8SRobert Watson if (error) { 3808f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3809f7b951a8SRobert Watson return (error); 3810f7b951a8SRobert Watson } 3811f7b951a8SRobert Watson 3812f7b951a8SRobert Watson mac_init_cred_label(&intlabel); 3813f7b951a8SRobert Watson error = mac_internalize_cred_label(&intlabel, buffer); 3814f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3815f7b951a8SRobert Watson if (error) { 3816f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3817f7b951a8SRobert Watson return (error); 3818f7b951a8SRobert Watson } 3819f7b951a8SRobert Watson 382095fab37eSRobert Watson newcred = crget(); 382195fab37eSRobert Watson 382295fab37eSRobert Watson p = td->td_proc; 382395fab37eSRobert Watson PROC_LOCK(p); 382495fab37eSRobert Watson oldcred = p->p_ucred; 382595fab37eSRobert Watson 382695fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 382795fab37eSRobert Watson if (error) { 382895fab37eSRobert Watson PROC_UNLOCK(p); 382995fab37eSRobert Watson crfree(newcred); 3830f7b951a8SRobert Watson goto out; 383195fab37eSRobert Watson } 383295fab37eSRobert Watson 383395fab37eSRobert Watson setsugid(p); 383495fab37eSRobert Watson crcopy(newcred, oldcred); 383595fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 383695fab37eSRobert Watson p->p_ucred = newcred; 3837e5cb5e37SRobert Watson 3838e5cb5e37SRobert Watson /* 3839e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3840e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3841e5cb5e37SRobert Watson */ 3842e5cb5e37SRobert Watson crhold(newcred); 384395fab37eSRobert Watson PROC_UNLOCK(p); 3844e5cb5e37SRobert Watson 3845f7b951a8SRobert Watson if (mac_enforce_vm) { 384616140035SRobert Watson mtx_lock(&Giant); 3847e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 384816140035SRobert Watson mtx_unlock(&Giant); 3849f7b951a8SRobert Watson } 3850e5cb5e37SRobert Watson 3851e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 385295fab37eSRobert Watson crfree(oldcred); 3853f7b951a8SRobert Watson 3854f7b951a8SRobert Watson out: 3855f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3856f7b951a8SRobert Watson return (error); 385795fab37eSRobert Watson } 385895fab37eSRobert Watson 385995fab37eSRobert Watson /* 386095fab37eSRobert Watson * MPSAFE 386195fab37eSRobert Watson */ 386295fab37eSRobert Watson int 386395fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 386495fab37eSRobert Watson { 3865f7b951a8SRobert Watson char *elements, *buffer; 3866f7b951a8SRobert Watson struct label intlabel; 386795fab37eSRobert Watson struct file *fp; 3868f7b951a8SRobert Watson struct mac mac; 386995fab37eSRobert Watson struct vnode *vp; 387095fab37eSRobert Watson struct pipe *pipe; 3871f7b951a8SRobert Watson short label_type; 387295fab37eSRobert Watson int error; 387395fab37eSRobert Watson 3874f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3875f7b951a8SRobert Watson if (error) 3876f7b951a8SRobert Watson return (error); 387795fab37eSRobert Watson 3878f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3879f7b951a8SRobert Watson if (error) 3880f7b951a8SRobert Watson return (error); 3881f7b951a8SRobert Watson 3882f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3883f7b951a8SRobert Watson 3884f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3885f7b951a8SRobert Watson if (error) { 3886f7b951a8SRobert Watson free(elements, M_MACTEMP); 3887f7b951a8SRobert Watson return (error); 3888f7b951a8SRobert Watson } 3889f7b951a8SRobert Watson 3890f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3891f7b951a8SRobert Watson 3892f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 389395fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 389495fab37eSRobert Watson if (error) 389595fab37eSRobert Watson goto out; 389695fab37eSRobert Watson 3897f7b951a8SRobert Watson label_type = fp->f_type; 389895fab37eSRobert Watson switch (fp->f_type) { 389995fab37eSRobert Watson case DTYPE_FIFO: 390095fab37eSRobert Watson case DTYPE_VNODE: 390195fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 390295fab37eSRobert Watson 3903f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3904f7b951a8SRobert Watson 390595fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 390695fab37eSRobert Watson error = vn_refreshlabel(vp, td->td_ucred); 390795fab37eSRobert Watson if (error == 0) 3908f7b951a8SRobert Watson mac_copy_vnode_label(&vp->v_label, &intlabel); 390995fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 3910f7b951a8SRobert Watson 391195fab37eSRobert Watson break; 391295fab37eSRobert Watson case DTYPE_PIPE: 391395fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 3914f7b951a8SRobert Watson 3915f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3916f7b951a8SRobert Watson 3917f7b951a8SRobert Watson PIPE_LOCK(pipe); 3918f7b951a8SRobert Watson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3919f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 392095fab37eSRobert Watson break; 392195fab37eSRobert Watson default: 392295fab37eSRobert Watson error = EINVAL; 3923f7b951a8SRobert Watson fdrop(fp, td); 3924f7b951a8SRobert Watson goto out; 3925f7b951a8SRobert Watson } 3926f7b951a8SRobert Watson fdrop(fp, td); 3927f7b951a8SRobert Watson 3928f7b951a8SRobert Watson switch (label_type) { 3929f7b951a8SRobert Watson case DTYPE_FIFO: 3930f7b951a8SRobert Watson case DTYPE_VNODE: 3931f7b951a8SRobert Watson if (error == 0) 3932f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, 3933f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3934f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3935f7b951a8SRobert Watson break; 3936f7b951a8SRobert Watson case DTYPE_PIPE: 3937f7b951a8SRobert Watson error = mac_externalize_pipe_label(&intlabel, elements, 3938f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3939f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 3940f7b951a8SRobert Watson break; 3941f7b951a8SRobert Watson default: 3942f7b951a8SRobert Watson panic("__mac_get_fd: corrupted label_type"); 394395fab37eSRobert Watson } 394495fab37eSRobert Watson 394595fab37eSRobert Watson if (error == 0) 3946f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 394795fab37eSRobert Watson 394895fab37eSRobert Watson out: 3949f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3950f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3951f7b951a8SRobert Watson free(elements, M_MACTEMP); 3952f7b951a8SRobert Watson 395395fab37eSRobert Watson return (error); 395495fab37eSRobert Watson } 395595fab37eSRobert Watson 395695fab37eSRobert Watson /* 395795fab37eSRobert Watson * MPSAFE 395895fab37eSRobert Watson */ 395995fab37eSRobert Watson int 396095fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 396195fab37eSRobert Watson { 3962f7b951a8SRobert Watson char *elements, *buffer; 396395fab37eSRobert Watson struct nameidata nd; 3964f7b951a8SRobert Watson struct label intlabel; 3965f7b951a8SRobert Watson struct mac mac; 396695fab37eSRobert Watson int error; 396795fab37eSRobert Watson 3968f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3969f7b951a8SRobert Watson if (error) 3970f7b951a8SRobert Watson return (error); 3971f7b951a8SRobert Watson 3972f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3973f7b951a8SRobert Watson if (error) 3974f7b951a8SRobert Watson return (error); 3975f7b951a8SRobert Watson 3976f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3977f7b951a8SRobert Watson 3978f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3979f7b951a8SRobert Watson if (error) { 3980f7b951a8SRobert Watson free(elements, M_MACTEMP); 3981f7b951a8SRobert Watson return (error); 3982f7b951a8SRobert Watson } 3983f7b951a8SRobert Watson 3984f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3985f7b951a8SRobert Watson 3986f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3987f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3988f7b951a8SRobert Watson td); 398995fab37eSRobert Watson error = namei(&nd); 399095fab37eSRobert Watson if (error) 399195fab37eSRobert Watson goto out; 399295fab37eSRobert Watson 3993f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 399495fab37eSRobert Watson error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 399595fab37eSRobert Watson if (error == 0) 3996f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3997f7b951a8SRobert Watson if (error == 0) 3998f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, 3999f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 4000f7b951a8SRobert Watson 400195fab37eSRobert Watson NDFREE(&nd, 0); 4002f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 4003f7b951a8SRobert Watson 4004f7b951a8SRobert Watson if (error == 0) 4005f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 4006f7b951a8SRobert Watson 4007f7b951a8SRobert Watson out: 4008f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 4009f7b951a8SRobert Watson 4010f7b951a8SRobert Watson free(buffer, M_MACTEMP); 4011f7b951a8SRobert Watson free(elements, M_MACTEMP); 4012f7b951a8SRobert Watson 4013f7b951a8SRobert Watson return (error); 4014f7b951a8SRobert Watson } 4015f7b951a8SRobert Watson 4016f7b951a8SRobert Watson /* 4017f7b951a8SRobert Watson * MPSAFE 4018f7b951a8SRobert Watson */ 4019f7b951a8SRobert Watson int 4020f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 4021f7b951a8SRobert Watson { 4022f7b951a8SRobert Watson char *elements, *buffer; 4023f7b951a8SRobert Watson struct nameidata nd; 4024f7b951a8SRobert Watson struct label intlabel; 4025f7b951a8SRobert Watson struct mac mac; 4026f7b951a8SRobert Watson int error; 4027f7b951a8SRobert Watson 4028f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 4029f7b951a8SRobert Watson if (error) 4030f7b951a8SRobert Watson return (error); 4031f7b951a8SRobert Watson 4032f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 4033f7b951a8SRobert Watson if (error) 4034f7b951a8SRobert Watson return (error); 4035f7b951a8SRobert Watson 4036f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 4037f7b951a8SRobert Watson 4038f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 4039f7b951a8SRobert Watson if (error) { 4040f7b951a8SRobert Watson free(elements, M_MACTEMP); 4041f7b951a8SRobert Watson return (error); 4042f7b951a8SRobert Watson } 4043f7b951a8SRobert Watson 4044f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 4045f7b951a8SRobert Watson 4046f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 4047f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 4048f7b951a8SRobert Watson td); 4049f7b951a8SRobert Watson error = namei(&nd); 405095fab37eSRobert Watson if (error) 405195fab37eSRobert Watson goto out; 405295fab37eSRobert Watson 4053f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 4054f7b951a8SRobert Watson error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 4055f7b951a8SRobert Watson if (error == 0) 4056f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 4057f7b951a8SRobert Watson if (error == 0) 4058f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, 4059f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 4060f7b951a8SRobert Watson NDFREE(&nd, 0); 4061f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 4062f7b951a8SRobert Watson 4063f7b951a8SRobert Watson if (error == 0) 4064f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 406595fab37eSRobert Watson 406695fab37eSRobert Watson out: 4067f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 4068f7b951a8SRobert Watson 4069f7b951a8SRobert Watson free(buffer, M_MACTEMP); 4070f7b951a8SRobert Watson free(elements, M_MACTEMP); 4071f7b951a8SRobert Watson 407295fab37eSRobert Watson return (error); 407395fab37eSRobert Watson } 407495fab37eSRobert Watson 407595fab37eSRobert Watson /* 407695fab37eSRobert Watson * MPSAFE 407795fab37eSRobert Watson */ 407895fab37eSRobert Watson int 407995fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 408095fab37eSRobert Watson { 408195fab37eSRobert Watson struct label intlabel; 4082f7b951a8SRobert Watson struct pipe *pipe; 4083f7b951a8SRobert Watson struct file *fp; 408495fab37eSRobert Watson struct mount *mp; 408595fab37eSRobert Watson struct vnode *vp; 4086f7b951a8SRobert Watson struct mac mac; 4087f7b951a8SRobert Watson char *buffer; 408895fab37eSRobert Watson int error; 408995fab37eSRobert Watson 4090f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 4091f7b951a8SRobert Watson if (error) 4092f7b951a8SRobert Watson return (error); 4093f7b951a8SRobert Watson 4094f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 4095f7b951a8SRobert Watson if (error) 4096f7b951a8SRobert Watson return (error); 4097f7b951a8SRobert Watson 4098f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 4099f7b951a8SRobert Watson 4100f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 4101f7b951a8SRobert Watson if (error) { 4102f7b951a8SRobert Watson free(buffer, M_MACTEMP); 4103f7b951a8SRobert Watson return (error); 4104f7b951a8SRobert Watson } 4105f7b951a8SRobert Watson 4106f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 4107f7b951a8SRobert Watson 410895fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 410995fab37eSRobert Watson if (error) 4110f7b951a8SRobert Watson goto out; 411195fab37eSRobert Watson 411295fab37eSRobert Watson switch (fp->f_type) { 411395fab37eSRobert Watson case DTYPE_FIFO: 411495fab37eSRobert Watson case DTYPE_VNODE: 4115f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 4116f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 4117f7b951a8SRobert Watson if (error) { 4118f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 4119f7b951a8SRobert Watson break; 4120f7b951a8SRobert Watson } 4121f7b951a8SRobert Watson 412295fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 412395fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 4124f7b951a8SRobert Watson if (error != 0) { 4125f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 412695fab37eSRobert Watson break; 4127f7b951a8SRobert Watson } 412895fab37eSRobert Watson 412995fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 413095fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 413195fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 413295fab37eSRobert Watson vn_finished_write(mp); 4133f7b951a8SRobert Watson 4134f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 413595fab37eSRobert Watson break; 4136f7b951a8SRobert Watson 413795fab37eSRobert Watson case DTYPE_PIPE: 4138f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 4139f7b951a8SRobert Watson error = mac_internalize_pipe_label(&intlabel, buffer); 4140f7b951a8SRobert Watson if (error == 0) { 414195fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 41421aa37f53SRobert Watson PIPE_LOCK(pipe); 4143f7b951a8SRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, 4144f7b951a8SRobert Watson &intlabel); 41451aa37f53SRobert Watson PIPE_UNLOCK(pipe); 4146f7b951a8SRobert Watson } 4147f7b951a8SRobert Watson 4148f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 414995fab37eSRobert Watson break; 4150f7b951a8SRobert Watson 415195fab37eSRobert Watson default: 415295fab37eSRobert Watson error = EINVAL; 415395fab37eSRobert Watson } 415495fab37eSRobert Watson 415595fab37eSRobert Watson fdrop(fp, td); 4156f7b951a8SRobert Watson out: 4157f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 4158f7b951a8SRobert Watson 4159f7b951a8SRobert Watson free(buffer, M_MACTEMP); 4160f7b951a8SRobert Watson 416195fab37eSRobert Watson return (error); 416295fab37eSRobert Watson } 416395fab37eSRobert Watson 416495fab37eSRobert Watson /* 416595fab37eSRobert Watson * MPSAFE 416695fab37eSRobert Watson */ 416795fab37eSRobert Watson int 416895fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 416995fab37eSRobert Watson { 417095fab37eSRobert Watson struct label intlabel; 4171f7b951a8SRobert Watson struct nameidata nd; 417295fab37eSRobert Watson struct mount *mp; 4173f7b951a8SRobert Watson struct mac mac; 4174f7b951a8SRobert Watson char *buffer; 417595fab37eSRobert Watson int error; 417695fab37eSRobert Watson 4177f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 417895fab37eSRobert Watson if (error) 4179f7b951a8SRobert Watson return (error); 418095fab37eSRobert Watson 4181f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 418295fab37eSRobert Watson if (error) 4183f7b951a8SRobert Watson return (error); 418495fab37eSRobert Watson 4185f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 418695fab37eSRobert Watson 4187f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 4188f7b951a8SRobert Watson if (error) { 4189f7b951a8SRobert Watson free(buffer, M_MACTEMP); 419095fab37eSRobert Watson return (error); 419195fab37eSRobert Watson } 419295fab37eSRobert Watson 4193f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 4194f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 4195f7b951a8SRobert Watson free(buffer, M_MACTEMP); 4196f7b951a8SRobert Watson if (error) { 4197f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 4198f7b951a8SRobert Watson return (error); 4199f7b951a8SRobert Watson } 4200f7b951a8SRobert Watson 4201f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 4202f7b951a8SRobert Watson 4203f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 4204f7b951a8SRobert Watson td); 4205f7b951a8SRobert Watson error = namei(&nd); 4206f7b951a8SRobert Watson if (error == 0) { 4207f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 4208f7b951a8SRobert Watson if (error == 0) 4209f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 4210f7b951a8SRobert Watson td->td_ucred); 4211f7b951a8SRobert Watson vn_finished_write(mp); 4212f7b951a8SRobert Watson } 4213f7b951a8SRobert Watson 4214f7b951a8SRobert Watson NDFREE(&nd, 0); 4215f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 4216f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 4217f7b951a8SRobert Watson 4218f7b951a8SRobert Watson return (error); 4219f7b951a8SRobert Watson } 4220f7b951a8SRobert Watson 4221f7b951a8SRobert Watson /* 4222f7b951a8SRobert Watson * MPSAFE 4223f7b951a8SRobert Watson */ 4224f7b951a8SRobert Watson int 4225f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 4226f7b951a8SRobert Watson { 4227f7b951a8SRobert Watson struct label intlabel; 4228f7b951a8SRobert Watson struct nameidata nd; 4229f7b951a8SRobert Watson struct mount *mp; 4230f7b951a8SRobert Watson struct mac mac; 4231f7b951a8SRobert Watson char *buffer; 4232f7b951a8SRobert Watson int error; 4233f7b951a8SRobert Watson 4234f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 4235f7b951a8SRobert Watson if (error) 4236f7b951a8SRobert Watson return (error); 4237f7b951a8SRobert Watson 4238f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 4239f7b951a8SRobert Watson if (error) 4240f7b951a8SRobert Watson return (error); 4241f7b951a8SRobert Watson 4242f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 4243f7b951a8SRobert Watson 4244f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 4245f7b951a8SRobert Watson if (error) { 4246f7b951a8SRobert Watson free(buffer, M_MACTEMP); 4247f7b951a8SRobert Watson return (error); 4248f7b951a8SRobert Watson } 4249f7b951a8SRobert Watson 4250f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 4251f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 4252f7b951a8SRobert Watson free(buffer, M_MACTEMP); 4253f7b951a8SRobert Watson if (error) { 4254f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 4255f7b951a8SRobert Watson return (error); 4256f7b951a8SRobert Watson } 4257f7b951a8SRobert Watson 4258f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 4259f7b951a8SRobert Watson 4260f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 4261f7b951a8SRobert Watson td); 4262f7b951a8SRobert Watson error = namei(&nd); 4263f7b951a8SRobert Watson if (error == 0) { 4264f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 4265f7b951a8SRobert Watson if (error == 0) 4266f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 4267f7b951a8SRobert Watson td->td_ucred); 4268f7b951a8SRobert Watson vn_finished_write(mp); 4269f7b951a8SRobert Watson } 4270f7b951a8SRobert Watson 4271f7b951a8SRobert Watson NDFREE(&nd, 0); 4272f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 4273f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 4274f7b951a8SRobert Watson 4275f7b951a8SRobert Watson return (error); 4276f7b951a8SRobert Watson } 4277f7b951a8SRobert Watson 4278f7b951a8SRobert Watson /* 4279f7b951a8SRobert Watson * MPSAFE 4280f7b951a8SRobert Watson */ 428127f2eac7SRobert Watson int 428227f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 428327f2eac7SRobert Watson { 428427f2eac7SRobert Watson struct mac_policy_conf *mpc; 428527f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 428627f2eac7SRobert Watson int error; 428727f2eac7SRobert Watson 428827f2eac7SRobert Watson error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 428927f2eac7SRobert Watson if (error) 429027f2eac7SRobert Watson return (error); 429127f2eac7SRobert Watson 429227f2eac7SRobert Watson error = ENOSYS; 429327f2eac7SRobert Watson MAC_POLICY_LIST_BUSY(); 429427f2eac7SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 429527f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 429627f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 429727f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 429827f2eac7SRobert Watson SCARG(uap, call), SCARG(uap, arg)); 429927f2eac7SRobert Watson goto out; 430027f2eac7SRobert Watson } 430127f2eac7SRobert Watson } 430227f2eac7SRobert Watson 430327f2eac7SRobert Watson out: 430427f2eac7SRobert Watson MAC_POLICY_LIST_UNBUSY(); 430527f2eac7SRobert Watson return (error); 430627f2eac7SRobert Watson } 430727f2eac7SRobert Watson 430895fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 430995fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 431095fab37eSRobert Watson 431195fab37eSRobert Watson #else /* !MAC */ 43127bc82500SRobert Watson 43137bc82500SRobert Watson int 4314f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 4315f7b951a8SRobert Watson { 4316f7b951a8SRobert Watson 4317f7b951a8SRobert Watson return (ENOSYS); 4318f7b951a8SRobert Watson } 4319f7b951a8SRobert Watson 4320f7b951a8SRobert Watson int 43217bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 43227bc82500SRobert Watson { 43237bc82500SRobert Watson 43247bc82500SRobert Watson return (ENOSYS); 43257bc82500SRobert Watson } 43267bc82500SRobert Watson 43277bc82500SRobert Watson int 43287bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 43297bc82500SRobert Watson { 43307bc82500SRobert Watson 43317bc82500SRobert Watson return (ENOSYS); 43327bc82500SRobert Watson } 43337bc82500SRobert Watson 43347bc82500SRobert Watson int 43357bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 43367bc82500SRobert Watson { 43377bc82500SRobert Watson 43387bc82500SRobert Watson return (ENOSYS); 43397bc82500SRobert Watson } 43407bc82500SRobert Watson 43417bc82500SRobert Watson int 43427bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 43437bc82500SRobert Watson { 43447bc82500SRobert Watson 43457bc82500SRobert Watson return (ENOSYS); 43467bc82500SRobert Watson } 43477bc82500SRobert Watson 43487bc82500SRobert Watson int 4349f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 4350f7b951a8SRobert Watson { 4351f7b951a8SRobert Watson 4352f7b951a8SRobert Watson return (ENOSYS); 4353f7b951a8SRobert Watson } 4354f7b951a8SRobert Watson 4355f7b951a8SRobert Watson int 43567bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 43577bc82500SRobert Watson { 43587bc82500SRobert Watson 43597bc82500SRobert Watson return (ENOSYS); 43607bc82500SRobert Watson } 43617bc82500SRobert Watson 43627bc82500SRobert Watson int 43637bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 43647bc82500SRobert Watson { 43657bc82500SRobert Watson 43667bc82500SRobert Watson return (ENOSYS); 43677bc82500SRobert Watson } 436895fab37eSRobert Watson 436927f2eac7SRobert Watson int 4370f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 4371f7b951a8SRobert Watson { 4372f7b951a8SRobert Watson 4373f7b951a8SRobert Watson return (ENOSYS); 4374f7b951a8SRobert Watson } 4375f7b951a8SRobert Watson 4376f7b951a8SRobert Watson int 437727f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 437827f2eac7SRobert Watson { 437927f2eac7SRobert Watson 438027f2eac7SRobert Watson return (ENOSYS); 438127f2eac7SRobert Watson } 438227f2eac7SRobert Watson 4383f7b951a8SRobert Watson #endif 4384