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 #ifndef MAC_MAX_POLICIES 10395fab37eSRobert Watson #define MAC_MAX_POLICIES 8 10495fab37eSRobert Watson #endif 10595fab37eSRobert Watson #if MAC_MAX_POLICIES > 32 10695fab37eSRobert Watson #error "MAC_MAX_POLICIES too large" 10795fab37eSRobert Watson #endif 10895fab37eSRobert Watson static unsigned int mac_max_policies = MAC_MAX_POLICIES; 10995fab37eSRobert Watson static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 11095fab37eSRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 11195fab37eSRobert Watson &mac_max_policies, 0, ""); 11295fab37eSRobert Watson 11395fab37eSRobert Watson static int mac_late = 0; 11495fab37eSRobert Watson 11595fab37eSRobert Watson static int mac_enforce_fs = 1; 11695fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 11795fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 11895fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 11995fab37eSRobert Watson 12095fab37eSRobert Watson static int mac_enforce_network = 1; 12195fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 12295fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 12395fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 12495fab37eSRobert Watson 125b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 126b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 127b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 128c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 129b88c98f6SRobert Watson 13095fab37eSRobert Watson static int mac_enforce_process = 1; 13195fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 13295fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 13395fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 13495fab37eSRobert Watson 13595fab37eSRobert Watson static int mac_enforce_socket = 1; 13695fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 13795fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 13895fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 13995fab37eSRobert Watson 140ca7850c3SRobert Watson static int mac_enforce_vm = 1; 141ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 142ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 143c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 144ca7850c3SRobert Watson 14595fab37eSRobert Watson static int mac_label_size = sizeof(struct mac); 14695fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, 14795fab37eSRobert Watson &mac_label_size, 0, "Pre-compiled MAC label size"); 14895fab37eSRobert Watson 14995fab37eSRobert Watson static int mac_cache_fslabel_in_vnode = 1; 15095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, 15195fab37eSRobert Watson &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); 15295fab37eSRobert Watson TUNABLE_INT("security.mac.cache_fslabel_in_vnode", 15395fab37eSRobert Watson &mac_cache_fslabel_in_vnode); 15495fab37eSRobert Watson 15595fab37eSRobert Watson static int mac_vnode_label_cache_hits = 0; 15695fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, 15795fab37eSRobert Watson &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); 15895fab37eSRobert Watson static int mac_vnode_label_cache_misses = 0; 15995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, 16095fab37eSRobert Watson &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); 161c0f39905SRobert Watson 162c0f39905SRobert Watson static int mac_mmap_revocation = 1; 163c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 164c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 165c0f39905SRobert Watson "relabel"); 16699fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 16795fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 16895fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 16995fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 17095fab37eSRobert Watson 171f050add5SRobert Watson #ifdef MAC_DEBUG 1726be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1736be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1746be0c25eSRobert Watson 1756be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1766be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1776be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1786be0c25eSRobert Watson "when label is corrupted."); 1796be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1806be0c25eSRobert Watson &mac_debug_label_fallback); 1816be0c25eSRobert Watson 182b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 183b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 184b2f0927aSRobert Watson 18595fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 18695fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 18795fab37eSRobert Watson nmacipqs, nmacpipes; 188b2f0927aSRobert Watson 189b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 19095fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 191b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 19295fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 193b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 19495fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 195b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 19695fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 197b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 19895fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 199b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 20095fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 201b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 20295fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 203b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 20495fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 205b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 20695fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 207b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 20895fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 209b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 21095fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 211f050add5SRobert Watson #endif 21295fab37eSRobert Watson 21395fab37eSRobert Watson static int error_select(int error1, int error2); 21495fab37eSRobert Watson static int mac_externalize(struct label *label, struct mac *mac); 21595fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 21695fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 21795fab37eSRobert Watson 21895fab37eSRobert Watson static int mac_stdcreatevnode_ea(struct vnode *vp); 219e183f80eSRobert Watson static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 220e183f80eSRobert Watson struct vnode *vp, int *prot); 22195fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 22295fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 22395fab37eSRobert Watson 22483985c26SRobert Watson static void mac_destroy_socket_label(struct label *label); 22583985c26SRobert Watson 22695fab37eSRobert Watson MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); 22795fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 22895fab37eSRobert Watson 22995fab37eSRobert Watson /* 23095fab37eSRobert Watson * mac_policy_list_lock protects the consistency of 'mac_policy_list', 23195fab37eSRobert Watson * the linked list of attached policy modules. Read-only consumers of 23295fab37eSRobert Watson * the list must acquire a shared lock for the duration of their use; 23395fab37eSRobert Watson * writers must acquire an exclusive lock. Note that for compound 23495fab37eSRobert Watson * operations, locks should be held for the entire compound operation, 23595fab37eSRobert Watson * and that this is not yet done for relabel requests. 23695fab37eSRobert Watson */ 23795fab37eSRobert Watson static struct mtx mac_policy_list_lock; 23895fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 23995fab37eSRobert Watson static int mac_policy_list_busy; 24095fab37eSRobert Watson #define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \ 24195fab37eSRobert Watson "mac_policy_list_lock", NULL, MTX_DEF); 24295fab37eSRobert Watson #define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock); 24395fab37eSRobert Watson #define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock); 24495fab37eSRobert Watson 24595fab37eSRobert Watson #define MAC_POLICY_LIST_BUSY() do { \ 24695fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 24795fab37eSRobert Watson mac_policy_list_busy++; \ 24895fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 24995fab37eSRobert Watson } while (0) 25095fab37eSRobert Watson 25195fab37eSRobert Watson #define MAC_POLICY_LIST_UNBUSY() do { \ 25295fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 25395fab37eSRobert Watson mac_policy_list_busy--; \ 25495fab37eSRobert Watson if (mac_policy_list_busy < 0) \ 25595fab37eSRobert Watson panic("Extra mac_policy_list_busy--"); \ 25695fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 25795fab37eSRobert Watson } while (0) 25895fab37eSRobert Watson 25995fab37eSRobert Watson /* 26095fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 26195fab37eSRobert Watson * module list and checking with each as to how it feels about the 26295fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 26395fab37eSRobert Watson * of the caller. 26495fab37eSRobert Watson */ 26595fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 26695fab37eSRobert Watson struct mac_policy_conf *mpc; \ 26795fab37eSRobert Watson \ 26895fab37eSRobert Watson error = 0; \ 26995fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 27095fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 27195fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 27295fab37eSRobert Watson error = error_select( \ 27395fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 27495fab37eSRobert Watson error); \ 27595fab37eSRobert Watson } \ 27695fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 27795fab37eSRobert Watson } while (0) 27895fab37eSRobert Watson 27995fab37eSRobert Watson /* 28095fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 28195fab37eSRobert Watson * the module list, invoking each instance of the operation, and 28295fab37eSRobert Watson * combining the results using the passed C operator. Note that it 28395fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 28495fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 28595fab37eSRobert Watson * a meaningful result. 28695fab37eSRobert Watson */ 28795fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 28895fab37eSRobert Watson struct mac_policy_conf *mpc; \ 28995fab37eSRobert Watson \ 29095fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 29195fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 29295fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 29395fab37eSRobert Watson result = result composition \ 29495fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 29595fab37eSRobert Watson } \ 29695fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 29795fab37eSRobert Watson } while (0) 29895fab37eSRobert Watson 29995fab37eSRobert Watson /* 30095fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 30195fab37eSRobert Watson * module list and invoking that operation for each policy. 30295fab37eSRobert Watson */ 30395fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 30495fab37eSRobert Watson struct mac_policy_conf *mpc; \ 30595fab37eSRobert Watson \ 30695fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 30795fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 30895fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 30995fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 31095fab37eSRobert Watson } \ 31195fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 31295fab37eSRobert Watson } while (0) 31395fab37eSRobert Watson 31495fab37eSRobert Watson /* 31595fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 31695fab37eSRobert Watson */ 31795fab37eSRobert Watson static void 31895fab37eSRobert Watson mac_init(void) 31995fab37eSRobert Watson { 32095fab37eSRobert Watson 32195fab37eSRobert Watson LIST_INIT(&mac_policy_list); 32295fab37eSRobert Watson MAC_POLICY_LIST_LOCKINIT(); 32395fab37eSRobert Watson } 32495fab37eSRobert Watson 32595fab37eSRobert Watson /* 32695fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 32795fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 32895fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 32995fab37eSRobert Watson */ 33095fab37eSRobert Watson static void 33195fab37eSRobert Watson mac_late_init(void) 33295fab37eSRobert Watson { 33395fab37eSRobert Watson 33495fab37eSRobert Watson mac_late = 1; 33595fab37eSRobert Watson } 33695fab37eSRobert Watson 33795fab37eSRobert Watson /* 33895fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 33995fab37eSRobert Watson */ 34095fab37eSRobert Watson int 34195fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 34295fab37eSRobert Watson { 34395fab37eSRobert Watson struct mac_policy_conf *mpc; 34495fab37eSRobert Watson int error; 34595fab37eSRobert Watson 34695fab37eSRobert Watson error = 0; 34795fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 34895fab37eSRobert Watson 34995fab37eSRobert Watson switch (type) { 35095fab37eSRobert Watson case MOD_LOAD: 35195fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 35295fab37eSRobert Watson mac_late) { 35395fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 35495fab37eSRobert Watson "after booting\n", mpc->mpc_name); 35595fab37eSRobert Watson error = EBUSY; 35695fab37eSRobert Watson break; 35795fab37eSRobert Watson } 35895fab37eSRobert Watson error = mac_policy_register(mpc); 35995fab37eSRobert Watson break; 36095fab37eSRobert Watson case MOD_UNLOAD: 36195fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 36295fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 36395fab37eSRobert Watson != 0) 36495fab37eSRobert Watson error = mac_policy_unregister(mpc); 36595fab37eSRobert Watson else 36695fab37eSRobert Watson error = 0; 36795fab37eSRobert Watson break; 36895fab37eSRobert Watson default: 36995fab37eSRobert Watson break; 37095fab37eSRobert Watson } 37195fab37eSRobert Watson 37295fab37eSRobert Watson return (error); 37395fab37eSRobert Watson } 37495fab37eSRobert Watson 37595fab37eSRobert Watson static int 37695fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 37795fab37eSRobert Watson { 37895fab37eSRobert Watson struct mac_policy_conf *tmpc; 37995fab37eSRobert Watson struct mac_policy_op_entry *mpe; 38095fab37eSRobert Watson int slot; 38195fab37eSRobert Watson 382cc51a2b5SRobert Watson MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops), 383cc51a2b5SRobert Watson M_MACOPVEC, M_WAITOK | M_ZERO); 38495fab37eSRobert Watson for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) { 38595fab37eSRobert Watson switch (mpe->mpe_constant) { 38695fab37eSRobert Watson case MAC_OP_LAST: 38795fab37eSRobert Watson /* 38895fab37eSRobert Watson * Doesn't actually happen, but this allows checking 38995fab37eSRobert Watson * that all enumerated values are handled. 39095fab37eSRobert Watson */ 39195fab37eSRobert Watson break; 39295fab37eSRobert Watson case MAC_DESTROY: 39395fab37eSRobert Watson mpc->mpc_ops->mpo_destroy = 39495fab37eSRobert Watson mpe->mpe_function; 39595fab37eSRobert Watson break; 39695fab37eSRobert Watson case MAC_INIT: 39795fab37eSRobert Watson mpc->mpc_ops->mpo_init = 39895fab37eSRobert Watson mpe->mpe_function; 39995fab37eSRobert Watson break; 40027f2eac7SRobert Watson case MAC_SYSCALL: 40127f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall = 40227f2eac7SRobert Watson mpe->mpe_function; 40327f2eac7SRobert Watson break; 40496adb909SRobert Watson case MAC_INIT_BPFDESC_LABEL: 40596adb909SRobert Watson mpc->mpc_ops->mpo_init_bpfdesc_label = 40695fab37eSRobert Watson mpe->mpe_function; 40795fab37eSRobert Watson break; 40896adb909SRobert Watson case MAC_INIT_CRED_LABEL: 40996adb909SRobert Watson mpc->mpc_ops->mpo_init_cred_label = 41095fab37eSRobert Watson mpe->mpe_function; 41195fab37eSRobert Watson break; 41296adb909SRobert Watson case MAC_INIT_DEVFSDIRENT_LABEL: 41396adb909SRobert Watson mpc->mpc_ops->mpo_init_devfsdirent_label = 41495fab37eSRobert Watson mpe->mpe_function; 41595fab37eSRobert Watson break; 41696adb909SRobert Watson case MAC_INIT_IFNET_LABEL: 41796adb909SRobert Watson mpc->mpc_ops->mpo_init_ifnet_label = 41895fab37eSRobert Watson mpe->mpe_function; 41995fab37eSRobert Watson break; 42096adb909SRobert Watson case MAC_INIT_IPQ_LABEL: 42196adb909SRobert Watson mpc->mpc_ops->mpo_init_ipq_label = 42295fab37eSRobert Watson mpe->mpe_function; 42395fab37eSRobert Watson break; 42496adb909SRobert Watson case MAC_INIT_MBUF_LABEL: 42596adb909SRobert Watson mpc->mpc_ops->mpo_init_mbuf_label = 42695fab37eSRobert Watson mpe->mpe_function; 42795fab37eSRobert Watson break; 42896adb909SRobert Watson case MAC_INIT_MOUNT_LABEL: 42996adb909SRobert Watson mpc->mpc_ops->mpo_init_mount_label = 43095fab37eSRobert Watson mpe->mpe_function; 43195fab37eSRobert Watson break; 43296adb909SRobert Watson case MAC_INIT_MOUNT_FS_LABEL: 43396adb909SRobert Watson mpc->mpc_ops->mpo_init_mount_fs_label = 43495fab37eSRobert Watson mpe->mpe_function; 43595fab37eSRobert Watson break; 43696adb909SRobert Watson case MAC_INIT_PIPE_LABEL: 43796adb909SRobert Watson mpc->mpc_ops->mpo_init_pipe_label = 43895fab37eSRobert Watson mpe->mpe_function; 43995fab37eSRobert Watson break; 44096adb909SRobert Watson case MAC_INIT_SOCKET_LABEL: 44196adb909SRobert Watson mpc->mpc_ops->mpo_init_socket_label = 44295fab37eSRobert Watson mpe->mpe_function; 44395fab37eSRobert Watson break; 44496adb909SRobert Watson case MAC_INIT_SOCKET_PEER_LABEL: 44596adb909SRobert Watson mpc->mpc_ops->mpo_init_socket_peer_label = 44695fab37eSRobert Watson mpe->mpe_function; 44795fab37eSRobert Watson break; 44896adb909SRobert Watson case MAC_INIT_TEMP_LABEL: 44996adb909SRobert Watson mpc->mpc_ops->mpo_init_temp_label = 45095fab37eSRobert Watson mpe->mpe_function; 45195fab37eSRobert Watson break; 45296adb909SRobert Watson case MAC_INIT_VNODE_LABEL: 45396adb909SRobert Watson mpc->mpc_ops->mpo_init_vnode_label = 45495fab37eSRobert Watson mpe->mpe_function; 45595fab37eSRobert Watson break; 45696adb909SRobert Watson case MAC_DESTROY_BPFDESC_LABEL: 45796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_bpfdesc_label = 45895fab37eSRobert Watson mpe->mpe_function; 45995fab37eSRobert Watson break; 46096adb909SRobert Watson case MAC_DESTROY_CRED_LABEL: 46196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_cred_label = 46295fab37eSRobert Watson mpe->mpe_function; 46395fab37eSRobert Watson break; 46496adb909SRobert Watson case MAC_DESTROY_DEVFSDIRENT_LABEL: 46596adb909SRobert Watson mpc->mpc_ops->mpo_destroy_devfsdirent_label = 46695fab37eSRobert Watson mpe->mpe_function; 46795fab37eSRobert Watson break; 46896adb909SRobert Watson case MAC_DESTROY_IFNET_LABEL: 46996adb909SRobert Watson mpc->mpc_ops->mpo_destroy_ifnet_label = 47095fab37eSRobert Watson mpe->mpe_function; 47195fab37eSRobert Watson break; 47296adb909SRobert Watson case MAC_DESTROY_IPQ_LABEL: 47396adb909SRobert Watson mpc->mpc_ops->mpo_destroy_ipq_label = 47495fab37eSRobert Watson mpe->mpe_function; 47595fab37eSRobert Watson break; 47696adb909SRobert Watson case MAC_DESTROY_MBUF_LABEL: 47796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mbuf_label = 47895fab37eSRobert Watson mpe->mpe_function; 47995fab37eSRobert Watson break; 48096adb909SRobert Watson case MAC_DESTROY_MOUNT_LABEL: 48196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mount_label = 48295fab37eSRobert Watson mpe->mpe_function; 48395fab37eSRobert Watson break; 48496adb909SRobert Watson case MAC_DESTROY_MOUNT_FS_LABEL: 48596adb909SRobert Watson mpc->mpc_ops->mpo_destroy_mount_fs_label = 48695fab37eSRobert Watson mpe->mpe_function; 48795fab37eSRobert Watson break; 48896adb909SRobert Watson case MAC_DESTROY_PIPE_LABEL: 48996adb909SRobert Watson mpc->mpc_ops->mpo_destroy_pipe_label = 49096adb909SRobert Watson mpe->mpe_function; 49196adb909SRobert Watson break; 49296adb909SRobert Watson case MAC_DESTROY_SOCKET_LABEL: 49396adb909SRobert Watson mpc->mpc_ops->mpo_destroy_socket_label = 49496adb909SRobert Watson mpe->mpe_function; 49596adb909SRobert Watson break; 49696adb909SRobert Watson case MAC_DESTROY_SOCKET_PEER_LABEL: 49796adb909SRobert Watson mpc->mpc_ops->mpo_destroy_socket_peer_label = 49896adb909SRobert Watson mpe->mpe_function; 49996adb909SRobert Watson break; 50096adb909SRobert Watson case MAC_DESTROY_TEMP_LABEL: 50196adb909SRobert Watson mpc->mpc_ops->mpo_destroy_temp_label = 50296adb909SRobert Watson mpe->mpe_function; 50396adb909SRobert Watson break; 50496adb909SRobert Watson case MAC_DESTROY_VNODE_LABEL: 50596adb909SRobert Watson mpc->mpc_ops->mpo_destroy_vnode_label = 50695fab37eSRobert Watson mpe->mpe_function; 50795fab37eSRobert Watson break; 50895fab37eSRobert Watson case MAC_EXTERNALIZE: 50995fab37eSRobert Watson mpc->mpc_ops->mpo_externalize = 51095fab37eSRobert Watson mpe->mpe_function; 51195fab37eSRobert Watson break; 51295fab37eSRobert Watson case MAC_INTERNALIZE: 51395fab37eSRobert Watson mpc->mpc_ops->mpo_internalize = 51495fab37eSRobert Watson mpe->mpe_function; 51595fab37eSRobert Watson break; 51695fab37eSRobert Watson case MAC_CREATE_DEVFS_DEVICE: 51795fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_device = 51895fab37eSRobert Watson mpe->mpe_function; 51995fab37eSRobert Watson break; 52095fab37eSRobert Watson case MAC_CREATE_DEVFS_DIRECTORY: 52195fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_directory = 52295fab37eSRobert Watson mpe->mpe_function; 52395fab37eSRobert Watson break; 52474e62b1bSRobert Watson case MAC_CREATE_DEVFS_SYMLINK: 52574e62b1bSRobert Watson mpc->mpc_ops->mpo_create_devfs_symlink = 52674e62b1bSRobert Watson mpe->mpe_function; 52774e62b1bSRobert Watson break; 52895fab37eSRobert Watson case MAC_CREATE_DEVFS_VNODE: 52995fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_vnode = 53095fab37eSRobert Watson mpe->mpe_function; 53195fab37eSRobert Watson break; 53295fab37eSRobert Watson case MAC_STDCREATEVNODE_EA: 53395fab37eSRobert Watson mpc->mpc_ops->mpo_stdcreatevnode_ea = 53495fab37eSRobert Watson mpe->mpe_function; 53595fab37eSRobert Watson break; 53695fab37eSRobert Watson case MAC_CREATE_VNODE: 53795fab37eSRobert Watson mpc->mpc_ops->mpo_create_vnode = 53895fab37eSRobert Watson mpe->mpe_function; 53995fab37eSRobert Watson break; 54095fab37eSRobert Watson case MAC_CREATE_MOUNT: 54195fab37eSRobert Watson mpc->mpc_ops->mpo_create_mount = 54295fab37eSRobert Watson mpe->mpe_function; 54395fab37eSRobert Watson break; 54495fab37eSRobert Watson case MAC_CREATE_ROOT_MOUNT: 54595fab37eSRobert Watson mpc->mpc_ops->mpo_create_root_mount = 54695fab37eSRobert Watson mpe->mpe_function; 54795fab37eSRobert Watson break; 54895fab37eSRobert Watson case MAC_RELABEL_VNODE: 54995fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_vnode = 55095fab37eSRobert Watson mpe->mpe_function; 55195fab37eSRobert Watson break; 55295fab37eSRobert Watson case MAC_UPDATE_DEVFSDIRENT: 55395fab37eSRobert Watson mpc->mpc_ops->mpo_update_devfsdirent = 55495fab37eSRobert Watson mpe->mpe_function; 55595fab37eSRobert Watson break; 55695fab37eSRobert Watson case MAC_UPDATE_PROCFSVNODE: 55795fab37eSRobert Watson mpc->mpc_ops->mpo_update_procfsvnode = 55895fab37eSRobert Watson mpe->mpe_function; 55995fab37eSRobert Watson break; 56095fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_EXTATTR: 56195fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_extattr = 56295fab37eSRobert Watson mpe->mpe_function; 56395fab37eSRobert Watson break; 56495fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: 56595fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_externalized = 56695fab37eSRobert Watson mpe->mpe_function; 56795fab37eSRobert Watson break; 56895fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_MOUNT: 56995fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_mount = 57095fab37eSRobert Watson mpe->mpe_function; 57195fab37eSRobert Watson break; 57295fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_SOCKET: 57395fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_socket = 57495fab37eSRobert Watson mpe->mpe_function; 57595fab37eSRobert Watson break; 57695fab37eSRobert Watson case MAC_CREATE_PIPE: 57795fab37eSRobert Watson mpc->mpc_ops->mpo_create_pipe = 57895fab37eSRobert Watson mpe->mpe_function; 57995fab37eSRobert Watson break; 58095fab37eSRobert Watson case MAC_CREATE_SOCKET: 58195fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket = 58295fab37eSRobert Watson mpe->mpe_function; 58395fab37eSRobert Watson break; 58495fab37eSRobert Watson case MAC_CREATE_SOCKET_FROM_SOCKET: 58595fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket_from_socket = 58695fab37eSRobert Watson mpe->mpe_function; 58795fab37eSRobert Watson break; 58895fab37eSRobert Watson case MAC_RELABEL_PIPE: 58995fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_pipe = 59095fab37eSRobert Watson mpe->mpe_function; 59195fab37eSRobert Watson break; 59295fab37eSRobert Watson case MAC_RELABEL_SOCKET: 59395fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_socket = 59495fab37eSRobert Watson mpe->mpe_function; 59595fab37eSRobert Watson break; 59695fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_MBUF: 59795fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_mbuf = 59895fab37eSRobert Watson mpe->mpe_function; 59995fab37eSRobert Watson break; 60095fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_SOCKET: 60195fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_socket = 60295fab37eSRobert Watson mpe->mpe_function; 60395fab37eSRobert Watson break; 60495fab37eSRobert Watson case MAC_CREATE_BPFDESC: 60595fab37eSRobert Watson mpc->mpc_ops->mpo_create_bpfdesc = 60695fab37eSRobert Watson mpe->mpe_function; 60795fab37eSRobert Watson break; 60895fab37eSRobert Watson case MAC_CREATE_DATAGRAM_FROM_IPQ: 60995fab37eSRobert Watson mpc->mpc_ops->mpo_create_datagram_from_ipq = 61095fab37eSRobert Watson mpe->mpe_function; 61195fab37eSRobert Watson break; 61295fab37eSRobert Watson case MAC_CREATE_FRAGMENT: 61395fab37eSRobert Watson mpc->mpc_ops->mpo_create_fragment = 61495fab37eSRobert Watson mpe->mpe_function; 61595fab37eSRobert Watson break; 61695fab37eSRobert Watson case MAC_CREATE_IFNET: 61795fab37eSRobert Watson mpc->mpc_ops->mpo_create_ifnet = 61895fab37eSRobert Watson mpe->mpe_function; 61995fab37eSRobert Watson break; 62095fab37eSRobert Watson case MAC_CREATE_IPQ: 62195fab37eSRobert Watson mpc->mpc_ops->mpo_create_ipq = 62295fab37eSRobert Watson mpe->mpe_function; 62395fab37eSRobert Watson break; 62495fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_MBUF: 62595fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_mbuf = 62695fab37eSRobert Watson mpe->mpe_function; 62795fab37eSRobert Watson break; 62895fab37eSRobert Watson case MAC_CREATE_MBUF_LINKLAYER: 62995fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_linklayer = 63095fab37eSRobert Watson mpe->mpe_function; 63195fab37eSRobert Watson break; 63295fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_BPFDESC: 63395fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc = 63495fab37eSRobert Watson mpe->mpe_function; 63595fab37eSRobert Watson break; 63695fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_IFNET: 63795fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_ifnet = 63895fab37eSRobert Watson mpe->mpe_function; 63995fab37eSRobert Watson break; 64095fab37eSRobert Watson case MAC_CREATE_MBUF_MULTICAST_ENCAP: 64195fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_multicast_encap = 64295fab37eSRobert Watson mpe->mpe_function; 64395fab37eSRobert Watson break; 64495fab37eSRobert Watson case MAC_CREATE_MBUF_NETLAYER: 64595fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_netlayer = 64695fab37eSRobert Watson mpe->mpe_function; 64795fab37eSRobert Watson break; 64895fab37eSRobert Watson case MAC_FRAGMENT_MATCH: 64995fab37eSRobert Watson mpc->mpc_ops->mpo_fragment_match = 65095fab37eSRobert Watson mpe->mpe_function; 65195fab37eSRobert Watson break; 65295fab37eSRobert Watson case MAC_RELABEL_IFNET: 65395fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_ifnet = 65495fab37eSRobert Watson mpe->mpe_function; 65595fab37eSRobert Watson break; 65695fab37eSRobert Watson case MAC_UPDATE_IPQ: 65795fab37eSRobert Watson mpc->mpc_ops->mpo_update_ipq = 65895fab37eSRobert Watson mpe->mpe_function; 65995fab37eSRobert Watson break; 66095fab37eSRobert Watson case MAC_CREATE_CRED: 66195fab37eSRobert Watson mpc->mpc_ops->mpo_create_cred = 66295fab37eSRobert Watson mpe->mpe_function; 66395fab37eSRobert Watson break; 66495fab37eSRobert Watson case MAC_EXECVE_TRANSITION: 66595fab37eSRobert Watson mpc->mpc_ops->mpo_execve_transition = 66695fab37eSRobert Watson mpe->mpe_function; 66795fab37eSRobert Watson break; 66895fab37eSRobert Watson case MAC_EXECVE_WILL_TRANSITION: 66995fab37eSRobert Watson mpc->mpc_ops->mpo_execve_will_transition = 67095fab37eSRobert Watson mpe->mpe_function; 67195fab37eSRobert Watson break; 67295fab37eSRobert Watson case MAC_CREATE_PROC0: 673226b96fbSRobert Watson mpc->mpc_ops->mpo_create_proc0 = 674226b96fbSRobert Watson mpe->mpe_function; 67595fab37eSRobert Watson break; 67695fab37eSRobert Watson case MAC_CREATE_PROC1: 677226b96fbSRobert Watson mpc->mpc_ops->mpo_create_proc1 = 678226b96fbSRobert Watson mpe->mpe_function; 67995fab37eSRobert Watson break; 68095fab37eSRobert Watson case MAC_RELABEL_CRED: 68195fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_cred = 68295fab37eSRobert Watson mpe->mpe_function; 68395fab37eSRobert Watson break; 68492dbb82aSRobert Watson case MAC_THREAD_USERRET: 68592dbb82aSRobert Watson mpc->mpc_ops->mpo_thread_userret = 68692dbb82aSRobert Watson mpe->mpe_function; 68792dbb82aSRobert Watson break; 68895fab37eSRobert Watson case MAC_CHECK_BPFDESC_RECEIVE: 68995fab37eSRobert Watson mpc->mpc_ops->mpo_check_bpfdesc_receive = 69095fab37eSRobert Watson mpe->mpe_function; 69195fab37eSRobert Watson break; 69295fab37eSRobert Watson case MAC_CHECK_CRED_RELABEL: 69395fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_relabel = 69495fab37eSRobert Watson mpe->mpe_function; 69595fab37eSRobert Watson break; 69695fab37eSRobert Watson case MAC_CHECK_CRED_VISIBLE: 69795fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_visible = 69895fab37eSRobert Watson mpe->mpe_function; 69995fab37eSRobert Watson break; 70095fab37eSRobert Watson case MAC_CHECK_IFNET_RELABEL: 70195fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_relabel = 70295fab37eSRobert Watson mpe->mpe_function; 70395fab37eSRobert Watson break; 70495fab37eSRobert Watson case MAC_CHECK_IFNET_TRANSMIT: 70595fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_transmit = 70695fab37eSRobert Watson mpe->mpe_function; 70795fab37eSRobert Watson break; 70895fab37eSRobert Watson case MAC_CHECK_MOUNT_STAT: 70995fab37eSRobert Watson mpc->mpc_ops->mpo_check_mount_stat = 71095fab37eSRobert Watson mpe->mpe_function; 71195fab37eSRobert Watson break; 71295fab37eSRobert Watson case MAC_CHECK_PIPE_IOCTL: 71395fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_ioctl = 71495fab37eSRobert Watson mpe->mpe_function; 71595fab37eSRobert Watson break; 716c024c3eeSRobert Watson case MAC_CHECK_PIPE_POLL: 717c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_poll = 718c024c3eeSRobert Watson mpe->mpe_function; 719c024c3eeSRobert Watson break; 720c024c3eeSRobert Watson case MAC_CHECK_PIPE_READ: 721c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_read = 72295fab37eSRobert Watson mpe->mpe_function; 72395fab37eSRobert Watson break; 72495fab37eSRobert Watson case MAC_CHECK_PIPE_RELABEL: 72595fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_relabel = 72695fab37eSRobert Watson mpe->mpe_function; 72795fab37eSRobert Watson break; 728c024c3eeSRobert Watson case MAC_CHECK_PIPE_STAT: 729c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_stat = 730c024c3eeSRobert Watson mpe->mpe_function; 731c024c3eeSRobert Watson break; 732c024c3eeSRobert Watson case MAC_CHECK_PIPE_WRITE: 733c024c3eeSRobert Watson mpc->mpc_ops->mpo_check_pipe_write = 734c024c3eeSRobert Watson mpe->mpe_function; 735c024c3eeSRobert Watson break; 73695fab37eSRobert Watson case MAC_CHECK_PROC_DEBUG: 73795fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_debug = 73895fab37eSRobert Watson mpe->mpe_function; 73995fab37eSRobert Watson break; 74095fab37eSRobert Watson case MAC_CHECK_PROC_SCHED: 74195fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_sched = 74295fab37eSRobert Watson mpe->mpe_function; 74395fab37eSRobert Watson break; 74495fab37eSRobert Watson case MAC_CHECK_PROC_SIGNAL: 74595fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_signal = 74695fab37eSRobert Watson mpe->mpe_function; 74795fab37eSRobert Watson break; 74895fab37eSRobert Watson case MAC_CHECK_SOCKET_BIND: 74995fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_bind = 75095fab37eSRobert Watson mpe->mpe_function; 75195fab37eSRobert Watson break; 75295fab37eSRobert Watson case MAC_CHECK_SOCKET_CONNECT: 75395fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_connect = 75495fab37eSRobert Watson mpe->mpe_function; 75595fab37eSRobert Watson break; 756d61198e4SRobert Watson case MAC_CHECK_SOCKET_DELIVER: 757d61198e4SRobert Watson mpc->mpc_ops->mpo_check_socket_deliver = 75895fab37eSRobert Watson mpe->mpe_function; 75995fab37eSRobert Watson break; 760d61198e4SRobert Watson case MAC_CHECK_SOCKET_LISTEN: 761d61198e4SRobert Watson mpc->mpc_ops->mpo_check_socket_listen = 76295fab37eSRobert Watson mpe->mpe_function; 76395fab37eSRobert Watson break; 764b371c939SRobert Watson case MAC_CHECK_SOCKET_RECEIVE: 765b371c939SRobert Watson mpc->mpc_ops->mpo_check_socket_receive = 766b371c939SRobert Watson mpe->mpe_function; 767b371c939SRobert Watson break; 76895fab37eSRobert Watson case MAC_CHECK_SOCKET_RELABEL: 76995fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_relabel = 77095fab37eSRobert Watson mpe->mpe_function; 77195fab37eSRobert Watson break; 772b371c939SRobert Watson case MAC_CHECK_SOCKET_SEND: 773b371c939SRobert Watson mpc->mpc_ops->mpo_check_socket_send = 774b371c939SRobert Watson mpe->mpe_function; 775b371c939SRobert Watson break; 77695fab37eSRobert Watson case MAC_CHECK_SOCKET_VISIBLE: 77795fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_visible = 77895fab37eSRobert Watson mpe->mpe_function; 77995fab37eSRobert Watson break; 78095fab37eSRobert Watson case MAC_CHECK_VNODE_ACCESS: 78195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_access = 78295fab37eSRobert Watson mpe->mpe_function; 78395fab37eSRobert Watson break; 78495fab37eSRobert Watson case MAC_CHECK_VNODE_CHDIR: 78595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chdir = 78695fab37eSRobert Watson mpe->mpe_function; 78795fab37eSRobert Watson break; 78895fab37eSRobert Watson case MAC_CHECK_VNODE_CHROOT: 78995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chroot = 79095fab37eSRobert Watson mpe->mpe_function; 79195fab37eSRobert Watson break; 79295fab37eSRobert Watson case MAC_CHECK_VNODE_CREATE: 79395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_create = 79495fab37eSRobert Watson mpe->mpe_function; 79595fab37eSRobert Watson break; 79695fab37eSRobert Watson case MAC_CHECK_VNODE_DELETE: 79795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_delete = 79895fab37eSRobert Watson mpe->mpe_function; 79995fab37eSRobert Watson break; 80095fab37eSRobert Watson case MAC_CHECK_VNODE_DELETEACL: 80195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_deleteacl = 80295fab37eSRobert Watson mpe->mpe_function; 80395fab37eSRobert Watson break; 80495fab37eSRobert Watson case MAC_CHECK_VNODE_EXEC: 80595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_exec = 80695fab37eSRobert Watson mpe->mpe_function; 80795fab37eSRobert Watson break; 80895fab37eSRobert Watson case MAC_CHECK_VNODE_GETACL: 80995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getacl = 81095fab37eSRobert Watson mpe->mpe_function; 81195fab37eSRobert Watson break; 81295fab37eSRobert Watson case MAC_CHECK_VNODE_GETEXTATTR: 81395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getextattr = 81495fab37eSRobert Watson mpe->mpe_function; 81595fab37eSRobert Watson break; 8160a694196SRobert Watson case MAC_CHECK_VNODE_LINK: 8170a694196SRobert Watson mpc->mpc_ops->mpo_check_vnode_link = 8180a694196SRobert Watson mpe->mpe_function; 8190a694196SRobert Watson break; 82095fab37eSRobert Watson case MAC_CHECK_VNODE_LOOKUP: 82195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_lookup = 82295fab37eSRobert Watson mpe->mpe_function; 82395fab37eSRobert Watson break; 824e183f80eSRobert Watson case MAC_CHECK_VNODE_MMAP: 825e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mmap = 826e183f80eSRobert Watson mpe->mpe_function; 827e183f80eSRobert Watson break; 828e183f80eSRobert Watson case MAC_CHECK_VNODE_MMAP_DOWNGRADE: 829e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mmap_downgrade = 830e183f80eSRobert Watson mpe->mpe_function; 831e183f80eSRobert Watson break; 832e183f80eSRobert Watson case MAC_CHECK_VNODE_MPROTECT: 833e183f80eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mprotect = 83495fab37eSRobert Watson mpe->mpe_function; 83595fab37eSRobert Watson break; 83695fab37eSRobert Watson case MAC_CHECK_VNODE_OPEN: 83795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_open = 83895fab37eSRobert Watson mpe->mpe_function; 83995fab37eSRobert Watson break; 8407f724f8bSRobert Watson case MAC_CHECK_VNODE_POLL: 8417f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_poll = 8427f724f8bSRobert Watson mpe->mpe_function; 8437f724f8bSRobert Watson break; 8447f724f8bSRobert Watson case MAC_CHECK_VNODE_READ: 8457f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_read = 8467f724f8bSRobert Watson mpe->mpe_function; 8477f724f8bSRobert Watson break; 84895fab37eSRobert Watson case MAC_CHECK_VNODE_READDIR: 84995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readdir = 85095fab37eSRobert Watson mpe->mpe_function; 85195fab37eSRobert Watson break; 85295fab37eSRobert Watson case MAC_CHECK_VNODE_READLINK: 85395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readlink = 85495fab37eSRobert Watson mpe->mpe_function; 85595fab37eSRobert Watson break; 85695fab37eSRobert Watson case MAC_CHECK_VNODE_RELABEL: 85795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_relabel = 85895fab37eSRobert Watson mpe->mpe_function; 85995fab37eSRobert Watson break; 86095fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_FROM: 86195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_from = 86295fab37eSRobert Watson mpe->mpe_function; 86395fab37eSRobert Watson break; 86495fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_TO: 86595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_to = 86695fab37eSRobert Watson mpe->mpe_function; 86795fab37eSRobert Watson break; 86895fab37eSRobert Watson case MAC_CHECK_VNODE_REVOKE: 86995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_revoke = 87095fab37eSRobert Watson mpe->mpe_function; 87195fab37eSRobert Watson break; 87295fab37eSRobert Watson case MAC_CHECK_VNODE_SETACL: 87395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setacl = 87495fab37eSRobert Watson mpe->mpe_function; 87595fab37eSRobert Watson break; 87695fab37eSRobert Watson case MAC_CHECK_VNODE_SETEXTATTR: 87795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setextattr = 87895fab37eSRobert Watson mpe->mpe_function; 87995fab37eSRobert Watson break; 88095fab37eSRobert Watson case MAC_CHECK_VNODE_SETFLAGS: 88195fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setflags = 88295fab37eSRobert Watson mpe->mpe_function; 88395fab37eSRobert Watson break; 88495fab37eSRobert Watson case MAC_CHECK_VNODE_SETMODE: 88595fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setmode = 88695fab37eSRobert Watson mpe->mpe_function; 88795fab37eSRobert Watson break; 88895fab37eSRobert Watson case MAC_CHECK_VNODE_SETOWNER: 88995fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setowner = 89095fab37eSRobert Watson mpe->mpe_function; 89195fab37eSRobert Watson break; 89295fab37eSRobert Watson case MAC_CHECK_VNODE_SETUTIMES: 89395fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setutimes = 89495fab37eSRobert Watson mpe->mpe_function; 89595fab37eSRobert Watson break; 89695fab37eSRobert Watson case MAC_CHECK_VNODE_STAT: 89795fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_stat = 89895fab37eSRobert Watson mpe->mpe_function; 89995fab37eSRobert Watson break; 9007f724f8bSRobert Watson case MAC_CHECK_VNODE_WRITE: 9017f724f8bSRobert Watson mpc->mpc_ops->mpo_check_vnode_write = 9027f724f8bSRobert Watson mpe->mpe_function; 9037f724f8bSRobert Watson break; 90495fab37eSRobert Watson /* 90595fab37eSRobert Watson default: 90695fab37eSRobert Watson printf("MAC policy `%s': unknown operation %d\n", 90795fab37eSRobert Watson mpc->mpc_name, mpe->mpe_constant); 90895fab37eSRobert Watson return (EINVAL); 90995fab37eSRobert Watson */ 91095fab37eSRobert Watson } 91195fab37eSRobert Watson } 91295fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); 91395fab37eSRobert Watson if (mac_policy_list_busy > 0) { 91495fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 91595fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 91695fab37eSRobert Watson mpc->mpc_ops = NULL; 91795fab37eSRobert Watson return (EBUSY); 91895fab37eSRobert Watson } 91995fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 92095fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 92195fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 92295fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 92395fab37eSRobert Watson mpc->mpc_ops = NULL; 92495fab37eSRobert Watson return (EEXIST); 92595fab37eSRobert Watson } 92695fab37eSRobert Watson } 92795fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 92895fab37eSRobert Watson slot = ffs(mac_policy_offsets_free); 92995fab37eSRobert Watson if (slot == 0) { 93095fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 93195fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 93295fab37eSRobert Watson mpc->mpc_ops = NULL; 93395fab37eSRobert Watson return (ENOMEM); 93495fab37eSRobert Watson } 93595fab37eSRobert Watson slot--; 93695fab37eSRobert Watson mac_policy_offsets_free &= ~(1 << slot); 93795fab37eSRobert Watson *mpc->mpc_field_off = slot; 93895fab37eSRobert Watson } 93995fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 94095fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 94195fab37eSRobert Watson 94295fab37eSRobert Watson /* Per-policy initialization. */ 94395fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 94495fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 94595fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 94695fab37eSRobert Watson 94795fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 94895fab37eSRobert Watson mpc->mpc_name); 94995fab37eSRobert Watson 95095fab37eSRobert Watson return (0); 95195fab37eSRobert Watson } 95295fab37eSRobert Watson 95395fab37eSRobert Watson static int 95495fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 95595fab37eSRobert Watson { 95695fab37eSRobert Watson 957ea599aa0SRobert Watson /* 958ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 959ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 960ea599aa0SRobert Watson * silently succeed. 961ea599aa0SRobert Watson */ 962ea599aa0SRobert Watson MAC_POLICY_LIST_LOCK(); 963ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 964ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 965ea599aa0SRobert Watson return (0); 966ea599aa0SRobert Watson } 96795fab37eSRobert Watson #if 0 96895fab37eSRobert Watson /* 96995fab37eSRobert Watson * Don't allow unloading modules with private data. 97095fab37eSRobert Watson */ 971ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 972ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 97395fab37eSRobert Watson return (EBUSY); 974ea599aa0SRobert Watson } 97595fab37eSRobert Watson #endif 976ea599aa0SRobert Watson /* 977ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 978ea599aa0SRobert Watson * by its own definition. 979ea599aa0SRobert Watson */ 980ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 981ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 98295fab37eSRobert Watson return (EBUSY); 983ea599aa0SRobert Watson } 984ea599aa0SRobert Watson /* 985ea599aa0SRobert Watson * Right now, we EBUSY if the list is in use. In the future, 986ea599aa0SRobert Watson * for reliability reasons, we might want to sleep and wakeup 987ea599aa0SRobert Watson * later to try again. 988ea599aa0SRobert Watson */ 98995fab37eSRobert Watson if (mac_policy_list_busy > 0) { 99095fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 99195fab37eSRobert Watson return (EBUSY); 99295fab37eSRobert Watson } 99395fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 99495fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 99595fab37eSRobert Watson 99695fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 99795fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 99895fab37eSRobert Watson 99995fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 100095fab37eSRobert Watson mpc->mpc_ops = NULL; 100195fab37eSRobert Watson 100295fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 100395fab37eSRobert Watson mpc->mpc_name); 100495fab37eSRobert Watson 100595fab37eSRobert Watson return (0); 100695fab37eSRobert Watson } 100795fab37eSRobert Watson 100895fab37eSRobert Watson /* 100995fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 101095fab37eSRobert Watson * value with the higher precedence. 101195fab37eSRobert Watson */ 101295fab37eSRobert Watson static int 101395fab37eSRobert Watson error_select(int error1, int error2) 101495fab37eSRobert Watson { 101595fab37eSRobert Watson 101695fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 101795fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 101895fab37eSRobert Watson return (EDEADLK); 101995fab37eSRobert Watson 102095fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 102195fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 102295fab37eSRobert Watson return (EINVAL); 102395fab37eSRobert Watson 102495fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 102595fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 102695fab37eSRobert Watson return (ESRCH); 102795fab37eSRobert Watson 102895fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 102995fab37eSRobert Watson return (ENOENT); 103095fab37eSRobert Watson 103195fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 103295fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 103395fab37eSRobert Watson return (EACCES); 103495fab37eSRobert Watson 103595fab37eSRobert Watson /* Precedence goes to privilege. */ 103695fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 103795fab37eSRobert Watson return (EPERM); 103895fab37eSRobert Watson 103995fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 104095fab37eSRobert Watson if (error1 != 0) 104195fab37eSRobert Watson return (error1); 104295fab37eSRobert Watson return (error2); 104395fab37eSRobert Watson } 104495fab37eSRobert Watson 104508bcdc58SRobert Watson static void 104608bcdc58SRobert Watson mac_init_label(struct label *label) 104708bcdc58SRobert Watson { 104808bcdc58SRobert Watson 104908bcdc58SRobert Watson bzero(label, sizeof(*label)); 105008bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 105108bcdc58SRobert Watson } 105208bcdc58SRobert Watson 105308bcdc58SRobert Watson static void 105408bcdc58SRobert Watson mac_destroy_label(struct label *label) 105508bcdc58SRobert Watson { 105608bcdc58SRobert Watson 105708bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 105808bcdc58SRobert Watson ("destroying uninitialized label")); 105908bcdc58SRobert Watson 106008bcdc58SRobert Watson bzero(label, sizeof(*label)); 106108bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 106208bcdc58SRobert Watson } 106308bcdc58SRobert Watson 106408bcdc58SRobert Watson static void 106508bcdc58SRobert Watson mac_init_structmac(struct mac *mac) 106608bcdc58SRobert Watson { 106708bcdc58SRobert Watson 106808bcdc58SRobert Watson bzero(mac, sizeof(*mac)); 106908bcdc58SRobert Watson mac->m_macflags = MAC_FLAG_INITIALIZED; 107008bcdc58SRobert Watson } 107108bcdc58SRobert Watson 107208bcdc58SRobert Watson void 107387807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 107408bcdc58SRobert Watson { 107508bcdc58SRobert Watson 107687807196SRobert Watson mac_init_label(&bpf_d->bd_label); 107787807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 107808bcdc58SRobert Watson #ifdef MAC_DEBUG 107987807196SRobert Watson atomic_add_int(&nmacbpfdescs, 1); 108008bcdc58SRobert Watson #endif 108108bcdc58SRobert Watson } 108208bcdc58SRobert Watson 108308bcdc58SRobert Watson void 108408bcdc58SRobert Watson mac_init_cred(struct ucred *cr) 108508bcdc58SRobert Watson { 108608bcdc58SRobert Watson 108708bcdc58SRobert Watson mac_init_label(&cr->cr_label); 108808bcdc58SRobert Watson MAC_PERFORM(init_cred_label, &cr->cr_label); 108908bcdc58SRobert Watson #ifdef MAC_DEBUG 109008bcdc58SRobert Watson atomic_add_int(&nmaccreds, 1); 109108bcdc58SRobert Watson #endif 109208bcdc58SRobert Watson } 109308bcdc58SRobert Watson 109408bcdc58SRobert Watson void 109587807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 109608bcdc58SRobert Watson { 109708bcdc58SRobert Watson 109887807196SRobert Watson mac_init_label(&de->de_label); 109987807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 110008bcdc58SRobert Watson #ifdef MAC_DEBUG 110187807196SRobert Watson atomic_add_int(&nmacdevfsdirents, 1); 110208bcdc58SRobert Watson #endif 110308bcdc58SRobert Watson } 110408bcdc58SRobert Watson 110508bcdc58SRobert Watson void 110608bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 110708bcdc58SRobert Watson { 110808bcdc58SRobert Watson 110908bcdc58SRobert Watson mac_init_label(&ifp->if_label); 111008bcdc58SRobert Watson MAC_PERFORM(init_ifnet_label, &ifp->if_label); 111108bcdc58SRobert Watson #ifdef MAC_DEBUG 111208bcdc58SRobert Watson atomic_add_int(&nmacifnets, 1); 111308bcdc58SRobert Watson #endif 111408bcdc58SRobert Watson } 111508bcdc58SRobert Watson 111608bcdc58SRobert Watson void 111708bcdc58SRobert Watson mac_init_ipq(struct ipq *ipq) 111808bcdc58SRobert Watson { 111908bcdc58SRobert Watson 112008bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 112108bcdc58SRobert Watson MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 112208bcdc58SRobert Watson #ifdef MAC_DEBUG 112308bcdc58SRobert Watson atomic_add_int(&nmacipqs, 1); 112408bcdc58SRobert Watson #endif 112508bcdc58SRobert Watson } 112608bcdc58SRobert Watson 112787807196SRobert Watson int 112887807196SRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 112908bcdc58SRobert Watson { 113056c15412SRobert Watson int error; 113156c15412SRobert Watson 113287807196SRobert Watson KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 113308bcdc58SRobert Watson 113487807196SRobert Watson mac_init_label(&m->m_pkthdr.label); 113587807196SRobert Watson 113656c15412SRobert Watson MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 113756c15412SRobert Watson if (error) { 113856c15412SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 113956c15412SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 114056c15412SRobert Watson } 114156c15412SRobert Watson 114208bcdc58SRobert Watson #ifdef MAC_DEBUG 114356c15412SRobert Watson if (error == 0) 114487807196SRobert Watson atomic_add_int(&nmacmbufs, 1); 114508bcdc58SRobert Watson #endif 114656c15412SRobert Watson return (error); 114708bcdc58SRobert Watson } 114808bcdc58SRobert Watson 114908bcdc58SRobert Watson void 115087807196SRobert Watson mac_init_mount(struct mount *mp) 115108bcdc58SRobert Watson { 115208bcdc58SRobert Watson 115387807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 115487807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 115587807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 115687807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 115708bcdc58SRobert Watson #ifdef MAC_DEBUG 115887807196SRobert Watson atomic_add_int(&nmacmounts, 1); 115908bcdc58SRobert Watson #endif 116008bcdc58SRobert Watson } 116108bcdc58SRobert Watson 116208bcdc58SRobert Watson void 116308bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 116408bcdc58SRobert Watson { 116508bcdc58SRobert Watson struct label *label; 116608bcdc58SRobert Watson 116708bcdc58SRobert Watson label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 116808bcdc58SRobert Watson mac_init_label(label); 116908bcdc58SRobert Watson pipe->pipe_label = label; 117008bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 117108bcdc58SRobert Watson MAC_PERFORM(init_pipe_label, pipe->pipe_label); 117208bcdc58SRobert Watson #ifdef MAC_DEBUG 117308bcdc58SRobert Watson atomic_add_int(&nmacpipes, 1); 117408bcdc58SRobert Watson #endif 117508bcdc58SRobert Watson } 117608bcdc58SRobert Watson 117783985c26SRobert Watson static int 117883985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 117908bcdc58SRobert Watson { 118083985c26SRobert Watson int error; 118108bcdc58SRobert Watson 118283985c26SRobert Watson mac_init_label(label); 118383985c26SRobert Watson 118483985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 118583985c26SRobert Watson if (error) { 118683985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 118783985c26SRobert Watson mac_destroy_label(label); 118883985c26SRobert Watson } 118983985c26SRobert Watson 119008bcdc58SRobert Watson #ifdef MAC_DEBUG 119183985c26SRobert Watson if (error == 0) 119287807196SRobert Watson atomic_add_int(&nmacsockets, 1); 119387807196SRobert Watson #endif 119483985c26SRobert Watson 119583985c26SRobert Watson return (error); 119683985c26SRobert Watson } 119783985c26SRobert Watson 119883985c26SRobert Watson static int 119983985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 120083985c26SRobert Watson { 120183985c26SRobert Watson int error; 120283985c26SRobert Watson 120383985c26SRobert Watson mac_init_label(label); 120483985c26SRobert Watson 120583985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 120683985c26SRobert Watson if (error) { 120783985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 120883985c26SRobert Watson mac_destroy_label(label); 120983985c26SRobert Watson } 121083985c26SRobert Watson 121183985c26SRobert Watson return (error); 121283985c26SRobert Watson } 121383985c26SRobert Watson 121483985c26SRobert Watson int 121583985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 121683985c26SRobert Watson { 121783985c26SRobert Watson int error; 121883985c26SRobert Watson 121983985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 122083985c26SRobert Watson if (error) 122183985c26SRobert Watson return (error); 122283985c26SRobert Watson 122383985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 122483985c26SRobert Watson if (error) 122583985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 122683985c26SRobert Watson 122783985c26SRobert Watson return (error); 122887807196SRobert Watson } 122987807196SRobert Watson 123087807196SRobert Watson static void 123187807196SRobert Watson mac_init_temp(struct label *label) 123287807196SRobert Watson { 123387807196SRobert Watson 123487807196SRobert Watson mac_init_label(label); 123587807196SRobert Watson MAC_PERFORM(init_temp_label, label); 123687807196SRobert Watson #ifdef MAC_DEBUG 123787807196SRobert Watson atomic_add_int(&nmactemp, 1); 123808bcdc58SRobert Watson #endif 123908bcdc58SRobert Watson } 124008bcdc58SRobert Watson 124108bcdc58SRobert Watson void 124287807196SRobert Watson mac_init_vnode(struct vnode *vp) 124308bcdc58SRobert Watson { 124408bcdc58SRobert Watson 124587807196SRobert Watson mac_init_label(&vp->v_label); 124687807196SRobert Watson MAC_PERFORM(init_vnode_label, &vp->v_label); 124708bcdc58SRobert Watson #ifdef MAC_DEBUG 124887807196SRobert Watson atomic_add_int(&nmacvnodes, 1); 124908bcdc58SRobert Watson #endif 125008bcdc58SRobert Watson } 125108bcdc58SRobert Watson 125208bcdc58SRobert Watson void 125308bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 125408bcdc58SRobert Watson { 125508bcdc58SRobert Watson 125608bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 125708bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 125808bcdc58SRobert Watson #ifdef MAC_DEBUG 125908bcdc58SRobert Watson atomic_subtract_int(&nmacbpfdescs, 1); 126008bcdc58SRobert Watson #endif 126108bcdc58SRobert Watson } 126208bcdc58SRobert Watson 126308bcdc58SRobert Watson void 126487807196SRobert Watson mac_destroy_cred(struct ucred *cr) 126508bcdc58SRobert Watson { 126608bcdc58SRobert Watson 126787807196SRobert Watson MAC_PERFORM(destroy_cred_label, &cr->cr_label); 126887807196SRobert Watson mac_destroy_label(&cr->cr_label); 126908bcdc58SRobert Watson #ifdef MAC_DEBUG 127087807196SRobert Watson atomic_subtract_int(&nmaccreds, 1); 127187807196SRobert Watson #endif 127287807196SRobert Watson } 127387807196SRobert Watson 127487807196SRobert Watson void 127587807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 127687807196SRobert Watson { 127787807196SRobert Watson 127887807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 127987807196SRobert Watson mac_destroy_label(&de->de_label); 128087807196SRobert Watson #ifdef MAC_DEBUG 128187807196SRobert Watson atomic_subtract_int(&nmacdevfsdirents, 1); 128287807196SRobert Watson #endif 128387807196SRobert Watson } 128487807196SRobert Watson 128587807196SRobert Watson void 128687807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 128787807196SRobert Watson { 128887807196SRobert Watson 128987807196SRobert Watson MAC_PERFORM(destroy_ifnet_label, &ifp->if_label); 129087807196SRobert Watson mac_destroy_label(&ifp->if_label); 129187807196SRobert Watson #ifdef MAC_DEBUG 129287807196SRobert Watson atomic_subtract_int(&nmacifnets, 1); 129387807196SRobert Watson #endif 129487807196SRobert Watson } 129587807196SRobert Watson 129687807196SRobert Watson void 129787807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 129887807196SRobert Watson { 129987807196SRobert Watson 130087807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 130187807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 130287807196SRobert Watson #ifdef MAC_DEBUG 130387807196SRobert Watson atomic_subtract_int(&nmacipqs, 1); 130487807196SRobert Watson #endif 130587807196SRobert Watson } 130687807196SRobert Watson 130787807196SRobert Watson void 130887807196SRobert Watson mac_destroy_mbuf(struct mbuf *m) 130987807196SRobert Watson { 131087807196SRobert Watson 131187807196SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 131287807196SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 131387807196SRobert Watson #ifdef MAC_DEBUG 131487807196SRobert Watson atomic_subtract_int(&nmacmbufs, 1); 131508bcdc58SRobert Watson #endif 131608bcdc58SRobert Watson } 131708bcdc58SRobert Watson 131808bcdc58SRobert Watson void 131908bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 132008bcdc58SRobert Watson { 132108bcdc58SRobert Watson 132208bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 132308bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 132408bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 132508bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 132608bcdc58SRobert Watson #ifdef MAC_DEBUG 132708bcdc58SRobert Watson atomic_subtract_int(&nmacmounts, 1); 132808bcdc58SRobert Watson #endif 132908bcdc58SRobert Watson } 133008bcdc58SRobert Watson 133187807196SRobert Watson void 133287807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 133308bcdc58SRobert Watson { 133408bcdc58SRobert Watson 133587807196SRobert Watson MAC_PERFORM(destroy_pipe_label, pipe->pipe_label); 133687807196SRobert Watson mac_destroy_label(pipe->pipe_label); 133787807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 133808bcdc58SRobert Watson #ifdef MAC_DEBUG 133987807196SRobert Watson atomic_subtract_int(&nmacpipes, 1); 134087807196SRobert Watson #endif 134187807196SRobert Watson } 134287807196SRobert Watson 134383985c26SRobert Watson static void 134483985c26SRobert Watson mac_destroy_socket_label(struct label *label) 134583985c26SRobert Watson { 134683985c26SRobert Watson 134783985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 134883985c26SRobert Watson mac_destroy_label(label); 134983985c26SRobert Watson #ifdef MAC_DEBUG 135083985c26SRobert Watson atomic_subtract_int(&nmacsockets, 1); 135183985c26SRobert Watson #endif 135283985c26SRobert Watson } 135383985c26SRobert Watson 135483985c26SRobert Watson static void 135583985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 135683985c26SRobert Watson { 135783985c26SRobert Watson 135883985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 135983985c26SRobert Watson mac_destroy_label(label); 136083985c26SRobert Watson } 136183985c26SRobert Watson 136287807196SRobert Watson void 136387807196SRobert Watson mac_destroy_socket(struct socket *socket) 136487807196SRobert Watson { 136587807196SRobert Watson 136683985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 136783985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 136808bcdc58SRobert Watson } 136908bcdc58SRobert Watson 137008bcdc58SRobert Watson static void 137108bcdc58SRobert Watson mac_destroy_temp(struct label *label) 137208bcdc58SRobert Watson { 137308bcdc58SRobert Watson 137408bcdc58SRobert Watson MAC_PERFORM(destroy_temp_label, label); 137508bcdc58SRobert Watson mac_destroy_label(label); 137608bcdc58SRobert Watson #ifdef MAC_DEBUG 137708bcdc58SRobert Watson atomic_subtract_int(&nmactemp, 1); 137808bcdc58SRobert Watson #endif 137908bcdc58SRobert Watson } 138008bcdc58SRobert Watson 138108bcdc58SRobert Watson void 138208bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 138308bcdc58SRobert Watson { 138408bcdc58SRobert Watson 138508bcdc58SRobert Watson MAC_PERFORM(destroy_vnode_label, &vp->v_label); 138608bcdc58SRobert Watson mac_destroy_label(&vp->v_label); 138708bcdc58SRobert Watson #ifdef MAC_DEBUG 138808bcdc58SRobert Watson atomic_subtract_int(&nmacvnodes, 1); 138908bcdc58SRobert Watson #endif 139008bcdc58SRobert Watson } 139108bcdc58SRobert Watson 139269bbb5b1SRobert Watson static int 139369bbb5b1SRobert Watson mac_externalize(struct label *label, struct mac *mac) 139469bbb5b1SRobert Watson { 139569bbb5b1SRobert Watson int error; 139669bbb5b1SRobert Watson 139769bbb5b1SRobert Watson mac_init_structmac(mac); 139869bbb5b1SRobert Watson MAC_CHECK(externalize, label, mac); 139969bbb5b1SRobert Watson 140069bbb5b1SRobert Watson return (error); 140169bbb5b1SRobert Watson } 140269bbb5b1SRobert Watson 140369bbb5b1SRobert Watson static int 140469bbb5b1SRobert Watson mac_internalize(struct label *label, struct mac *mac) 140569bbb5b1SRobert Watson { 140669bbb5b1SRobert Watson int error; 140769bbb5b1SRobert Watson 140869bbb5b1SRobert Watson mac_init_temp(label); 140969bbb5b1SRobert Watson MAC_CHECK(internalize, label, mac); 141069bbb5b1SRobert Watson if (error) 141169bbb5b1SRobert Watson mac_destroy_temp(label); 141269bbb5b1SRobert Watson 141369bbb5b1SRobert Watson return (error); 141469bbb5b1SRobert Watson } 141569bbb5b1SRobert Watson 141669bbb5b1SRobert Watson /* 141769bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 141869bbb5b1SRobert Watson * kernel processes and threads are spawned. 141969bbb5b1SRobert Watson */ 142069bbb5b1SRobert Watson void 142169bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 142269bbb5b1SRobert Watson { 142369bbb5b1SRobert Watson 142469bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 142569bbb5b1SRobert Watson } 142669bbb5b1SRobert Watson 142769bbb5b1SRobert Watson /* 142869bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 142969bbb5b1SRobert Watson * userland processes and threads are spawned. 143069bbb5b1SRobert Watson */ 143169bbb5b1SRobert Watson void 143269bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 143369bbb5b1SRobert Watson { 143469bbb5b1SRobert Watson 143569bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 143669bbb5b1SRobert Watson } 143769bbb5b1SRobert Watson 143869bbb5b1SRobert Watson void 143969bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 144069bbb5b1SRobert Watson { 144169bbb5b1SRobert Watson 144269bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 144369bbb5b1SRobert Watson } 144469bbb5b1SRobert Watson 144569bbb5b1SRobert Watson /* 144669bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 144769bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 144869bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 144969bbb5b1SRobert Watson */ 145069bbb5b1SRobert Watson void 145169bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 145269bbb5b1SRobert Watson { 145369bbb5b1SRobert Watson 145469bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 145569bbb5b1SRobert Watson } 145669bbb5b1SRobert Watson 145795fab37eSRobert Watson void 145895fab37eSRobert Watson mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 145995fab37eSRobert Watson { 146095fab37eSRobert Watson 146195fab37eSRobert Watson MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 146295fab37eSRobert Watson } 146395fab37eSRobert Watson 146495fab37eSRobert Watson void 146595fab37eSRobert Watson mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) 146695fab37eSRobert Watson { 146795fab37eSRobert Watson 146895fab37eSRobert Watson MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); 146995fab37eSRobert Watson } 147095fab37eSRobert Watson 147195fab37eSRobert Watson /* 147295fab37eSRobert Watson * Support callout for policies that manage their own externalization 147395fab37eSRobert Watson * using extended attributes. 147495fab37eSRobert Watson */ 147595fab37eSRobert Watson static int 147695fab37eSRobert Watson mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) 147795fab37eSRobert Watson { 147895fab37eSRobert Watson int error; 147995fab37eSRobert Watson 148095fab37eSRobert Watson MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, 148195fab37eSRobert Watson &mp->mnt_fslabel); 148295fab37eSRobert Watson 148395fab37eSRobert Watson return (error); 148495fab37eSRobert Watson } 148595fab37eSRobert Watson 148695fab37eSRobert Watson /* 148795fab37eSRobert Watson * Given an externalized mac label, internalize it and stamp it on a 148895fab37eSRobert Watson * vnode. 148995fab37eSRobert Watson */ 149095fab37eSRobert Watson static int 149195fab37eSRobert Watson mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac) 149295fab37eSRobert Watson { 149395fab37eSRobert Watson int error; 149495fab37eSRobert Watson 149595fab37eSRobert Watson MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); 149695fab37eSRobert Watson 149795fab37eSRobert Watson return (error); 149895fab37eSRobert Watson } 149995fab37eSRobert Watson 150095fab37eSRobert Watson /* 150195fab37eSRobert Watson * Call out to individual policies to update the label in a vnode from 150295fab37eSRobert Watson * the mountpoint. 150395fab37eSRobert Watson */ 150495fab37eSRobert Watson void 150595fab37eSRobert Watson mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) 150695fab37eSRobert Watson { 150795fab37eSRobert Watson 150895fab37eSRobert Watson MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, 150995fab37eSRobert Watson &mp->mnt_fslabel); 151095fab37eSRobert Watson 1511e6e370a7SJeff Roberson ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); 151295fab37eSRobert Watson if (mac_cache_fslabel_in_vnode) 1513e6e370a7SJeff Roberson vp->v_vflag |= VV_CACHEDLABEL; 151495fab37eSRobert Watson } 151595fab37eSRobert Watson 151695fab37eSRobert Watson /* 151795fab37eSRobert Watson * Implementation of VOP_REFRESHLABEL() that relies on extended attributes 151895fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 151995fab37eSRobert Watson * extended attributes. 152095fab37eSRobert Watson */ 152195fab37eSRobert Watson int 152295fab37eSRobert Watson vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) 152395fab37eSRobert Watson { 152495fab37eSRobert Watson struct vnode *vp = ap->a_vp; 152595fab37eSRobert Watson struct mac extmac; 152695fab37eSRobert Watson int buflen, error; 152795fab37eSRobert Watson 152895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); 152995fab37eSRobert Watson 153095fab37eSRobert Watson /* 153195fab37eSRobert Watson * Call out to external policies first. Order doesn't really 153295fab37eSRobert Watson * matter, as long as failure of one assures failure of all. 153395fab37eSRobert Watson */ 153495fab37eSRobert Watson error = mac_update_vnode_from_extattr(vp, vp->v_mount); 153595fab37eSRobert Watson if (error) 153695fab37eSRobert Watson return (error); 153795fab37eSRobert Watson 153895fab37eSRobert Watson buflen = sizeof(extmac); 153995fab37eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, 154095fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, 154195fab37eSRobert Watson (char *)&extmac, curthread); 154295fab37eSRobert Watson switch (error) { 154395fab37eSRobert Watson case 0: 154495fab37eSRobert Watson /* Got it */ 154595fab37eSRobert Watson break; 154695fab37eSRobert Watson 154795fab37eSRobert Watson case ENOATTR: 154895fab37eSRobert Watson /* 154995fab37eSRobert Watson * Use the label from the mount point. 155095fab37eSRobert Watson */ 155195fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 155295fab37eSRobert Watson return (0); 155395fab37eSRobert Watson 155495fab37eSRobert Watson case EOPNOTSUPP: 155595fab37eSRobert Watson default: 155695fab37eSRobert Watson /* Fail horribly. */ 155795fab37eSRobert Watson return (error); 155895fab37eSRobert Watson } 155995fab37eSRobert Watson 156095fab37eSRobert Watson if (buflen != sizeof(extmac)) 156195fab37eSRobert Watson error = EPERM; /* Fail very closed. */ 156295fab37eSRobert Watson if (error == 0) 156395fab37eSRobert Watson error = mac_update_vnode_from_externalized(vp, &extmac); 156495fab37eSRobert Watson if (error == 0) 1565e6e370a7SJeff Roberson vp->v_vflag |= VV_CACHEDLABEL; 156695fab37eSRobert Watson else { 156795fab37eSRobert Watson struct vattr va; 156895fab37eSRobert Watson 156995fab37eSRobert Watson printf("Corrupted label on %s", 157095fab37eSRobert Watson vp->v_mount->mnt_stat.f_mntonname); 157195fab37eSRobert Watson if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) 157295fab37eSRobert Watson printf(" inum %ld", va.va_fileid); 15736be0c25eSRobert Watson #ifdef MAC_DEBUG 157495fab37eSRobert Watson if (mac_debug_label_fallback) { 157595fab37eSRobert Watson printf(", falling back.\n"); 157695fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 157795fab37eSRobert Watson error = 0; 157895fab37eSRobert Watson } else { 15796be0c25eSRobert Watson #endif 158095fab37eSRobert Watson printf(".\n"); 158195fab37eSRobert Watson error = EPERM; 15826be0c25eSRobert Watson #ifdef MAC_DEBUG 158395fab37eSRobert Watson } 15846be0c25eSRobert Watson #endif 158595fab37eSRobert Watson } 158695fab37eSRobert Watson 158795fab37eSRobert Watson return (error); 158895fab37eSRobert Watson } 158995fab37eSRobert Watson 159095fab37eSRobert Watson /* 159195fab37eSRobert Watson * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle 159295fab37eSRobert Watson * the labeling activity outselves. Filesystems should be careful not 159395fab37eSRobert Watson * to change their minds regarding whether they support vop_refreshlabel() 159495fab37eSRobert Watson * for a vnode or not. Don't cache the vnode here, allow the file 159595fab37eSRobert Watson * system code to determine if it's safe to cache. If we update from 159695fab37eSRobert Watson * the mount, don't cache since a change to the mount label should affect 159795fab37eSRobert Watson * all vnodes. 159895fab37eSRobert Watson */ 159995fab37eSRobert Watson static int 160095fab37eSRobert Watson vn_refreshlabel(struct vnode *vp, struct ucred *cred) 160195fab37eSRobert Watson { 160295fab37eSRobert Watson int error; 160395fab37eSRobert Watson 160495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); 160595fab37eSRobert Watson 160695fab37eSRobert Watson if (vp->v_mount == NULL) { 160795fab37eSRobert Watson /* 160895fab37eSRobert Watson Eventually, we probably want to special-case refreshing 160995fab37eSRobert Watson of deadfs vnodes, and if there's a lock-free race somewhere, 161095fab37eSRobert Watson that case might be handled here. 161195fab37eSRobert Watson 161295fab37eSRobert Watson mac_update_vnode_deadfs(vp); 161395fab37eSRobert Watson return (0); 161495fab37eSRobert Watson */ 161595fab37eSRobert Watson /* printf("vn_refreshlabel: null v_mount\n"); */ 161606be2aaaSNate Lawson if (vp->v_type != VNON) 161795fab37eSRobert Watson printf( 161806be2aaaSNate Lawson "vn_refreshlabel: null v_mount with non-VNON\n"); 161995fab37eSRobert Watson return (EBADF); 162095fab37eSRobert Watson } 162195fab37eSRobert Watson 1622e6e370a7SJeff Roberson if (vp->v_vflag & VV_CACHEDLABEL) { 162395fab37eSRobert Watson mac_vnode_label_cache_hits++; 162495fab37eSRobert Watson return (0); 162595fab37eSRobert Watson } else 162695fab37eSRobert Watson mac_vnode_label_cache_misses++; 162795fab37eSRobert Watson 162895fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 162995fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 163095fab37eSRobert Watson return (0); 163195fab37eSRobert Watson } 163295fab37eSRobert Watson 163395fab37eSRobert Watson error = VOP_REFRESHLABEL(vp, cred, curthread); 163495fab37eSRobert Watson switch (error) { 163595fab37eSRobert Watson case EOPNOTSUPP: 163695fab37eSRobert Watson /* 163795fab37eSRobert Watson * If labels are not supported on this vnode, fall back to 163895fab37eSRobert Watson * the label in the mount and propagate it to the vnode. 163995fab37eSRobert Watson * There should probably be some sort of policy/flag/decision 164095fab37eSRobert Watson * about doing this. 164195fab37eSRobert Watson */ 164295fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 164395fab37eSRobert Watson error = 0; 164495fab37eSRobert Watson default: 164595fab37eSRobert Watson return (error); 164695fab37eSRobert Watson } 164795fab37eSRobert Watson } 164895fab37eSRobert Watson 164995fab37eSRobert Watson /* 165095fab37eSRobert Watson * Helper function for file systems using the vop_std*_ea() calls. This 165195fab37eSRobert Watson * function must be called after EA service is available for the vnode, 165295fab37eSRobert Watson * but before it's hooked up to the namespace so that the node persists 165395fab37eSRobert Watson * if there's a crash, or before it can be accessed. On successful 165495fab37eSRobert Watson * commit of the label to disk (etc), do cache the label. 165595fab37eSRobert Watson */ 165695fab37eSRobert Watson int 165795fab37eSRobert Watson vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) 165895fab37eSRobert Watson { 165995fab37eSRobert Watson struct mac extmac; 166095fab37eSRobert Watson int error; 166195fab37eSRobert Watson 1662e6e370a7SJeff Roberson ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); 166395fab37eSRobert Watson if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 166495fab37eSRobert Watson mac_update_vnode_from_mount(tvp, tvp->v_mount); 166595fab37eSRobert Watson } else { 166695fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 166795fab37eSRobert Watson if (error) 166895fab37eSRobert Watson return (error); 166995fab37eSRobert Watson 167095fab37eSRobert Watson /* 167195fab37eSRobert Watson * Stick the label in the vnode. Then try to write to 167295fab37eSRobert Watson * disk. If we fail, return a failure to abort the 167395fab37eSRobert Watson * create operation. Really, this failure shouldn't 167495fab37eSRobert Watson * happen except in fairly unusual circumstances (out 167595fab37eSRobert Watson * of disk, etc). 167695fab37eSRobert Watson */ 167795fab37eSRobert Watson mac_create_vnode(cred, dvp, tvp); 167895fab37eSRobert Watson 167995fab37eSRobert Watson error = mac_stdcreatevnode_ea(tvp); 168095fab37eSRobert Watson if (error) 168195fab37eSRobert Watson return (error); 168295fab37eSRobert Watson 168395fab37eSRobert Watson /* 168495fab37eSRobert Watson * XXX: Eventually this will go away and all policies will 168595fab37eSRobert Watson * directly manage their extended attributes. 168695fab37eSRobert Watson */ 168795fab37eSRobert Watson error = mac_externalize(&tvp->v_label, &extmac); 168895fab37eSRobert Watson if (error) 168995fab37eSRobert Watson return (error); 169095fab37eSRobert Watson 169195fab37eSRobert Watson error = vn_extattr_set(tvp, IO_NODELOCKED, 169295fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 169395fab37eSRobert Watson sizeof(extmac), (char *)&extmac, curthread); 169495fab37eSRobert Watson if (error == 0) 1695e6e370a7SJeff Roberson tvp->v_vflag |= VV_CACHEDLABEL; 169695fab37eSRobert Watson else { 169795fab37eSRobert Watson #if 0 169895fab37eSRobert Watson /* 169995fab37eSRobert Watson * In theory, we could have fall-back behavior here. 170095fab37eSRobert Watson * It would probably be incorrect. 170195fab37eSRobert Watson */ 170295fab37eSRobert Watson #endif 170395fab37eSRobert Watson return (error); 170495fab37eSRobert Watson } 170595fab37eSRobert Watson } 170695fab37eSRobert Watson 170795fab37eSRobert Watson return (0); 170895fab37eSRobert Watson } 170995fab37eSRobert Watson 171095fab37eSRobert Watson void 171195fab37eSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 171295fab37eSRobert Watson { 171395fab37eSRobert Watson int error; 171495fab37eSRobert Watson 171595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 171695fab37eSRobert Watson 171795fab37eSRobert Watson error = vn_refreshlabel(vp, old); 171895fab37eSRobert Watson if (error) { 171995fab37eSRobert Watson printf("mac_execve_transition: vn_refreshlabel returned %d\n", 172095fab37eSRobert Watson error); 172195fab37eSRobert Watson printf("mac_execve_transition: using old vnode label\n"); 172295fab37eSRobert Watson } 172395fab37eSRobert Watson 172495fab37eSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 172595fab37eSRobert Watson } 172695fab37eSRobert Watson 172795fab37eSRobert Watson int 172895fab37eSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp) 172995fab37eSRobert Watson { 173095fab37eSRobert Watson int error, result; 173195fab37eSRobert Watson 173295fab37eSRobert Watson error = vn_refreshlabel(vp, old); 173395fab37eSRobert Watson if (error) 173495fab37eSRobert Watson return (error); 173595fab37eSRobert Watson 173695fab37eSRobert Watson result = 0; 173795fab37eSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 173895fab37eSRobert Watson 173995fab37eSRobert Watson return (result); 174095fab37eSRobert Watson } 174195fab37eSRobert Watson 174295fab37eSRobert Watson int 174395fab37eSRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 174495fab37eSRobert Watson { 174595fab37eSRobert Watson int error; 174695fab37eSRobert Watson 174795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 174895fab37eSRobert Watson 174995fab37eSRobert Watson if (!mac_enforce_fs) 175095fab37eSRobert Watson return (0); 175195fab37eSRobert Watson 175295fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 175395fab37eSRobert Watson if (error) 175495fab37eSRobert Watson return (error); 175595fab37eSRobert Watson 175695fab37eSRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 175795fab37eSRobert Watson return (error); 175895fab37eSRobert Watson } 175995fab37eSRobert Watson 176095fab37eSRobert Watson int 176195fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 176295fab37eSRobert Watson { 176395fab37eSRobert Watson int error; 176495fab37eSRobert Watson 176595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 176695fab37eSRobert Watson 176795fab37eSRobert Watson if (!mac_enforce_fs) 176895fab37eSRobert Watson return (0); 176995fab37eSRobert Watson 177095fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 177195fab37eSRobert Watson if (error) 177295fab37eSRobert Watson return (error); 177395fab37eSRobert Watson 177495fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 177595fab37eSRobert Watson return (error); 177695fab37eSRobert Watson } 177795fab37eSRobert Watson 177895fab37eSRobert Watson int 177995fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 178095fab37eSRobert Watson { 178195fab37eSRobert Watson int error; 178295fab37eSRobert Watson 178395fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 178495fab37eSRobert Watson 178595fab37eSRobert Watson if (!mac_enforce_fs) 178695fab37eSRobert Watson return (0); 178795fab37eSRobert Watson 178895fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 178995fab37eSRobert Watson if (error) 179095fab37eSRobert Watson return (error); 179195fab37eSRobert Watson 179295fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 179395fab37eSRobert Watson return (error); 179495fab37eSRobert Watson } 179595fab37eSRobert Watson 179695fab37eSRobert Watson int 179795fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 179895fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 179995fab37eSRobert Watson { 180095fab37eSRobert Watson int error; 180195fab37eSRobert Watson 180295fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 180395fab37eSRobert Watson 180495fab37eSRobert Watson if (!mac_enforce_fs) 180595fab37eSRobert Watson return (0); 180695fab37eSRobert Watson 180795fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 180895fab37eSRobert Watson if (error) 180995fab37eSRobert Watson return (error); 181095fab37eSRobert Watson 181195fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 181295fab37eSRobert Watson return (error); 181395fab37eSRobert Watson } 181495fab37eSRobert Watson 181595fab37eSRobert Watson int 181695fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 181795fab37eSRobert Watson struct componentname *cnp) 181895fab37eSRobert Watson { 181995fab37eSRobert Watson int error; 182095fab37eSRobert Watson 182195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 182295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 182395fab37eSRobert Watson 182495fab37eSRobert Watson if (!mac_enforce_fs) 182595fab37eSRobert Watson return (0); 182695fab37eSRobert Watson 182795fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 182895fab37eSRobert Watson if (error) 182995fab37eSRobert Watson return (error); 183095fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 183195fab37eSRobert Watson if (error) 183295fab37eSRobert Watson return (error); 183395fab37eSRobert Watson 183495fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 183595fab37eSRobert Watson &vp->v_label, cnp); 183695fab37eSRobert Watson return (error); 183795fab37eSRobert Watson } 183895fab37eSRobert Watson 183995fab37eSRobert Watson int 184095fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 184195fab37eSRobert Watson acl_type_t type) 184295fab37eSRobert Watson { 184395fab37eSRobert Watson int error; 184495fab37eSRobert Watson 184595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 184695fab37eSRobert Watson 184795fab37eSRobert Watson if (!mac_enforce_fs) 184895fab37eSRobert Watson return (0); 184995fab37eSRobert Watson 185095fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 185195fab37eSRobert Watson if (error) 185295fab37eSRobert Watson return (error); 185395fab37eSRobert Watson 185495fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 185595fab37eSRobert Watson return (error); 185695fab37eSRobert Watson } 185795fab37eSRobert Watson 185895fab37eSRobert Watson int 185995fab37eSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 186095fab37eSRobert Watson { 186195fab37eSRobert Watson int error; 186295fab37eSRobert Watson 1863851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1864851704bbSRobert Watson 186595fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 186695fab37eSRobert Watson return (0); 186795fab37eSRobert Watson 186895fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 186995fab37eSRobert Watson if (error) 187095fab37eSRobert Watson return (error); 187195fab37eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 187295fab37eSRobert Watson 187395fab37eSRobert Watson return (error); 187495fab37eSRobert Watson } 187595fab37eSRobert Watson 187695fab37eSRobert Watson int 187795fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 187895fab37eSRobert Watson { 187995fab37eSRobert Watson int error; 188095fab37eSRobert Watson 188195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 188295fab37eSRobert Watson 188395fab37eSRobert Watson if (!mac_enforce_fs) 188495fab37eSRobert Watson return (0); 188595fab37eSRobert Watson 188695fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 188795fab37eSRobert Watson if (error) 188895fab37eSRobert Watson return (error); 188995fab37eSRobert Watson 189095fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 189195fab37eSRobert Watson return (error); 189295fab37eSRobert Watson } 189395fab37eSRobert Watson 189495fab37eSRobert Watson int 189595fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 189695fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 189795fab37eSRobert Watson { 189895fab37eSRobert Watson int error; 189995fab37eSRobert Watson 190095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 190195fab37eSRobert Watson 190295fab37eSRobert Watson if (!mac_enforce_fs) 190395fab37eSRobert Watson return (0); 190495fab37eSRobert Watson 190595fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 190695fab37eSRobert Watson if (error) 190795fab37eSRobert Watson return (error); 190895fab37eSRobert Watson 190995fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 191095fab37eSRobert Watson attrnamespace, name, uio); 191195fab37eSRobert Watson return (error); 191295fab37eSRobert Watson } 191395fab37eSRobert Watson 191495fab37eSRobert Watson int 19150a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 19160a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 19170a694196SRobert Watson { 19180a694196SRobert Watson 19190a694196SRobert Watson int error; 19200a694196SRobert Watson 19210a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 19220a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 19230a694196SRobert Watson 19240a694196SRobert Watson if (!mac_enforce_fs) 19250a694196SRobert Watson return (0); 19260a694196SRobert Watson 19270a694196SRobert Watson error = vn_refreshlabel(dvp, cred); 19280a694196SRobert Watson if (error) 19290a694196SRobert Watson return (error); 19300a694196SRobert Watson 19310a694196SRobert Watson error = vn_refreshlabel(vp, cred); 19320a694196SRobert Watson if (error) 19330a694196SRobert Watson return (error); 19340a694196SRobert Watson 19350a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 19360a694196SRobert Watson &vp->v_label, cnp); 19370a694196SRobert Watson return (error); 19380a694196SRobert Watson } 19390a694196SRobert Watson 19400a694196SRobert Watson int 194195fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 194295fab37eSRobert Watson struct componentname *cnp) 194395fab37eSRobert Watson { 194495fab37eSRobert Watson int error; 194595fab37eSRobert Watson 194695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 194795fab37eSRobert Watson 194895fab37eSRobert Watson if (!mac_enforce_fs) 194995fab37eSRobert Watson return (0); 195095fab37eSRobert Watson 195195fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 195295fab37eSRobert Watson if (error) 195395fab37eSRobert Watson return (error); 195495fab37eSRobert Watson 195595fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 195695fab37eSRobert Watson return (error); 195795fab37eSRobert Watson } 195895fab37eSRobert Watson 1959e183f80eSRobert Watson int 1960e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 196195fab37eSRobert Watson { 1962e183f80eSRobert Watson int error; 196395fab37eSRobert Watson 1964e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1965ca7850c3SRobert Watson 1966e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1967e183f80eSRobert Watson return (0); 1968e183f80eSRobert Watson 1969e183f80eSRobert Watson error = vn_refreshlabel(vp, cred); 1970e183f80eSRobert Watson if (error) 1971e183f80eSRobert Watson return (error); 1972e183f80eSRobert Watson 1973e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1974e183f80eSRobert Watson return (error); 1975e183f80eSRobert Watson } 1976e183f80eSRobert Watson 1977e183f80eSRobert Watson void 1978e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1979e183f80eSRobert Watson { 1980e183f80eSRobert Watson int result = *prot; 1981e183f80eSRobert Watson 1982e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1983e183f80eSRobert Watson 1984e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1985e183f80eSRobert Watson return; 1986e183f80eSRobert Watson 1987e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1988e183f80eSRobert Watson &result); 1989e183f80eSRobert Watson 1990e183f80eSRobert Watson *prot = result; 1991e183f80eSRobert Watson } 1992e183f80eSRobert Watson 1993e183f80eSRobert Watson int 1994e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1995e183f80eSRobert Watson { 1996e183f80eSRobert Watson int error; 1997e183f80eSRobert Watson 1998e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1999e183f80eSRobert Watson 2000e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 2001e183f80eSRobert Watson return (0); 2002e183f80eSRobert Watson 2003e183f80eSRobert Watson error = vn_refreshlabel(vp, cred); 2004e183f80eSRobert Watson if (error) 2005e183f80eSRobert Watson return (error); 2006e183f80eSRobert Watson 2007e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 2008e183f80eSRobert Watson return (error); 200995fab37eSRobert Watson } 201095fab37eSRobert Watson 201195fab37eSRobert Watson int 201295fab37eSRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 201395fab37eSRobert Watson { 201495fab37eSRobert Watson int error; 201595fab37eSRobert Watson 201695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 201795fab37eSRobert Watson 201895fab37eSRobert Watson if (!mac_enforce_fs) 201995fab37eSRobert Watson return (0); 202095fab37eSRobert Watson 202195fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 202295fab37eSRobert Watson if (error) 202395fab37eSRobert Watson return (error); 202495fab37eSRobert Watson 202595fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 202695fab37eSRobert Watson return (error); 202795fab37eSRobert Watson } 202895fab37eSRobert Watson 202995fab37eSRobert Watson int 2030177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 2031177142e4SRobert Watson struct vnode *vp) 20327f724f8bSRobert Watson { 20337f724f8bSRobert Watson int error; 20347f724f8bSRobert Watson 20357f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 20367f724f8bSRobert Watson 20377f724f8bSRobert Watson if (!mac_enforce_fs) 20387f724f8bSRobert Watson return (0); 20397f724f8bSRobert Watson 2040177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 20417f724f8bSRobert Watson if (error) 20427f724f8bSRobert Watson return (error); 20437f724f8bSRobert Watson 2044177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 2045177142e4SRobert Watson &vp->v_label); 20467f724f8bSRobert Watson 20477f724f8bSRobert Watson return (error); 20487f724f8bSRobert Watson } 20497f724f8bSRobert Watson 20507f724f8bSRobert Watson int 2051177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 2052177142e4SRobert Watson struct vnode *vp) 20537f724f8bSRobert Watson { 20547f724f8bSRobert Watson int error; 20557f724f8bSRobert Watson 20567f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 20577f724f8bSRobert Watson 20587f724f8bSRobert Watson if (!mac_enforce_fs) 20597f724f8bSRobert Watson return (0); 20607f724f8bSRobert Watson 2061177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 20627f724f8bSRobert Watson if (error) 20637f724f8bSRobert Watson return (error); 20647f724f8bSRobert Watson 2065177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 2066177142e4SRobert Watson &vp->v_label); 20677f724f8bSRobert Watson 20687f724f8bSRobert Watson return (error); 20697f724f8bSRobert Watson } 20707f724f8bSRobert Watson 20717f724f8bSRobert Watson int 207295fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 207395fab37eSRobert Watson { 207495fab37eSRobert Watson int error; 207595fab37eSRobert Watson 207695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 207795fab37eSRobert Watson 207895fab37eSRobert Watson if (!mac_enforce_fs) 207995fab37eSRobert Watson return (0); 208095fab37eSRobert Watson 208195fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 208295fab37eSRobert Watson if (error) 208395fab37eSRobert Watson return (error); 208495fab37eSRobert Watson 208595fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 208695fab37eSRobert Watson return (error); 208795fab37eSRobert Watson } 208895fab37eSRobert Watson 208995fab37eSRobert Watson int 209095fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 209195fab37eSRobert Watson { 209295fab37eSRobert Watson int error; 209395fab37eSRobert Watson 209495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 209595fab37eSRobert Watson 209695fab37eSRobert Watson if (!mac_enforce_fs) 209795fab37eSRobert Watson return (0); 209895fab37eSRobert Watson 209995fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 210095fab37eSRobert Watson if (error) 210195fab37eSRobert Watson return (error); 210295fab37eSRobert Watson 210395fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 210495fab37eSRobert Watson return (error); 210595fab37eSRobert Watson } 210695fab37eSRobert Watson 210795fab37eSRobert Watson static int 210895fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 210995fab37eSRobert Watson struct label *newlabel) 211095fab37eSRobert Watson { 211195fab37eSRobert Watson int error; 211295fab37eSRobert Watson 211395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 211495fab37eSRobert Watson 211595fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 211695fab37eSRobert Watson if (error) 211795fab37eSRobert Watson return (error); 211895fab37eSRobert Watson 211995fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 212095fab37eSRobert Watson 212195fab37eSRobert Watson return (error); 212295fab37eSRobert Watson } 212395fab37eSRobert Watson 212495fab37eSRobert Watson int 212595fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 212695fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 212795fab37eSRobert Watson { 212895fab37eSRobert Watson int error; 212995fab37eSRobert Watson 213095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 213195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 213295fab37eSRobert Watson 213395fab37eSRobert Watson if (!mac_enforce_fs) 213495fab37eSRobert Watson return (0); 213595fab37eSRobert Watson 213695fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 213795fab37eSRobert Watson if (error) 213895fab37eSRobert Watson return (error); 213995fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 214095fab37eSRobert Watson if (error) 214195fab37eSRobert Watson return (error); 214295fab37eSRobert Watson 214395fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 214495fab37eSRobert Watson &vp->v_label, cnp); 214595fab37eSRobert Watson return (error); 214695fab37eSRobert Watson } 214795fab37eSRobert Watson 214895fab37eSRobert Watson int 214995fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 215095fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 215195fab37eSRobert Watson { 215295fab37eSRobert Watson int error; 215395fab37eSRobert Watson 215495fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 215595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 215695fab37eSRobert Watson 215795fab37eSRobert Watson if (!mac_enforce_fs) 215895fab37eSRobert Watson return (0); 215995fab37eSRobert Watson 216095fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 216195fab37eSRobert Watson if (error) 216295fab37eSRobert Watson return (error); 216395fab37eSRobert Watson if (vp != NULL) { 216495fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 216595fab37eSRobert Watson if (error) 216695fab37eSRobert Watson return (error); 216795fab37eSRobert Watson } 216895fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 216995fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 217095fab37eSRobert Watson return (error); 217195fab37eSRobert Watson } 217295fab37eSRobert Watson 217395fab37eSRobert Watson int 217495fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 217595fab37eSRobert Watson { 217695fab37eSRobert Watson int error; 217795fab37eSRobert Watson 217895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 217995fab37eSRobert Watson 218095fab37eSRobert Watson if (!mac_enforce_fs) 218195fab37eSRobert Watson return (0); 218295fab37eSRobert Watson 218395fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 218495fab37eSRobert Watson if (error) 218595fab37eSRobert Watson return (error); 218695fab37eSRobert Watson 218795fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 218895fab37eSRobert Watson return (error); 218995fab37eSRobert Watson } 219095fab37eSRobert Watson 219195fab37eSRobert Watson int 219295fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 219395fab37eSRobert Watson struct acl *acl) 219495fab37eSRobert Watson { 219595fab37eSRobert Watson int error; 219695fab37eSRobert Watson 219795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 219895fab37eSRobert Watson 219995fab37eSRobert Watson if (!mac_enforce_fs) 220095fab37eSRobert Watson return (0); 220195fab37eSRobert Watson 220295fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 220395fab37eSRobert Watson if (error) 220495fab37eSRobert Watson return (error); 220595fab37eSRobert Watson 220695fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 220795fab37eSRobert Watson return (error); 220895fab37eSRobert Watson } 220995fab37eSRobert Watson 221095fab37eSRobert Watson int 221195fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 221295fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 221395fab37eSRobert Watson { 221495fab37eSRobert Watson int error; 221595fab37eSRobert Watson 221695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 221795fab37eSRobert Watson 221895fab37eSRobert Watson if (!mac_enforce_fs) 221995fab37eSRobert Watson return (0); 222095fab37eSRobert Watson 222195fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 222295fab37eSRobert Watson if (error) 222395fab37eSRobert Watson return (error); 222495fab37eSRobert Watson 222595fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 222695fab37eSRobert Watson attrnamespace, name, uio); 222795fab37eSRobert Watson return (error); 222895fab37eSRobert Watson } 222995fab37eSRobert Watson 223095fab37eSRobert Watson int 223195fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 223295fab37eSRobert Watson { 223395fab37eSRobert Watson int error; 223495fab37eSRobert Watson 223595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 223695fab37eSRobert Watson 223795fab37eSRobert Watson if (!mac_enforce_fs) 223895fab37eSRobert Watson return (0); 223995fab37eSRobert Watson 224095fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 224195fab37eSRobert Watson if (error) 224295fab37eSRobert Watson return (error); 224395fab37eSRobert Watson 224495fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 224595fab37eSRobert Watson return (error); 224695fab37eSRobert Watson } 224795fab37eSRobert Watson 224895fab37eSRobert Watson int 224995fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 225095fab37eSRobert Watson { 225195fab37eSRobert Watson int error; 225295fab37eSRobert Watson 225395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 225495fab37eSRobert Watson 225595fab37eSRobert Watson if (!mac_enforce_fs) 225695fab37eSRobert Watson return (0); 225795fab37eSRobert Watson 225895fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 225995fab37eSRobert Watson if (error) 226095fab37eSRobert Watson return (error); 226195fab37eSRobert Watson 226295fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 226395fab37eSRobert Watson return (error); 226495fab37eSRobert Watson } 226595fab37eSRobert Watson 226695fab37eSRobert Watson int 226795fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 226895fab37eSRobert Watson gid_t gid) 226995fab37eSRobert Watson { 227095fab37eSRobert Watson int error; 227195fab37eSRobert Watson 227295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 227395fab37eSRobert Watson 227495fab37eSRobert Watson if (!mac_enforce_fs) 227595fab37eSRobert Watson return (0); 227695fab37eSRobert Watson 227795fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 227895fab37eSRobert Watson if (error) 227995fab37eSRobert Watson return (error); 228095fab37eSRobert Watson 228195fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 228295fab37eSRobert Watson return (error); 228395fab37eSRobert Watson } 228495fab37eSRobert Watson 228595fab37eSRobert Watson int 228695fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 228795fab37eSRobert Watson struct timespec atime, struct timespec mtime) 228895fab37eSRobert Watson { 228995fab37eSRobert Watson int error; 229095fab37eSRobert Watson 229195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 229295fab37eSRobert Watson 229395fab37eSRobert Watson if (!mac_enforce_fs) 229495fab37eSRobert Watson return (0); 229595fab37eSRobert Watson 229695fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 229795fab37eSRobert Watson if (error) 229895fab37eSRobert Watson return (error); 229995fab37eSRobert Watson 230095fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 230195fab37eSRobert Watson mtime); 230295fab37eSRobert Watson return (error); 230395fab37eSRobert Watson } 230495fab37eSRobert Watson 230595fab37eSRobert Watson int 2306177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2307177142e4SRobert Watson struct vnode *vp) 230895fab37eSRobert Watson { 230995fab37eSRobert Watson int error; 231095fab37eSRobert Watson 231195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 231295fab37eSRobert Watson 231395fab37eSRobert Watson if (!mac_enforce_fs) 231495fab37eSRobert Watson return (0); 231595fab37eSRobert Watson 2316177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 231795fab37eSRobert Watson if (error) 231895fab37eSRobert Watson return (error); 231995fab37eSRobert Watson 2320177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2321177142e4SRobert Watson &vp->v_label); 232295fab37eSRobert Watson return (error); 232395fab37eSRobert Watson } 232495fab37eSRobert Watson 23257f724f8bSRobert Watson int 2326177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2327177142e4SRobert Watson struct vnode *vp) 23287f724f8bSRobert Watson { 23297f724f8bSRobert Watson int error; 23307f724f8bSRobert Watson 23317f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 23327f724f8bSRobert Watson 23337f724f8bSRobert Watson if (!mac_enforce_fs) 23347f724f8bSRobert Watson return (0); 23357f724f8bSRobert Watson 2336177142e4SRobert Watson error = vn_refreshlabel(vp, active_cred); 23377f724f8bSRobert Watson if (error) 23387f724f8bSRobert Watson return (error); 23397f724f8bSRobert Watson 2340177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2341177142e4SRobert Watson &vp->v_label); 23427f724f8bSRobert Watson 23437f724f8bSRobert Watson return (error); 23447f724f8bSRobert Watson } 23457f724f8bSRobert Watson 234695fab37eSRobert Watson /* 234795fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 234895fab37eSRobert Watson * permission allowed for each object type we know about in its 234995fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 235095fab37eSRobert Watson * know) when necessary. The process lock is not held here. 235195fab37eSRobert Watson */ 235295fab37eSRobert Watson static void 235395fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 235495fab37eSRobert Watson { 235595fab37eSRobert Watson 235695fab37eSRobert Watson /* XXX freeze all other threads */ 235795fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 235895fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 235995fab37eSRobert Watson /* XXX allow other threads to continue */ 236095fab37eSRobert Watson } 236195fab37eSRobert Watson 236295fab37eSRobert Watson static __inline const char * 236395fab37eSRobert Watson prot2str(vm_prot_t prot) 236495fab37eSRobert Watson { 236595fab37eSRobert Watson 236695fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 236795fab37eSRobert Watson case VM_PROT_READ: 236895fab37eSRobert Watson return ("r--"); 236995fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 237095fab37eSRobert Watson return ("rw-"); 237195fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 237295fab37eSRobert Watson return ("r-x"); 237395fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 237495fab37eSRobert Watson return ("rwx"); 237595fab37eSRobert Watson case VM_PROT_WRITE: 237695fab37eSRobert Watson return ("-w-"); 237795fab37eSRobert Watson case VM_PROT_EXECUTE: 237895fab37eSRobert Watson return ("--x"); 237995fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 238095fab37eSRobert Watson return ("-wx"); 238195fab37eSRobert Watson default: 238295fab37eSRobert Watson return ("---"); 238395fab37eSRobert Watson } 238495fab37eSRobert Watson } 238595fab37eSRobert Watson 238695fab37eSRobert Watson static void 238795fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 238895fab37eSRobert Watson struct vm_map *map) 238995fab37eSRobert Watson { 239095fab37eSRobert Watson struct vm_map_entry *vme; 2391e183f80eSRobert Watson int result; 2392e183f80eSRobert Watson vm_prot_t revokeperms; 239395fab37eSRobert Watson vm_object_t object; 239495fab37eSRobert Watson vm_ooffset_t offset; 239595fab37eSRobert Watson struct vnode *vp; 239695fab37eSRobert Watson 2397c0f39905SRobert Watson if (!mac_mmap_revocation) 2398c0f39905SRobert Watson return; 2399c0f39905SRobert Watson 240095fab37eSRobert Watson vm_map_lock_read(map); 240195fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 240295fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 240395fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 240495fab37eSRobert Watson vme->object.sub_map); 240595fab37eSRobert Watson continue; 240695fab37eSRobert Watson } 240795fab37eSRobert Watson /* 240895fab37eSRobert Watson * Skip over entries that obviously are not shared. 240995fab37eSRobert Watson */ 241095fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 241195fab37eSRobert Watson !vme->max_protection) 241295fab37eSRobert Watson continue; 241395fab37eSRobert Watson /* 241495fab37eSRobert Watson * Drill down to the deepest backing object. 241595fab37eSRobert Watson */ 241695fab37eSRobert Watson offset = vme->offset; 241795fab37eSRobert Watson object = vme->object.vm_object; 241895fab37eSRobert Watson if (object == NULL) 241995fab37eSRobert Watson continue; 242095fab37eSRobert Watson while (object->backing_object != NULL) { 242195fab37eSRobert Watson object = object->backing_object; 242295fab37eSRobert Watson offset += object->backing_object_offset; 242395fab37eSRobert Watson } 242495fab37eSRobert Watson /* 242595fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 242695fab37eSRobert Watson * by the MAC system, so only things with backing by a 242795fab37eSRobert Watson * normal object (read: vnodes) are checked. 242895fab37eSRobert Watson */ 242995fab37eSRobert Watson if (object->type != OBJT_VNODE) 243095fab37eSRobert Watson continue; 243195fab37eSRobert Watson vp = (struct vnode *)object->handle; 243295fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2433e183f80eSRobert Watson result = vme->max_protection; 2434e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 243595fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 243695fab37eSRobert Watson /* 243795fab37eSRobert Watson * Find out what maximum protection we may be allowing 243895fab37eSRobert Watson * now but a policy needs to get removed. 243995fab37eSRobert Watson */ 244095fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 244195fab37eSRobert Watson if (!revokeperms) 244295fab37eSRobert Watson continue; 2443b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 2444b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2445b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 2446b656366bSBruce Evans (long)(vme->end - vme->start), 244795fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 244895fab37eSRobert Watson vm_map_lock_upgrade(map); 244995fab37eSRobert Watson /* 245095fab37eSRobert Watson * This is the really simple case: if a map has more 245195fab37eSRobert Watson * max_protection than is allowed, but it's not being 245295fab37eSRobert Watson * actually used (that is, the current protection is 245395fab37eSRobert Watson * still allowed), we can just wipe it out and do 245495fab37eSRobert Watson * nothing more. 245595fab37eSRobert Watson */ 245695fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 245795fab37eSRobert Watson vme->max_protection -= revokeperms; 245895fab37eSRobert Watson } else { 245995fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 246095fab37eSRobert Watson /* 246195fab37eSRobert Watson * In the more complicated case, flush out all 246295fab37eSRobert Watson * pending changes to the object then turn it 246395fab37eSRobert Watson * copy-on-write. 246495fab37eSRobert Watson */ 246595fab37eSRobert Watson vm_object_reference(object); 246695fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 246795fab37eSRobert Watson vm_object_page_clean(object, 246895fab37eSRobert Watson OFF_TO_IDX(offset), 246995fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 247095fab37eSRobert Watson PAGE_MASK), 247195fab37eSRobert Watson OBJPC_SYNC); 247295fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 247395fab37eSRobert Watson vm_object_deallocate(object); 247495fab37eSRobert Watson /* 247595fab37eSRobert Watson * Why bother if there's no read permissions 247695fab37eSRobert Watson * anymore? For the rest, we need to leave 247795fab37eSRobert Watson * the write permissions on for COW, or 247895fab37eSRobert Watson * remove them entirely if configured to. 247995fab37eSRobert Watson */ 248095fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 248195fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 248295fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 248395fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 248495fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 248595fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 248695fab37eSRobert Watson } 248795fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 248895fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 248995fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 249095fab37eSRobert Watson } 249195fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 249295fab37eSRobert Watson vme->max_protection = 0; 249395fab37eSRobert Watson vme->protection = 0; 249495fab37eSRobert Watson } 249595fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 249695fab37eSRobert Watson vme->protection & ~revokeperms); 249795fab37eSRobert Watson vm_map_simplify_entry(map, vme); 249895fab37eSRobert Watson } 249995fab37eSRobert Watson vm_map_lock_downgrade(map); 250095fab37eSRobert Watson } 250195fab37eSRobert Watson vm_map_unlock_read(map); 250295fab37eSRobert Watson } 250395fab37eSRobert Watson 250495fab37eSRobert Watson /* 250595fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 250695fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 250795fab37eSRobert Watson * buffer cache. 250895fab37eSRobert Watson */ 250995fab37eSRobert Watson static void 251095fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 251195fab37eSRobert Watson { 251295fab37eSRobert Watson 251395fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 251495fab37eSRobert Watson } 251595fab37eSRobert Watson 251695fab37eSRobert Watson void 251795fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 251895fab37eSRobert Watson { 251995fab37eSRobert Watson 252095fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 252195fab37eSRobert Watson } 252295fab37eSRobert Watson 252395fab37eSRobert Watson void 252495fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 252595fab37eSRobert Watson { 252695fab37eSRobert Watson 252795fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 252895fab37eSRobert Watson } 252995fab37eSRobert Watson 253095fab37eSRobert Watson void 253195fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 253295fab37eSRobert Watson { 253395fab37eSRobert Watson 253495fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 253595fab37eSRobert Watson } 253695fab37eSRobert Watson 253795fab37eSRobert Watson void 253895fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 253995fab37eSRobert Watson { 254095fab37eSRobert Watson 254195fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 254295fab37eSRobert Watson } 254395fab37eSRobert Watson 254495fab37eSRobert Watson void 254595fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 254695fab37eSRobert Watson { 254795fab37eSRobert Watson 254895fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 254995fab37eSRobert Watson } 255095fab37eSRobert Watson 255195fab37eSRobert Watson void 255295fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 255395fab37eSRobert Watson struct socket *newsocket) 255495fab37eSRobert Watson { 255595fab37eSRobert Watson 255695fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 255795fab37eSRobert Watson newsocket, &newsocket->so_label); 255895fab37eSRobert Watson } 255995fab37eSRobert Watson 256095fab37eSRobert Watson static void 256195fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 256295fab37eSRobert Watson struct label *newlabel) 256395fab37eSRobert Watson { 256495fab37eSRobert Watson 256595fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 256695fab37eSRobert Watson } 256795fab37eSRobert Watson 256895fab37eSRobert Watson static void 256995fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 257095fab37eSRobert Watson { 257195fab37eSRobert Watson 257295fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 257395fab37eSRobert Watson } 257495fab37eSRobert Watson 257595fab37eSRobert Watson void 257695fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 257795fab37eSRobert Watson { 257895fab37eSRobert Watson 257995fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 258095fab37eSRobert Watson socket, &socket->so_peerlabel); 258195fab37eSRobert Watson } 258295fab37eSRobert Watson 258395fab37eSRobert Watson void 258495fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 258595fab37eSRobert Watson struct socket *newsocket) 258695fab37eSRobert Watson { 258795fab37eSRobert Watson 258895fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 258995fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 259095fab37eSRobert Watson } 259195fab37eSRobert Watson 259295fab37eSRobert Watson void 259395fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 259495fab37eSRobert Watson { 259595fab37eSRobert Watson 259695fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 259795fab37eSRobert Watson datagram, &datagram->m_pkthdr.label); 259895fab37eSRobert Watson } 259995fab37eSRobert Watson 260095fab37eSRobert Watson void 260195fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 260295fab37eSRobert Watson { 260395fab37eSRobert Watson 260495fab37eSRobert Watson MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 260595fab37eSRobert Watson fragment, &fragment->m_pkthdr.label); 260695fab37eSRobert Watson } 260795fab37eSRobert Watson 260895fab37eSRobert Watson void 260995fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 261095fab37eSRobert Watson { 261195fab37eSRobert Watson 261295fab37eSRobert Watson MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 261395fab37eSRobert Watson &ipq->ipq_label); 261495fab37eSRobert Watson } 261595fab37eSRobert Watson 261695fab37eSRobert Watson void 261795fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 261895fab37eSRobert Watson { 261995fab37eSRobert Watson 262095fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 262195fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 262295fab37eSRobert Watson } 262395fab37eSRobert Watson 262495fab37eSRobert Watson void 262595fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 262695fab37eSRobert Watson { 262795fab37eSRobert Watson 262895fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 262995fab37eSRobert Watson &mbuf->m_pkthdr.label); 263095fab37eSRobert Watson } 263195fab37eSRobert Watson 263295fab37eSRobert Watson void 263395fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 263495fab37eSRobert Watson { 263595fab37eSRobert Watson 263695fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 263795fab37eSRobert Watson &mbuf->m_pkthdr.label); 263895fab37eSRobert Watson } 263995fab37eSRobert Watson 264095fab37eSRobert Watson void 264195fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 264295fab37eSRobert Watson { 264395fab37eSRobert Watson 264495fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 264595fab37eSRobert Watson &mbuf->m_pkthdr.label); 264695fab37eSRobert Watson } 264795fab37eSRobert Watson 264895fab37eSRobert Watson void 264995fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 265095fab37eSRobert Watson struct mbuf *newmbuf) 265195fab37eSRobert Watson { 265295fab37eSRobert Watson 265395fab37eSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 265495fab37eSRobert Watson &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 265595fab37eSRobert Watson &newmbuf->m_pkthdr.label); 265695fab37eSRobert Watson } 265795fab37eSRobert Watson 265895fab37eSRobert Watson void 265995fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 266095fab37eSRobert Watson { 266195fab37eSRobert Watson 266295fab37eSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 266395fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 266495fab37eSRobert Watson } 266595fab37eSRobert Watson 266695fab37eSRobert Watson int 266795fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 266895fab37eSRobert Watson { 266995fab37eSRobert Watson int result; 267095fab37eSRobert Watson 267195fab37eSRobert Watson result = 1; 267295fab37eSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 267395fab37eSRobert Watson ipq, &ipq->ipq_label); 267495fab37eSRobert Watson 267595fab37eSRobert Watson return (result); 267695fab37eSRobert Watson } 267795fab37eSRobert Watson 267895fab37eSRobert Watson void 267995fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 268095fab37eSRobert Watson { 268195fab37eSRobert Watson 268295fab37eSRobert Watson MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 268395fab37eSRobert Watson &ipq->ipq_label); 268495fab37eSRobert Watson } 268595fab37eSRobert Watson 268695fab37eSRobert Watson void 268795fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 268895fab37eSRobert Watson { 268995fab37eSRobert Watson 269095fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 269195fab37eSRobert Watson &mbuf->m_pkthdr.label); 269295fab37eSRobert Watson } 269395fab37eSRobert Watson 269495fab37eSRobert Watson void 269595fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 269695fab37eSRobert Watson { 269795fab37eSRobert Watson 269895fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 269995fab37eSRobert Watson &mp->mnt_fslabel); 270095fab37eSRobert Watson } 270195fab37eSRobert Watson 270295fab37eSRobert Watson void 270395fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 270495fab37eSRobert Watson { 270595fab37eSRobert Watson 270695fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 270795fab37eSRobert Watson &mp->mnt_fslabel); 270895fab37eSRobert Watson } 270995fab37eSRobert Watson 271095fab37eSRobert Watson int 271195fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 271295fab37eSRobert Watson { 271395fab37eSRobert Watson int error; 271495fab37eSRobert Watson 271595fab37eSRobert Watson if (!mac_enforce_network) 271695fab37eSRobert Watson return (0); 271795fab37eSRobert Watson 271895fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 271995fab37eSRobert Watson &ifnet->if_label); 272095fab37eSRobert Watson 272195fab37eSRobert Watson return (error); 272295fab37eSRobert Watson } 272395fab37eSRobert Watson 272495fab37eSRobert Watson static int 272595fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 272695fab37eSRobert Watson { 272795fab37eSRobert Watson int error; 272895fab37eSRobert Watson 272995fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 273095fab37eSRobert Watson 273195fab37eSRobert Watson return (error); 273295fab37eSRobert Watson } 273395fab37eSRobert Watson 273495fab37eSRobert Watson int 273595fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 273695fab37eSRobert Watson { 273795fab37eSRobert Watson int error; 273895fab37eSRobert Watson 273995fab37eSRobert Watson if (!mac_enforce_process) 274095fab37eSRobert Watson return (0); 274195fab37eSRobert Watson 274295fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 274395fab37eSRobert Watson 274495fab37eSRobert Watson return (error); 274595fab37eSRobert Watson } 274695fab37eSRobert Watson 274795fab37eSRobert Watson int 274895fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 274995fab37eSRobert Watson { 275095fab37eSRobert Watson int error; 275195fab37eSRobert Watson 275295fab37eSRobert Watson if (!mac_enforce_network) 275395fab37eSRobert Watson return (0); 275495fab37eSRobert Watson 275595fab37eSRobert Watson KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 275695fab37eSRobert Watson if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 275795fab37eSRobert Watson printf("%s%d: not initialized\n", ifnet->if_name, 275895fab37eSRobert Watson ifnet->if_unit); 275995fab37eSRobert Watson 276095fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 276195fab37eSRobert Watson &mbuf->m_pkthdr.label); 276295fab37eSRobert Watson 276395fab37eSRobert Watson return (error); 276495fab37eSRobert Watson } 276595fab37eSRobert Watson 276695fab37eSRobert Watson int 276795fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 276895fab37eSRobert Watson { 276995fab37eSRobert Watson int error; 277095fab37eSRobert Watson 277195fab37eSRobert Watson if (!mac_enforce_fs) 277295fab37eSRobert Watson return (0); 277395fab37eSRobert Watson 277495fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 277595fab37eSRobert Watson 277695fab37eSRobert Watson return (error); 277795fab37eSRobert Watson } 277895fab37eSRobert Watson 277995fab37eSRobert Watson int 278095fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 278195fab37eSRobert Watson void *data) 278295fab37eSRobert Watson { 278395fab37eSRobert Watson int error; 278495fab37eSRobert Watson 27851aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 27861aa37f53SRobert Watson 27871aa37f53SRobert Watson if (!mac_enforce_pipe) 27881aa37f53SRobert Watson return (0); 27891aa37f53SRobert Watson 279095fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 279195fab37eSRobert Watson 279295fab37eSRobert Watson return (error); 279395fab37eSRobert Watson } 279495fab37eSRobert Watson 279595fab37eSRobert Watson int 2796c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 279795fab37eSRobert Watson { 279895fab37eSRobert Watson int error; 279995fab37eSRobert Watson 28001aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28011aa37f53SRobert Watson 28021aa37f53SRobert Watson if (!mac_enforce_pipe) 28031aa37f53SRobert Watson return (0); 28041aa37f53SRobert Watson 2805c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2806c024c3eeSRobert Watson 2807c024c3eeSRobert Watson return (error); 2808c024c3eeSRobert Watson } 2809c024c3eeSRobert Watson 2810c024c3eeSRobert Watson int 2811c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2812c024c3eeSRobert Watson { 2813c024c3eeSRobert Watson int error; 2814c024c3eeSRobert Watson 28151aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28161aa37f53SRobert Watson 28171aa37f53SRobert Watson if (!mac_enforce_pipe) 28181aa37f53SRobert Watson return (0); 28191aa37f53SRobert Watson 2820c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 282195fab37eSRobert Watson 282295fab37eSRobert Watson return (error); 282395fab37eSRobert Watson } 282495fab37eSRobert Watson 282595fab37eSRobert Watson static int 282695fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 282795fab37eSRobert Watson struct label *newlabel) 282895fab37eSRobert Watson { 282995fab37eSRobert Watson int error; 283095fab37eSRobert Watson 28311aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28321aa37f53SRobert Watson 28331aa37f53SRobert Watson if (!mac_enforce_pipe) 28341aa37f53SRobert Watson return (0); 28351aa37f53SRobert Watson 283695fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 283795fab37eSRobert Watson 283895fab37eSRobert Watson return (error); 283995fab37eSRobert Watson } 284095fab37eSRobert Watson 284195fab37eSRobert Watson int 2842c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2843c024c3eeSRobert Watson { 2844c024c3eeSRobert Watson int error; 2845c024c3eeSRobert Watson 28461aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28471aa37f53SRobert Watson 28481aa37f53SRobert Watson if (!mac_enforce_pipe) 28491aa37f53SRobert Watson return (0); 28501aa37f53SRobert Watson 2851c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2852c024c3eeSRobert Watson 2853c024c3eeSRobert Watson return (error); 2854c024c3eeSRobert Watson } 2855c024c3eeSRobert Watson 2856c024c3eeSRobert Watson int 2857c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2858c024c3eeSRobert Watson { 2859c024c3eeSRobert Watson int error; 2860c024c3eeSRobert Watson 28611aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28621aa37f53SRobert Watson 28631aa37f53SRobert Watson if (!mac_enforce_pipe) 28641aa37f53SRobert Watson return (0); 28651aa37f53SRobert Watson 2866c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2867c024c3eeSRobert Watson 2868c024c3eeSRobert Watson return (error); 2869c024c3eeSRobert Watson } 2870c024c3eeSRobert Watson 2871c024c3eeSRobert Watson int 287295fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 287395fab37eSRobert Watson { 287495fab37eSRobert Watson int error; 287595fab37eSRobert Watson 2876b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2877b12baf55SRobert Watson 287895fab37eSRobert Watson if (!mac_enforce_process) 287995fab37eSRobert Watson return (0); 288095fab37eSRobert Watson 288195fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 288295fab37eSRobert Watson 288395fab37eSRobert Watson return (error); 288495fab37eSRobert Watson } 288595fab37eSRobert Watson 288695fab37eSRobert Watson int 288795fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 288895fab37eSRobert Watson { 288995fab37eSRobert Watson int error; 289095fab37eSRobert Watson 2891b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2892b12baf55SRobert Watson 289395fab37eSRobert Watson if (!mac_enforce_process) 289495fab37eSRobert Watson return (0); 289595fab37eSRobert Watson 289695fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 289795fab37eSRobert Watson 289895fab37eSRobert Watson return (error); 289995fab37eSRobert Watson } 290095fab37eSRobert Watson 290195fab37eSRobert Watson int 290295fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 290395fab37eSRobert Watson { 290495fab37eSRobert Watson int error; 290595fab37eSRobert Watson 2906b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2907b12baf55SRobert Watson 290895fab37eSRobert Watson if (!mac_enforce_process) 290995fab37eSRobert Watson return (0); 291095fab37eSRobert Watson 291195fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 291295fab37eSRobert Watson 291395fab37eSRobert Watson return (error); 291495fab37eSRobert Watson } 291595fab37eSRobert Watson 291695fab37eSRobert Watson int 291795fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 291895fab37eSRobert Watson struct sockaddr *sockaddr) 291995fab37eSRobert Watson { 292095fab37eSRobert Watson int error; 292195fab37eSRobert Watson 292295fab37eSRobert Watson if (!mac_enforce_socket) 292395fab37eSRobert Watson return (0); 292495fab37eSRobert Watson 292595fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 292695fab37eSRobert Watson sockaddr); 292795fab37eSRobert Watson 292895fab37eSRobert Watson return (error); 292995fab37eSRobert Watson } 293095fab37eSRobert Watson 293195fab37eSRobert Watson int 293295fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 293395fab37eSRobert Watson struct sockaddr *sockaddr) 293495fab37eSRobert Watson { 293595fab37eSRobert Watson int error; 293695fab37eSRobert Watson 293795fab37eSRobert Watson if (!mac_enforce_socket) 293895fab37eSRobert Watson return (0); 293995fab37eSRobert Watson 294095fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 294195fab37eSRobert Watson sockaddr); 294295fab37eSRobert Watson 294395fab37eSRobert Watson return (error); 294495fab37eSRobert Watson } 294595fab37eSRobert Watson 294695fab37eSRobert Watson int 2947d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2948d61198e4SRobert Watson { 2949d61198e4SRobert Watson int error; 2950d61198e4SRobert Watson 2951d61198e4SRobert Watson if (!mac_enforce_socket) 2952d61198e4SRobert Watson return (0); 2953d61198e4SRobert Watson 2954d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2955d61198e4SRobert Watson &mbuf->m_pkthdr.label); 2956d61198e4SRobert Watson 2957d61198e4SRobert Watson return (error); 2958d61198e4SRobert Watson } 2959d61198e4SRobert Watson 2960d61198e4SRobert Watson int 296195fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 296295fab37eSRobert Watson { 296395fab37eSRobert Watson int error; 296495fab37eSRobert Watson 296595fab37eSRobert Watson if (!mac_enforce_socket) 296695fab37eSRobert Watson return (0); 296795fab37eSRobert Watson 296895fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 296995fab37eSRobert Watson return (error); 297095fab37eSRobert Watson } 297195fab37eSRobert Watson 2972b371c939SRobert Watson int 2973b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 2974b371c939SRobert Watson { 2975b371c939SRobert Watson int error; 2976b371c939SRobert Watson 2977b371c939SRobert Watson if (!mac_enforce_socket) 2978b371c939SRobert Watson return (0); 2979b371c939SRobert Watson 2980b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2981b371c939SRobert Watson 2982b371c939SRobert Watson return (error); 2983b371c939SRobert Watson } 2984b371c939SRobert Watson 298595fab37eSRobert Watson static int 298695fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 298795fab37eSRobert Watson struct label *newlabel) 298895fab37eSRobert Watson { 298995fab37eSRobert Watson int error; 299095fab37eSRobert Watson 299195fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 299295fab37eSRobert Watson newlabel); 299395fab37eSRobert Watson 299495fab37eSRobert Watson return (error); 299595fab37eSRobert Watson } 299695fab37eSRobert Watson 299795fab37eSRobert Watson int 2998b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 2999b371c939SRobert Watson { 3000b371c939SRobert Watson int error; 3001b371c939SRobert Watson 3002b371c939SRobert Watson if (!mac_enforce_socket) 3003b371c939SRobert Watson return (0); 3004b371c939SRobert Watson 3005b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 3006b371c939SRobert Watson 3007b371c939SRobert Watson return (error); 3008b371c939SRobert Watson } 3009b371c939SRobert Watson 3010b371c939SRobert Watson int 301195fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 301295fab37eSRobert Watson { 301395fab37eSRobert Watson int error; 301495fab37eSRobert Watson 301595fab37eSRobert Watson if (!mac_enforce_socket) 301695fab37eSRobert Watson return (0); 301795fab37eSRobert Watson 301895fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 301995fab37eSRobert Watson 302095fab37eSRobert Watson return (error); 302195fab37eSRobert Watson } 302295fab37eSRobert Watson 302395fab37eSRobert Watson int 302495fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 302595fab37eSRobert Watson struct ifnet *ifnet) 302695fab37eSRobert Watson { 302795fab37eSRobert Watson struct mac label; 302895fab37eSRobert Watson int error; 302995fab37eSRobert Watson 303095fab37eSRobert Watson error = mac_externalize(&ifnet->if_label, &label); 303195fab37eSRobert Watson if (error) 303295fab37eSRobert Watson return (error); 303395fab37eSRobert Watson 303495fab37eSRobert Watson return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label))); 303595fab37eSRobert Watson } 303695fab37eSRobert Watson 303795fab37eSRobert Watson int 303895fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 303995fab37eSRobert Watson struct ifnet *ifnet) 304095fab37eSRobert Watson { 304195fab37eSRobert Watson struct mac newlabel; 304295fab37eSRobert Watson struct label intlabel; 304395fab37eSRobert Watson int error; 304495fab37eSRobert Watson 304595fab37eSRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel)); 304695fab37eSRobert Watson if (error) 304795fab37eSRobert Watson return (error); 304895fab37eSRobert Watson 304995fab37eSRobert Watson error = mac_internalize(&intlabel, &newlabel); 305095fab37eSRobert Watson if (error) 305195fab37eSRobert Watson return (error); 305295fab37eSRobert Watson 305395fab37eSRobert Watson /* 305495fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 305595fab37eSRobert Watson * policies impose this check themselves if required by the 305695fab37eSRobert Watson * policy. Eventually, this should go away. 305795fab37eSRobert Watson */ 305895fab37eSRobert Watson error = suser_cred(cred, 0); 305995fab37eSRobert Watson if (error) 306095fab37eSRobert Watson goto out; 306195fab37eSRobert Watson 306295fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 306395fab37eSRobert Watson &intlabel); 306495fab37eSRobert Watson if (error) 306595fab37eSRobert Watson goto out; 306695fab37eSRobert Watson 306795fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 306895fab37eSRobert Watson 306995fab37eSRobert Watson out: 307095fab37eSRobert Watson mac_destroy_temp(&intlabel); 307195fab37eSRobert Watson return (error); 307295fab37eSRobert Watson } 307395fab37eSRobert Watson 307495fab37eSRobert Watson void 307595fab37eSRobert Watson mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 307695fab37eSRobert Watson { 307795fab37eSRobert Watson 307895fab37eSRobert Watson MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 307995fab37eSRobert Watson } 308095fab37eSRobert Watson 308195fab37eSRobert Watson void 308295fab37eSRobert Watson mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 308395fab37eSRobert Watson { 308495fab37eSRobert Watson 308595fab37eSRobert Watson MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 308695fab37eSRobert Watson } 308795fab37eSRobert Watson 308874e62b1bSRobert Watson void 308974e62b1bSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 309074e62b1bSRobert Watson struct devfs_dirent *de) 309174e62b1bSRobert Watson { 309274e62b1bSRobert Watson 309374e62b1bSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 309474e62b1bSRobert Watson &de->de_label); 309574e62b1bSRobert Watson } 309674e62b1bSRobert Watson 309795fab37eSRobert Watson static int 309895fab37eSRobert Watson mac_stdcreatevnode_ea(struct vnode *vp) 309995fab37eSRobert Watson { 310095fab37eSRobert Watson int error; 310195fab37eSRobert Watson 310295fab37eSRobert Watson MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); 310395fab37eSRobert Watson 310495fab37eSRobert Watson return (error); 310595fab37eSRobert Watson } 310695fab37eSRobert Watson 310795fab37eSRobert Watson void 310895fab37eSRobert Watson mac_create_devfs_directory(char *dirname, int dirnamelen, 310995fab37eSRobert Watson struct devfs_dirent *de) 311095fab37eSRobert Watson { 311195fab37eSRobert Watson 311295fab37eSRobert Watson MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 311395fab37eSRobert Watson &de->de_label); 311495fab37eSRobert Watson } 311595fab37eSRobert Watson 311695fab37eSRobert Watson /* 311795fab37eSRobert Watson * When a new vnode is created, this call will initialize its label. 311895fab37eSRobert Watson */ 311995fab37eSRobert Watson void 312095fab37eSRobert Watson mac_create_vnode(struct ucred *cred, struct vnode *parent, 312195fab37eSRobert Watson struct vnode *child) 312295fab37eSRobert Watson { 312395fab37eSRobert Watson int error; 312495fab37eSRobert Watson 312595fab37eSRobert Watson ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); 312695fab37eSRobert Watson ASSERT_VOP_LOCKED(child, "mac_create_vnode"); 312795fab37eSRobert Watson 312895fab37eSRobert Watson error = vn_refreshlabel(parent, cred); 312995fab37eSRobert Watson if (error) { 313095fab37eSRobert Watson printf("mac_create_vnode: vn_refreshlabel returned %d\n", 313195fab37eSRobert Watson error); 313295fab37eSRobert Watson printf("mac_create_vnode: using old vnode label\n"); 313395fab37eSRobert Watson } 313495fab37eSRobert Watson 313595fab37eSRobert Watson MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, 313695fab37eSRobert Watson &child->v_label); 313795fab37eSRobert Watson } 313895fab37eSRobert Watson 313995fab37eSRobert Watson int 314095fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 314195fab37eSRobert Watson struct mac *extmac) 314295fab37eSRobert Watson { 314395fab37eSRobert Watson struct label intlabel; 314495fab37eSRobert Watson int error; 314595fab37eSRobert Watson 314695fab37eSRobert Watson error = mac_internalize(&intlabel, extmac); 314795fab37eSRobert Watson if (error) 314895fab37eSRobert Watson return (error); 314995fab37eSRobert Watson 315095fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 315195fab37eSRobert Watson if (error) { 315295fab37eSRobert Watson mac_destroy_temp(&intlabel); 315395fab37eSRobert Watson return (error); 315495fab37eSRobert Watson } 315595fab37eSRobert Watson 315695fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 315795fab37eSRobert Watson 315895fab37eSRobert Watson mac_destroy_temp(&intlabel); 315995fab37eSRobert Watson return (0); 316095fab37eSRobert Watson } 316195fab37eSRobert Watson 316295fab37eSRobert Watson int 316395fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 316495fab37eSRobert Watson { 316595fab37eSRobert Watson int error; 316695fab37eSRobert Watson 31671aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31681aa37f53SRobert Watson 316995fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 317095fab37eSRobert Watson if (error) 317195fab37eSRobert Watson return (error); 317295fab37eSRobert Watson 317395fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 317495fab37eSRobert Watson 317595fab37eSRobert Watson return (0); 317695fab37eSRobert Watson } 317795fab37eSRobert Watson 317895fab37eSRobert Watson int 317995fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 318095fab37eSRobert Watson struct mac *extmac) 318195fab37eSRobert Watson { 318295fab37eSRobert Watson 318395fab37eSRobert Watson return (mac_externalize(&so->so_label, extmac)); 318495fab37eSRobert Watson } 318595fab37eSRobert Watson 318695fab37eSRobert Watson int 318795fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 318895fab37eSRobert Watson struct mac *extmac) 318995fab37eSRobert Watson { 319095fab37eSRobert Watson 319195fab37eSRobert Watson return (mac_externalize(&so->so_peerlabel, extmac)); 319295fab37eSRobert Watson } 319395fab37eSRobert Watson 319495fab37eSRobert Watson /* 319595fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 319695fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 319795fab37eSRobert Watson * extended attributes. 319895fab37eSRobert Watson */ 319995fab37eSRobert Watson int 320095fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 320195fab37eSRobert Watson { 320295fab37eSRobert Watson struct vnode *vp = ap->a_vp; 320395fab37eSRobert Watson struct label *intlabel = ap->a_label; 320495fab37eSRobert Watson struct mac extmac; 320595fab37eSRobert Watson int error; 320695fab37eSRobert Watson 320795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 320895fab37eSRobert Watson 320995fab37eSRobert Watson /* 321095fab37eSRobert Watson * XXX: Eventually call out to EA check/set calls here. 321195fab37eSRobert Watson * Be particularly careful to avoid race conditions, 321295fab37eSRobert Watson * consistency problems, and stability problems when 321395fab37eSRobert Watson * dealing with multiple EAs. In particular, we require 321495fab37eSRobert Watson * the ability to write multiple EAs on the same file in 321595fab37eSRobert Watson * a single transaction, which the current EA interface 321695fab37eSRobert Watson * does not provide. 321795fab37eSRobert Watson */ 321895fab37eSRobert Watson 321995fab37eSRobert Watson error = mac_externalize(intlabel, &extmac); 322095fab37eSRobert Watson if (error) 322195fab37eSRobert Watson return (error); 322295fab37eSRobert Watson 322395fab37eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, 322495fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 322595fab37eSRobert Watson sizeof(extmac), (char *)&extmac, curthread); 322695fab37eSRobert Watson if (error) 322795fab37eSRobert Watson return (error); 322895fab37eSRobert Watson 322995fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 323095fab37eSRobert Watson 3231e6e370a7SJeff Roberson vp->v_vflag |= VV_CACHEDLABEL; 323295fab37eSRobert Watson 323395fab37eSRobert Watson return (0); 323495fab37eSRobert Watson } 323595fab37eSRobert Watson 323695fab37eSRobert Watson static int 323795fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 323895fab37eSRobert Watson { 323995fab37eSRobert Watson int error; 324095fab37eSRobert Watson 324195fab37eSRobert Watson if (vp->v_mount == NULL) { 324295fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 324306be2aaaSNate Lawson if (vp->v_type != VNON) 324406be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 324595fab37eSRobert Watson return (EBADF); 324695fab37eSRobert Watson } 324795fab37eSRobert Watson 324895fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 324995fab37eSRobert Watson return (EOPNOTSUPP); 325095fab37eSRobert Watson 325195fab37eSRobert Watson /* 325295fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 325395fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 325495fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 325595fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 325695fab37eSRobert Watson */ 325795fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 325895fab37eSRobert Watson if (error) 325995fab37eSRobert Watson return (error); 326095fab37eSRobert Watson 326195fab37eSRobert Watson /* 326295fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 326395fab37eSRobert Watson * decisions about who is and is not able to modify labels 326495fab37eSRobert Watson * and protections on files. This might not be right. We can't 326595fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 326695fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 326795fab37eSRobert Watson */ 326895fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 326995fab37eSRobert Watson if (error) 327095fab37eSRobert Watson return (error); 327195fab37eSRobert Watson 327295fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 327395fab37eSRobert Watson if (error) 327495fab37eSRobert Watson return (error); 327595fab37eSRobert Watson 327695fab37eSRobert Watson return (0); 327795fab37eSRobert Watson } 327895fab37eSRobert Watson 327995fab37eSRobert Watson /* 328095fab37eSRobert Watson * MPSAFE 328195fab37eSRobert Watson */ 328295fab37eSRobert Watson int 328395fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 328495fab37eSRobert Watson { 328595fab37eSRobert Watson struct mac extmac; 328695fab37eSRobert Watson int error; 328795fab37eSRobert Watson 328895fab37eSRobert Watson error = mac_externalize(&td->td_ucred->cr_label, &extmac); 328995fab37eSRobert Watson if (error == 0) 329095fab37eSRobert Watson error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 329195fab37eSRobert Watson 329295fab37eSRobert Watson return (error); 329395fab37eSRobert Watson } 329495fab37eSRobert Watson 329595fab37eSRobert Watson /* 329695fab37eSRobert Watson * MPSAFE 329795fab37eSRobert Watson */ 329895fab37eSRobert Watson int 329995fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 330095fab37eSRobert Watson { 330195fab37eSRobert Watson struct ucred *newcred, *oldcred; 330295fab37eSRobert Watson struct proc *p; 330395fab37eSRobert Watson struct mac extmac; 330495fab37eSRobert Watson struct label intlabel; 330595fab37eSRobert Watson int error; 330695fab37eSRobert Watson 330795fab37eSRobert Watson error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 330895fab37eSRobert Watson if (error) 330995fab37eSRobert Watson return (error); 331095fab37eSRobert Watson 331195fab37eSRobert Watson error = mac_internalize(&intlabel, &extmac); 331295fab37eSRobert Watson if (error) 331395fab37eSRobert Watson return (error); 331495fab37eSRobert Watson 331595fab37eSRobert Watson newcred = crget(); 331695fab37eSRobert Watson 331795fab37eSRobert Watson p = td->td_proc; 331895fab37eSRobert Watson PROC_LOCK(p); 331995fab37eSRobert Watson oldcred = p->p_ucred; 332095fab37eSRobert Watson 332195fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 332295fab37eSRobert Watson if (error) { 332395fab37eSRobert Watson PROC_UNLOCK(p); 332495fab37eSRobert Watson mac_destroy_temp(&intlabel); 332595fab37eSRobert Watson crfree(newcred); 332695fab37eSRobert Watson return (error); 332795fab37eSRobert Watson } 332895fab37eSRobert Watson 332995fab37eSRobert Watson setsugid(p); 333095fab37eSRobert Watson crcopy(newcred, oldcred); 333195fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 333295fab37eSRobert Watson p->p_ucred = newcred; 3333e5cb5e37SRobert Watson 3334e5cb5e37SRobert Watson /* 3335e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3336e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3337e5cb5e37SRobert Watson */ 3338e5cb5e37SRobert Watson crhold(newcred); 333995fab37eSRobert Watson PROC_UNLOCK(p); 3340e5cb5e37SRobert Watson 334116140035SRobert Watson mtx_lock(&Giant); 3342e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 334316140035SRobert Watson mtx_unlock(&Giant); 3344e5cb5e37SRobert Watson 3345e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 334695fab37eSRobert Watson crfree(oldcred); 334795fab37eSRobert Watson mac_destroy_temp(&intlabel); 334895fab37eSRobert Watson return (0); 334995fab37eSRobert Watson } 335095fab37eSRobert Watson 335195fab37eSRobert Watson /* 335295fab37eSRobert Watson * MPSAFE 335395fab37eSRobert Watson */ 335495fab37eSRobert Watson int 335595fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 335695fab37eSRobert Watson { 335795fab37eSRobert Watson struct file *fp; 335895fab37eSRobert Watson struct mac extmac; 335995fab37eSRobert Watson struct vnode *vp; 336095fab37eSRobert Watson struct pipe *pipe; 336195fab37eSRobert Watson int error; 336295fab37eSRobert Watson 336395fab37eSRobert Watson mtx_lock(&Giant); 336495fab37eSRobert Watson 336595fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 336695fab37eSRobert Watson if (error) 336795fab37eSRobert Watson goto out; 336895fab37eSRobert Watson 336995fab37eSRobert Watson switch (fp->f_type) { 337095fab37eSRobert Watson case DTYPE_FIFO: 337195fab37eSRobert Watson case DTYPE_VNODE: 337295fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 337395fab37eSRobert Watson 337495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 337595fab37eSRobert Watson error = vn_refreshlabel(vp, td->td_ucred); 337695fab37eSRobert Watson if (error == 0) 337795fab37eSRobert Watson error = mac_externalize(&vp->v_label, &extmac); 337895fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 337995fab37eSRobert Watson break; 338095fab37eSRobert Watson case DTYPE_PIPE: 338195fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 338295fab37eSRobert Watson error = mac_externalize(pipe->pipe_label, &extmac); 338395fab37eSRobert Watson break; 338495fab37eSRobert Watson default: 338595fab37eSRobert Watson error = EINVAL; 338695fab37eSRobert Watson } 338795fab37eSRobert Watson 338895fab37eSRobert Watson if (error == 0) 338995fab37eSRobert Watson error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 339095fab37eSRobert Watson 339195fab37eSRobert Watson fdrop(fp, td); 339295fab37eSRobert Watson 339395fab37eSRobert Watson out: 339495fab37eSRobert Watson mtx_unlock(&Giant); 339595fab37eSRobert Watson return (error); 339695fab37eSRobert Watson } 339795fab37eSRobert Watson 339895fab37eSRobert Watson /* 339995fab37eSRobert Watson * MPSAFE 340095fab37eSRobert Watson */ 340195fab37eSRobert Watson int 340295fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 340395fab37eSRobert Watson { 340495fab37eSRobert Watson struct nameidata nd; 340595fab37eSRobert Watson struct mac extmac; 340695fab37eSRobert Watson int error; 340795fab37eSRobert Watson 340895fab37eSRobert Watson mtx_lock(&Giant); 340995fab37eSRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 341095fab37eSRobert Watson SCARG(uap, path_p), td); 341195fab37eSRobert Watson error = namei(&nd); 341295fab37eSRobert Watson if (error) 341395fab37eSRobert Watson goto out; 341495fab37eSRobert Watson 341595fab37eSRobert Watson error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 341695fab37eSRobert Watson if (error == 0) 341795fab37eSRobert Watson error = mac_externalize(&nd.ni_vp->v_label, &extmac); 341895fab37eSRobert Watson NDFREE(&nd, 0); 341995fab37eSRobert Watson if (error) 342095fab37eSRobert Watson goto out; 342195fab37eSRobert Watson 342295fab37eSRobert Watson error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 342395fab37eSRobert Watson 342495fab37eSRobert Watson out: 342595fab37eSRobert Watson mtx_unlock(&Giant); 342695fab37eSRobert Watson return (error); 342795fab37eSRobert Watson } 342895fab37eSRobert Watson 342995fab37eSRobert Watson /* 343095fab37eSRobert Watson * MPSAFE 343195fab37eSRobert Watson */ 343295fab37eSRobert Watson int 343395fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 343495fab37eSRobert Watson { 343595fab37eSRobert Watson struct file *fp; 343695fab37eSRobert Watson struct mac extmac; 343795fab37eSRobert Watson struct label intlabel; 343895fab37eSRobert Watson struct mount *mp; 343995fab37eSRobert Watson struct vnode *vp; 344095fab37eSRobert Watson struct pipe *pipe; 344195fab37eSRobert Watson int error; 344295fab37eSRobert Watson 344395fab37eSRobert Watson mtx_lock(&Giant); 344495fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 344595fab37eSRobert Watson if (error) 344695fab37eSRobert Watson goto out1; 344795fab37eSRobert Watson 344895fab37eSRobert Watson error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 344995fab37eSRobert Watson if (error) 345095fab37eSRobert Watson goto out2; 345195fab37eSRobert Watson 345295fab37eSRobert Watson error = mac_internalize(&intlabel, &extmac); 345395fab37eSRobert Watson if (error) 345495fab37eSRobert Watson goto out2; 345595fab37eSRobert Watson 345695fab37eSRobert Watson switch (fp->f_type) { 345795fab37eSRobert Watson case DTYPE_FIFO: 345895fab37eSRobert Watson case DTYPE_VNODE: 345995fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 346095fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 346195fab37eSRobert Watson if (error != 0) 346295fab37eSRobert Watson break; 346395fab37eSRobert Watson 346495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 346595fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 346695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 346795fab37eSRobert Watson vn_finished_write(mp); 346895fab37eSRobert Watson mac_destroy_temp(&intlabel); 346995fab37eSRobert Watson break; 347095fab37eSRobert Watson case DTYPE_PIPE: 347195fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 34721aa37f53SRobert Watson PIPE_LOCK(pipe); 347395fab37eSRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel); 34741aa37f53SRobert Watson PIPE_UNLOCK(pipe); 347595fab37eSRobert Watson break; 347695fab37eSRobert Watson default: 347795fab37eSRobert Watson error = EINVAL; 347895fab37eSRobert Watson } 347995fab37eSRobert Watson 348095fab37eSRobert Watson out2: 348195fab37eSRobert Watson fdrop(fp, td); 348295fab37eSRobert Watson out1: 348395fab37eSRobert Watson mtx_unlock(&Giant); 348495fab37eSRobert Watson return (error); 348595fab37eSRobert Watson } 348695fab37eSRobert Watson 348795fab37eSRobert Watson /* 348895fab37eSRobert Watson * MPSAFE 348995fab37eSRobert Watson */ 349095fab37eSRobert Watson int 349195fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 349295fab37eSRobert Watson { 349395fab37eSRobert Watson struct nameidata nd; 349495fab37eSRobert Watson struct mac extmac; 349595fab37eSRobert Watson struct label intlabel; 349695fab37eSRobert Watson struct mount *mp; 349795fab37eSRobert Watson int error; 349895fab37eSRobert Watson 349995fab37eSRobert Watson mtx_lock(&Giant); 350095fab37eSRobert Watson 350195fab37eSRobert Watson error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 350295fab37eSRobert Watson if (error) 350395fab37eSRobert Watson goto out; 350495fab37eSRobert Watson 350595fab37eSRobert Watson error = mac_internalize(&intlabel, &extmac); 350695fab37eSRobert Watson if (error) 350795fab37eSRobert Watson goto out; 350895fab37eSRobert Watson 350995fab37eSRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 351095fab37eSRobert Watson SCARG(uap, path_p), td); 351195fab37eSRobert Watson error = namei(&nd); 351295fab37eSRobert Watson if (error) 351395fab37eSRobert Watson goto out2; 351495fab37eSRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 351595fab37eSRobert Watson if (error) 351695fab37eSRobert Watson goto out2; 351795fab37eSRobert Watson 351895fab37eSRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred); 351995fab37eSRobert Watson 352095fab37eSRobert Watson vn_finished_write(mp); 352195fab37eSRobert Watson out2: 352295fab37eSRobert Watson mac_destroy_temp(&intlabel); 352395fab37eSRobert Watson NDFREE(&nd, 0); 352495fab37eSRobert Watson out: 352595fab37eSRobert Watson mtx_unlock(&Giant); 352695fab37eSRobert Watson return (error); 352795fab37eSRobert Watson } 352895fab37eSRobert Watson 352927f2eac7SRobert Watson int 353027f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 353127f2eac7SRobert Watson { 353227f2eac7SRobert Watson struct mac_policy_conf *mpc; 353327f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 353427f2eac7SRobert Watson int error; 353527f2eac7SRobert Watson 353627f2eac7SRobert Watson error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 353727f2eac7SRobert Watson if (error) 353827f2eac7SRobert Watson return (error); 353927f2eac7SRobert Watson 354027f2eac7SRobert Watson error = ENOSYS; 354127f2eac7SRobert Watson MAC_POLICY_LIST_BUSY(); 354227f2eac7SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 354327f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 354427f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 354527f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 354627f2eac7SRobert Watson SCARG(uap, call), SCARG(uap, arg)); 354727f2eac7SRobert Watson goto out; 354827f2eac7SRobert Watson } 354927f2eac7SRobert Watson } 355027f2eac7SRobert Watson 355127f2eac7SRobert Watson out: 355227f2eac7SRobert Watson MAC_POLICY_LIST_UNBUSY(); 355327f2eac7SRobert Watson return (error); 355427f2eac7SRobert Watson } 355527f2eac7SRobert Watson 355695fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 355795fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 355895fab37eSRobert Watson 355995fab37eSRobert Watson #else /* !MAC */ 35607bc82500SRobert Watson 35617bc82500SRobert Watson int 35627bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 35637bc82500SRobert Watson { 35647bc82500SRobert Watson 35657bc82500SRobert Watson return (ENOSYS); 35667bc82500SRobert Watson } 35677bc82500SRobert Watson 35687bc82500SRobert Watson int 35697bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 35707bc82500SRobert Watson { 35717bc82500SRobert Watson 35727bc82500SRobert Watson return (ENOSYS); 35737bc82500SRobert Watson } 35747bc82500SRobert Watson 35757bc82500SRobert Watson int 35767bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 35777bc82500SRobert Watson { 35787bc82500SRobert Watson 35797bc82500SRobert Watson return (ENOSYS); 35807bc82500SRobert Watson } 35817bc82500SRobert Watson 35827bc82500SRobert Watson int 35837bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 35847bc82500SRobert Watson { 35857bc82500SRobert Watson 35867bc82500SRobert Watson return (ENOSYS); 35877bc82500SRobert Watson } 35887bc82500SRobert Watson 35897bc82500SRobert Watson int 35907bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 35917bc82500SRobert Watson { 35927bc82500SRobert Watson 35937bc82500SRobert Watson return (ENOSYS); 35947bc82500SRobert Watson } 35957bc82500SRobert Watson 35967bc82500SRobert Watson int 35977bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 35987bc82500SRobert Watson { 35997bc82500SRobert Watson 36007bc82500SRobert Watson return (ENOSYS); 36017bc82500SRobert Watson } 360295fab37eSRobert Watson 360327f2eac7SRobert Watson int 360427f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 360527f2eac7SRobert Watson { 360627f2eac7SRobert Watson 360727f2eac7SRobert Watson return (ENOSYS); 360827f2eac7SRobert Watson } 360927f2eac7SRobert Watson 361095fab37eSRobert Watson #endif /* !MAC */ 3611