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" 497bc82500SRobert Watson #include <sys/param.h> 5095fab37eSRobert Watson #include <sys/extattr.h> 5195fab37eSRobert Watson #include <sys/kernel.h> 5295fab37eSRobert Watson #include <sys/lock.h> 5395fab37eSRobert Watson #include <sys/mutex.h> 5495fab37eSRobert Watson #include <sys/sx.h> 5595fab37eSRobert Watson #include <sys/mac.h> 5695fab37eSRobert Watson #include <sys/proc.h> 5795fab37eSRobert Watson #include <sys/systm.h> 587bc82500SRobert Watson #include <sys/sysproto.h> 597bc82500SRobert Watson #include <sys/sysent.h> 6095fab37eSRobert Watson #include <sys/vnode.h> 6195fab37eSRobert Watson #include <sys/mount.h> 6295fab37eSRobert Watson #include <sys/file.h> 6395fab37eSRobert Watson #include <sys/namei.h> 6495fab37eSRobert Watson #include <sys/socket.h> 6595fab37eSRobert Watson #include <sys/pipe.h> 6695fab37eSRobert Watson #include <sys/socketvar.h> 6795fab37eSRobert Watson #include <sys/sx.h> 6895fab37eSRobert Watson #include <sys/sysctl.h> 6995fab37eSRobert Watson 7095fab37eSRobert Watson #include <vm/vm.h> 7195fab37eSRobert Watson #include <vm/pmap.h> 7295fab37eSRobert Watson #include <vm/vm_map.h> 7395fab37eSRobert Watson #include <vm/vm_object.h> 7495fab37eSRobert Watson 7595fab37eSRobert Watson #include <sys/mac_policy.h> 7695fab37eSRobert Watson 7795fab37eSRobert Watson #include <fs/devfs/devfs.h> 7895fab37eSRobert Watson 7995fab37eSRobert Watson #include <net/bpf.h> 8095fab37eSRobert Watson #include <net/bpfdesc.h> 8195fab37eSRobert Watson #include <net/if.h> 8295fab37eSRobert Watson #include <net/if_var.h> 8395fab37eSRobert Watson 8495fab37eSRobert Watson #include <netinet/in.h> 8595fab37eSRobert Watson #include <netinet/ip_var.h> 8695fab37eSRobert Watson 8795fab37eSRobert Watson #ifdef MAC 8895fab37eSRobert Watson 8995fab37eSRobert Watson SYSCTL_DECL(_security); 9095fab37eSRobert Watson 9195fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 9295fab37eSRobert Watson "TrustedBSD MAC policy controls"); 9395fab37eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 9495fab37eSRobert Watson "TrustedBSD MAC debug info"); 9595fab37eSRobert Watson 9695fab37eSRobert Watson static int mac_debug_label_fallback = 0; 9795fab37eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 9895fab37eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 9995fab37eSRobert Watson "when label is corrupted."); 10095fab37eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 10195fab37eSRobert Watson &mac_debug_label_fallback); 10295fab37eSRobert Watson 10395fab37eSRobert Watson #ifndef MAC_MAX_POLICIES 10495fab37eSRobert Watson #define MAC_MAX_POLICIES 8 10595fab37eSRobert Watson #endif 10695fab37eSRobert Watson #if MAC_MAX_POLICIES > 32 10795fab37eSRobert Watson #error "MAC_MAX_POLICIES too large" 10895fab37eSRobert Watson #endif 10995fab37eSRobert Watson static unsigned int mac_max_policies = MAC_MAX_POLICIES; 11095fab37eSRobert Watson static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 11195fab37eSRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 11295fab37eSRobert Watson &mac_max_policies, 0, ""); 11395fab37eSRobert Watson 11495fab37eSRobert Watson static int mac_late = 0; 11595fab37eSRobert Watson 11695fab37eSRobert Watson static int mac_enforce_fs = 1; 11795fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 11895fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 11995fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 12095fab37eSRobert Watson 12195fab37eSRobert Watson static int mac_enforce_network = 1; 12295fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 12395fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 12495fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 12595fab37eSRobert Watson 12695fab37eSRobert Watson static int mac_enforce_process = 1; 12795fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 12895fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 12995fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 13095fab37eSRobert Watson 13195fab37eSRobert Watson static int mac_enforce_socket = 1; 13295fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 13395fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 13495fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 13595fab37eSRobert Watson 13695fab37eSRobert Watson static int mac_enforce_pipe = 1; 13795fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 13895fab37eSRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 13995fab37eSRobert Watson 14095fab37eSRobert Watson static int mac_label_size = sizeof(struct mac); 14195fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, 14295fab37eSRobert Watson &mac_label_size, 0, "Pre-compiled MAC label size"); 14395fab37eSRobert Watson 14495fab37eSRobert Watson static int mac_cache_fslabel_in_vnode = 1; 14595fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, 14695fab37eSRobert Watson &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); 14795fab37eSRobert Watson TUNABLE_INT("security.mac.cache_fslabel_in_vnode", 14895fab37eSRobert Watson &mac_cache_fslabel_in_vnode); 14995fab37eSRobert Watson 15095fab37eSRobert Watson static int mac_vnode_label_cache_hits = 0; 15195fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, 15295fab37eSRobert Watson &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); 15395fab37eSRobert Watson static int mac_vnode_label_cache_misses = 0; 15495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, 15595fab37eSRobert Watson &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); 15695fab37eSRobert Watson static int mac_mmap_revocation_via_cow = 1; 15795fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 15895fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 15995fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 16095fab37eSRobert Watson 16195fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 16295fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 16395fab37eSRobert Watson nmacipqs, nmacpipes; 16495fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, mbufs, CTLFLAG_RD, 16595fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 16695fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, creds, CTLFLAG_RD, 16795fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 16895fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, ifnets, CTLFLAG_RD, 16995fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 17095fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, ipqs, CTLFLAG_RD, 17195fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 17295fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, bpfdescs, CTLFLAG_RD, 17395fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 17495fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, sockets, CTLFLAG_RD, 17595fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 17695fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, pipes, CTLFLAG_RD, 17795fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 17895fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, mounts, CTLFLAG_RD, 17995fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 18095fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, temp, CTLFLAG_RD, 18195fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 18295fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, vnodes, CTLFLAG_RD, 18395fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 18495fab37eSRobert Watson SYSCTL_UINT(_security_mac_debug, OID_AUTO, devfsdirents, CTLFLAG_RD, 18595fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 18695fab37eSRobert Watson 18795fab37eSRobert Watson static int error_select(int error1, int error2); 18895fab37eSRobert Watson static int mac_externalize(struct label *label, struct mac *mac); 18995fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 19095fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 19195fab37eSRobert Watson 19295fab37eSRobert Watson static int mac_stdcreatevnode_ea(struct vnode *vp); 19395fab37eSRobert Watson static void mac_cred_mmapped_drop_perms(struct thread *td, 19495fab37eSRobert Watson struct ucred *cred); 19595fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 19695fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 19795fab37eSRobert Watson 19895fab37eSRobert Watson MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); 19995fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 20095fab37eSRobert Watson 20195fab37eSRobert Watson /* 20295fab37eSRobert Watson * mac_policy_list_lock protects the consistency of 'mac_policy_list', 20395fab37eSRobert Watson * the linked list of attached policy modules. Read-only consumers of 20495fab37eSRobert Watson * the list must acquire a shared lock for the duration of their use; 20595fab37eSRobert Watson * writers must acquire an exclusive lock. Note that for compound 20695fab37eSRobert Watson * operations, locks should be held for the entire compound operation, 20795fab37eSRobert Watson * and that this is not yet done for relabel requests. 20895fab37eSRobert Watson */ 20995fab37eSRobert Watson static struct mtx mac_policy_list_lock; 21095fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 21195fab37eSRobert Watson static int mac_policy_list_busy; 21295fab37eSRobert Watson #define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \ 21395fab37eSRobert Watson "mac_policy_list_lock", NULL, MTX_DEF); 21495fab37eSRobert Watson #define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock); 21595fab37eSRobert Watson #define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock); 21695fab37eSRobert Watson 21795fab37eSRobert Watson #define MAC_POLICY_LIST_BUSY() do { \ 21895fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 21995fab37eSRobert Watson mac_policy_list_busy++; \ 22095fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 22195fab37eSRobert Watson } while (0) 22295fab37eSRobert Watson 22395fab37eSRobert Watson #define MAC_POLICY_LIST_UNBUSY() do { \ 22495fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 22595fab37eSRobert Watson mac_policy_list_busy--; \ 22695fab37eSRobert Watson if (mac_policy_list_busy < 0) \ 22795fab37eSRobert Watson panic("Extra mac_policy_list_busy--"); \ 22895fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 22995fab37eSRobert Watson } while (0) 23095fab37eSRobert Watson 23195fab37eSRobert Watson /* 23295fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 23395fab37eSRobert Watson * module list and checking with each as to how it feels about the 23495fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 23595fab37eSRobert Watson * of the caller. 23695fab37eSRobert Watson */ 23795fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 23895fab37eSRobert Watson struct mac_policy_conf *mpc; \ 23995fab37eSRobert Watson \ 24095fab37eSRobert Watson error = 0; \ 24195fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 24295fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 24395fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 24495fab37eSRobert Watson error = error_select( \ 24595fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 24695fab37eSRobert Watson error); \ 24795fab37eSRobert Watson } \ 24895fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 24995fab37eSRobert Watson } while (0) 25095fab37eSRobert Watson 25195fab37eSRobert Watson /* 25295fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 25395fab37eSRobert Watson * the module list, invoking each instance of the operation, and 25495fab37eSRobert Watson * combining the results using the passed C operator. Note that it 25595fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 25695fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 25795fab37eSRobert Watson * a meaningful result. 25895fab37eSRobert Watson */ 25995fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 26095fab37eSRobert Watson struct mac_policy_conf *mpc; \ 26195fab37eSRobert Watson \ 26295fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 26395fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 26495fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 26595fab37eSRobert Watson result = result composition \ 26695fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 26795fab37eSRobert Watson } \ 26895fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 26995fab37eSRobert Watson } while (0) 27095fab37eSRobert Watson 27195fab37eSRobert Watson /* 27295fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 27395fab37eSRobert Watson * module list and invoking that operation for each policy. 27495fab37eSRobert Watson */ 27595fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 27695fab37eSRobert Watson struct mac_policy_conf *mpc; \ 27795fab37eSRobert Watson \ 27895fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 27995fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 28095fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 28195fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 28295fab37eSRobert Watson } \ 28395fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 28495fab37eSRobert Watson } while (0) 28595fab37eSRobert Watson 28695fab37eSRobert Watson /* 28795fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 28895fab37eSRobert Watson */ 28995fab37eSRobert Watson static void 29095fab37eSRobert Watson mac_init(void) 29195fab37eSRobert Watson { 29295fab37eSRobert Watson 29395fab37eSRobert Watson LIST_INIT(&mac_policy_list); 29495fab37eSRobert Watson MAC_POLICY_LIST_LOCKINIT(); 29595fab37eSRobert Watson } 29695fab37eSRobert Watson 29795fab37eSRobert Watson /* 29895fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 29995fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 30095fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 30195fab37eSRobert Watson */ 30295fab37eSRobert Watson static void 30395fab37eSRobert Watson mac_late_init(void) 30495fab37eSRobert Watson { 30595fab37eSRobert Watson 30695fab37eSRobert Watson mac_late = 1; 30795fab37eSRobert Watson } 30895fab37eSRobert Watson 30995fab37eSRobert Watson /* 31095fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 31195fab37eSRobert Watson */ 31295fab37eSRobert Watson int 31395fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 31495fab37eSRobert Watson { 31595fab37eSRobert Watson struct mac_policy_conf *mpc; 31695fab37eSRobert Watson int error; 31795fab37eSRobert Watson 31895fab37eSRobert Watson error = 0; 31995fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 32095fab37eSRobert Watson 32195fab37eSRobert Watson switch (type) { 32295fab37eSRobert Watson case MOD_LOAD: 32395fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 32495fab37eSRobert Watson mac_late) { 32595fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 32695fab37eSRobert Watson "after booting\n", mpc->mpc_name); 32795fab37eSRobert Watson error = EBUSY; 32895fab37eSRobert Watson break; 32995fab37eSRobert Watson } 33095fab37eSRobert Watson error = mac_policy_register(mpc); 33195fab37eSRobert Watson break; 33295fab37eSRobert Watson case MOD_UNLOAD: 33395fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 33495fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 33595fab37eSRobert Watson != 0) 33695fab37eSRobert Watson error = mac_policy_unregister(mpc); 33795fab37eSRobert Watson else 33895fab37eSRobert Watson error = 0; 33995fab37eSRobert Watson break; 34095fab37eSRobert Watson default: 34195fab37eSRobert Watson break; 34295fab37eSRobert Watson } 34395fab37eSRobert Watson 34495fab37eSRobert Watson return (error); 34595fab37eSRobert Watson } 34695fab37eSRobert Watson 34795fab37eSRobert Watson static int 34895fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 34995fab37eSRobert Watson { 35095fab37eSRobert Watson struct mac_policy_conf *tmpc; 35195fab37eSRobert Watson struct mac_policy_ops *ops; 35295fab37eSRobert Watson struct mac_policy_op_entry *mpe; 35395fab37eSRobert Watson int slot; 35495fab37eSRobert Watson 35595fab37eSRobert Watson MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*ops), M_MACOPVEC, 35695fab37eSRobert Watson M_WAITOK | M_ZERO); 35795fab37eSRobert Watson for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) { 35895fab37eSRobert Watson switch (mpe->mpe_constant) { 35995fab37eSRobert Watson case MAC_OP_LAST: 36095fab37eSRobert Watson /* 36195fab37eSRobert Watson * Doesn't actually happen, but this allows checking 36295fab37eSRobert Watson * that all enumerated values are handled. 36395fab37eSRobert Watson */ 36495fab37eSRobert Watson break; 36595fab37eSRobert Watson case MAC_DESTROY: 36695fab37eSRobert Watson mpc->mpc_ops->mpo_destroy = 36795fab37eSRobert Watson mpe->mpe_function; 36895fab37eSRobert Watson break; 36995fab37eSRobert Watson case MAC_INIT: 37095fab37eSRobert Watson mpc->mpc_ops->mpo_init = 37195fab37eSRobert Watson mpe->mpe_function; 37295fab37eSRobert Watson break; 37395fab37eSRobert Watson case MAC_INIT_BPFDESC: 37495fab37eSRobert Watson mpc->mpc_ops->mpo_init_bpfdesc = 37595fab37eSRobert Watson mpe->mpe_function; 37695fab37eSRobert Watson break; 37795fab37eSRobert Watson case MAC_INIT_CRED: 37895fab37eSRobert Watson mpc->mpc_ops->mpo_init_cred = 37995fab37eSRobert Watson mpe->mpe_function; 38095fab37eSRobert Watson break; 38195fab37eSRobert Watson case MAC_INIT_DEVFSDIRENT: 38295fab37eSRobert Watson mpc->mpc_ops->mpo_init_devfsdirent = 38395fab37eSRobert Watson mpe->mpe_function; 38495fab37eSRobert Watson break; 38595fab37eSRobert Watson case MAC_INIT_IFNET: 38695fab37eSRobert Watson mpc->mpc_ops->mpo_init_ifnet = 38795fab37eSRobert Watson mpe->mpe_function; 38895fab37eSRobert Watson break; 38995fab37eSRobert Watson case MAC_INIT_IPQ: 39095fab37eSRobert Watson mpc->mpc_ops->mpo_init_ipq = 39195fab37eSRobert Watson mpe->mpe_function; 39295fab37eSRobert Watson break; 39395fab37eSRobert Watson case MAC_INIT_MBUF: 39495fab37eSRobert Watson mpc->mpc_ops->mpo_init_mbuf = 39595fab37eSRobert Watson mpe->mpe_function; 39695fab37eSRobert Watson break; 39795fab37eSRobert Watson case MAC_INIT_MOUNT: 39895fab37eSRobert Watson mpc->mpc_ops->mpo_init_mount = 39995fab37eSRobert Watson mpe->mpe_function; 40095fab37eSRobert Watson break; 40195fab37eSRobert Watson case MAC_INIT_PIPE: 40295fab37eSRobert Watson mpc->mpc_ops->mpo_init_pipe = 40395fab37eSRobert Watson mpe->mpe_function; 40495fab37eSRobert Watson break; 40595fab37eSRobert Watson case MAC_INIT_SOCKET: 40695fab37eSRobert Watson mpc->mpc_ops->mpo_init_socket = 40795fab37eSRobert Watson mpe->mpe_function; 40895fab37eSRobert Watson break; 40995fab37eSRobert Watson case MAC_INIT_TEMP: 41095fab37eSRobert Watson mpc->mpc_ops->mpo_init_temp = 41195fab37eSRobert Watson mpe->mpe_function; 41295fab37eSRobert Watson break; 41395fab37eSRobert Watson case MAC_INIT_VNODE: 41495fab37eSRobert Watson mpc->mpc_ops->mpo_init_vnode = 41595fab37eSRobert Watson mpe->mpe_function; 41695fab37eSRobert Watson break; 41795fab37eSRobert Watson case MAC_DESTROY_BPFDESC: 41895fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_bpfdesc = 41995fab37eSRobert Watson mpe->mpe_function; 42095fab37eSRobert Watson break; 42195fab37eSRobert Watson case MAC_DESTROY_CRED: 42295fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_cred = 42395fab37eSRobert Watson mpe->mpe_function; 42495fab37eSRobert Watson break; 42595fab37eSRobert Watson case MAC_DESTROY_DEVFSDIRENT: 42695fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_devfsdirent = 42795fab37eSRobert Watson mpe->mpe_function; 42895fab37eSRobert Watson break; 42995fab37eSRobert Watson case MAC_DESTROY_IFNET: 43095fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_ifnet = 43195fab37eSRobert Watson mpe->mpe_function; 43295fab37eSRobert Watson break; 43395fab37eSRobert Watson case MAC_DESTROY_IPQ: 43495fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_ipq = 43595fab37eSRobert Watson mpe->mpe_function; 43695fab37eSRobert Watson break; 43795fab37eSRobert Watson case MAC_DESTROY_MBUF: 43895fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_mbuf = 43995fab37eSRobert Watson mpe->mpe_function; 44095fab37eSRobert Watson break; 44195fab37eSRobert Watson case MAC_DESTROY_MOUNT: 44295fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_mount = 44395fab37eSRobert Watson mpe->mpe_function; 44495fab37eSRobert Watson break; 44595fab37eSRobert Watson case MAC_DESTROY_PIPE: 44695fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_pipe = 44795fab37eSRobert Watson mpe->mpe_function; 44895fab37eSRobert Watson break; 44995fab37eSRobert Watson case MAC_DESTROY_SOCKET: 45095fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_socket = 45195fab37eSRobert Watson mpe->mpe_function; 45295fab37eSRobert Watson break; 45395fab37eSRobert Watson case MAC_DESTROY_TEMP: 45495fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_temp = 45595fab37eSRobert Watson mpe->mpe_function; 45695fab37eSRobert Watson break; 45795fab37eSRobert Watson case MAC_DESTROY_VNODE: 45895fab37eSRobert Watson mpc->mpc_ops->mpo_destroy_vnode = 45995fab37eSRobert Watson mpe->mpe_function; 46095fab37eSRobert Watson break; 46195fab37eSRobert Watson case MAC_EXTERNALIZE: 46295fab37eSRobert Watson mpc->mpc_ops->mpo_externalize = 46395fab37eSRobert Watson mpe->mpe_function; 46495fab37eSRobert Watson break; 46595fab37eSRobert Watson case MAC_INTERNALIZE: 46695fab37eSRobert Watson mpc->mpc_ops->mpo_internalize = 46795fab37eSRobert Watson mpe->mpe_function; 46895fab37eSRobert Watson break; 46995fab37eSRobert Watson case MAC_CREATE_DEVFS_DEVICE: 47095fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_device = 47195fab37eSRobert Watson mpe->mpe_function; 47295fab37eSRobert Watson break; 47395fab37eSRobert Watson case MAC_CREATE_DEVFS_DIRECTORY: 47495fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_directory = 47595fab37eSRobert Watson mpe->mpe_function; 47695fab37eSRobert Watson break; 47795fab37eSRobert Watson case MAC_CREATE_DEVFS_VNODE: 47895fab37eSRobert Watson mpc->mpc_ops->mpo_create_devfs_vnode = 47995fab37eSRobert Watson mpe->mpe_function; 48095fab37eSRobert Watson break; 48195fab37eSRobert Watson case MAC_STDCREATEVNODE_EA: 48295fab37eSRobert Watson mpc->mpc_ops->mpo_stdcreatevnode_ea = 48395fab37eSRobert Watson mpe->mpe_function; 48495fab37eSRobert Watson break; 48595fab37eSRobert Watson case MAC_CREATE_VNODE: 48695fab37eSRobert Watson mpc->mpc_ops->mpo_create_vnode = 48795fab37eSRobert Watson mpe->mpe_function; 48895fab37eSRobert Watson break; 48995fab37eSRobert Watson case MAC_CREATE_MOUNT: 49095fab37eSRobert Watson mpc->mpc_ops->mpo_create_mount = 49195fab37eSRobert Watson mpe->mpe_function; 49295fab37eSRobert Watson break; 49395fab37eSRobert Watson case MAC_CREATE_ROOT_MOUNT: 49495fab37eSRobert Watson mpc->mpc_ops->mpo_create_root_mount = 49595fab37eSRobert Watson mpe->mpe_function; 49695fab37eSRobert Watson break; 49795fab37eSRobert Watson case MAC_RELABEL_VNODE: 49895fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_vnode = 49995fab37eSRobert Watson mpe->mpe_function; 50095fab37eSRobert Watson break; 50195fab37eSRobert Watson case MAC_UPDATE_DEVFSDIRENT: 50295fab37eSRobert Watson mpc->mpc_ops->mpo_update_devfsdirent = 50395fab37eSRobert Watson mpe->mpe_function; 50495fab37eSRobert Watson break; 50595fab37eSRobert Watson case MAC_UPDATE_PROCFSVNODE: 50695fab37eSRobert Watson mpc->mpc_ops->mpo_update_procfsvnode = 50795fab37eSRobert Watson mpe->mpe_function; 50895fab37eSRobert Watson break; 50995fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_EXTATTR: 51095fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_extattr = 51195fab37eSRobert Watson mpe->mpe_function; 51295fab37eSRobert Watson break; 51395fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: 51495fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_externalized = 51595fab37eSRobert Watson mpe->mpe_function; 51695fab37eSRobert Watson break; 51795fab37eSRobert Watson case MAC_UPDATE_VNODE_FROM_MOUNT: 51895fab37eSRobert Watson mpc->mpc_ops->mpo_update_vnode_from_mount = 51995fab37eSRobert Watson mpe->mpe_function; 52095fab37eSRobert Watson break; 52195fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_SOCKET: 52295fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_socket = 52395fab37eSRobert Watson mpe->mpe_function; 52495fab37eSRobert Watson break; 52595fab37eSRobert Watson case MAC_CREATE_PIPE: 52695fab37eSRobert Watson mpc->mpc_ops->mpo_create_pipe = 52795fab37eSRobert Watson mpe->mpe_function; 52895fab37eSRobert Watson break; 52995fab37eSRobert Watson case MAC_CREATE_SOCKET: 53095fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket = 53195fab37eSRobert Watson mpe->mpe_function; 53295fab37eSRobert Watson break; 53395fab37eSRobert Watson case MAC_CREATE_SOCKET_FROM_SOCKET: 53495fab37eSRobert Watson mpc->mpc_ops->mpo_create_socket_from_socket = 53595fab37eSRobert Watson mpe->mpe_function; 53695fab37eSRobert Watson break; 53795fab37eSRobert Watson case MAC_RELABEL_PIPE: 53895fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_pipe = 53995fab37eSRobert Watson mpe->mpe_function; 54095fab37eSRobert Watson break; 54195fab37eSRobert Watson case MAC_RELABEL_SOCKET: 54295fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_socket = 54395fab37eSRobert Watson mpe->mpe_function; 54495fab37eSRobert Watson break; 54595fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_MBUF: 54695fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_mbuf = 54795fab37eSRobert Watson mpe->mpe_function; 54895fab37eSRobert Watson break; 54995fab37eSRobert Watson case MAC_SET_SOCKET_PEER_FROM_SOCKET: 55095fab37eSRobert Watson mpc->mpc_ops->mpo_set_socket_peer_from_socket = 55195fab37eSRobert Watson mpe->mpe_function; 55295fab37eSRobert Watson break; 55395fab37eSRobert Watson case MAC_CREATE_BPFDESC: 55495fab37eSRobert Watson mpc->mpc_ops->mpo_create_bpfdesc = 55595fab37eSRobert Watson mpe->mpe_function; 55695fab37eSRobert Watson break; 55795fab37eSRobert Watson case MAC_CREATE_DATAGRAM_FROM_IPQ: 55895fab37eSRobert Watson mpc->mpc_ops->mpo_create_datagram_from_ipq = 55995fab37eSRobert Watson mpe->mpe_function; 56095fab37eSRobert Watson break; 56195fab37eSRobert Watson case MAC_CREATE_FRAGMENT: 56295fab37eSRobert Watson mpc->mpc_ops->mpo_create_fragment = 56395fab37eSRobert Watson mpe->mpe_function; 56495fab37eSRobert Watson break; 56595fab37eSRobert Watson case MAC_CREATE_IFNET: 56695fab37eSRobert Watson mpc->mpc_ops->mpo_create_ifnet = 56795fab37eSRobert Watson mpe->mpe_function; 56895fab37eSRobert Watson break; 56995fab37eSRobert Watson case MAC_CREATE_IPQ: 57095fab37eSRobert Watson mpc->mpc_ops->mpo_create_ipq = 57195fab37eSRobert Watson mpe->mpe_function; 57295fab37eSRobert Watson break; 57395fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_MBUF: 57495fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_mbuf = 57595fab37eSRobert Watson mpe->mpe_function; 57695fab37eSRobert Watson break; 57795fab37eSRobert Watson case MAC_CREATE_MBUF_LINKLAYER: 57895fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_linklayer = 57995fab37eSRobert Watson mpe->mpe_function; 58095fab37eSRobert Watson break; 58195fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_BPFDESC: 58295fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc = 58395fab37eSRobert Watson mpe->mpe_function; 58495fab37eSRobert Watson break; 58595fab37eSRobert Watson case MAC_CREATE_MBUF_FROM_IFNET: 58695fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_from_ifnet = 58795fab37eSRobert Watson mpe->mpe_function; 58895fab37eSRobert Watson break; 58995fab37eSRobert Watson case MAC_CREATE_MBUF_MULTICAST_ENCAP: 59095fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_multicast_encap = 59195fab37eSRobert Watson mpe->mpe_function; 59295fab37eSRobert Watson break; 59395fab37eSRobert Watson case MAC_CREATE_MBUF_NETLAYER: 59495fab37eSRobert Watson mpc->mpc_ops->mpo_create_mbuf_netlayer = 59595fab37eSRobert Watson mpe->mpe_function; 59695fab37eSRobert Watson break; 59795fab37eSRobert Watson case MAC_FRAGMENT_MATCH: 59895fab37eSRobert Watson mpc->mpc_ops->mpo_fragment_match = 59995fab37eSRobert Watson mpe->mpe_function; 60095fab37eSRobert Watson break; 60195fab37eSRobert Watson case MAC_RELABEL_IFNET: 60295fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_ifnet = 60395fab37eSRobert Watson mpe->mpe_function; 60495fab37eSRobert Watson break; 60595fab37eSRobert Watson case MAC_UPDATE_IPQ: 60695fab37eSRobert Watson mpc->mpc_ops->mpo_update_ipq = 60795fab37eSRobert Watson mpe->mpe_function; 60895fab37eSRobert Watson break; 60995fab37eSRobert Watson case MAC_CREATE_CRED: 61095fab37eSRobert Watson mpc->mpc_ops->mpo_create_cred = 61195fab37eSRobert Watson mpe->mpe_function; 61295fab37eSRobert Watson break; 61395fab37eSRobert Watson case MAC_EXECVE_TRANSITION: 61495fab37eSRobert Watson mpc->mpc_ops->mpo_execve_transition = 61595fab37eSRobert Watson mpe->mpe_function; 61695fab37eSRobert Watson break; 61795fab37eSRobert Watson case MAC_EXECVE_WILL_TRANSITION: 61895fab37eSRobert Watson mpc->mpc_ops->mpo_execve_will_transition = 61995fab37eSRobert Watson mpe->mpe_function; 62095fab37eSRobert Watson break; 62195fab37eSRobert Watson case MAC_CREATE_PROC0: 62295fab37eSRobert Watson mpc->mpc_ops->mpo_create_proc0 = mpe->mpe_function; 62395fab37eSRobert Watson break; 62495fab37eSRobert Watson case MAC_CREATE_PROC1: 62595fab37eSRobert Watson mpc->mpc_ops->mpo_create_proc1 = mpe->mpe_function; 62695fab37eSRobert Watson break; 62795fab37eSRobert Watson case MAC_RELABEL_CRED: 62895fab37eSRobert Watson mpc->mpc_ops->mpo_relabel_cred = 62995fab37eSRobert Watson mpe->mpe_function; 63095fab37eSRobert Watson break; 63195fab37eSRobert Watson case MAC_CHECK_BPFDESC_RECEIVE: 63295fab37eSRobert Watson mpc->mpc_ops->mpo_check_bpfdesc_receive = 63395fab37eSRobert Watson mpe->mpe_function; 63495fab37eSRobert Watson break; 63595fab37eSRobert Watson case MAC_CHECK_CRED_RELABEL: 63695fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_relabel = 63795fab37eSRobert Watson mpe->mpe_function; 63895fab37eSRobert Watson break; 63995fab37eSRobert Watson case MAC_CHECK_CRED_VISIBLE: 64095fab37eSRobert Watson mpc->mpc_ops->mpo_check_cred_visible = 64195fab37eSRobert Watson mpe->mpe_function; 64295fab37eSRobert Watson break; 64395fab37eSRobert Watson case MAC_CHECK_IFNET_RELABEL: 64495fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_relabel = 64595fab37eSRobert Watson mpe->mpe_function; 64695fab37eSRobert Watson break; 64795fab37eSRobert Watson case MAC_CHECK_IFNET_TRANSMIT: 64895fab37eSRobert Watson mpc->mpc_ops->mpo_check_ifnet_transmit = 64995fab37eSRobert Watson mpe->mpe_function; 65095fab37eSRobert Watson break; 65195fab37eSRobert Watson case MAC_CHECK_MOUNT_STAT: 65295fab37eSRobert Watson mpc->mpc_ops->mpo_check_mount_stat = 65395fab37eSRobert Watson mpe->mpe_function; 65495fab37eSRobert Watson break; 65595fab37eSRobert Watson case MAC_CHECK_PIPE_IOCTL: 65695fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_ioctl = 65795fab37eSRobert Watson mpe->mpe_function; 65895fab37eSRobert Watson break; 65995fab37eSRobert Watson case MAC_CHECK_PIPE_OP: 66095fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_op = 66195fab37eSRobert Watson mpe->mpe_function; 66295fab37eSRobert Watson break; 66395fab37eSRobert Watson case MAC_CHECK_PIPE_RELABEL: 66495fab37eSRobert Watson mpc->mpc_ops->mpo_check_pipe_relabel = 66595fab37eSRobert Watson mpe->mpe_function; 66695fab37eSRobert Watson break; 66795fab37eSRobert Watson case MAC_CHECK_PROC_DEBUG: 66895fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_debug = 66995fab37eSRobert Watson mpe->mpe_function; 67095fab37eSRobert Watson break; 67195fab37eSRobert Watson case MAC_CHECK_PROC_SCHED: 67295fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_sched = 67395fab37eSRobert Watson mpe->mpe_function; 67495fab37eSRobert Watson break; 67595fab37eSRobert Watson case MAC_CHECK_PROC_SIGNAL: 67695fab37eSRobert Watson mpc->mpc_ops->mpo_check_proc_signal = 67795fab37eSRobert Watson mpe->mpe_function; 67895fab37eSRobert Watson break; 67995fab37eSRobert Watson case MAC_CHECK_SOCKET_BIND: 68095fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_bind = 68195fab37eSRobert Watson mpe->mpe_function; 68295fab37eSRobert Watson break; 68395fab37eSRobert Watson case MAC_CHECK_SOCKET_CONNECT: 68495fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_connect = 68595fab37eSRobert Watson mpe->mpe_function; 68695fab37eSRobert Watson break; 68795fab37eSRobert Watson case MAC_CHECK_SOCKET_LISTEN: 68895fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_listen = 68995fab37eSRobert Watson mpe->mpe_function; 69095fab37eSRobert Watson break; 69195fab37eSRobert Watson case MAC_CHECK_SOCKET_RECEIVE: 69295fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_receive = 69395fab37eSRobert Watson mpe->mpe_function; 69495fab37eSRobert Watson break; 69595fab37eSRobert Watson case MAC_CHECK_SOCKET_RELABEL: 69695fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_relabel = 69795fab37eSRobert Watson mpe->mpe_function; 69895fab37eSRobert Watson break; 69995fab37eSRobert Watson case MAC_CHECK_SOCKET_VISIBLE: 70095fab37eSRobert Watson mpc->mpc_ops->mpo_check_socket_visible = 70195fab37eSRobert Watson mpe->mpe_function; 70295fab37eSRobert Watson break; 70395fab37eSRobert Watson case MAC_CHECK_VNODE_ACCESS: 70495fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_access = 70595fab37eSRobert Watson mpe->mpe_function; 70695fab37eSRobert Watson break; 70795fab37eSRobert Watson case MAC_CHECK_VNODE_CHDIR: 70895fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chdir = 70995fab37eSRobert Watson mpe->mpe_function; 71095fab37eSRobert Watson break; 71195fab37eSRobert Watson case MAC_CHECK_VNODE_CHROOT: 71295fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_chroot = 71395fab37eSRobert Watson mpe->mpe_function; 71495fab37eSRobert Watson break; 71595fab37eSRobert Watson case MAC_CHECK_VNODE_CREATE: 71695fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_create = 71795fab37eSRobert Watson mpe->mpe_function; 71895fab37eSRobert Watson break; 71995fab37eSRobert Watson case MAC_CHECK_VNODE_DELETE: 72095fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_delete = 72195fab37eSRobert Watson mpe->mpe_function; 72295fab37eSRobert Watson break; 72395fab37eSRobert Watson case MAC_CHECK_VNODE_DELETEACL: 72495fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_deleteacl = 72595fab37eSRobert Watson mpe->mpe_function; 72695fab37eSRobert Watson break; 72795fab37eSRobert Watson case MAC_CHECK_VNODE_EXEC: 72895fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_exec = 72995fab37eSRobert Watson mpe->mpe_function; 73095fab37eSRobert Watson break; 73195fab37eSRobert Watson case MAC_CHECK_VNODE_GETACL: 73295fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getacl = 73395fab37eSRobert Watson mpe->mpe_function; 73495fab37eSRobert Watson break; 73595fab37eSRobert Watson case MAC_CHECK_VNODE_GETEXTATTR: 73695fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_getextattr = 73795fab37eSRobert Watson mpe->mpe_function; 73895fab37eSRobert Watson break; 73995fab37eSRobert Watson case MAC_CHECK_VNODE_LOOKUP: 74095fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_lookup = 74195fab37eSRobert Watson mpe->mpe_function; 74295fab37eSRobert Watson break; 74395fab37eSRobert Watson case MAC_CHECK_VNODE_MMAP_PERMS: 74495fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_mmap_perms = 74595fab37eSRobert Watson mpe->mpe_function; 74695fab37eSRobert Watson break; 74795fab37eSRobert Watson case MAC_CHECK_VNODE_OP: 74895fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_op = 74995fab37eSRobert Watson mpe->mpe_function; 75095fab37eSRobert Watson break; 75195fab37eSRobert Watson case MAC_CHECK_VNODE_OPEN: 75295fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_open = 75395fab37eSRobert Watson mpe->mpe_function; 75495fab37eSRobert Watson break; 75595fab37eSRobert Watson case MAC_CHECK_VNODE_READDIR: 75695fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readdir = 75795fab37eSRobert Watson mpe->mpe_function; 75895fab37eSRobert Watson break; 75995fab37eSRobert Watson case MAC_CHECK_VNODE_READLINK: 76095fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_readlink = 76195fab37eSRobert Watson mpe->mpe_function; 76295fab37eSRobert Watson break; 76395fab37eSRobert Watson case MAC_CHECK_VNODE_RELABEL: 76495fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_relabel = 76595fab37eSRobert Watson mpe->mpe_function; 76695fab37eSRobert Watson break; 76795fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_FROM: 76895fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_from = 76995fab37eSRobert Watson mpe->mpe_function; 77095fab37eSRobert Watson break; 77195fab37eSRobert Watson case MAC_CHECK_VNODE_RENAME_TO: 77295fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_rename_to = 77395fab37eSRobert Watson mpe->mpe_function; 77495fab37eSRobert Watson break; 77595fab37eSRobert Watson case MAC_CHECK_VNODE_REVOKE: 77695fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_revoke = 77795fab37eSRobert Watson mpe->mpe_function; 77895fab37eSRobert Watson break; 77995fab37eSRobert Watson case MAC_CHECK_VNODE_SETACL: 78095fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setacl = 78195fab37eSRobert Watson mpe->mpe_function; 78295fab37eSRobert Watson break; 78395fab37eSRobert Watson case MAC_CHECK_VNODE_SETEXTATTR: 78495fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setextattr = 78595fab37eSRobert Watson mpe->mpe_function; 78695fab37eSRobert Watson break; 78795fab37eSRobert Watson case MAC_CHECK_VNODE_SETFLAGS: 78895fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setflags = 78995fab37eSRobert Watson mpe->mpe_function; 79095fab37eSRobert Watson break; 79195fab37eSRobert Watson case MAC_CHECK_VNODE_SETMODE: 79295fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setmode = 79395fab37eSRobert Watson mpe->mpe_function; 79495fab37eSRobert Watson break; 79595fab37eSRobert Watson case MAC_CHECK_VNODE_SETOWNER: 79695fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setowner = 79795fab37eSRobert Watson mpe->mpe_function; 79895fab37eSRobert Watson break; 79995fab37eSRobert Watson case MAC_CHECK_VNODE_SETUTIMES: 80095fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_setutimes = 80195fab37eSRobert Watson mpe->mpe_function; 80295fab37eSRobert Watson break; 80395fab37eSRobert Watson case MAC_CHECK_VNODE_STAT: 80495fab37eSRobert Watson mpc->mpc_ops->mpo_check_vnode_stat = 80595fab37eSRobert Watson mpe->mpe_function; 80695fab37eSRobert Watson break; 80795fab37eSRobert Watson /* 80895fab37eSRobert Watson default: 80995fab37eSRobert Watson printf("MAC policy `%s': unknown operation %d\n", 81095fab37eSRobert Watson mpc->mpc_name, mpe->mpe_constant); 81195fab37eSRobert Watson return (EINVAL); 81295fab37eSRobert Watson */ 81395fab37eSRobert Watson } 81495fab37eSRobert Watson } 81595fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); 81695fab37eSRobert Watson if (mac_policy_list_busy > 0) { 81795fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 81895fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 81995fab37eSRobert Watson mpc->mpc_ops = NULL; 82095fab37eSRobert Watson return (EBUSY); 82195fab37eSRobert Watson } 82295fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 82395fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 82495fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 82595fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 82695fab37eSRobert Watson mpc->mpc_ops = NULL; 82795fab37eSRobert Watson return (EEXIST); 82895fab37eSRobert Watson } 82995fab37eSRobert Watson } 83095fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 83195fab37eSRobert Watson slot = ffs(mac_policy_offsets_free); 83295fab37eSRobert Watson if (slot == 0) { 83395fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 83495fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 83595fab37eSRobert Watson mpc->mpc_ops = NULL; 83695fab37eSRobert Watson return (ENOMEM); 83795fab37eSRobert Watson } 83895fab37eSRobert Watson slot--; 83995fab37eSRobert Watson mac_policy_offsets_free &= ~(1 << slot); 84095fab37eSRobert Watson *mpc->mpc_field_off = slot; 84195fab37eSRobert Watson } 84295fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 84395fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 84495fab37eSRobert Watson 84595fab37eSRobert Watson /* Per-policy initialization. */ 84695fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 84795fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 84895fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 84995fab37eSRobert Watson 85095fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 85195fab37eSRobert Watson mpc->mpc_name); 85295fab37eSRobert Watson 85395fab37eSRobert Watson return (0); 85495fab37eSRobert Watson } 85595fab37eSRobert Watson 85695fab37eSRobert Watson static int 85795fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 85895fab37eSRobert Watson { 85995fab37eSRobert Watson 86095fab37eSRobert Watson #if 0 86195fab37eSRobert Watson /* 86295fab37eSRobert Watson * Don't allow unloading modules with private data. 86395fab37eSRobert Watson */ 86495fab37eSRobert Watson if (mpc->mpc_field_off != NULL) 86595fab37eSRobert Watson return (EBUSY); 86695fab37eSRobert Watson #endif 86795fab37eSRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) 86895fab37eSRobert Watson return (EBUSY); 86995fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); 87095fab37eSRobert Watson if (mac_policy_list_busy > 0) { 87195fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 87295fab37eSRobert Watson return (EBUSY); 87395fab37eSRobert Watson } 87495fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 87595fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 87695fab37eSRobert Watson 87795fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 87895fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 87995fab37eSRobert Watson 88095fab37eSRobert Watson FREE(mpc->mpc_ops, M_MACOPVEC); 88195fab37eSRobert Watson mpc->mpc_ops = NULL; 88295fab37eSRobert Watson 88395fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 88495fab37eSRobert Watson mpc->mpc_name); 88595fab37eSRobert Watson 88695fab37eSRobert Watson return (0); 88795fab37eSRobert Watson } 88895fab37eSRobert Watson 88995fab37eSRobert Watson /* 89095fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 89195fab37eSRobert Watson * value with the higher precedence. 89295fab37eSRobert Watson */ 89395fab37eSRobert Watson static int 89495fab37eSRobert Watson error_select(int error1, int error2) 89595fab37eSRobert Watson { 89695fab37eSRobert Watson 89795fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 89895fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 89995fab37eSRobert Watson return (EDEADLK); 90095fab37eSRobert Watson 90195fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 90295fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 90395fab37eSRobert Watson return (EINVAL); 90495fab37eSRobert Watson 90595fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 90695fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 90795fab37eSRobert Watson return (ESRCH); 90895fab37eSRobert Watson 90995fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 91095fab37eSRobert Watson return (ENOENT); 91195fab37eSRobert Watson 91295fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 91395fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 91495fab37eSRobert Watson return (EACCES); 91595fab37eSRobert Watson 91695fab37eSRobert Watson /* Precedence goes to privilege. */ 91795fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 91895fab37eSRobert Watson return (EPERM); 91995fab37eSRobert Watson 92095fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 92195fab37eSRobert Watson if (error1 != 0) 92295fab37eSRobert Watson return (error1); 92395fab37eSRobert Watson return (error2); 92495fab37eSRobert Watson } 92595fab37eSRobert Watson 92695fab37eSRobert Watson void 92795fab37eSRobert Watson mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 92895fab37eSRobert Watson { 92995fab37eSRobert Watson 93095fab37eSRobert Watson MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 93195fab37eSRobert Watson } 93295fab37eSRobert Watson 93395fab37eSRobert Watson void 93495fab37eSRobert Watson mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) 93595fab37eSRobert Watson { 93695fab37eSRobert Watson 93795fab37eSRobert Watson MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); 93895fab37eSRobert Watson } 93995fab37eSRobert Watson 94095fab37eSRobert Watson /* 94195fab37eSRobert Watson * Support callout for policies that manage their own externalization 94295fab37eSRobert Watson * using extended attributes. 94395fab37eSRobert Watson */ 94495fab37eSRobert Watson static int 94595fab37eSRobert Watson mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) 94695fab37eSRobert Watson { 94795fab37eSRobert Watson int error; 94895fab37eSRobert Watson 94995fab37eSRobert Watson MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, 95095fab37eSRobert Watson &mp->mnt_fslabel); 95195fab37eSRobert Watson 95295fab37eSRobert Watson return (error); 95395fab37eSRobert Watson } 95495fab37eSRobert Watson 95595fab37eSRobert Watson /* 95695fab37eSRobert Watson * Given an externalized mac label, internalize it and stamp it on a 95795fab37eSRobert Watson * vnode. 95895fab37eSRobert Watson */ 95995fab37eSRobert Watson static int 96095fab37eSRobert Watson mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac) 96195fab37eSRobert Watson { 96295fab37eSRobert Watson int error; 96395fab37eSRobert Watson 96495fab37eSRobert Watson MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); 96595fab37eSRobert Watson 96695fab37eSRobert Watson return (error); 96795fab37eSRobert Watson } 96895fab37eSRobert Watson 96995fab37eSRobert Watson /* 97095fab37eSRobert Watson * Call out to individual policies to update the label in a vnode from 97195fab37eSRobert Watson * the mountpoint. 97295fab37eSRobert Watson */ 97395fab37eSRobert Watson void 97495fab37eSRobert Watson mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) 97595fab37eSRobert Watson { 97695fab37eSRobert Watson 97795fab37eSRobert Watson MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, 97895fab37eSRobert Watson &mp->mnt_fslabel); 97995fab37eSRobert Watson 98095fab37eSRobert Watson if (mac_cache_fslabel_in_vnode) 98195fab37eSRobert Watson vp->v_flag |= VCACHEDLABEL; 98295fab37eSRobert Watson } 98395fab37eSRobert Watson 98495fab37eSRobert Watson /* 98595fab37eSRobert Watson * Implementation of VOP_REFRESHLABEL() that relies on extended attributes 98695fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 98795fab37eSRobert Watson * extended attributes. 98895fab37eSRobert Watson */ 98995fab37eSRobert Watson int 99095fab37eSRobert Watson vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) 99195fab37eSRobert Watson { 99295fab37eSRobert Watson struct vnode *vp = ap->a_vp; 99395fab37eSRobert Watson struct mac extmac; 99495fab37eSRobert Watson int buflen, error; 99595fab37eSRobert Watson 99695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); 99795fab37eSRobert Watson 99895fab37eSRobert Watson /* 99995fab37eSRobert Watson * Call out to external policies first. Order doesn't really 100095fab37eSRobert Watson * matter, as long as failure of one assures failure of all. 100195fab37eSRobert Watson */ 100295fab37eSRobert Watson error = mac_update_vnode_from_extattr(vp, vp->v_mount); 100395fab37eSRobert Watson if (error) 100495fab37eSRobert Watson return (error); 100595fab37eSRobert Watson 100695fab37eSRobert Watson buflen = sizeof(extmac); 100795fab37eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, 100895fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, 100995fab37eSRobert Watson (char *)&extmac, curthread); 101095fab37eSRobert Watson switch (error) { 101195fab37eSRobert Watson case 0: 101295fab37eSRobert Watson /* Got it */ 101395fab37eSRobert Watson break; 101495fab37eSRobert Watson 101595fab37eSRobert Watson case ENOATTR: 101695fab37eSRobert Watson /* 101795fab37eSRobert Watson * Use the label from the mount point. 101895fab37eSRobert Watson */ 101995fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 102095fab37eSRobert Watson return (0); 102195fab37eSRobert Watson 102295fab37eSRobert Watson case EOPNOTSUPP: 102395fab37eSRobert Watson default: 102495fab37eSRobert Watson /* Fail horribly. */ 102595fab37eSRobert Watson return (error); 102695fab37eSRobert Watson } 102795fab37eSRobert Watson 102895fab37eSRobert Watson if (buflen != sizeof(extmac)) 102995fab37eSRobert Watson error = EPERM; /* Fail very closed. */ 103095fab37eSRobert Watson if (error == 0) 103195fab37eSRobert Watson error = mac_update_vnode_from_externalized(vp, &extmac); 103295fab37eSRobert Watson if (error == 0) 103395fab37eSRobert Watson vp->v_flag |= VCACHEDLABEL; 103495fab37eSRobert Watson else { 103595fab37eSRobert Watson struct vattr va; 103695fab37eSRobert Watson 103795fab37eSRobert Watson printf("Corrupted label on %s", 103895fab37eSRobert Watson vp->v_mount->mnt_stat.f_mntonname); 103995fab37eSRobert Watson if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) 104095fab37eSRobert Watson printf(" inum %ld", va.va_fileid); 104195fab37eSRobert Watson if (mac_debug_label_fallback) { 104295fab37eSRobert Watson printf(", falling back.\n"); 104395fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 104495fab37eSRobert Watson error = 0; 104595fab37eSRobert Watson } else { 104695fab37eSRobert Watson printf(".\n"); 104795fab37eSRobert Watson error = EPERM; 104895fab37eSRobert Watson } 104995fab37eSRobert Watson } 105095fab37eSRobert Watson 105195fab37eSRobert Watson return (error); 105295fab37eSRobert Watson } 105395fab37eSRobert Watson 105495fab37eSRobert Watson /* 105595fab37eSRobert Watson * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle 105695fab37eSRobert Watson * the labeling activity outselves. Filesystems should be careful not 105795fab37eSRobert Watson * to change their minds regarding whether they support vop_refreshlabel() 105895fab37eSRobert Watson * for a vnode or not. Don't cache the vnode here, allow the file 105995fab37eSRobert Watson * system code to determine if it's safe to cache. If we update from 106095fab37eSRobert Watson * the mount, don't cache since a change to the mount label should affect 106195fab37eSRobert Watson * all vnodes. 106295fab37eSRobert Watson */ 106395fab37eSRobert Watson static int 106495fab37eSRobert Watson vn_refreshlabel(struct vnode *vp, struct ucred *cred) 106595fab37eSRobert Watson { 106695fab37eSRobert Watson int error; 106795fab37eSRobert Watson 106895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); 106995fab37eSRobert Watson 107095fab37eSRobert Watson if (vp->v_mount == NULL) { 107195fab37eSRobert Watson /* 107295fab37eSRobert Watson Eventually, we probably want to special-case refreshing 107395fab37eSRobert Watson of deadfs vnodes, and if there's a lock-free race somewhere, 107495fab37eSRobert Watson that case might be handled here. 107595fab37eSRobert Watson 107695fab37eSRobert Watson mac_update_vnode_deadfs(vp); 107795fab37eSRobert Watson return (0); 107895fab37eSRobert Watson */ 107995fab37eSRobert Watson /* printf("vn_refreshlabel: null v_mount\n"); */ 108095fab37eSRobert Watson if (vp->v_tag != VT_NON) 108195fab37eSRobert Watson printf( 108295fab37eSRobert Watson "vn_refreshlabel: null v_mount with non-VT_NON\n"); 108395fab37eSRobert Watson return (EBADF); 108495fab37eSRobert Watson } 108595fab37eSRobert Watson 108695fab37eSRobert Watson if (vp->v_flag & VCACHEDLABEL) { 108795fab37eSRobert Watson mac_vnode_label_cache_hits++; 108895fab37eSRobert Watson return (0); 108995fab37eSRobert Watson } else 109095fab37eSRobert Watson mac_vnode_label_cache_misses++; 109195fab37eSRobert Watson 109295fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 109395fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 109495fab37eSRobert Watson return (0); 109595fab37eSRobert Watson } 109695fab37eSRobert Watson 109795fab37eSRobert Watson error = VOP_REFRESHLABEL(vp, cred, curthread); 109895fab37eSRobert Watson switch (error) { 109995fab37eSRobert Watson case EOPNOTSUPP: 110095fab37eSRobert Watson /* 110195fab37eSRobert Watson * If labels are not supported on this vnode, fall back to 110295fab37eSRobert Watson * the label in the mount and propagate it to the vnode. 110395fab37eSRobert Watson * There should probably be some sort of policy/flag/decision 110495fab37eSRobert Watson * about doing this. 110595fab37eSRobert Watson */ 110695fab37eSRobert Watson mac_update_vnode_from_mount(vp, vp->v_mount); 110795fab37eSRobert Watson error = 0; 110895fab37eSRobert Watson default: 110995fab37eSRobert Watson return (error); 111095fab37eSRobert Watson } 111195fab37eSRobert Watson } 111295fab37eSRobert Watson 111395fab37eSRobert Watson /* 111495fab37eSRobert Watson * Helper function for file systems using the vop_std*_ea() calls. This 111595fab37eSRobert Watson * function must be called after EA service is available for the vnode, 111695fab37eSRobert Watson * but before it's hooked up to the namespace so that the node persists 111795fab37eSRobert Watson * if there's a crash, or before it can be accessed. On successful 111895fab37eSRobert Watson * commit of the label to disk (etc), do cache the label. 111995fab37eSRobert Watson */ 112095fab37eSRobert Watson int 112195fab37eSRobert Watson vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) 112295fab37eSRobert Watson { 112395fab37eSRobert Watson struct mac extmac; 112495fab37eSRobert Watson int error; 112595fab37eSRobert Watson 112695fab37eSRobert Watson if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 112795fab37eSRobert Watson mac_update_vnode_from_mount(tvp, tvp->v_mount); 112895fab37eSRobert Watson } else { 112995fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 113095fab37eSRobert Watson if (error) 113195fab37eSRobert Watson return (error); 113295fab37eSRobert Watson 113395fab37eSRobert Watson /* 113495fab37eSRobert Watson * Stick the label in the vnode. Then try to write to 113595fab37eSRobert Watson * disk. If we fail, return a failure to abort the 113695fab37eSRobert Watson * create operation. Really, this failure shouldn't 113795fab37eSRobert Watson * happen except in fairly unusual circumstances (out 113895fab37eSRobert Watson * of disk, etc). 113995fab37eSRobert Watson */ 114095fab37eSRobert Watson mac_create_vnode(cred, dvp, tvp); 114195fab37eSRobert Watson 114295fab37eSRobert Watson error = mac_stdcreatevnode_ea(tvp); 114395fab37eSRobert Watson if (error) 114495fab37eSRobert Watson return (error); 114595fab37eSRobert Watson 114695fab37eSRobert Watson /* 114795fab37eSRobert Watson * XXX: Eventually this will go away and all policies will 114895fab37eSRobert Watson * directly manage their extended attributes. 114995fab37eSRobert Watson */ 115095fab37eSRobert Watson error = mac_externalize(&tvp->v_label, &extmac); 115195fab37eSRobert Watson if (error) 115295fab37eSRobert Watson return (error); 115395fab37eSRobert Watson 115495fab37eSRobert Watson error = vn_extattr_set(tvp, IO_NODELOCKED, 115595fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 115695fab37eSRobert Watson sizeof(extmac), (char *)&extmac, curthread); 115795fab37eSRobert Watson if (error == 0) 115895fab37eSRobert Watson tvp->v_flag |= VCACHEDLABEL; 115995fab37eSRobert Watson else { 116095fab37eSRobert Watson #if 0 116195fab37eSRobert Watson /* 116295fab37eSRobert Watson * In theory, we could have fall-back behavior here. 116395fab37eSRobert Watson * It would probably be incorrect. 116495fab37eSRobert Watson */ 116595fab37eSRobert Watson #endif 116695fab37eSRobert Watson return (error); 116795fab37eSRobert Watson } 116895fab37eSRobert Watson } 116995fab37eSRobert Watson 117095fab37eSRobert Watson return (0); 117195fab37eSRobert Watson } 117295fab37eSRobert Watson 117395fab37eSRobert Watson void 117495fab37eSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 117595fab37eSRobert Watson { 117695fab37eSRobert Watson int error; 117795fab37eSRobert Watson 117895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 117995fab37eSRobert Watson 118095fab37eSRobert Watson error = vn_refreshlabel(vp, old); 118195fab37eSRobert Watson if (error) { 118295fab37eSRobert Watson printf("mac_execve_transition: vn_refreshlabel returned %d\n", 118395fab37eSRobert Watson error); 118495fab37eSRobert Watson printf("mac_execve_transition: using old vnode label\n"); 118595fab37eSRobert Watson } 118695fab37eSRobert Watson 118795fab37eSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 118895fab37eSRobert Watson } 118995fab37eSRobert Watson 119095fab37eSRobert Watson int 119195fab37eSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp) 119295fab37eSRobert Watson { 119395fab37eSRobert Watson int error, result; 119495fab37eSRobert Watson 119595fab37eSRobert Watson error = vn_refreshlabel(vp, old); 119695fab37eSRobert Watson if (error) 119795fab37eSRobert Watson return (error); 119895fab37eSRobert Watson 119995fab37eSRobert Watson result = 0; 120095fab37eSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 120195fab37eSRobert Watson 120295fab37eSRobert Watson return (result); 120395fab37eSRobert Watson } 120495fab37eSRobert Watson 120595fab37eSRobert Watson static void 120695fab37eSRobert Watson mac_init_label(struct label *label) 120795fab37eSRobert Watson { 120895fab37eSRobert Watson 120995fab37eSRobert Watson bzero(label, sizeof(*label)); 121095fab37eSRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 121195fab37eSRobert Watson } 121295fab37eSRobert Watson 121395fab37eSRobert Watson static void 121495fab37eSRobert Watson mac_init_structmac(struct mac *mac) 121595fab37eSRobert Watson { 121695fab37eSRobert Watson 121795fab37eSRobert Watson bzero(mac, sizeof(*mac)); 121895fab37eSRobert Watson mac->m_macflags = MAC_FLAG_INITIALIZED; 121995fab37eSRobert Watson } 122095fab37eSRobert Watson 122195fab37eSRobert Watson static void 122295fab37eSRobert Watson mac_destroy_label(struct label *label) 122395fab37eSRobert Watson { 122495fab37eSRobert Watson 122595fab37eSRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 122695fab37eSRobert Watson ("destroying uninitialized label")); 122795fab37eSRobert Watson 122895fab37eSRobert Watson bzero(label, sizeof(*label)); 122995fab37eSRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 123095fab37eSRobert Watson } 123195fab37eSRobert Watson 123295fab37eSRobert Watson int 123395fab37eSRobert Watson mac_init_mbuf(struct mbuf *m, int how) 123495fab37eSRobert Watson { 123595fab37eSRobert Watson KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 123695fab37eSRobert Watson 123795fab37eSRobert Watson /* "how" is one of M_(TRY|DONT)WAIT */ 123895fab37eSRobert Watson mac_init_label(&m->m_pkthdr.label); 123995fab37eSRobert Watson MAC_PERFORM(init_mbuf, m, how, &m->m_pkthdr.label); 124095fab37eSRobert Watson atomic_add_int(&nmacmbufs, 1); 124195fab37eSRobert Watson return (0); 124295fab37eSRobert Watson } 124395fab37eSRobert Watson 124495fab37eSRobert Watson void 124595fab37eSRobert Watson mac_destroy_mbuf(struct mbuf *m) 124695fab37eSRobert Watson { 124795fab37eSRobert Watson 124895fab37eSRobert Watson MAC_PERFORM(destroy_mbuf, m, &m->m_pkthdr.label); 124995fab37eSRobert Watson mac_destroy_label(&m->m_pkthdr.label); 125095fab37eSRobert Watson atomic_subtract_int(&nmacmbufs, 1); 125195fab37eSRobert Watson } 125295fab37eSRobert Watson 125395fab37eSRobert Watson void 125495fab37eSRobert Watson mac_init_cred(struct ucred *cr) 125595fab37eSRobert Watson { 125695fab37eSRobert Watson 125795fab37eSRobert Watson mac_init_label(&cr->cr_label); 125895fab37eSRobert Watson MAC_PERFORM(init_cred, cr, &cr->cr_label); 125995fab37eSRobert Watson atomic_add_int(&nmaccreds, 1); 126095fab37eSRobert Watson } 126195fab37eSRobert Watson 126295fab37eSRobert Watson void 126395fab37eSRobert Watson mac_destroy_cred(struct ucred *cr) 126495fab37eSRobert Watson { 126595fab37eSRobert Watson 126695fab37eSRobert Watson MAC_PERFORM(destroy_cred, cr, &cr->cr_label); 126795fab37eSRobert Watson mac_destroy_label(&cr->cr_label); 126895fab37eSRobert Watson atomic_subtract_int(&nmaccreds, 1); 126995fab37eSRobert Watson } 127095fab37eSRobert Watson 127195fab37eSRobert Watson void 127295fab37eSRobert Watson mac_init_ifnet(struct ifnet *ifp) 127395fab37eSRobert Watson { 127495fab37eSRobert Watson 127595fab37eSRobert Watson mac_init_label(&ifp->if_label); 127695fab37eSRobert Watson MAC_PERFORM(init_ifnet, ifp, &ifp->if_label); 127795fab37eSRobert Watson atomic_add_int(&nmacifnets, 1); 127895fab37eSRobert Watson } 127995fab37eSRobert Watson 128095fab37eSRobert Watson void 128195fab37eSRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 128295fab37eSRobert Watson { 128395fab37eSRobert Watson 128495fab37eSRobert Watson MAC_PERFORM(destroy_ifnet, ifp, &ifp->if_label); 128595fab37eSRobert Watson mac_destroy_label(&ifp->if_label); 128695fab37eSRobert Watson atomic_subtract_int(&nmacifnets, 1); 128795fab37eSRobert Watson } 128895fab37eSRobert Watson 128995fab37eSRobert Watson void 129095fab37eSRobert Watson mac_init_ipq(struct ipq *ipq) 129195fab37eSRobert Watson { 129295fab37eSRobert Watson 129395fab37eSRobert Watson mac_init_label(&ipq->ipq_label); 129495fab37eSRobert Watson MAC_PERFORM(init_ipq, ipq, &ipq->ipq_label); 129595fab37eSRobert Watson atomic_add_int(&nmacipqs, 1); 129695fab37eSRobert Watson } 129795fab37eSRobert Watson 129895fab37eSRobert Watson void 129995fab37eSRobert Watson mac_destroy_ipq(struct ipq *ipq) 130095fab37eSRobert Watson { 130195fab37eSRobert Watson 130295fab37eSRobert Watson MAC_PERFORM(destroy_ipq, ipq, &ipq->ipq_label); 130395fab37eSRobert Watson mac_destroy_label(&ipq->ipq_label); 130495fab37eSRobert Watson atomic_subtract_int(&nmacipqs, 1); 130595fab37eSRobert Watson } 130695fab37eSRobert Watson 130795fab37eSRobert Watson void 130895fab37eSRobert Watson mac_init_socket(struct socket *socket) 130995fab37eSRobert Watson { 131095fab37eSRobert Watson 131195fab37eSRobert Watson mac_init_label(&socket->so_label); 131295fab37eSRobert Watson mac_init_label(&socket->so_peerlabel); 131395fab37eSRobert Watson MAC_PERFORM(init_socket, socket, &socket->so_label, 131495fab37eSRobert Watson &socket->so_peerlabel); 131595fab37eSRobert Watson atomic_add_int(&nmacsockets, 1); 131695fab37eSRobert Watson } 131795fab37eSRobert Watson 131895fab37eSRobert Watson void 131995fab37eSRobert Watson mac_destroy_socket(struct socket *socket) 132095fab37eSRobert Watson { 132195fab37eSRobert Watson 132295fab37eSRobert Watson MAC_PERFORM(destroy_socket, socket, &socket->so_label, 132395fab37eSRobert Watson &socket->so_peerlabel); 132495fab37eSRobert Watson mac_destroy_label(&socket->so_label); 132595fab37eSRobert Watson mac_destroy_label(&socket->so_peerlabel); 132695fab37eSRobert Watson atomic_subtract_int(&nmacsockets, 1); 132795fab37eSRobert Watson } 132895fab37eSRobert Watson 132995fab37eSRobert Watson void 133095fab37eSRobert Watson mac_init_pipe(struct pipe *pipe) 133195fab37eSRobert Watson { 133295fab37eSRobert Watson struct label *label; 133395fab37eSRobert Watson 133495fab37eSRobert Watson label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 133595fab37eSRobert Watson mac_init_label(label); 133695fab37eSRobert Watson pipe->pipe_label = label; 133795fab37eSRobert Watson pipe->pipe_peer->pipe_label = label; 133895fab37eSRobert Watson MAC_PERFORM(init_pipe, pipe, pipe->pipe_label); 133995fab37eSRobert Watson atomic_add_int(&nmacpipes, 1); 134095fab37eSRobert Watson } 134195fab37eSRobert Watson 134295fab37eSRobert Watson void 134395fab37eSRobert Watson mac_destroy_pipe(struct pipe *pipe) 134495fab37eSRobert Watson { 134595fab37eSRobert Watson 134695fab37eSRobert Watson MAC_PERFORM(destroy_pipe, pipe, pipe->pipe_label); 134795fab37eSRobert Watson mac_destroy_label(pipe->pipe_label); 134895fab37eSRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 134995fab37eSRobert Watson atomic_subtract_int(&nmacpipes, 1); 135095fab37eSRobert Watson } 135195fab37eSRobert Watson 135295fab37eSRobert Watson void 135395fab37eSRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 135495fab37eSRobert Watson { 135595fab37eSRobert Watson 135695fab37eSRobert Watson mac_init_label(&bpf_d->bd_label); 135795fab37eSRobert Watson MAC_PERFORM(init_bpfdesc, bpf_d, &bpf_d->bd_label); 135895fab37eSRobert Watson atomic_add_int(&nmacbpfdescs, 1); 135995fab37eSRobert Watson } 136095fab37eSRobert Watson 136195fab37eSRobert Watson void 136295fab37eSRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 136395fab37eSRobert Watson { 136495fab37eSRobert Watson 136595fab37eSRobert Watson MAC_PERFORM(destroy_bpfdesc, bpf_d, &bpf_d->bd_label); 136695fab37eSRobert Watson mac_destroy_label(&bpf_d->bd_label); 136795fab37eSRobert Watson atomic_subtract_int(&nmacbpfdescs, 1); 136895fab37eSRobert Watson } 136995fab37eSRobert Watson 137095fab37eSRobert Watson void 137195fab37eSRobert Watson mac_init_mount(struct mount *mp) 137295fab37eSRobert Watson { 137395fab37eSRobert Watson 137495fab37eSRobert Watson mac_init_label(&mp->mnt_mntlabel); 137595fab37eSRobert Watson mac_init_label(&mp->mnt_fslabel); 137695fab37eSRobert Watson MAC_PERFORM(init_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 137795fab37eSRobert Watson atomic_add_int(&nmacmounts, 1); 137895fab37eSRobert Watson } 137995fab37eSRobert Watson 138095fab37eSRobert Watson void 138195fab37eSRobert Watson mac_destroy_mount(struct mount *mp) 138295fab37eSRobert Watson { 138395fab37eSRobert Watson 138495fab37eSRobert Watson MAC_PERFORM(destroy_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 138595fab37eSRobert Watson mac_destroy_label(&mp->mnt_fslabel); 138695fab37eSRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 138795fab37eSRobert Watson atomic_subtract_int(&nmacmounts, 1); 138895fab37eSRobert Watson } 138995fab37eSRobert Watson 139095fab37eSRobert Watson static void 139195fab37eSRobert Watson mac_init_temp(struct label *label) 139295fab37eSRobert Watson { 139395fab37eSRobert Watson 139495fab37eSRobert Watson mac_init_label(label); 139595fab37eSRobert Watson MAC_PERFORM(init_temp, label); 139695fab37eSRobert Watson atomic_add_int(&nmactemp, 1); 139795fab37eSRobert Watson } 139895fab37eSRobert Watson 139995fab37eSRobert Watson static void 140095fab37eSRobert Watson mac_destroy_temp(struct label *label) 140195fab37eSRobert Watson { 140295fab37eSRobert Watson 140395fab37eSRobert Watson MAC_PERFORM(destroy_temp, label); 140495fab37eSRobert Watson mac_destroy_label(label); 140595fab37eSRobert Watson atomic_subtract_int(&nmactemp, 1); 140695fab37eSRobert Watson } 140795fab37eSRobert Watson 140895fab37eSRobert Watson void 140995fab37eSRobert Watson mac_init_vnode(struct vnode *vp) 141095fab37eSRobert Watson { 141195fab37eSRobert Watson 141295fab37eSRobert Watson mac_init_label(&vp->v_label); 141395fab37eSRobert Watson MAC_PERFORM(init_vnode, vp, &vp->v_label); 141495fab37eSRobert Watson atomic_add_int(&nmacvnodes, 1); 141595fab37eSRobert Watson } 141695fab37eSRobert Watson 141795fab37eSRobert Watson void 141895fab37eSRobert Watson mac_destroy_vnode(struct vnode *vp) 141995fab37eSRobert Watson { 142095fab37eSRobert Watson 142195fab37eSRobert Watson MAC_PERFORM(destroy_vnode, vp, &vp->v_label); 142295fab37eSRobert Watson mac_destroy_label(&vp->v_label); 142395fab37eSRobert Watson atomic_subtract_int(&nmacvnodes, 1); 142495fab37eSRobert Watson } 142595fab37eSRobert Watson 142695fab37eSRobert Watson void 142795fab37eSRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 142895fab37eSRobert Watson { 142995fab37eSRobert Watson 143095fab37eSRobert Watson mac_init_label(&de->de_label); 143195fab37eSRobert Watson MAC_PERFORM(init_devfsdirent, de, &de->de_label); 143295fab37eSRobert Watson atomic_add_int(&nmacdevfsdirents, 1); 143395fab37eSRobert Watson } 143495fab37eSRobert Watson 143595fab37eSRobert Watson void 143695fab37eSRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 143795fab37eSRobert Watson { 143895fab37eSRobert Watson 143995fab37eSRobert Watson MAC_PERFORM(destroy_devfsdirent, de, &de->de_label); 144095fab37eSRobert Watson mac_destroy_label(&de->de_label); 144195fab37eSRobert Watson atomic_subtract_int(&nmacdevfsdirents, 1); 144295fab37eSRobert Watson } 144395fab37eSRobert Watson 144495fab37eSRobert Watson static int 144595fab37eSRobert Watson mac_externalize(struct label *label, struct mac *mac) 144695fab37eSRobert Watson { 144795fab37eSRobert Watson int error; 144895fab37eSRobert Watson 144995fab37eSRobert Watson mac_init_structmac(mac); 145095fab37eSRobert Watson MAC_CHECK(externalize, label, mac); 145195fab37eSRobert Watson 145295fab37eSRobert Watson return (error); 145395fab37eSRobert Watson } 145495fab37eSRobert Watson 145595fab37eSRobert Watson static int 145695fab37eSRobert Watson mac_internalize(struct label *label, struct mac *mac) 145795fab37eSRobert Watson { 145895fab37eSRobert Watson int error; 145995fab37eSRobert Watson 146095fab37eSRobert Watson mac_init_temp(label); 146195fab37eSRobert Watson MAC_CHECK(internalize, label, mac); 146295fab37eSRobert Watson if (error) 146395fab37eSRobert Watson mac_destroy_temp(label); 146495fab37eSRobert Watson 146595fab37eSRobert Watson return (error); 146695fab37eSRobert Watson } 146795fab37eSRobert Watson 146895fab37eSRobert Watson /* 146995fab37eSRobert Watson * Initialize MAC label for the first kernel process, from which other 147095fab37eSRobert Watson * kernel processes and threads are spawned. 147195fab37eSRobert Watson */ 147295fab37eSRobert Watson void 147395fab37eSRobert Watson mac_create_proc0(struct ucred *cred) 147495fab37eSRobert Watson { 147595fab37eSRobert Watson 147695fab37eSRobert Watson MAC_PERFORM(create_proc0, cred); 147795fab37eSRobert Watson } 147895fab37eSRobert Watson 147995fab37eSRobert Watson /* 148095fab37eSRobert Watson * Initialize MAC label for the first userland process, from which other 148195fab37eSRobert Watson * userland processes and threads are spawned. 148295fab37eSRobert Watson */ 148395fab37eSRobert Watson void 148495fab37eSRobert Watson mac_create_proc1(struct ucred *cred) 148595fab37eSRobert Watson { 148695fab37eSRobert Watson 148795fab37eSRobert Watson MAC_PERFORM(create_proc1, cred); 148895fab37eSRobert Watson } 148995fab37eSRobert Watson 149095fab37eSRobert Watson /* 149195fab37eSRobert Watson * When a new process is created, its label must be initialized. Generally, 149295fab37eSRobert Watson * this involves inheritence from the parent process, modulo possible 149395fab37eSRobert Watson * deltas. This function allows that processing to take place. 149495fab37eSRobert Watson */ 149595fab37eSRobert Watson void 149695fab37eSRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 149795fab37eSRobert Watson { 149895fab37eSRobert Watson 149995fab37eSRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 150095fab37eSRobert Watson } 150195fab37eSRobert Watson 150295fab37eSRobert Watson int 150395fab37eSRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 150495fab37eSRobert Watson { 150595fab37eSRobert Watson int error; 150695fab37eSRobert Watson 150795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 150895fab37eSRobert Watson 150995fab37eSRobert Watson if (!mac_enforce_fs) 151095fab37eSRobert Watson return (0); 151195fab37eSRobert Watson 151295fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 151395fab37eSRobert Watson if (error) 151495fab37eSRobert Watson return (error); 151595fab37eSRobert Watson 151695fab37eSRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 151795fab37eSRobert Watson return (error); 151895fab37eSRobert Watson } 151995fab37eSRobert Watson 152095fab37eSRobert Watson int 152195fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 152295fab37eSRobert Watson { 152395fab37eSRobert Watson int error; 152495fab37eSRobert Watson 152595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 152695fab37eSRobert Watson 152795fab37eSRobert Watson if (!mac_enforce_fs) 152895fab37eSRobert Watson return (0); 152995fab37eSRobert Watson 153095fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 153195fab37eSRobert Watson if (error) 153295fab37eSRobert Watson return (error); 153395fab37eSRobert Watson 153495fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 153595fab37eSRobert Watson return (error); 153695fab37eSRobert Watson } 153795fab37eSRobert Watson 153895fab37eSRobert Watson int 153995fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 154095fab37eSRobert Watson { 154195fab37eSRobert Watson int error; 154295fab37eSRobert Watson 154395fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 154495fab37eSRobert Watson 154595fab37eSRobert Watson if (!mac_enforce_fs) 154695fab37eSRobert Watson return (0); 154795fab37eSRobert Watson 154895fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 154995fab37eSRobert Watson if (error) 155095fab37eSRobert Watson return (error); 155195fab37eSRobert Watson 155295fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 155395fab37eSRobert Watson return (error); 155495fab37eSRobert Watson } 155595fab37eSRobert Watson 155695fab37eSRobert Watson int 155795fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 155895fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 155995fab37eSRobert Watson { 156095fab37eSRobert Watson int error; 156195fab37eSRobert Watson 156295fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 156395fab37eSRobert Watson 156495fab37eSRobert Watson if (!mac_enforce_fs) 156595fab37eSRobert Watson return (0); 156695fab37eSRobert Watson 156795fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 156895fab37eSRobert Watson if (error) 156995fab37eSRobert Watson return (error); 157095fab37eSRobert Watson 157195fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 157295fab37eSRobert Watson return (error); 157395fab37eSRobert Watson } 157495fab37eSRobert Watson 157595fab37eSRobert Watson int 157695fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 157795fab37eSRobert Watson struct componentname *cnp) 157895fab37eSRobert Watson { 157995fab37eSRobert Watson int error; 158095fab37eSRobert Watson 158195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 158295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 158395fab37eSRobert Watson 158495fab37eSRobert Watson if (!mac_enforce_fs) 158595fab37eSRobert Watson return (0); 158695fab37eSRobert Watson 158795fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 158895fab37eSRobert Watson if (error) 158995fab37eSRobert Watson return (error); 159095fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 159195fab37eSRobert Watson if (error) 159295fab37eSRobert Watson return (error); 159395fab37eSRobert Watson 159495fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 159595fab37eSRobert Watson &vp->v_label, cnp); 159695fab37eSRobert Watson return (error); 159795fab37eSRobert Watson } 159895fab37eSRobert Watson 159995fab37eSRobert Watson int 160095fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 160195fab37eSRobert Watson acl_type_t type) 160295fab37eSRobert Watson { 160395fab37eSRobert Watson int error; 160495fab37eSRobert Watson 160595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 160695fab37eSRobert Watson 160795fab37eSRobert Watson if (!mac_enforce_fs) 160895fab37eSRobert Watson return (0); 160995fab37eSRobert Watson 161095fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 161195fab37eSRobert Watson if (error) 161295fab37eSRobert Watson return (error); 161395fab37eSRobert Watson 161495fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 161595fab37eSRobert Watson return (error); 161695fab37eSRobert Watson } 161795fab37eSRobert Watson 161895fab37eSRobert Watson int 161995fab37eSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 162095fab37eSRobert Watson { 162195fab37eSRobert Watson int error; 162295fab37eSRobert Watson 162395fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 162495fab37eSRobert Watson return (0); 162595fab37eSRobert Watson 162695fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 162795fab37eSRobert Watson if (error) 162895fab37eSRobert Watson return (error); 162995fab37eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 163095fab37eSRobert Watson 163195fab37eSRobert Watson return (error); 163295fab37eSRobert Watson } 163395fab37eSRobert Watson 163495fab37eSRobert Watson int 163595fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 163695fab37eSRobert Watson { 163795fab37eSRobert Watson int error; 163895fab37eSRobert Watson 163995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 164095fab37eSRobert Watson 164195fab37eSRobert Watson if (!mac_enforce_fs) 164295fab37eSRobert Watson return (0); 164395fab37eSRobert Watson 164495fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 164595fab37eSRobert Watson if (error) 164695fab37eSRobert Watson return (error); 164795fab37eSRobert Watson 164895fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 164995fab37eSRobert Watson return (error); 165095fab37eSRobert Watson } 165195fab37eSRobert Watson 165295fab37eSRobert Watson int 165395fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 165495fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 165595fab37eSRobert Watson { 165695fab37eSRobert Watson int error; 165795fab37eSRobert Watson 165895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 165995fab37eSRobert Watson 166095fab37eSRobert Watson if (!mac_enforce_fs) 166195fab37eSRobert Watson return (0); 166295fab37eSRobert Watson 166395fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 166495fab37eSRobert Watson if (error) 166595fab37eSRobert Watson return (error); 166695fab37eSRobert Watson 166795fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 166895fab37eSRobert Watson attrnamespace, name, uio); 166995fab37eSRobert Watson return (error); 167095fab37eSRobert Watson } 167195fab37eSRobert Watson 167295fab37eSRobert Watson int 167395fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 167495fab37eSRobert Watson struct componentname *cnp) 167595fab37eSRobert Watson { 167695fab37eSRobert Watson int error; 167795fab37eSRobert Watson 167895fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 167995fab37eSRobert Watson 168095fab37eSRobert Watson if (!mac_enforce_fs) 168195fab37eSRobert Watson return (0); 168295fab37eSRobert Watson 168395fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 168495fab37eSRobert Watson if (error) 168595fab37eSRobert Watson return (error); 168695fab37eSRobert Watson 168795fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 168895fab37eSRobert Watson return (error); 168995fab37eSRobert Watson } 169095fab37eSRobert Watson 169195fab37eSRobert Watson vm_prot_t 169295fab37eSRobert Watson mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping) 169395fab37eSRobert Watson { 169495fab37eSRobert Watson vm_prot_t result = VM_PROT_ALL; 169595fab37eSRobert Watson 169695fab37eSRobert Watson /* 169795fab37eSRobert Watson * This should be some sort of MAC_BITWISE, maybe :) 169895fab37eSRobert Watson */ 169995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms"); 170095fab37eSRobert Watson MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label, 170195fab37eSRobert Watson newmapping); 170295fab37eSRobert Watson return (result); 170395fab37eSRobert Watson } 170495fab37eSRobert Watson 170595fab37eSRobert Watson int 170695fab37eSRobert Watson mac_check_vnode_op(struct ucred *cred, struct vnode *vp, int op) 170795fab37eSRobert Watson { 170895fab37eSRobert Watson int error; 170995fab37eSRobert Watson 171095fab37eSRobert Watson if (!mac_enforce_fs) 171195fab37eSRobert Watson return (0); 171295fab37eSRobert Watson 171395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_op"); 171495fab37eSRobert Watson 171595fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 171695fab37eSRobert Watson if (error) 171795fab37eSRobert Watson return (error); 171895fab37eSRobert Watson 171995fab37eSRobert Watson MAC_CHECK(check_vnode_op, cred, vp, &vp->v_label, op); 172095fab37eSRobert Watson 172195fab37eSRobert Watson return (error); 172295fab37eSRobert Watson } 172395fab37eSRobert Watson 172495fab37eSRobert Watson int 172595fab37eSRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 172695fab37eSRobert Watson { 172795fab37eSRobert Watson int error; 172895fab37eSRobert Watson 172995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 173095fab37eSRobert Watson 173195fab37eSRobert Watson if (!mac_enforce_fs) 173295fab37eSRobert Watson return (0); 173395fab37eSRobert Watson 173495fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 173595fab37eSRobert Watson if (error) 173695fab37eSRobert Watson return (error); 173795fab37eSRobert Watson 173895fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 173995fab37eSRobert Watson return (error); 174095fab37eSRobert Watson } 174195fab37eSRobert Watson 174295fab37eSRobert Watson int 174395fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 174495fab37eSRobert Watson { 174595fab37eSRobert Watson int error; 174695fab37eSRobert Watson 174795fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 174895fab37eSRobert Watson 174995fab37eSRobert Watson if (!mac_enforce_fs) 175095fab37eSRobert Watson return (0); 175195fab37eSRobert Watson 175295fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 175395fab37eSRobert Watson if (error) 175495fab37eSRobert Watson return (error); 175595fab37eSRobert Watson 175695fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 175795fab37eSRobert Watson return (error); 175895fab37eSRobert Watson } 175995fab37eSRobert Watson 176095fab37eSRobert Watson int 176195fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 176295fab37eSRobert Watson { 176395fab37eSRobert Watson int error; 176495fab37eSRobert Watson 176595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 176695fab37eSRobert Watson 176795fab37eSRobert Watson if (!mac_enforce_fs) 176895fab37eSRobert Watson return (0); 176995fab37eSRobert Watson 177095fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 177195fab37eSRobert Watson if (error) 177295fab37eSRobert Watson return (error); 177395fab37eSRobert Watson 177495fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 177595fab37eSRobert Watson return (error); 177695fab37eSRobert Watson } 177795fab37eSRobert Watson 177895fab37eSRobert Watson static int 177995fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 178095fab37eSRobert Watson struct label *newlabel) 178195fab37eSRobert Watson { 178295fab37eSRobert Watson int error; 178395fab37eSRobert Watson 178495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 178595fab37eSRobert Watson 178695fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 178795fab37eSRobert Watson if (error) 178895fab37eSRobert Watson return (error); 178995fab37eSRobert Watson 179095fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 179195fab37eSRobert Watson 179295fab37eSRobert Watson return (error); 179395fab37eSRobert Watson } 179495fab37eSRobert Watson 179595fab37eSRobert Watson int 179695fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 179795fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 179895fab37eSRobert Watson { 179995fab37eSRobert Watson int error; 180095fab37eSRobert Watson 180195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 180295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 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 error = vn_refreshlabel(vp, cred); 181195fab37eSRobert Watson if (error) 181295fab37eSRobert Watson return (error); 181395fab37eSRobert Watson 181495fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 181595fab37eSRobert Watson &vp->v_label, cnp); 181695fab37eSRobert Watson return (error); 181795fab37eSRobert Watson } 181895fab37eSRobert Watson 181995fab37eSRobert Watson int 182095fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 182195fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 182295fab37eSRobert Watson { 182395fab37eSRobert Watson int error; 182495fab37eSRobert Watson 182595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 182695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 182795fab37eSRobert Watson 182895fab37eSRobert Watson if (!mac_enforce_fs) 182995fab37eSRobert Watson return (0); 183095fab37eSRobert Watson 183195fab37eSRobert Watson error = vn_refreshlabel(dvp, cred); 183295fab37eSRobert Watson if (error) 183395fab37eSRobert Watson return (error); 183495fab37eSRobert Watson if (vp != NULL) { 183595fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 183695fab37eSRobert Watson if (error) 183795fab37eSRobert Watson return (error); 183895fab37eSRobert Watson } 183995fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 184095fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 184195fab37eSRobert Watson return (error); 184295fab37eSRobert Watson } 184395fab37eSRobert Watson 184495fab37eSRobert Watson int 184595fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 184695fab37eSRobert Watson { 184795fab37eSRobert Watson int error; 184895fab37eSRobert Watson 184995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 185095fab37eSRobert Watson 185195fab37eSRobert Watson if (!mac_enforce_fs) 185295fab37eSRobert Watson return (0); 185395fab37eSRobert Watson 185495fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 185595fab37eSRobert Watson if (error) 185695fab37eSRobert Watson return (error); 185795fab37eSRobert Watson 185895fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 185995fab37eSRobert Watson return (error); 186095fab37eSRobert Watson } 186195fab37eSRobert Watson 186295fab37eSRobert Watson int 186395fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 186495fab37eSRobert Watson struct acl *acl) 186595fab37eSRobert Watson { 186695fab37eSRobert Watson int error; 186795fab37eSRobert Watson 186895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 186995fab37eSRobert Watson 187095fab37eSRobert Watson if (!mac_enforce_fs) 187195fab37eSRobert Watson return (0); 187295fab37eSRobert Watson 187395fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 187495fab37eSRobert Watson if (error) 187595fab37eSRobert Watson return (error); 187695fab37eSRobert Watson 187795fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 187895fab37eSRobert Watson return (error); 187995fab37eSRobert Watson } 188095fab37eSRobert Watson 188195fab37eSRobert Watson int 188295fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 188395fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 188495fab37eSRobert Watson { 188595fab37eSRobert Watson int error; 188695fab37eSRobert Watson 188795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 188895fab37eSRobert Watson 188995fab37eSRobert Watson if (!mac_enforce_fs) 189095fab37eSRobert Watson return (0); 189195fab37eSRobert Watson 189295fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 189395fab37eSRobert Watson if (error) 189495fab37eSRobert Watson return (error); 189595fab37eSRobert Watson 189695fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 189795fab37eSRobert Watson attrnamespace, name, uio); 189895fab37eSRobert Watson return (error); 189995fab37eSRobert Watson } 190095fab37eSRobert Watson 190195fab37eSRobert Watson int 190295fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 190395fab37eSRobert Watson { 190495fab37eSRobert Watson int error; 190595fab37eSRobert Watson 190695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 190795fab37eSRobert Watson 190895fab37eSRobert Watson if (!mac_enforce_fs) 190995fab37eSRobert Watson return (0); 191095fab37eSRobert Watson 191195fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 191295fab37eSRobert Watson if (error) 191395fab37eSRobert Watson return (error); 191495fab37eSRobert Watson 191595fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 191695fab37eSRobert Watson return (error); 191795fab37eSRobert Watson } 191895fab37eSRobert Watson 191995fab37eSRobert Watson int 192095fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 192195fab37eSRobert Watson { 192295fab37eSRobert Watson int error; 192395fab37eSRobert Watson 192495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 192595fab37eSRobert Watson 192695fab37eSRobert Watson if (!mac_enforce_fs) 192795fab37eSRobert Watson return (0); 192895fab37eSRobert Watson 192995fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 193095fab37eSRobert Watson if (error) 193195fab37eSRobert Watson return (error); 193295fab37eSRobert Watson 193395fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 193495fab37eSRobert Watson return (error); 193595fab37eSRobert Watson } 193695fab37eSRobert Watson 193795fab37eSRobert Watson int 193895fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 193995fab37eSRobert Watson gid_t gid) 194095fab37eSRobert Watson { 194195fab37eSRobert Watson int error; 194295fab37eSRobert Watson 194395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 194495fab37eSRobert Watson 194595fab37eSRobert Watson if (!mac_enforce_fs) 194695fab37eSRobert Watson return (0); 194795fab37eSRobert Watson 194895fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 194995fab37eSRobert Watson if (error) 195095fab37eSRobert Watson return (error); 195195fab37eSRobert Watson 195295fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 195395fab37eSRobert Watson return (error); 195495fab37eSRobert Watson } 195595fab37eSRobert Watson 195695fab37eSRobert Watson int 195795fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 195895fab37eSRobert Watson struct timespec atime, struct timespec mtime) 195995fab37eSRobert Watson { 196095fab37eSRobert Watson int error; 196195fab37eSRobert Watson 196295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 196395fab37eSRobert Watson 196495fab37eSRobert Watson if (!mac_enforce_fs) 196595fab37eSRobert Watson return (0); 196695fab37eSRobert Watson 196795fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 196895fab37eSRobert Watson if (error) 196995fab37eSRobert Watson return (error); 197095fab37eSRobert Watson 197195fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 197295fab37eSRobert Watson mtime); 197395fab37eSRobert Watson return (error); 197495fab37eSRobert Watson } 197595fab37eSRobert Watson 197695fab37eSRobert Watson int 197795fab37eSRobert Watson mac_check_vnode_stat(struct ucred *cred, struct vnode *vp) 197895fab37eSRobert Watson { 197995fab37eSRobert Watson int error; 198095fab37eSRobert Watson 198195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 198295fab37eSRobert Watson 198395fab37eSRobert Watson if (!mac_enforce_fs) 198495fab37eSRobert Watson return (0); 198595fab37eSRobert Watson 198695fab37eSRobert Watson error = vn_refreshlabel(vp, cred); 198795fab37eSRobert Watson if (error) 198895fab37eSRobert Watson return (error); 198995fab37eSRobert Watson 199095fab37eSRobert Watson MAC_CHECK(check_vnode_stat, cred, vp, &vp->v_label); 199195fab37eSRobert Watson return (error); 199295fab37eSRobert Watson } 199395fab37eSRobert Watson 199495fab37eSRobert Watson /* 199595fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 199695fab37eSRobert Watson * permission allowed for each object type we know about in its 199795fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 199895fab37eSRobert Watson * know) when necessary. The process lock is not held here. 199995fab37eSRobert Watson */ 200095fab37eSRobert Watson static void 200195fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 200295fab37eSRobert Watson { 200395fab37eSRobert Watson 200495fab37eSRobert Watson /* XXX freeze all other threads */ 200595fab37eSRobert Watson mtx_lock(&Giant); 200695fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 200795fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 200895fab37eSRobert Watson mtx_unlock(&Giant); 200995fab37eSRobert Watson /* XXX allow other threads to continue */ 201095fab37eSRobert Watson } 201195fab37eSRobert Watson 201295fab37eSRobert Watson static __inline const char * 201395fab37eSRobert Watson prot2str(vm_prot_t prot) 201495fab37eSRobert Watson { 201595fab37eSRobert Watson 201695fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 201795fab37eSRobert Watson case VM_PROT_READ: 201895fab37eSRobert Watson return ("r--"); 201995fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 202095fab37eSRobert Watson return ("rw-"); 202195fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 202295fab37eSRobert Watson return ("r-x"); 202395fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 202495fab37eSRobert Watson return ("rwx"); 202595fab37eSRobert Watson case VM_PROT_WRITE: 202695fab37eSRobert Watson return ("-w-"); 202795fab37eSRobert Watson case VM_PROT_EXECUTE: 202895fab37eSRobert Watson return ("--x"); 202995fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 203095fab37eSRobert Watson return ("-wx"); 203195fab37eSRobert Watson default: 203295fab37eSRobert Watson return ("---"); 203395fab37eSRobert Watson } 203495fab37eSRobert Watson } 203595fab37eSRobert Watson 203695fab37eSRobert Watson static void 203795fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 203895fab37eSRobert Watson struct vm_map *map) 203995fab37eSRobert Watson { 204095fab37eSRobert Watson struct vm_map_entry *vme; 204195fab37eSRobert Watson vm_prot_t result, revokeperms; 204295fab37eSRobert Watson vm_object_t object; 204395fab37eSRobert Watson vm_ooffset_t offset; 204495fab37eSRobert Watson struct vnode *vp; 204595fab37eSRobert Watson 204695fab37eSRobert Watson vm_map_lock_read(map); 204795fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 204895fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 204995fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 205095fab37eSRobert Watson vme->object.sub_map); 205195fab37eSRobert Watson continue; 205295fab37eSRobert Watson } 205395fab37eSRobert Watson /* 205495fab37eSRobert Watson * Skip over entries that obviously are not shared. 205595fab37eSRobert Watson */ 205695fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 205795fab37eSRobert Watson !vme->max_protection) 205895fab37eSRobert Watson continue; 205995fab37eSRobert Watson /* 206095fab37eSRobert Watson * Drill down to the deepest backing object. 206195fab37eSRobert Watson */ 206295fab37eSRobert Watson offset = vme->offset; 206395fab37eSRobert Watson object = vme->object.vm_object; 206495fab37eSRobert Watson if (object == NULL) 206595fab37eSRobert Watson continue; 206695fab37eSRobert Watson while (object->backing_object != NULL) { 206795fab37eSRobert Watson object = object->backing_object; 206895fab37eSRobert Watson offset += object->backing_object_offset; 206995fab37eSRobert Watson } 207095fab37eSRobert Watson /* 207195fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 207295fab37eSRobert Watson * by the MAC system, so only things with backing by a 207395fab37eSRobert Watson * normal object (read: vnodes) are checked. 207495fab37eSRobert Watson */ 207595fab37eSRobert Watson if (object->type != OBJT_VNODE) 207695fab37eSRobert Watson continue; 207795fab37eSRobert Watson vp = (struct vnode *)object->handle; 207895fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 207995fab37eSRobert Watson result = mac_check_vnode_mmap_prot(cred, vp, 0); 208095fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 208195fab37eSRobert Watson /* 208295fab37eSRobert Watson * Find out what maximum protection we may be allowing 208395fab37eSRobert Watson * now but a policy needs to get removed. 208495fab37eSRobert Watson */ 208595fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 208695fab37eSRobert Watson if (!revokeperms) 208795fab37eSRobert Watson continue; 208895fab37eSRobert Watson printf("pid %d: revoking %s perms from %#lx:%d " 208995fab37eSRobert Watson "(max %s/cur %s)\n", td->td_proc->p_pid, 209095fab37eSRobert Watson prot2str(revokeperms), vme->start, vme->end - vme->start, 209195fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 209295fab37eSRobert Watson vm_map_lock_upgrade(map); 209395fab37eSRobert Watson /* 209495fab37eSRobert Watson * This is the really simple case: if a map has more 209595fab37eSRobert Watson * max_protection than is allowed, but it's not being 209695fab37eSRobert Watson * actually used (that is, the current protection is 209795fab37eSRobert Watson * still allowed), we can just wipe it out and do 209895fab37eSRobert Watson * nothing more. 209995fab37eSRobert Watson */ 210095fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 210195fab37eSRobert Watson vme->max_protection -= revokeperms; 210295fab37eSRobert Watson } else { 210395fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 210495fab37eSRobert Watson /* 210595fab37eSRobert Watson * In the more complicated case, flush out all 210695fab37eSRobert Watson * pending changes to the object then turn it 210795fab37eSRobert Watson * copy-on-write. 210895fab37eSRobert Watson */ 210995fab37eSRobert Watson vm_object_reference(object); 211095fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 211195fab37eSRobert Watson vm_object_page_clean(object, 211295fab37eSRobert Watson OFF_TO_IDX(offset), 211395fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 211495fab37eSRobert Watson PAGE_MASK), 211595fab37eSRobert Watson OBJPC_SYNC); 211695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 211795fab37eSRobert Watson vm_object_deallocate(object); 211895fab37eSRobert Watson /* 211995fab37eSRobert Watson * Why bother if there's no read permissions 212095fab37eSRobert Watson * anymore? For the rest, we need to leave 212195fab37eSRobert Watson * the write permissions on for COW, or 212295fab37eSRobert Watson * remove them entirely if configured to. 212395fab37eSRobert Watson */ 212495fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 212595fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 212695fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 212795fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 212895fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 212995fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 213095fab37eSRobert Watson } 213195fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 213295fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 213395fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 213495fab37eSRobert Watson } 213595fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 213695fab37eSRobert Watson vme->max_protection = 0; 213795fab37eSRobert Watson vme->protection = 0; 213895fab37eSRobert Watson } 213995fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 214095fab37eSRobert Watson vme->protection & ~revokeperms); 214195fab37eSRobert Watson vm_map_simplify_entry(map, vme); 214295fab37eSRobert Watson } 214395fab37eSRobert Watson vm_map_lock_downgrade(map); 214495fab37eSRobert Watson } 214595fab37eSRobert Watson vm_map_unlock_read(map); 214695fab37eSRobert Watson } 214795fab37eSRobert Watson 214895fab37eSRobert Watson /* 214995fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 215095fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 215195fab37eSRobert Watson * buffer cache. 215295fab37eSRobert Watson */ 215395fab37eSRobert Watson static void 215495fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 215595fab37eSRobert Watson { 215695fab37eSRobert Watson 215795fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 215895fab37eSRobert Watson mac_cred_mmapped_drop_perms(curthread, cred); 215995fab37eSRobert Watson } 216095fab37eSRobert Watson 216195fab37eSRobert Watson void 216295fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 216395fab37eSRobert Watson { 216495fab37eSRobert Watson 216595fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 216695fab37eSRobert Watson } 216795fab37eSRobert Watson 216895fab37eSRobert Watson void 216995fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 217095fab37eSRobert Watson { 217195fab37eSRobert Watson 217295fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 217395fab37eSRobert Watson } 217495fab37eSRobert Watson 217595fab37eSRobert Watson void 217695fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 217795fab37eSRobert Watson { 217895fab37eSRobert Watson 217995fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 218095fab37eSRobert Watson } 218195fab37eSRobert Watson 218295fab37eSRobert Watson void 218395fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 218495fab37eSRobert Watson { 218595fab37eSRobert Watson 218695fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 218795fab37eSRobert Watson } 218895fab37eSRobert Watson 218995fab37eSRobert Watson void 219095fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 219195fab37eSRobert Watson { 219295fab37eSRobert Watson 219395fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 219495fab37eSRobert Watson } 219595fab37eSRobert Watson 219695fab37eSRobert Watson void 219795fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 219895fab37eSRobert Watson struct socket *newsocket) 219995fab37eSRobert Watson { 220095fab37eSRobert Watson 220195fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 220295fab37eSRobert Watson newsocket, &newsocket->so_label); 220395fab37eSRobert Watson } 220495fab37eSRobert Watson 220595fab37eSRobert Watson static void 220695fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 220795fab37eSRobert Watson struct label *newlabel) 220895fab37eSRobert Watson { 220995fab37eSRobert Watson 221095fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 221195fab37eSRobert Watson } 221295fab37eSRobert Watson 221395fab37eSRobert Watson static void 221495fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 221595fab37eSRobert Watson { 221695fab37eSRobert Watson 221795fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 221895fab37eSRobert Watson } 221995fab37eSRobert Watson 222095fab37eSRobert Watson void 222195fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 222295fab37eSRobert Watson { 222395fab37eSRobert Watson 222495fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 222595fab37eSRobert Watson socket, &socket->so_peerlabel); 222695fab37eSRobert Watson } 222795fab37eSRobert Watson 222895fab37eSRobert Watson void 222995fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 223095fab37eSRobert Watson struct socket *newsocket) 223195fab37eSRobert Watson { 223295fab37eSRobert Watson 223395fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 223495fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 223595fab37eSRobert Watson } 223695fab37eSRobert Watson 223795fab37eSRobert Watson void 223895fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 223995fab37eSRobert Watson { 224095fab37eSRobert Watson 224195fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 224295fab37eSRobert Watson datagram, &datagram->m_pkthdr.label); 224395fab37eSRobert Watson } 224495fab37eSRobert Watson 224595fab37eSRobert Watson void 224695fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 224795fab37eSRobert Watson { 224895fab37eSRobert Watson 224995fab37eSRobert Watson MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 225095fab37eSRobert Watson fragment, &fragment->m_pkthdr.label); 225195fab37eSRobert Watson } 225295fab37eSRobert Watson 225395fab37eSRobert Watson void 225495fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 225595fab37eSRobert Watson { 225695fab37eSRobert Watson 225795fab37eSRobert Watson MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 225895fab37eSRobert Watson &ipq->ipq_label); 225995fab37eSRobert Watson } 226095fab37eSRobert Watson 226195fab37eSRobert Watson void 226295fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 226395fab37eSRobert Watson { 226495fab37eSRobert Watson 226595fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 226695fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 226795fab37eSRobert Watson } 226895fab37eSRobert Watson 226995fab37eSRobert Watson void 227095fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 227195fab37eSRobert Watson { 227295fab37eSRobert Watson 227395fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 227495fab37eSRobert Watson &mbuf->m_pkthdr.label); 227595fab37eSRobert Watson } 227695fab37eSRobert Watson 227795fab37eSRobert Watson void 227895fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 227995fab37eSRobert Watson { 228095fab37eSRobert Watson 228195fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 228295fab37eSRobert Watson &mbuf->m_pkthdr.label); 228395fab37eSRobert Watson } 228495fab37eSRobert Watson 228595fab37eSRobert Watson void 228695fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 228795fab37eSRobert Watson { 228895fab37eSRobert Watson 228995fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 229095fab37eSRobert Watson &mbuf->m_pkthdr.label); 229195fab37eSRobert Watson } 229295fab37eSRobert Watson 229395fab37eSRobert Watson void 229495fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 229595fab37eSRobert Watson struct mbuf *newmbuf) 229695fab37eSRobert Watson { 229795fab37eSRobert Watson 229895fab37eSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 229995fab37eSRobert Watson &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 230095fab37eSRobert Watson &newmbuf->m_pkthdr.label); 230195fab37eSRobert Watson } 230295fab37eSRobert Watson 230395fab37eSRobert Watson void 230495fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 230595fab37eSRobert Watson { 230695fab37eSRobert Watson 230795fab37eSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 230895fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 230995fab37eSRobert Watson } 231095fab37eSRobert Watson 231195fab37eSRobert Watson int 231295fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 231395fab37eSRobert Watson { 231495fab37eSRobert Watson int result; 231595fab37eSRobert Watson 231695fab37eSRobert Watson result = 1; 231795fab37eSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 231895fab37eSRobert Watson ipq, &ipq->ipq_label); 231995fab37eSRobert Watson 232095fab37eSRobert Watson return (result); 232195fab37eSRobert Watson } 232295fab37eSRobert Watson 232395fab37eSRobert Watson void 232495fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 232595fab37eSRobert Watson { 232695fab37eSRobert Watson 232795fab37eSRobert Watson MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 232895fab37eSRobert Watson &ipq->ipq_label); 232995fab37eSRobert Watson } 233095fab37eSRobert Watson 233195fab37eSRobert Watson void 233295fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 233395fab37eSRobert Watson { 233495fab37eSRobert Watson 233595fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 233695fab37eSRobert Watson &mbuf->m_pkthdr.label); 233795fab37eSRobert Watson } 233895fab37eSRobert Watson 233995fab37eSRobert Watson void 234095fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 234195fab37eSRobert Watson { 234295fab37eSRobert Watson 234395fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 234495fab37eSRobert Watson &mp->mnt_fslabel); 234595fab37eSRobert Watson } 234695fab37eSRobert Watson 234795fab37eSRobert Watson void 234895fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 234995fab37eSRobert Watson { 235095fab37eSRobert Watson 235195fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 235295fab37eSRobert Watson &mp->mnt_fslabel); 235395fab37eSRobert Watson } 235495fab37eSRobert Watson 235595fab37eSRobert Watson int 235695fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 235795fab37eSRobert Watson { 235895fab37eSRobert Watson int error; 235995fab37eSRobert Watson 236095fab37eSRobert Watson if (!mac_enforce_network) 236195fab37eSRobert Watson return (0); 236295fab37eSRobert Watson 236395fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 236495fab37eSRobert Watson &ifnet->if_label); 236595fab37eSRobert Watson 236695fab37eSRobert Watson return (error); 236795fab37eSRobert Watson } 236895fab37eSRobert Watson 236995fab37eSRobert Watson static int 237095fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 237195fab37eSRobert Watson { 237295fab37eSRobert Watson int error; 237395fab37eSRobert Watson 237495fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 237595fab37eSRobert Watson 237695fab37eSRobert Watson return (error); 237795fab37eSRobert Watson } 237895fab37eSRobert Watson 237995fab37eSRobert Watson int 238095fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 238195fab37eSRobert Watson { 238295fab37eSRobert Watson int error; 238395fab37eSRobert Watson 238495fab37eSRobert Watson if (!mac_enforce_process) 238595fab37eSRobert Watson return (0); 238695fab37eSRobert Watson 238795fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 238895fab37eSRobert Watson 238995fab37eSRobert Watson return (error); 239095fab37eSRobert Watson } 239195fab37eSRobert Watson 239295fab37eSRobert Watson int 239395fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 239495fab37eSRobert Watson { 239595fab37eSRobert Watson int error; 239695fab37eSRobert Watson 239795fab37eSRobert Watson if (!mac_enforce_network) 239895fab37eSRobert Watson return (0); 239995fab37eSRobert Watson 240095fab37eSRobert Watson KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 240195fab37eSRobert Watson if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 240295fab37eSRobert Watson printf("%s%d: not initialized\n", ifnet->if_name, 240395fab37eSRobert Watson ifnet->if_unit); 240495fab37eSRobert Watson 240595fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 240695fab37eSRobert Watson &mbuf->m_pkthdr.label); 240795fab37eSRobert Watson 240895fab37eSRobert Watson return (error); 240995fab37eSRobert Watson } 241095fab37eSRobert Watson 241195fab37eSRobert Watson int 241295fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 241395fab37eSRobert Watson { 241495fab37eSRobert Watson int error; 241595fab37eSRobert Watson 241695fab37eSRobert Watson if (!mac_enforce_fs) 241795fab37eSRobert Watson return (0); 241895fab37eSRobert Watson 241995fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 242095fab37eSRobert Watson 242195fab37eSRobert Watson return (error); 242295fab37eSRobert Watson } 242395fab37eSRobert Watson 242495fab37eSRobert Watson int 242595fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 242695fab37eSRobert Watson void *data) 242795fab37eSRobert Watson { 242895fab37eSRobert Watson int error; 242995fab37eSRobert Watson 243095fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 243195fab37eSRobert Watson 243295fab37eSRobert Watson return (error); 243395fab37eSRobert Watson } 243495fab37eSRobert Watson 243595fab37eSRobert Watson int 243695fab37eSRobert Watson mac_check_pipe_op(struct ucred *cred, struct pipe *pipe, int op) 243795fab37eSRobert Watson { 243895fab37eSRobert Watson int error; 243995fab37eSRobert Watson 244095fab37eSRobert Watson MAC_CHECK(check_pipe_op, cred, pipe, pipe->pipe_label, op); 244195fab37eSRobert Watson 244295fab37eSRobert Watson return (error); 244395fab37eSRobert Watson } 244495fab37eSRobert Watson 244595fab37eSRobert Watson static int 244695fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 244795fab37eSRobert Watson struct label *newlabel) 244895fab37eSRobert Watson { 244995fab37eSRobert Watson int error; 245095fab37eSRobert Watson 245195fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 245295fab37eSRobert Watson 245395fab37eSRobert Watson return (error); 245495fab37eSRobert Watson } 245595fab37eSRobert Watson 245695fab37eSRobert Watson int 245795fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 245895fab37eSRobert Watson { 245995fab37eSRobert Watson int error; 246095fab37eSRobert Watson 246195fab37eSRobert Watson if (!mac_enforce_process) 246295fab37eSRobert Watson return (0); 246395fab37eSRobert Watson 246495fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 246595fab37eSRobert Watson 246695fab37eSRobert Watson return (error); 246795fab37eSRobert Watson } 246895fab37eSRobert Watson 246995fab37eSRobert Watson int 247095fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 247195fab37eSRobert Watson { 247295fab37eSRobert Watson int error; 247395fab37eSRobert Watson 247495fab37eSRobert Watson if (!mac_enforce_process) 247595fab37eSRobert Watson return (0); 247695fab37eSRobert Watson 247795fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 247895fab37eSRobert Watson 247995fab37eSRobert Watson return (error); 248095fab37eSRobert Watson } 248195fab37eSRobert Watson 248295fab37eSRobert Watson int 248395fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 248495fab37eSRobert Watson { 248595fab37eSRobert Watson int error; 248695fab37eSRobert Watson 248795fab37eSRobert Watson if (!mac_enforce_process) 248895fab37eSRobert Watson return (0); 248995fab37eSRobert Watson 249095fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 249195fab37eSRobert Watson 249295fab37eSRobert Watson return (error); 249395fab37eSRobert Watson } 249495fab37eSRobert Watson 249595fab37eSRobert Watson int 249695fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 249795fab37eSRobert Watson struct sockaddr *sockaddr) 249895fab37eSRobert Watson { 249995fab37eSRobert Watson int error; 250095fab37eSRobert Watson 250195fab37eSRobert Watson if (!mac_enforce_socket) 250295fab37eSRobert Watson return (0); 250395fab37eSRobert Watson 250495fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 250595fab37eSRobert Watson sockaddr); 250695fab37eSRobert Watson 250795fab37eSRobert Watson return (error); 250895fab37eSRobert Watson } 250995fab37eSRobert Watson 251095fab37eSRobert Watson int 251195fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 251295fab37eSRobert Watson struct sockaddr *sockaddr) 251395fab37eSRobert Watson { 251495fab37eSRobert Watson int error; 251595fab37eSRobert Watson 251695fab37eSRobert Watson if (!mac_enforce_socket) 251795fab37eSRobert Watson return (0); 251895fab37eSRobert Watson 251995fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 252095fab37eSRobert Watson sockaddr); 252195fab37eSRobert Watson 252295fab37eSRobert Watson return (error); 252395fab37eSRobert Watson } 252495fab37eSRobert Watson 252595fab37eSRobert Watson int 252695fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 252795fab37eSRobert Watson { 252895fab37eSRobert Watson int error; 252995fab37eSRobert Watson 253095fab37eSRobert Watson if (!mac_enforce_socket) 253195fab37eSRobert Watson return (0); 253295fab37eSRobert Watson 253395fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 253495fab37eSRobert Watson return (error); 253595fab37eSRobert Watson } 253695fab37eSRobert Watson 253795fab37eSRobert Watson int 253895fab37eSRobert Watson mac_check_socket_receive(struct socket *socket, struct mbuf *mbuf) 253995fab37eSRobert Watson { 254095fab37eSRobert Watson int error; 254195fab37eSRobert Watson 254295fab37eSRobert Watson if (!mac_enforce_socket) 254395fab37eSRobert Watson return (0); 254495fab37eSRobert Watson 254595fab37eSRobert Watson MAC_CHECK(check_socket_receive, socket, &socket->so_label, mbuf, 254695fab37eSRobert Watson &mbuf->m_pkthdr.label); 254795fab37eSRobert Watson 254895fab37eSRobert Watson return (error); 254995fab37eSRobert Watson } 255095fab37eSRobert Watson 255195fab37eSRobert Watson static int 255295fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 255395fab37eSRobert Watson struct label *newlabel) 255495fab37eSRobert Watson { 255595fab37eSRobert Watson int error; 255695fab37eSRobert Watson 255795fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 255895fab37eSRobert Watson newlabel); 255995fab37eSRobert Watson 256095fab37eSRobert Watson return (error); 256195fab37eSRobert Watson } 256295fab37eSRobert Watson 256395fab37eSRobert Watson int 256495fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 256595fab37eSRobert Watson { 256695fab37eSRobert Watson int error; 256795fab37eSRobert Watson 256895fab37eSRobert Watson if (!mac_enforce_socket) 256995fab37eSRobert Watson return (0); 257095fab37eSRobert Watson 257195fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 257295fab37eSRobert Watson 257395fab37eSRobert Watson return (error); 257495fab37eSRobert Watson } 257595fab37eSRobert Watson 257695fab37eSRobert Watson int 257795fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 257895fab37eSRobert Watson struct ifnet *ifnet) 257995fab37eSRobert Watson { 258095fab37eSRobert Watson struct mac label; 258195fab37eSRobert Watson int error; 258295fab37eSRobert Watson 258395fab37eSRobert Watson error = mac_externalize(&ifnet->if_label, &label); 258495fab37eSRobert Watson if (error) 258595fab37eSRobert Watson return (error); 258695fab37eSRobert Watson 258795fab37eSRobert Watson return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label))); 258895fab37eSRobert Watson } 258995fab37eSRobert Watson 259095fab37eSRobert Watson int 259195fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 259295fab37eSRobert Watson struct ifnet *ifnet) 259395fab37eSRobert Watson { 259495fab37eSRobert Watson struct mac newlabel; 259595fab37eSRobert Watson struct label intlabel; 259695fab37eSRobert Watson int error; 259795fab37eSRobert Watson 259895fab37eSRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel)); 259995fab37eSRobert Watson if (error) 260095fab37eSRobert Watson return (error); 260195fab37eSRobert Watson 260295fab37eSRobert Watson error = mac_internalize(&intlabel, &newlabel); 260395fab37eSRobert Watson if (error) 260495fab37eSRobert Watson return (error); 260595fab37eSRobert Watson 260695fab37eSRobert Watson /* 260795fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 260895fab37eSRobert Watson * policies impose this check themselves if required by the 260995fab37eSRobert Watson * policy. Eventually, this should go away. 261095fab37eSRobert Watson */ 261195fab37eSRobert Watson error = suser_cred(cred, 0); 261295fab37eSRobert Watson if (error) 261395fab37eSRobert Watson goto out; 261495fab37eSRobert Watson 261595fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 261695fab37eSRobert Watson &intlabel); 261795fab37eSRobert Watson if (error) 261895fab37eSRobert Watson goto out; 261995fab37eSRobert Watson 262095fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 262195fab37eSRobert Watson 262295fab37eSRobert Watson out: 262395fab37eSRobert Watson mac_destroy_temp(&intlabel); 262495fab37eSRobert Watson return (error); 262595fab37eSRobert Watson } 262695fab37eSRobert Watson 262795fab37eSRobert Watson void 262895fab37eSRobert Watson mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 262995fab37eSRobert Watson { 263095fab37eSRobert Watson 263195fab37eSRobert Watson MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 263295fab37eSRobert Watson } 263395fab37eSRobert Watson 263495fab37eSRobert Watson void 263595fab37eSRobert Watson mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 263695fab37eSRobert Watson { 263795fab37eSRobert Watson 263895fab37eSRobert Watson MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 263995fab37eSRobert Watson } 264095fab37eSRobert Watson 264195fab37eSRobert Watson static int 264295fab37eSRobert Watson mac_stdcreatevnode_ea(struct vnode *vp) 264395fab37eSRobert Watson { 264495fab37eSRobert Watson int error; 264595fab37eSRobert Watson 264695fab37eSRobert Watson MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); 264795fab37eSRobert Watson 264895fab37eSRobert Watson return (error); 264995fab37eSRobert Watson } 265095fab37eSRobert Watson 265195fab37eSRobert Watson void 265295fab37eSRobert Watson mac_create_devfs_directory(char *dirname, int dirnamelen, 265395fab37eSRobert Watson struct devfs_dirent *de) 265495fab37eSRobert Watson { 265595fab37eSRobert Watson 265695fab37eSRobert Watson MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 265795fab37eSRobert Watson &de->de_label); 265895fab37eSRobert Watson } 265995fab37eSRobert Watson 266095fab37eSRobert Watson /* 266195fab37eSRobert Watson * When a new vnode is created, this call will initialize its label. 266295fab37eSRobert Watson */ 266395fab37eSRobert Watson void 266495fab37eSRobert Watson mac_create_vnode(struct ucred *cred, struct vnode *parent, 266595fab37eSRobert Watson struct vnode *child) 266695fab37eSRobert Watson { 266795fab37eSRobert Watson int error; 266895fab37eSRobert Watson 266995fab37eSRobert Watson ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); 267095fab37eSRobert Watson ASSERT_VOP_LOCKED(child, "mac_create_vnode"); 267195fab37eSRobert Watson 267295fab37eSRobert Watson error = vn_refreshlabel(parent, cred); 267395fab37eSRobert Watson if (error) { 267495fab37eSRobert Watson printf("mac_create_vnode: vn_refreshlabel returned %d\n", 267595fab37eSRobert Watson error); 267695fab37eSRobert Watson printf("mac_create_vnode: using old vnode label\n"); 267795fab37eSRobert Watson } 267895fab37eSRobert Watson 267995fab37eSRobert Watson MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, 268095fab37eSRobert Watson &child->v_label); 268195fab37eSRobert Watson } 268295fab37eSRobert Watson 268395fab37eSRobert Watson int 268495fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 268595fab37eSRobert Watson struct mac *extmac) 268695fab37eSRobert Watson { 268795fab37eSRobert Watson struct label intlabel; 268895fab37eSRobert Watson int error; 268995fab37eSRobert Watson 269095fab37eSRobert Watson error = mac_internalize(&intlabel, extmac); 269195fab37eSRobert Watson if (error) 269295fab37eSRobert Watson return (error); 269395fab37eSRobert Watson 269495fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 269595fab37eSRobert Watson if (error) { 269695fab37eSRobert Watson mac_destroy_temp(&intlabel); 269795fab37eSRobert Watson return (error); 269895fab37eSRobert Watson } 269995fab37eSRobert Watson 270095fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 270195fab37eSRobert Watson 270295fab37eSRobert Watson mac_destroy_temp(&intlabel); 270395fab37eSRobert Watson return (0); 270495fab37eSRobert Watson } 270595fab37eSRobert Watson 270695fab37eSRobert Watson int 270795fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 270895fab37eSRobert Watson { 270995fab37eSRobert Watson int error; 271095fab37eSRobert Watson 271195fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 271295fab37eSRobert Watson if (error) 271395fab37eSRobert Watson return (error); 271495fab37eSRobert Watson 271595fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 271695fab37eSRobert Watson 271795fab37eSRobert Watson return (0); 271895fab37eSRobert Watson } 271995fab37eSRobert Watson 272095fab37eSRobert Watson int 272195fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 272295fab37eSRobert Watson struct mac *extmac) 272395fab37eSRobert Watson { 272495fab37eSRobert Watson 272595fab37eSRobert Watson return (mac_externalize(&so->so_label, extmac)); 272695fab37eSRobert Watson } 272795fab37eSRobert Watson 272895fab37eSRobert Watson int 272995fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 273095fab37eSRobert Watson struct mac *extmac) 273195fab37eSRobert Watson { 273295fab37eSRobert Watson 273395fab37eSRobert Watson return (mac_externalize(&so->so_peerlabel, extmac)); 273495fab37eSRobert Watson } 273595fab37eSRobert Watson 273695fab37eSRobert Watson /* 273795fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 273895fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 273995fab37eSRobert Watson * extended attributes. 274095fab37eSRobert Watson */ 274195fab37eSRobert Watson int 274295fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 274395fab37eSRobert Watson { 274495fab37eSRobert Watson struct vnode *vp = ap->a_vp; 274595fab37eSRobert Watson struct label *intlabel = ap->a_label; 274695fab37eSRobert Watson struct mac extmac; 274795fab37eSRobert Watson int error; 274895fab37eSRobert Watson 274995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 275095fab37eSRobert Watson 275195fab37eSRobert Watson /* 275295fab37eSRobert Watson * XXX: Eventually call out to EA check/set calls here. 275395fab37eSRobert Watson * Be particularly careful to avoid race conditions, 275495fab37eSRobert Watson * consistency problems, and stability problems when 275595fab37eSRobert Watson * dealing with multiple EAs. In particular, we require 275695fab37eSRobert Watson * the ability to write multiple EAs on the same file in 275795fab37eSRobert Watson * a single transaction, which the current EA interface 275895fab37eSRobert Watson * does not provide. 275995fab37eSRobert Watson */ 276095fab37eSRobert Watson 276195fab37eSRobert Watson error = mac_externalize(intlabel, &extmac); 276295fab37eSRobert Watson if (error) 276395fab37eSRobert Watson return (error); 276495fab37eSRobert Watson 276595fab37eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, 276695fab37eSRobert Watson FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 276795fab37eSRobert Watson sizeof(extmac), (char *)&extmac, curthread); 276895fab37eSRobert Watson if (error) 276995fab37eSRobert Watson return (error); 277095fab37eSRobert Watson 277195fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 277295fab37eSRobert Watson 277395fab37eSRobert Watson vp->v_flag |= VCACHEDLABEL; 277495fab37eSRobert Watson 277595fab37eSRobert Watson return (0); 277695fab37eSRobert Watson } 277795fab37eSRobert Watson 277895fab37eSRobert Watson static int 277995fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 278095fab37eSRobert Watson { 278195fab37eSRobert Watson int error; 278295fab37eSRobert Watson 278395fab37eSRobert Watson if (vp->v_mount == NULL) { 278495fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 278595fab37eSRobert Watson if (vp->v_tag != VT_NON) 278695fab37eSRobert Watson printf("vn_setlabel: null v_mount with non-VT_NON\n"); 278795fab37eSRobert Watson return (EBADF); 278895fab37eSRobert Watson } 278995fab37eSRobert Watson 279095fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 279195fab37eSRobert Watson return (EOPNOTSUPP); 279295fab37eSRobert Watson 279395fab37eSRobert Watson /* 279495fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 279595fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 279695fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 279795fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 279895fab37eSRobert Watson */ 279995fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 280095fab37eSRobert Watson if (error) 280195fab37eSRobert Watson return (error); 280295fab37eSRobert Watson 280395fab37eSRobert Watson /* 280495fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 280595fab37eSRobert Watson * decisions about who is and is not able to modify labels 280695fab37eSRobert Watson * and protections on files. This might not be right. We can't 280795fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 280895fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 280995fab37eSRobert Watson */ 281095fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 281195fab37eSRobert Watson if (error) 281295fab37eSRobert Watson return (error); 281395fab37eSRobert Watson 281495fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 281595fab37eSRobert Watson if (error) 281695fab37eSRobert Watson return (error); 281795fab37eSRobert Watson 281895fab37eSRobert Watson return (0); 281995fab37eSRobert Watson } 282095fab37eSRobert Watson 282195fab37eSRobert Watson /* 282295fab37eSRobert Watson * MPSAFE 282395fab37eSRobert Watson */ 282495fab37eSRobert Watson int 282595fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 282695fab37eSRobert Watson { 282795fab37eSRobert Watson struct mac extmac; 282895fab37eSRobert Watson int error; 282995fab37eSRobert Watson 283095fab37eSRobert Watson error = mac_externalize(&td->td_ucred->cr_label, &extmac); 283195fab37eSRobert Watson if (error == 0) 283295fab37eSRobert Watson error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 283395fab37eSRobert Watson 283495fab37eSRobert Watson return (error); 283595fab37eSRobert Watson } 283695fab37eSRobert Watson 283795fab37eSRobert Watson /* 283895fab37eSRobert Watson * MPSAFE 283995fab37eSRobert Watson * 284095fab37eSRobert Watson * XXX: Needs to be re-written for proc locking. 284195fab37eSRobert Watson */ 284295fab37eSRobert Watson int 284395fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 284495fab37eSRobert Watson { 284595fab37eSRobert Watson struct ucred *newcred, *oldcred; 284695fab37eSRobert Watson struct proc *p; 284795fab37eSRobert Watson struct mac extmac; 284895fab37eSRobert Watson struct label intlabel; 284995fab37eSRobert Watson int error; 285095fab37eSRobert Watson 285195fab37eSRobert Watson error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 285295fab37eSRobert Watson if (error) 285395fab37eSRobert Watson return (error); 285495fab37eSRobert Watson 285595fab37eSRobert Watson error = mac_internalize(&intlabel, &extmac); 285695fab37eSRobert Watson if (error) 285795fab37eSRobert Watson return (error); 285895fab37eSRobert Watson 285995fab37eSRobert Watson newcred = crget(); 286095fab37eSRobert Watson 286195fab37eSRobert Watson p = td->td_proc; 286295fab37eSRobert Watson PROC_LOCK(p); 286395fab37eSRobert Watson oldcred = p->p_ucred; 286495fab37eSRobert Watson 286595fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 286695fab37eSRobert Watson if (error) { 286795fab37eSRobert Watson PROC_UNLOCK(p); 286895fab37eSRobert Watson mac_destroy_temp(&intlabel); 286995fab37eSRobert Watson crfree(newcred); 287095fab37eSRobert Watson return (error); 287195fab37eSRobert Watson } 287295fab37eSRobert Watson 287395fab37eSRobert Watson setsugid(p); 287495fab37eSRobert Watson crcopy(newcred, oldcred); 287595fab37eSRobert Watson PROC_UNLOCK(p); 287695fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 287795fab37eSRobert Watson 287895fab37eSRobert Watson PROC_LOCK(p); 287995fab37eSRobert Watson p->p_ucred = newcred; 288095fab37eSRobert Watson PROC_UNLOCK(p); 288195fab37eSRobert Watson crfree(oldcred); 288295fab37eSRobert Watson mac_destroy_temp(&intlabel); 288395fab37eSRobert Watson return (0); 288495fab37eSRobert Watson } 288595fab37eSRobert Watson 288695fab37eSRobert Watson /* 288795fab37eSRobert Watson * MPSAFE 288895fab37eSRobert Watson */ 288995fab37eSRobert Watson int 289095fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 289195fab37eSRobert Watson { 289295fab37eSRobert Watson struct file *fp; 289395fab37eSRobert Watson struct mac extmac; 289495fab37eSRobert Watson struct vnode *vp; 289595fab37eSRobert Watson struct pipe *pipe; 289695fab37eSRobert Watson int error; 289795fab37eSRobert Watson 289895fab37eSRobert Watson mtx_lock(&Giant); 289995fab37eSRobert Watson 290095fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 290195fab37eSRobert Watson if (error) 290295fab37eSRobert Watson goto out; 290395fab37eSRobert Watson 290495fab37eSRobert Watson switch (fp->f_type) { 290595fab37eSRobert Watson case DTYPE_FIFO: 290695fab37eSRobert Watson case DTYPE_VNODE: 290795fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 290895fab37eSRobert Watson 290995fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 291095fab37eSRobert Watson error = vn_refreshlabel(vp, td->td_ucred); 291195fab37eSRobert Watson if (error == 0) 291295fab37eSRobert Watson error = mac_externalize(&vp->v_label, &extmac); 291395fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 291495fab37eSRobert Watson break; 291595fab37eSRobert Watson case DTYPE_PIPE: 291695fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 291795fab37eSRobert Watson error = mac_externalize(pipe->pipe_label, &extmac); 291895fab37eSRobert Watson break; 291995fab37eSRobert Watson default: 292095fab37eSRobert Watson error = EINVAL; 292195fab37eSRobert Watson } 292295fab37eSRobert Watson 292395fab37eSRobert Watson if (error == 0) 292495fab37eSRobert Watson error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 292595fab37eSRobert Watson 292695fab37eSRobert Watson fdrop(fp, td); 292795fab37eSRobert Watson 292895fab37eSRobert Watson out: 292995fab37eSRobert Watson mtx_unlock(&Giant); 293095fab37eSRobert Watson return (error); 293195fab37eSRobert Watson } 293295fab37eSRobert Watson 293395fab37eSRobert Watson /* 293495fab37eSRobert Watson * MPSAFE 293595fab37eSRobert Watson */ 293695fab37eSRobert Watson int 293795fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 293895fab37eSRobert Watson { 293995fab37eSRobert Watson struct nameidata nd; 294095fab37eSRobert Watson struct mac extmac; 294195fab37eSRobert Watson int error; 294295fab37eSRobert Watson 294395fab37eSRobert Watson mtx_lock(&Giant); 294495fab37eSRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 294595fab37eSRobert Watson SCARG(uap, path_p), td); 294695fab37eSRobert Watson error = namei(&nd); 294795fab37eSRobert Watson if (error) 294895fab37eSRobert Watson goto out; 294995fab37eSRobert Watson 295095fab37eSRobert Watson error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 295195fab37eSRobert Watson if (error == 0) 295295fab37eSRobert Watson error = mac_externalize(&nd.ni_vp->v_label, &extmac); 295395fab37eSRobert Watson NDFREE(&nd, 0); 295495fab37eSRobert Watson if (error) 295595fab37eSRobert Watson goto out; 295695fab37eSRobert Watson 295795fab37eSRobert Watson error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 295895fab37eSRobert Watson 295995fab37eSRobert Watson out: 296095fab37eSRobert Watson mtx_unlock(&Giant); 296195fab37eSRobert Watson return (error); 296295fab37eSRobert Watson } 296395fab37eSRobert Watson 296495fab37eSRobert Watson /* 296595fab37eSRobert Watson * MPSAFE 296695fab37eSRobert Watson */ 296795fab37eSRobert Watson int 296895fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 296995fab37eSRobert Watson { 297095fab37eSRobert Watson struct file *fp; 297195fab37eSRobert Watson struct mac extmac; 297295fab37eSRobert Watson struct label intlabel; 297395fab37eSRobert Watson struct mount *mp; 297495fab37eSRobert Watson struct vnode *vp; 297595fab37eSRobert Watson struct pipe *pipe; 297695fab37eSRobert Watson int error; 297795fab37eSRobert Watson 297895fab37eSRobert Watson mtx_lock(&Giant); 297995fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 298095fab37eSRobert Watson if (error) 298195fab37eSRobert Watson goto out1; 298295fab37eSRobert Watson 298395fab37eSRobert Watson error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 298495fab37eSRobert Watson if (error) 298595fab37eSRobert Watson goto out2; 298695fab37eSRobert Watson 298795fab37eSRobert Watson error = mac_internalize(&intlabel, &extmac); 298895fab37eSRobert Watson if (error) 298995fab37eSRobert Watson goto out2; 299095fab37eSRobert Watson 299195fab37eSRobert Watson switch (fp->f_type) { 299295fab37eSRobert Watson case DTYPE_FIFO: 299395fab37eSRobert Watson case DTYPE_VNODE: 299495fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 299595fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 299695fab37eSRobert Watson if (error != 0) 299795fab37eSRobert Watson break; 299895fab37eSRobert Watson 299995fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 300095fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 300195fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 300295fab37eSRobert Watson vn_finished_write(mp); 300395fab37eSRobert Watson mac_destroy_temp(&intlabel); 300495fab37eSRobert Watson break; 300595fab37eSRobert Watson case DTYPE_PIPE: 300695fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 300795fab37eSRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel); 300895fab37eSRobert Watson break; 300995fab37eSRobert Watson default: 301095fab37eSRobert Watson error = EINVAL; 301195fab37eSRobert Watson } 301295fab37eSRobert Watson 301395fab37eSRobert Watson out2: 301495fab37eSRobert Watson fdrop(fp, td); 301595fab37eSRobert Watson out1: 301695fab37eSRobert Watson mtx_unlock(&Giant); 301795fab37eSRobert Watson return (error); 301895fab37eSRobert Watson } 301995fab37eSRobert Watson 302095fab37eSRobert Watson /* 302195fab37eSRobert Watson * MPSAFE 302295fab37eSRobert Watson */ 302395fab37eSRobert Watson int 302495fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 302595fab37eSRobert Watson { 302695fab37eSRobert Watson struct nameidata nd; 302795fab37eSRobert Watson struct mac extmac; 302895fab37eSRobert Watson struct label intlabel; 302995fab37eSRobert Watson struct mount *mp; 303095fab37eSRobert Watson int error; 303195fab37eSRobert Watson 303295fab37eSRobert Watson mtx_lock(&Giant); 303395fab37eSRobert Watson 303495fab37eSRobert Watson error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 303595fab37eSRobert Watson if (error) 303695fab37eSRobert Watson goto out; 303795fab37eSRobert Watson 303895fab37eSRobert Watson error = mac_internalize(&intlabel, &extmac); 303995fab37eSRobert Watson if (error) 304095fab37eSRobert Watson goto out; 304195fab37eSRobert Watson 304295fab37eSRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 304395fab37eSRobert Watson SCARG(uap, path_p), td); 304495fab37eSRobert Watson error = namei(&nd); 304595fab37eSRobert Watson if (error) 304695fab37eSRobert Watson goto out2; 304795fab37eSRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 304895fab37eSRobert Watson if (error) 304995fab37eSRobert Watson goto out2; 305095fab37eSRobert Watson 305195fab37eSRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred); 305295fab37eSRobert Watson 305395fab37eSRobert Watson vn_finished_write(mp); 305495fab37eSRobert Watson out2: 305595fab37eSRobert Watson mac_destroy_temp(&intlabel); 305695fab37eSRobert Watson NDFREE(&nd, 0); 305795fab37eSRobert Watson out: 305895fab37eSRobert Watson mtx_unlock(&Giant); 305995fab37eSRobert Watson return (error); 306095fab37eSRobert Watson } 306195fab37eSRobert Watson 306295fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 306395fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 306495fab37eSRobert Watson 306595fab37eSRobert Watson #else /* !MAC */ 30667bc82500SRobert Watson 30677bc82500SRobert Watson int 30687bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 30697bc82500SRobert Watson { 30707bc82500SRobert Watson 30717bc82500SRobert Watson return (ENOSYS); 30727bc82500SRobert Watson } 30737bc82500SRobert Watson 30747bc82500SRobert Watson int 30757bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 30767bc82500SRobert Watson { 30777bc82500SRobert Watson 30787bc82500SRobert Watson return (ENOSYS); 30797bc82500SRobert Watson } 30807bc82500SRobert Watson 30817bc82500SRobert Watson int 30827bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 30837bc82500SRobert Watson { 30847bc82500SRobert Watson 30857bc82500SRobert Watson return (ENOSYS); 30867bc82500SRobert Watson } 30877bc82500SRobert Watson 30887bc82500SRobert Watson int 30897bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 30907bc82500SRobert Watson { 30917bc82500SRobert Watson 30927bc82500SRobert Watson return (ENOSYS); 30937bc82500SRobert Watson } 30947bc82500SRobert Watson 30957bc82500SRobert Watson int 30967bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 30977bc82500SRobert Watson { 30987bc82500SRobert Watson 30997bc82500SRobert Watson return (ENOSYS); 31007bc82500SRobert Watson } 31017bc82500SRobert Watson 31027bc82500SRobert Watson int 31037bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 31047bc82500SRobert Watson { 31057bc82500SRobert Watson 31067bc82500SRobert Watson return (ENOSYS); 31077bc82500SRobert Watson } 310895fab37eSRobert Watson 310995fab37eSRobert Watson #endif /* !MAC */ 3110