17bc82500SRobert Watson /*- 27bc82500SRobert Watson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 37bc82500SRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 42d3db0b8SRobert Watson * Copyright (c) 2001, 2002, 2003 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 * 106201265bSRobert Watson * This software was developed for the FreeBSD Project in part by Network 116201265bSRobert Watson * Associates Laboratories, the Security Research Division of Network 126201265bSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 136201265bSRobert Watson * as part of the DARPA 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 * 247bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 257bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 267bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 277bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 287bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 297bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 307bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 317bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 327bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 337bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 347bc82500SRobert Watson * SUCH DAMAGE. 357bc82500SRobert Watson */ 36677b542eSDavid E. O'Brien 377bc82500SRobert Watson /* 387bc82500SRobert Watson * Framework for extensible kernel access control. Kernel and userland 397bc82500SRobert Watson * interface to the framework, policy registration and composition. 407bc82500SRobert Watson */ 417bc82500SRobert Watson 42677b542eSDavid E. O'Brien #include <sys/cdefs.h> 43677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 44677b542eSDavid E. O'Brien 457bc82500SRobert Watson #include "opt_mac.h" 46328048bcSPoul-Henning Kamp #include "opt_devfs.h" 47f9d0d524SRobert Watson 487bc82500SRobert Watson #include <sys/param.h> 49a96acd1aSRobert Watson #include <sys/condvar.h> 5095fab37eSRobert Watson #include <sys/extattr.h> 51670cb89bSRobert Watson #include <sys/imgact.h> 5295fab37eSRobert Watson #include <sys/kernel.h> 5395fab37eSRobert Watson #include <sys/lock.h> 54b656366bSBruce Evans #include <sys/malloc.h> 5595fab37eSRobert Watson #include <sys/mutex.h> 5695fab37eSRobert Watson #include <sys/mac.h> 577ba28492SRobert Watson #include <sys/module.h> 5895fab37eSRobert Watson #include <sys/proc.h> 59f51e5803SRobert Watson #include <sys/sbuf.h> 6095fab37eSRobert Watson #include <sys/systm.h> 617bc82500SRobert Watson #include <sys/sysproto.h> 627bc82500SRobert Watson #include <sys/sysent.h> 6395fab37eSRobert Watson #include <sys/vnode.h> 6495fab37eSRobert Watson #include <sys/mount.h> 6595fab37eSRobert Watson #include <sys/file.h> 6695fab37eSRobert Watson #include <sys/namei.h> 6795fab37eSRobert Watson #include <sys/socket.h> 6895fab37eSRobert Watson #include <sys/pipe.h> 6995fab37eSRobert Watson #include <sys/socketvar.h> 7095fab37eSRobert Watson #include <sys/sysctl.h> 7195fab37eSRobert Watson 7295fab37eSRobert Watson #include <vm/vm.h> 7395fab37eSRobert Watson #include <vm/pmap.h> 7495fab37eSRobert Watson #include <vm/vm_map.h> 7595fab37eSRobert Watson #include <vm/vm_object.h> 7695fab37eSRobert Watson 7795fab37eSRobert Watson #include <sys/mac_policy.h> 7895fab37eSRobert Watson 7995fab37eSRobert Watson #include <fs/devfs/devfs.h> 8095fab37eSRobert Watson 8195fab37eSRobert Watson #include <net/bpfdesc.h> 8295fab37eSRobert Watson #include <net/if.h> 8395fab37eSRobert Watson #include <net/if_var.h> 8495fab37eSRobert Watson 8595fab37eSRobert Watson #include <netinet/in.h> 8695fab37eSRobert Watson #include <netinet/ip_var.h> 8795fab37eSRobert Watson 8895fab37eSRobert Watson #ifdef MAC 8995fab37eSRobert Watson 907ba28492SRobert Watson /* 917ba28492SRobert Watson * Declare that the kernel provides MAC support, version 1. This permits 927ba28492SRobert Watson * modules to refuse to be loaded if the necessary support isn't present, 937ba28492SRobert Watson * even if it's pre-boot. 947ba28492SRobert Watson */ 957ba28492SRobert Watson MODULE_VERSION(kernel_mac_support, 1); 967ba28492SRobert Watson 9795fab37eSRobert Watson SYSCTL_DECL(_security); 9895fab37eSRobert Watson 9995fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 10095fab37eSRobert Watson "TrustedBSD MAC policy controls"); 101b2f0927aSRobert Watson 102b2aef571SRobert Watson #if MAC_MAX_SLOTS > 32 103b2aef571SRobert Watson #error "MAC_MAX_SLOTS too large" 10495fab37eSRobert Watson #endif 105a13c67daSRobert Watson 106b2aef571SRobert Watson static unsigned int mac_max_slots = MAC_MAX_SLOTS; 107b2aef571SRobert Watson static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 108b2aef571SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 109b2aef571SRobert Watson &mac_max_slots, 0, ""); 11095fab37eSRobert Watson 111a67fe518SRobert Watson /* 112a67fe518SRobert Watson * Has the kernel started generating labeled objects yet? All read/write 113a67fe518SRobert Watson * access to this variable is serialized during the boot process. Following 114a67fe518SRobert Watson * the end of serialization, we don't update this flag; no locking. 115a67fe518SRobert Watson */ 11695fab37eSRobert Watson static int mac_late = 0; 11795fab37eSRobert Watson 118763bbd2fSRobert Watson /* 119763bbd2fSRobert Watson * Warn about EA transactions only the first time they happen. 120763bbd2fSRobert Watson * Weak coherency, no locking. 121763bbd2fSRobert Watson */ 122763bbd2fSRobert Watson static int ea_warn_once = 0; 123763bbd2fSRobert Watson 124225bff6fSRobert Watson /* 125225bff6fSRobert Watson * Flag to indicate whether or not we should allocate label storage for 126225bff6fSRobert Watson * new mbufs. Since most dynamic policies we currently work with don't 127225bff6fSRobert Watson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 128225bff6fSRobert Watson * unless specifically notified of interest. One result of this is 129225bff6fSRobert Watson * that if a dynamically loaded policy requests mbuf labels, it must 130225bff6fSRobert Watson * be able to deal with a NULL label being returned on any mbufs that 131225bff6fSRobert Watson * were already in flight when the policy was loaded. Since the policy 132225bff6fSRobert Watson * already has to deal with uninitialized labels, this probably won't 133225bff6fSRobert Watson * be a problem. Note: currently no locking. Will this be a problem? 134225bff6fSRobert Watson */ 13519c3e120SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 136225bff6fSRobert Watson static int mac_labelmbufs = 0; 137225bff6fSRobert Watson #endif 138225bff6fSRobert Watson 13995fab37eSRobert Watson static int mac_enforce_fs = 1; 14095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 14195fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 14295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 14395fab37eSRobert Watson 144a3df768bSRobert Watson static int mac_enforce_kld = 1; 145a3df768bSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW, 146a3df768bSRobert Watson &mac_enforce_kld, 0, "Enforce MAC policy on kld operations"); 147a3df768bSRobert Watson TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld); 148a3df768bSRobert Watson 14995fab37eSRobert Watson static int mac_enforce_network = 1; 15095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 15195fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 15295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 15395fab37eSRobert Watson 154b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 155b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 156b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 157c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 158b88c98f6SRobert Watson 15995fab37eSRobert Watson static int mac_enforce_process = 1; 16095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 16195fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 16295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 16395fab37eSRobert Watson 16495fab37eSRobert Watson static int mac_enforce_socket = 1; 16595fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 16695fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 16795fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 16895fab37eSRobert Watson 1699e913ebdSRobert Watson static int mac_enforce_system = 1; 1709e913ebdSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 1719e913ebdSRobert Watson &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 1729e913ebdSRobert Watson TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 173d3fc69eeSRobert Watson 174ca7850c3SRobert Watson static int mac_enforce_vm = 1; 175ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 176ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 177c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 178ca7850c3SRobert Watson 179c0f39905SRobert Watson static int mac_mmap_revocation = 1; 180c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 181c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 182c0f39905SRobert Watson "relabel"); 18399fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 18495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 18595fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 18695fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 18795fab37eSRobert Watson 188f050add5SRobert Watson #ifdef MAC_DEBUG 1896be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1906be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1916be0c25eSRobert Watson 1926be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1936be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1946be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1956be0c25eSRobert Watson "when label is corrupted."); 1966be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1976be0c25eSRobert Watson &mac_debug_label_fallback); 1986be0c25eSRobert Watson 199b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 200b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 201b2f0927aSRobert Watson 20295fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 20395fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 2042555374cSRobert Watson nmacipqs, nmacpipes, nmacprocs; 205b2f0927aSRobert Watson 2068d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_INC(x) atomic_add_int(x, 1); 2078d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_DEC(x) atomic_subtract_int(x, 1); 2088d8d5ea8SRobert Watson 209b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 21095fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 211b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 21295fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 213b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 21495fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 215b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 21695fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 217b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 21895fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 219b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 22095fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 221b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 22295fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 2232555374cSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD, 2242555374cSRobert Watson &nmacprocs, 0, "number of procs in use"); 225b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 22695fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 227b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 22895fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 229b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 23095fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 231b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 23295fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 2338d8d5ea8SRobert Watson #else 2348d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_INC(x) 2358d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_DEC(x) 236f050add5SRobert Watson #endif 23795fab37eSRobert Watson 23895fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 23995fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 24095fab37eSRobert Watson 241e183f80eSRobert Watson static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 242e183f80eSRobert Watson struct vnode *vp, int *prot); 24395fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 24495fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 24595fab37eSRobert Watson 24683985c26SRobert Watson static void mac_destroy_socket_label(struct label *label); 24783985c26SRobert Watson 248763bbd2fSRobert Watson static int mac_setlabel_vnode_extattr(struct ucred *cred, 249763bbd2fSRobert Watson struct vnode *vp, struct label *intlabel); 250763bbd2fSRobert Watson 25195fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 252f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 25395fab37eSRobert Watson 25495fab37eSRobert Watson /* 25541a17fe3SRobert Watson * mac_static_policy_list holds a list of policy modules that are not 25641a17fe3SRobert Watson * loaded while the system is "live", and cannot be unloaded. These 25741a17fe3SRobert Watson * policies can be invoked without holding the busy count. 25841a17fe3SRobert Watson * 25941a17fe3SRobert Watson * mac_policy_list stores the list of dynamic policies. A busy count is 260a96acd1aSRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count 26141a17fe3SRobert Watson * is protected by mac_policy_mtx; the list may be modified only 262a96acd1aSRobert Watson * while the busy count is 0, requiring that the lock be held to 263a96acd1aSRobert Watson * prevent new references to the list from being acquired. For almost 264a96acd1aSRobert Watson * all operations, incrementing the busy count is sufficient to 265a96acd1aSRobert Watson * guarantee consistency, as the list cannot be modified while the 266a96acd1aSRobert Watson * busy count is elevated. For a few special operations involving a 26741a17fe3SRobert Watson * change to the list of active policies, the mtx itself must be held. 26841a17fe3SRobert Watson * A condition variable, mac_policy_cv, is used to signal potential 26941a17fe3SRobert Watson * exclusive consumers that they should try to acquire the lock if a 27041a17fe3SRobert Watson * first attempt at exclusive access fails. 27195fab37eSRobert Watson */ 27241a17fe3SRobert Watson static struct mtx mac_policy_mtx; 27341a17fe3SRobert Watson static struct cv mac_policy_cv; 27441a17fe3SRobert Watson static int mac_policy_count; 27595fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 27641a17fe3SRobert Watson static LIST_HEAD(, mac_policy_conf) mac_static_policy_list; 277a96acd1aSRobert Watson 278a96acd1aSRobert Watson /* 27926306795SJohn Baldwin * We manually invoke WITNESS_WARN() to allow Witness to generate 280a96acd1aSRobert Watson * warnings even if we don't end up ever triggering the wait at 281a96acd1aSRobert Watson * run-time. The consumer of the exclusive interface must not hold 282a96acd1aSRobert Watson * any locks (other than potentially Giant) since we may sleep for 283a96acd1aSRobert Watson * long (potentially indefinite) periods of time waiting for the 284a96acd1aSRobert Watson * framework to become quiescent so that a policy list change may 285a96acd1aSRobert Watson * be made. 286a96acd1aSRobert Watson */ 28741a17fe3SRobert Watson static __inline void 28841a17fe3SRobert Watson mac_policy_grab_exclusive(void) 28941a17fe3SRobert Watson { 29041a17fe3SRobert Watson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 29141a17fe3SRobert Watson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 29241a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 29341a17fe3SRobert Watson while (mac_policy_count != 0) 29441a17fe3SRobert Watson cv_wait(&mac_policy_cv, &mac_policy_mtx); 29541a17fe3SRobert Watson } 29695fab37eSRobert Watson 29741a17fe3SRobert Watson static __inline void 29841a17fe3SRobert Watson mac_policy_assert_exclusive(void) 29941a17fe3SRobert Watson { 30041a17fe3SRobert Watson mtx_assert(&mac_policy_mtx, MA_OWNED); 30141a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 30241a17fe3SRobert Watson ("mac_policy_assert_exclusive(): not exclusive")); 30341a17fe3SRobert Watson } 304225bff6fSRobert Watson 30541a17fe3SRobert Watson static __inline void 30641a17fe3SRobert Watson mac_policy_release_exclusive(void) 30741a17fe3SRobert Watson { 30895fab37eSRobert Watson 30941a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 31041a17fe3SRobert Watson ("mac_policy_release_exclusive(): not exclusive")); 31141a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 31241a17fe3SRobert Watson cv_signal(&mac_policy_cv); 31341a17fe3SRobert Watson } 31441a17fe3SRobert Watson 31541a17fe3SRobert Watson static __inline void 31641a17fe3SRobert Watson mac_policy_list_busy(void) 31741a17fe3SRobert Watson { 31841a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 31941a17fe3SRobert Watson mac_policy_count++; 32041a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 32141a17fe3SRobert Watson } 32241a17fe3SRobert Watson 32341a17fe3SRobert Watson static __inline int 32441a17fe3SRobert Watson mac_policy_list_conditional_busy(void) 32541a17fe3SRobert Watson { 32641a17fe3SRobert Watson int ret; 32741a17fe3SRobert Watson 32841a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 32941a17fe3SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 33041a17fe3SRobert Watson mac_policy_count++; 33141a17fe3SRobert Watson ret = 1; 33241a17fe3SRobert Watson } else 33341a17fe3SRobert Watson ret = 0; 33441a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 33541a17fe3SRobert Watson return (ret); 33641a17fe3SRobert Watson } 33741a17fe3SRobert Watson 33841a17fe3SRobert Watson static __inline void 33941a17fe3SRobert Watson mac_policy_list_unbusy(void) 34041a17fe3SRobert Watson { 34141a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 34241a17fe3SRobert Watson mac_policy_count--; 34341a17fe3SRobert Watson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 34441a17fe3SRobert Watson if (mac_policy_count == 0) 34541a17fe3SRobert Watson cv_signal(&mac_policy_cv); 34641a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 34741a17fe3SRobert Watson } 34895fab37eSRobert Watson 34995fab37eSRobert Watson /* 35095fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 35195fab37eSRobert Watson * module list and checking with each as to how it feels about the 35295fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 35395fab37eSRobert Watson * of the caller. 35495fab37eSRobert Watson */ 35595fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 35695fab37eSRobert Watson struct mac_policy_conf *mpc; \ 35741a17fe3SRobert Watson int entrycount; \ 35895fab37eSRobert Watson \ 35995fab37eSRobert Watson error = 0; \ 36041a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 36141a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 3629e7bf51cSRobert Watson error = mac_error_select( \ 36341a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 36441a17fe3SRobert Watson error); \ 36541a17fe3SRobert Watson } \ 36641a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 36795fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 36895fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 3699e7bf51cSRobert Watson error = mac_error_select( \ 37095fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 37195fab37eSRobert Watson error); \ 37295fab37eSRobert Watson } \ 37341a17fe3SRobert Watson mac_policy_list_unbusy(); \ 37441a17fe3SRobert Watson } \ 37595fab37eSRobert Watson } while (0) 37695fab37eSRobert Watson 37795fab37eSRobert Watson /* 37895fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 37995fab37eSRobert Watson * the module list, invoking each instance of the operation, and 38095fab37eSRobert Watson * combining the results using the passed C operator. Note that it 38195fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 38295fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 38395fab37eSRobert Watson * a meaningful result. 38495fab37eSRobert Watson */ 38595fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 38695fab37eSRobert Watson struct mac_policy_conf *mpc; \ 38741a17fe3SRobert Watson int entrycount; \ 38895fab37eSRobert Watson \ 38941a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 39095fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 39195fab37eSRobert Watson result = result composition \ 39295fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 39395fab37eSRobert Watson } \ 39441a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 39541a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 39641a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 39741a17fe3SRobert Watson result = result composition \ 39841a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## operation \ 39941a17fe3SRobert Watson (args); \ 40041a17fe3SRobert Watson } \ 40141a17fe3SRobert Watson mac_policy_list_unbusy(); \ 40241a17fe3SRobert Watson } \ 40395fab37eSRobert Watson } while (0) 40495fab37eSRobert Watson 405f7b951a8SRobert Watson #define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 406f7b951a8SRobert Watson outbuflen) do { \ 407f51e5803SRobert Watson int claimed, first, ignorenotfound, savedlen; \ 408f51e5803SRobert Watson char *element_name, *element_temp; \ 409f51e5803SRobert Watson struct sbuf sb; \ 410f7b951a8SRobert Watson \ 411f7b951a8SRobert Watson error = 0; \ 412f7b951a8SRobert Watson first = 1; \ 413f51e5803SRobert Watson sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN); \ 414f51e5803SRobert Watson element_temp = elementlist; \ 415f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 416f7b951a8SRobert Watson if (element_name[0] == '?') { \ 417f7b951a8SRobert Watson element_name++; \ 418f7b951a8SRobert Watson ignorenotfound = 1; \ 419f7b951a8SRobert Watson } else \ 420f7b951a8SRobert Watson ignorenotfound = 0; \ 421f51e5803SRobert Watson savedlen = sbuf_len(&sb); \ 422f7b951a8SRobert Watson if (first) { \ 423f51e5803SRobert Watson error = sbuf_printf(&sb, "%s/", element_name); \ 424f7b951a8SRobert Watson first = 0; \ 425f7b951a8SRobert Watson } else \ 426f51e5803SRobert Watson error = sbuf_printf(&sb, ",%s/", element_name); \ 427f51e5803SRobert Watson if (error == -1) { \ 428f51e5803SRobert Watson error = EINVAL; /* XXX: E2BIG? */ \ 429f7b951a8SRobert Watson break; \ 430f7b951a8SRobert Watson } \ 431f51e5803SRobert Watson claimed = 0; \ 432f7b951a8SRobert Watson MAC_CHECK(externalize_ ## type, label, element_name, \ 433f51e5803SRobert Watson &sb, &claimed); \ 434f7b951a8SRobert Watson if (error) \ 435f7b951a8SRobert Watson break; \ 436f51e5803SRobert Watson if (claimed == 0 && ignorenotfound) { \ 437f51e5803SRobert Watson /* Revert last label name. */ \ 438f51e5803SRobert Watson sbuf_setpos(&sb, savedlen); \ 439f51e5803SRobert Watson } else if (claimed != 1) { \ 440f51e5803SRobert Watson error = EINVAL; /* XXX: ENOLABEL? */ \ 441f7b951a8SRobert Watson break; \ 442f7b951a8SRobert Watson } \ 443f7b951a8SRobert Watson } \ 444f51e5803SRobert Watson sbuf_finish(&sb); \ 445f7b951a8SRobert Watson } while (0) 446f7b951a8SRobert Watson 447f7b951a8SRobert Watson #define MAC_INTERNALIZE(type, label, instring) do { \ 448f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 449f7b951a8SRobert Watson int claimed; \ 450f7b951a8SRobert Watson \ 451f7b951a8SRobert Watson error = 0; \ 452f7b951a8SRobert Watson element = instring; \ 453f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 454f7b951a8SRobert Watson element_data = element_name; \ 455f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 456f7b951a8SRobert Watson if (element_data == NULL) { \ 457f7b951a8SRobert Watson error = EINVAL; \ 458f7b951a8SRobert Watson break; \ 459f7b951a8SRobert Watson } \ 460f7b951a8SRobert Watson claimed = 0; \ 461f7b951a8SRobert Watson MAC_CHECK(internalize_ ## type, label, element_name, \ 462f7b951a8SRobert Watson element_data, &claimed); \ 463f7b951a8SRobert Watson if (error) \ 464f7b951a8SRobert Watson break; \ 465f7b951a8SRobert Watson if (claimed != 1) { \ 466f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 467f7b951a8SRobert Watson error = EINVAL; \ 468f7b951a8SRobert Watson break; \ 469f7b951a8SRobert Watson } \ 470f7b951a8SRobert Watson } \ 471f7b951a8SRobert Watson } while (0) 472f7b951a8SRobert Watson 47395fab37eSRobert Watson /* 47495fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 47595fab37eSRobert Watson * module list and invoking that operation for each policy. 47695fab37eSRobert Watson */ 47795fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 47895fab37eSRobert Watson struct mac_policy_conf *mpc; \ 47941a17fe3SRobert Watson int entrycount; \ 48095fab37eSRobert Watson \ 48141a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 48241a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 48341a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 48441a17fe3SRobert Watson } \ 48541a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 48695fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 48795fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 48895fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 48995fab37eSRobert Watson } \ 49041a17fe3SRobert Watson mac_policy_list_unbusy(); \ 49141a17fe3SRobert Watson } \ 49295fab37eSRobert Watson } while (0) 49395fab37eSRobert Watson 49495fab37eSRobert Watson /* 49595fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 49695fab37eSRobert Watson */ 49795fab37eSRobert Watson static void 49895fab37eSRobert Watson mac_init(void) 49995fab37eSRobert Watson { 50095fab37eSRobert Watson 50141a17fe3SRobert Watson LIST_INIT(&mac_static_policy_list); 50295fab37eSRobert Watson LIST_INIT(&mac_policy_list); 50341a17fe3SRobert Watson 50441a17fe3SRobert Watson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 50541a17fe3SRobert Watson cv_init(&mac_policy_cv, "mac_policy_cv"); 50695fab37eSRobert Watson } 50795fab37eSRobert Watson 50895fab37eSRobert Watson /* 50995fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 51095fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 51195fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 51295fab37eSRobert Watson */ 51395fab37eSRobert Watson static void 51495fab37eSRobert Watson mac_late_init(void) 51595fab37eSRobert Watson { 51695fab37eSRobert Watson 51795fab37eSRobert Watson mac_late = 1; 51895fab37eSRobert Watson } 51995fab37eSRobert Watson 52095fab37eSRobert Watson /* 521225bff6fSRobert Watson * After the policy list has changed, walk the list to update any global 52219c3e120SRobert Watson * flags. Currently, we support only one flag, and it's conditionally 52319c3e120SRobert Watson * defined; as a result, the entire function is conditional. Eventually, 52419c3e120SRobert Watson * the #else case might also iterate across the policies. 525225bff6fSRobert Watson */ 526225bff6fSRobert Watson static void 527225bff6fSRobert Watson mac_policy_updateflags(void) 528225bff6fSRobert Watson { 529225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 53019c3e120SRobert Watson struct mac_policy_conf *tmpc; 531225bff6fSRobert Watson int labelmbufs; 532225bff6fSRobert Watson 53341a17fe3SRobert Watson mac_policy_assert_exclusive(); 534225bff6fSRobert Watson 535225bff6fSRobert Watson labelmbufs = 0; 53641a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 53741a17fe3SRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 53841a17fe3SRobert Watson labelmbufs++; 53941a17fe3SRobert Watson } 540225bff6fSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 541225bff6fSRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 542225bff6fSRobert Watson labelmbufs++; 543225bff6fSRobert Watson } 544225bff6fSRobert Watson mac_labelmbufs = (labelmbufs != 0); 545225bff6fSRobert Watson #endif 546225bff6fSRobert Watson } 547225bff6fSRobert Watson 548225bff6fSRobert Watson /* 54995fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 55095fab37eSRobert Watson */ 55195fab37eSRobert Watson int 55295fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 55395fab37eSRobert Watson { 55495fab37eSRobert Watson struct mac_policy_conf *mpc; 55595fab37eSRobert Watson int error; 55695fab37eSRobert Watson 55795fab37eSRobert Watson error = 0; 55895fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 55995fab37eSRobert Watson 56095fab37eSRobert Watson switch (type) { 56195fab37eSRobert Watson case MOD_LOAD: 56295fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 56395fab37eSRobert Watson mac_late) { 56495fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 56595fab37eSRobert Watson "after booting\n", mpc->mpc_name); 56695fab37eSRobert Watson error = EBUSY; 56795fab37eSRobert Watson break; 56895fab37eSRobert Watson } 56995fab37eSRobert Watson error = mac_policy_register(mpc); 57095fab37eSRobert Watson break; 57195fab37eSRobert Watson case MOD_UNLOAD: 57295fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 57395fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 57495fab37eSRobert Watson != 0) 57595fab37eSRobert Watson error = mac_policy_unregister(mpc); 57695fab37eSRobert Watson else 57795fab37eSRobert Watson error = 0; 57895fab37eSRobert Watson break; 57995fab37eSRobert Watson default: 58095fab37eSRobert Watson break; 58195fab37eSRobert Watson } 58295fab37eSRobert Watson 58395fab37eSRobert Watson return (error); 58495fab37eSRobert Watson } 58595fab37eSRobert Watson 58695fab37eSRobert Watson static int 58795fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 58895fab37eSRobert Watson { 58995fab37eSRobert Watson struct mac_policy_conf *tmpc; 59041a17fe3SRobert Watson int error, slot, static_entry; 59195fab37eSRobert Watson 59241a17fe3SRobert Watson error = 0; 59341a17fe3SRobert Watson 59441a17fe3SRobert Watson /* 59541a17fe3SRobert Watson * We don't technically need exclusive access while !mac_late, 59641a17fe3SRobert Watson * but hold it for assertion consistency. 59741a17fe3SRobert Watson */ 59841a17fe3SRobert Watson mac_policy_grab_exclusive(); 59941a17fe3SRobert Watson 60041a17fe3SRobert Watson /* 60141a17fe3SRobert Watson * If the module can potentially be unloaded, or we're loading 60241a17fe3SRobert Watson * late, we have to stick it in the non-static list and pay 60341a17fe3SRobert Watson * an extra performance overhead. Otherwise, we can pay a 60441a17fe3SRobert Watson * light locking cost and stick it in the static list. 60541a17fe3SRobert Watson */ 60641a17fe3SRobert Watson static_entry = (!mac_late && 60741a17fe3SRobert Watson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 60841a17fe3SRobert Watson 60941a17fe3SRobert Watson if (static_entry) { 61041a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 61141a17fe3SRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 61241a17fe3SRobert Watson error = EEXIST; 61341a17fe3SRobert Watson goto out; 61441a17fe3SRobert Watson } 61541a17fe3SRobert Watson } 61641a17fe3SRobert Watson } else { 61795fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 61895fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 61941a17fe3SRobert Watson error = EEXIST; 62041a17fe3SRobert Watson goto out; 62141a17fe3SRobert Watson } 62295fab37eSRobert Watson } 62395fab37eSRobert Watson } 62495fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 625b2aef571SRobert Watson slot = ffs(mac_slot_offsets_free); 62695fab37eSRobert Watson if (slot == 0) { 62741a17fe3SRobert Watson error = ENOMEM; 62841a17fe3SRobert Watson goto out; 62995fab37eSRobert Watson } 63095fab37eSRobert Watson slot--; 631b2aef571SRobert Watson mac_slot_offsets_free &= ~(1 << slot); 63295fab37eSRobert Watson *mpc->mpc_field_off = slot; 63395fab37eSRobert Watson } 63495fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 63541a17fe3SRobert Watson 63641a17fe3SRobert Watson /* 63741a17fe3SRobert Watson * If we're loading a MAC module after the framework has 63841a17fe3SRobert Watson * initialized, it has to go into the dynamic list. If 63941a17fe3SRobert Watson * we're loading it before we've finished initializing, 64041a17fe3SRobert Watson * it can go into the static list with weaker locker 64141a17fe3SRobert Watson * requirements. 64241a17fe3SRobert Watson */ 64341a17fe3SRobert Watson if (static_entry) 64441a17fe3SRobert Watson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 64541a17fe3SRobert Watson else 64695fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 64795fab37eSRobert Watson 64895fab37eSRobert Watson /* Per-policy initialization. */ 64995fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 65095fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 651225bff6fSRobert Watson mac_policy_updateflags(); 65295fab37eSRobert Watson 65395fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 65495fab37eSRobert Watson mpc->mpc_name); 65595fab37eSRobert Watson 65641a17fe3SRobert Watson out: 65741a17fe3SRobert Watson mac_policy_release_exclusive(); 65841a17fe3SRobert Watson return (error); 65995fab37eSRobert Watson } 66095fab37eSRobert Watson 66195fab37eSRobert Watson static int 66295fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 66395fab37eSRobert Watson { 66495fab37eSRobert Watson 665ea599aa0SRobert Watson /* 666ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 667ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 668ea599aa0SRobert Watson * silently succeed. 669ea599aa0SRobert Watson */ 67041a17fe3SRobert Watson mac_policy_grab_exclusive(); 671ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 67241a17fe3SRobert Watson mac_policy_release_exclusive(); 673ea599aa0SRobert Watson return (0); 674ea599aa0SRobert Watson } 67595fab37eSRobert Watson #if 0 67695fab37eSRobert Watson /* 67795fab37eSRobert Watson * Don't allow unloading modules with private data. 67895fab37eSRobert Watson */ 679ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 680ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 68195fab37eSRobert Watson return (EBUSY); 682ea599aa0SRobert Watson } 68395fab37eSRobert Watson #endif 684ea599aa0SRobert Watson /* 685ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 686ea599aa0SRobert Watson * by its own definition. 687ea599aa0SRobert Watson */ 688ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 68941a17fe3SRobert Watson mac_policy_release_exclusive(); 69095fab37eSRobert Watson return (EBUSY); 691ea599aa0SRobert Watson } 69295fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 69395fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 69495fab37eSRobert Watson 69595fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 6969aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 697225bff6fSRobert Watson mac_policy_updateflags(); 69841a17fe3SRobert Watson 69941a17fe3SRobert Watson mac_policy_release_exclusive(); 700a96acd1aSRobert Watson 70195fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 70295fab37eSRobert Watson mpc->mpc_name); 70395fab37eSRobert Watson 70495fab37eSRobert Watson return (0); 70595fab37eSRobert Watson } 70695fab37eSRobert Watson 70795fab37eSRobert Watson /* 70895fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 70995fab37eSRobert Watson * value with the higher precedence. 71095fab37eSRobert Watson */ 7119e7bf51cSRobert Watson int 7129e7bf51cSRobert Watson mac_error_select(int error1, int error2) 71395fab37eSRobert Watson { 71495fab37eSRobert Watson 71595fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 71695fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 71795fab37eSRobert Watson return (EDEADLK); 71895fab37eSRobert Watson 71995fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 72095fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 72195fab37eSRobert Watson return (EINVAL); 72295fab37eSRobert Watson 72395fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 72495fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 72595fab37eSRobert Watson return (ESRCH); 72695fab37eSRobert Watson 72795fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 72895fab37eSRobert Watson return (ENOENT); 72995fab37eSRobert Watson 73095fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 73195fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 73295fab37eSRobert Watson return (EACCES); 73395fab37eSRobert Watson 73495fab37eSRobert Watson /* Precedence goes to privilege. */ 73595fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 73695fab37eSRobert Watson return (EPERM); 73795fab37eSRobert Watson 73895fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 73995fab37eSRobert Watson if (error1 != 0) 74095fab37eSRobert Watson return (error1); 74195fab37eSRobert Watson return (error2); 74295fab37eSRobert Watson } 74395fab37eSRobert Watson 74410eeb10cSRobert Watson static struct label * 74510eeb10cSRobert Watson mbuf_to_label(struct mbuf *mbuf) 74610eeb10cSRobert Watson { 747225bff6fSRobert Watson struct m_tag *tag; 74810eeb10cSRobert Watson struct label *label; 74910eeb10cSRobert Watson 750225bff6fSRobert Watson tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL); 751225bff6fSRobert Watson label = (struct label *)(tag+1); 75210eeb10cSRobert Watson 75310eeb10cSRobert Watson return (label); 75410eeb10cSRobert Watson } 75510eeb10cSRobert Watson 75608bcdc58SRobert Watson static void 75708bcdc58SRobert Watson mac_init_label(struct label *label) 75808bcdc58SRobert Watson { 75908bcdc58SRobert Watson 76008bcdc58SRobert Watson bzero(label, sizeof(*label)); 76108bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 76208bcdc58SRobert Watson } 76308bcdc58SRobert Watson 76408bcdc58SRobert Watson static void 76508bcdc58SRobert Watson mac_destroy_label(struct label *label) 76608bcdc58SRobert Watson { 76708bcdc58SRobert Watson 76808bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 76908bcdc58SRobert Watson ("destroying uninitialized label")); 77008bcdc58SRobert Watson 77108bcdc58SRobert Watson bzero(label, sizeof(*label)); 77208bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 77308bcdc58SRobert Watson } 77408bcdc58SRobert Watson 77508bcdc58SRobert Watson void 77687807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 77708bcdc58SRobert Watson { 77808bcdc58SRobert Watson 77987807196SRobert Watson mac_init_label(&bpf_d->bd_label); 78087807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 7818d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacbpfdescs); 78208bcdc58SRobert Watson } 78308bcdc58SRobert Watson 784f7b951a8SRobert Watson static void 785f7b951a8SRobert Watson mac_init_cred_label(struct label *label) 78608bcdc58SRobert Watson { 78708bcdc58SRobert Watson 788f7b951a8SRobert Watson mac_init_label(label); 789f7b951a8SRobert Watson MAC_PERFORM(init_cred_label, label); 7908d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmaccreds); 79108bcdc58SRobert Watson } 79208bcdc58SRobert Watson 79308bcdc58SRobert Watson void 794f7b951a8SRobert Watson mac_init_cred(struct ucred *cred) 795f7b951a8SRobert Watson { 796f7b951a8SRobert Watson 797f7b951a8SRobert Watson mac_init_cred_label(&cred->cr_label); 798f7b951a8SRobert Watson } 799f7b951a8SRobert Watson 800f7b951a8SRobert Watson void 80187807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 80208bcdc58SRobert Watson { 80308bcdc58SRobert Watson 80487807196SRobert Watson mac_init_label(&de->de_label); 80587807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 8068d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents); 80708bcdc58SRobert Watson } 80808bcdc58SRobert Watson 809f7b951a8SRobert Watson static void 810f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label) 811f7b951a8SRobert Watson { 812f7b951a8SRobert Watson 813f7b951a8SRobert Watson mac_init_label(label); 814f7b951a8SRobert Watson MAC_PERFORM(init_ifnet_label, label); 8158d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacifnets); 816f7b951a8SRobert Watson } 817f7b951a8SRobert Watson 81808bcdc58SRobert Watson void 81908bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 82008bcdc58SRobert Watson { 82108bcdc58SRobert Watson 822f7b951a8SRobert Watson mac_init_ifnet_label(&ifp->if_label); 82308bcdc58SRobert Watson } 82408bcdc58SRobert Watson 8255e7ce478SRobert Watson int 8265e7ce478SRobert Watson mac_init_ipq(struct ipq *ipq, int flag) 82708bcdc58SRobert Watson { 8285e7ce478SRobert Watson int error; 82908bcdc58SRobert Watson 83008bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 8315e7ce478SRobert Watson 8325e7ce478SRobert Watson MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag); 8335e7ce478SRobert Watson if (error) { 8345e7ce478SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 8355e7ce478SRobert Watson mac_destroy_label(&ipq->ipq_label); 8368d8d5ea8SRobert Watson } else { 8378d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacipqs); 8385e7ce478SRobert Watson } 8395e7ce478SRobert Watson return (error); 84008bcdc58SRobert Watson } 84108bcdc58SRobert Watson 84287807196SRobert Watson int 843225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag) 84408bcdc58SRobert Watson { 845225bff6fSRobert Watson struct label *label; 8466d1a6a9aSRobert Watson int error; 84756c15412SRobert Watson 848225bff6fSRobert Watson label = (struct label *) (tag + 1); 849225bff6fSRobert Watson mac_init_label(label); 85008bcdc58SRobert Watson 8516d1a6a9aSRobert Watson MAC_CHECK(init_mbuf_label, label, flag); 85256c15412SRobert Watson if (error) { 853225bff6fSRobert Watson MAC_PERFORM(destroy_mbuf_label, label); 854225bff6fSRobert Watson mac_destroy_label(label); 8558d8d5ea8SRobert Watson } else { 8568d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacmbufs); 85756c15412SRobert Watson } 85856c15412SRobert Watson return (error); 85908bcdc58SRobert Watson } 86008bcdc58SRobert Watson 861225bff6fSRobert Watson int 862225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 863225bff6fSRobert Watson { 864225bff6fSRobert Watson struct m_tag *tag; 865225bff6fSRobert Watson int error; 866225bff6fSRobert Watson 867225bff6fSRobert Watson M_ASSERTPKTHDR(m); 868225bff6fSRobert Watson 869225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 870225bff6fSRobert Watson /* 87119c3e120SRobert Watson * If conditionally allocating mbuf labels, don't allocate unless 87219c3e120SRobert Watson * they are required. 873225bff6fSRobert Watson */ 87419c3e120SRobert Watson if (!mac_labelmbufs) 87519c3e120SRobert Watson return (0); 876225bff6fSRobert Watson #endif 877225bff6fSRobert Watson tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label), 878225bff6fSRobert Watson flag); 879225bff6fSRobert Watson if (tag == NULL) 880225bff6fSRobert Watson return (ENOMEM); 881225bff6fSRobert Watson error = mac_init_mbuf_tag(tag, flag); 882225bff6fSRobert Watson if (error) { 883225bff6fSRobert Watson m_tag_free(tag); 884225bff6fSRobert Watson return (error); 885225bff6fSRobert Watson } 886225bff6fSRobert Watson m_tag_prepend(m, tag); 887225bff6fSRobert Watson return (0); 888225bff6fSRobert Watson } 889225bff6fSRobert Watson 89008bcdc58SRobert Watson void 89187807196SRobert Watson mac_init_mount(struct mount *mp) 89208bcdc58SRobert Watson { 89308bcdc58SRobert Watson 89487807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 89587807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 89687807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 89787807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 8988d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacmounts); 89908bcdc58SRobert Watson } 90008bcdc58SRobert Watson 901f7b951a8SRobert Watson static void 902f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 903f7b951a8SRobert Watson { 904f7b951a8SRobert Watson 905f7b951a8SRobert Watson mac_init_label(label); 906f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 9078d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacpipes); 908f7b951a8SRobert Watson } 909f7b951a8SRobert Watson 91008bcdc58SRobert Watson void 91108bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 91208bcdc58SRobert Watson { 91308bcdc58SRobert Watson struct label *label; 91408bcdc58SRobert Watson 915a163d034SWarner Losh label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 91608bcdc58SRobert Watson pipe->pipe_label = label; 91708bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 918f7b951a8SRobert Watson mac_init_pipe_label(label); 91908bcdc58SRobert Watson } 92008bcdc58SRobert Watson 9212555374cSRobert Watson void 9222555374cSRobert Watson mac_init_proc(struct proc *p) 9232555374cSRobert Watson { 9242555374cSRobert Watson 9252555374cSRobert Watson mac_init_label(&p->p_label); 9262555374cSRobert Watson MAC_PERFORM(init_proc_label, &p->p_label); 9278d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacprocs); 9282555374cSRobert Watson } 9292555374cSRobert Watson 93083985c26SRobert Watson static int 93183985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 93208bcdc58SRobert Watson { 93383985c26SRobert Watson int error; 93408bcdc58SRobert Watson 93583985c26SRobert Watson mac_init_label(label); 93683985c26SRobert Watson 93783985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 93883985c26SRobert Watson if (error) { 93983985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 94083985c26SRobert Watson mac_destroy_label(label); 9418d8d5ea8SRobert Watson } else { 9428d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacsockets); 94383985c26SRobert Watson } 94483985c26SRobert Watson 94583985c26SRobert Watson return (error); 94683985c26SRobert Watson } 94783985c26SRobert Watson 94883985c26SRobert Watson static int 94983985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 95083985c26SRobert Watson { 95183985c26SRobert Watson int error; 95283985c26SRobert Watson 95383985c26SRobert Watson mac_init_label(label); 95483985c26SRobert Watson 95583985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 95683985c26SRobert Watson if (error) { 95783985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 95883985c26SRobert Watson mac_destroy_label(label); 95983985c26SRobert Watson } 96083985c26SRobert Watson 96183985c26SRobert Watson return (error); 96283985c26SRobert Watson } 96383985c26SRobert Watson 96483985c26SRobert Watson int 96583985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 96683985c26SRobert Watson { 96783985c26SRobert Watson int error; 96883985c26SRobert Watson 96983985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 97083985c26SRobert Watson if (error) 97183985c26SRobert Watson return (error); 97283985c26SRobert Watson 97383985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 97483985c26SRobert Watson if (error) 97583985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 97683985c26SRobert Watson 97783985c26SRobert Watson return (error); 97887807196SRobert Watson } 97987807196SRobert Watson 980763bbd2fSRobert Watson void 981f7b951a8SRobert Watson mac_init_vnode_label(struct label *label) 98287807196SRobert Watson { 98387807196SRobert Watson 98487807196SRobert Watson mac_init_label(label); 985f7b951a8SRobert Watson MAC_PERFORM(init_vnode_label, label); 9868d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacvnodes); 98708bcdc58SRobert Watson } 98808bcdc58SRobert Watson 98908bcdc58SRobert Watson void 99087807196SRobert Watson mac_init_vnode(struct vnode *vp) 99108bcdc58SRobert Watson { 99208bcdc58SRobert Watson 993f7b951a8SRobert Watson mac_init_vnode_label(&vp->v_label); 99408bcdc58SRobert Watson } 99508bcdc58SRobert Watson 99608bcdc58SRobert Watson void 99708bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 99808bcdc58SRobert Watson { 99908bcdc58SRobert Watson 100008bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 100108bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 10028d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs); 100308bcdc58SRobert Watson } 100408bcdc58SRobert Watson 1005f7b951a8SRobert Watson static void 1006f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label) 100708bcdc58SRobert Watson { 100808bcdc58SRobert Watson 1009f7b951a8SRobert Watson MAC_PERFORM(destroy_cred_label, label); 1010f7b951a8SRobert Watson mac_destroy_label(label); 10118d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmaccreds); 101287807196SRobert Watson } 101387807196SRobert Watson 101487807196SRobert Watson void 1015f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred) 1016f7b951a8SRobert Watson { 1017f7b951a8SRobert Watson 1018f7b951a8SRobert Watson mac_destroy_cred_label(&cred->cr_label); 1019f7b951a8SRobert Watson } 1020f7b951a8SRobert Watson 1021f7b951a8SRobert Watson void 102287807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 102387807196SRobert Watson { 102487807196SRobert Watson 102587807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 102687807196SRobert Watson mac_destroy_label(&de->de_label); 10278d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents); 102887807196SRobert Watson } 102987807196SRobert Watson 1030f7b951a8SRobert Watson static void 1031f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label) 1032f7b951a8SRobert Watson { 1033f7b951a8SRobert Watson 1034f7b951a8SRobert Watson MAC_PERFORM(destroy_ifnet_label, label); 1035f7b951a8SRobert Watson mac_destroy_label(label); 10368d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacifnets); 1037f7b951a8SRobert Watson } 1038f7b951a8SRobert Watson 103987807196SRobert Watson void 104087807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 104187807196SRobert Watson { 104287807196SRobert Watson 1043f7b951a8SRobert Watson mac_destroy_ifnet_label(&ifp->if_label); 104487807196SRobert Watson } 104587807196SRobert Watson 104687807196SRobert Watson void 104787807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 104887807196SRobert Watson { 104987807196SRobert Watson 105087807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 105187807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 10528d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacipqs); 105387807196SRobert Watson } 105487807196SRobert Watson 105587807196SRobert Watson void 1056225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag) 105787807196SRobert Watson { 1058225bff6fSRobert Watson struct label *label; 105987807196SRobert Watson 1060225bff6fSRobert Watson label = (struct label *)(tag+1); 1061225bff6fSRobert Watson 1062225bff6fSRobert Watson MAC_PERFORM(destroy_mbuf_label, label); 1063225bff6fSRobert Watson mac_destroy_label(label); 10648d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacmbufs); 106508bcdc58SRobert Watson } 106608bcdc58SRobert Watson 106708bcdc58SRobert Watson void 106808bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 106908bcdc58SRobert Watson { 107008bcdc58SRobert Watson 107108bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 107208bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 107308bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 107408bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 10758d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacmounts); 107608bcdc58SRobert Watson } 107708bcdc58SRobert Watson 1078f7b951a8SRobert Watson static void 1079f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 1080f7b951a8SRobert Watson { 1081f7b951a8SRobert Watson 1082f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 1083f7b951a8SRobert Watson mac_destroy_label(label); 10848d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacpipes); 1085f7b951a8SRobert Watson } 1086f7b951a8SRobert Watson 108787807196SRobert Watson void 108887807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 108908bcdc58SRobert Watson { 109008bcdc58SRobert Watson 1091f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 109287807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 109387807196SRobert Watson } 109487807196SRobert Watson 10952555374cSRobert Watson void 10962555374cSRobert Watson mac_destroy_proc(struct proc *p) 10972555374cSRobert Watson { 10982555374cSRobert Watson 10992555374cSRobert Watson MAC_PERFORM(destroy_proc_label, &p->p_label); 11002555374cSRobert Watson mac_destroy_label(&p->p_label); 11018d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacprocs); 11022555374cSRobert Watson } 11032555374cSRobert Watson 110483985c26SRobert Watson static void 110583985c26SRobert Watson mac_destroy_socket_label(struct label *label) 110683985c26SRobert Watson { 110783985c26SRobert Watson 110883985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 110983985c26SRobert Watson mac_destroy_label(label); 11108d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacsockets); 111183985c26SRobert Watson } 111283985c26SRobert Watson 111383985c26SRobert Watson static void 111483985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 111583985c26SRobert Watson { 111683985c26SRobert Watson 111783985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 111883985c26SRobert Watson mac_destroy_label(label); 111983985c26SRobert Watson } 112083985c26SRobert Watson 112187807196SRobert Watson void 112287807196SRobert Watson mac_destroy_socket(struct socket *socket) 112387807196SRobert Watson { 112487807196SRobert Watson 112583985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 112683985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 112708bcdc58SRobert Watson } 112808bcdc58SRobert Watson 1129763bbd2fSRobert Watson void 1130f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label) 113108bcdc58SRobert Watson { 113208bcdc58SRobert Watson 1133f7b951a8SRobert Watson MAC_PERFORM(destroy_vnode_label, label); 113408bcdc58SRobert Watson mac_destroy_label(label); 11358d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacvnodes); 113608bcdc58SRobert Watson } 113708bcdc58SRobert Watson 113808bcdc58SRobert Watson void 113908bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 114008bcdc58SRobert Watson { 114108bcdc58SRobert Watson 1142f7b951a8SRobert Watson mac_destroy_vnode_label(&vp->v_label); 1143f7b951a8SRobert Watson } 1144f7b951a8SRobert Watson 1145225bff6fSRobert Watson void 1146225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest) 1147225bff6fSRobert Watson { 1148225bff6fSRobert Watson struct label *src_label, *dest_label; 1149225bff6fSRobert Watson 1150225bff6fSRobert Watson src_label = (struct label *)(src+1); 1151225bff6fSRobert Watson dest_label = (struct label *)(dest+1); 1152225bff6fSRobert Watson 1153225bff6fSRobert Watson /* 1154225bff6fSRobert Watson * mac_init_mbuf_tag() is called on the target tag in 1155225bff6fSRobert Watson * m_tag_copy(), so we don't need to call it here. 1156225bff6fSRobert Watson */ 1157225bff6fSRobert Watson MAC_PERFORM(copy_mbuf_label, src_label, dest_label); 1158225bff6fSRobert Watson } 1159225bff6fSRobert Watson 1160f7b951a8SRobert Watson static void 1161f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 1162f7b951a8SRobert Watson { 1163f7b951a8SRobert Watson 1164f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 1165f7b951a8SRobert Watson } 1166f7b951a8SRobert Watson 1167763bbd2fSRobert Watson void 1168f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest) 1169f7b951a8SRobert Watson { 1170f7b951a8SRobert Watson 1171f7b951a8SRobert Watson MAC_PERFORM(copy_vnode_label, src, dest); 117208bcdc58SRobert Watson } 117308bcdc58SRobert Watson 117469bbb5b1SRobert Watson static int 1175f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 1176f7b951a8SRobert Watson { 1177f7b951a8SRobert Watson 1178cc7b13bfSRobert Watson if (mac->m_buflen < 0 || 1179cc7b13bfSRobert Watson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1180f7b951a8SRobert Watson return (EINVAL); 1181f7b951a8SRobert Watson 1182f7b951a8SRobert Watson return (0); 1183f7b951a8SRobert Watson } 1184f7b951a8SRobert Watson 1185f7b951a8SRobert Watson static int 1186f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements, 1187f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 118869bbb5b1SRobert Watson { 118969bbb5b1SRobert Watson int error; 119069bbb5b1SRobert Watson 1191f7b951a8SRobert Watson MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 119269bbb5b1SRobert Watson 119369bbb5b1SRobert Watson return (error); 119469bbb5b1SRobert Watson } 119569bbb5b1SRobert Watson 119669bbb5b1SRobert Watson static int 1197f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements, 1198f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 119969bbb5b1SRobert Watson { 120069bbb5b1SRobert Watson int error; 120169bbb5b1SRobert Watson 1202f7b951a8SRobert Watson MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1203f7b951a8SRobert Watson 1204f7b951a8SRobert Watson return (error); 1205f7b951a8SRobert Watson } 1206f7b951a8SRobert Watson 1207f7b951a8SRobert Watson static int 1208f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 1209f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1210f7b951a8SRobert Watson { 1211f7b951a8SRobert Watson int error; 1212f7b951a8SRobert Watson 1213f7b951a8SRobert Watson MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1214f7b951a8SRobert Watson 1215f7b951a8SRobert Watson return (error); 1216f7b951a8SRobert Watson } 1217f7b951a8SRobert Watson 1218f7b951a8SRobert Watson static int 1219f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 1220f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1221f7b951a8SRobert Watson { 1222f7b951a8SRobert Watson int error; 1223f7b951a8SRobert Watson 1224f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1225f7b951a8SRobert Watson 1226f7b951a8SRobert Watson return (error); 1227f7b951a8SRobert Watson } 1228f7b951a8SRobert Watson 1229f7b951a8SRobert Watson static int 1230f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 1231f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1232f7b951a8SRobert Watson { 1233f7b951a8SRobert Watson int error; 1234f7b951a8SRobert Watson 1235f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1236f7b951a8SRobert Watson 1237f7b951a8SRobert Watson return (error); 1238f7b951a8SRobert Watson } 1239f7b951a8SRobert Watson 1240f7b951a8SRobert Watson static int 1241f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements, 1242f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1243f7b951a8SRobert Watson { 1244f7b951a8SRobert Watson int error; 1245f7b951a8SRobert Watson 1246f7b951a8SRobert Watson MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1247f7b951a8SRobert Watson 1248f7b951a8SRobert Watson return (error); 1249f7b951a8SRobert Watson } 1250f7b951a8SRobert Watson 1251f7b951a8SRobert Watson static int 1252f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string) 1253f7b951a8SRobert Watson { 1254f7b951a8SRobert Watson int error; 1255f7b951a8SRobert Watson 1256f7b951a8SRobert Watson MAC_INTERNALIZE(cred_label, label, string); 1257f7b951a8SRobert Watson 1258f7b951a8SRobert Watson return (error); 1259f7b951a8SRobert Watson } 1260f7b951a8SRobert Watson 1261f7b951a8SRobert Watson static int 1262f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string) 1263f7b951a8SRobert Watson { 1264f7b951a8SRobert Watson int error; 1265f7b951a8SRobert Watson 1266f7b951a8SRobert Watson MAC_INTERNALIZE(ifnet_label, label, string); 1267f7b951a8SRobert Watson 1268f7b951a8SRobert Watson return (error); 1269f7b951a8SRobert Watson } 1270f7b951a8SRobert Watson 1271f7b951a8SRobert Watson static int 1272f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 1273f7b951a8SRobert Watson { 1274f7b951a8SRobert Watson int error; 1275f7b951a8SRobert Watson 1276f7b951a8SRobert Watson MAC_INTERNALIZE(pipe_label, label, string); 1277f7b951a8SRobert Watson 1278f7b951a8SRobert Watson return (error); 1279f7b951a8SRobert Watson } 1280f7b951a8SRobert Watson 1281f7b951a8SRobert Watson static int 1282f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string) 1283f7b951a8SRobert Watson { 1284f7b951a8SRobert Watson int error; 1285f7b951a8SRobert Watson 1286f7b951a8SRobert Watson MAC_INTERNALIZE(socket_label, label, string); 1287f7b951a8SRobert Watson 1288f7b951a8SRobert Watson return (error); 1289f7b951a8SRobert Watson } 1290f7b951a8SRobert Watson 1291f7b951a8SRobert Watson static int 1292f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string) 1293f7b951a8SRobert Watson { 1294f7b951a8SRobert Watson int error; 1295f7b951a8SRobert Watson 1296f7b951a8SRobert Watson MAC_INTERNALIZE(vnode_label, label, string); 129769bbb5b1SRobert Watson 129869bbb5b1SRobert Watson return (error); 129969bbb5b1SRobert Watson } 130069bbb5b1SRobert Watson 130169bbb5b1SRobert Watson /* 130269bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 130369bbb5b1SRobert Watson * kernel processes and threads are spawned. 130469bbb5b1SRobert Watson */ 130569bbb5b1SRobert Watson void 130669bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 130769bbb5b1SRobert Watson { 130869bbb5b1SRobert Watson 130969bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 131069bbb5b1SRobert Watson } 131169bbb5b1SRobert Watson 131269bbb5b1SRobert Watson /* 131369bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 131469bbb5b1SRobert Watson * userland processes and threads are spawned. 131569bbb5b1SRobert Watson */ 131669bbb5b1SRobert Watson void 131769bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 131869bbb5b1SRobert Watson { 131969bbb5b1SRobert Watson 132069bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 132169bbb5b1SRobert Watson } 132269bbb5b1SRobert Watson 132369bbb5b1SRobert Watson void 132469bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 132569bbb5b1SRobert Watson { 132669bbb5b1SRobert Watson 132769bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 132869bbb5b1SRobert Watson } 132969bbb5b1SRobert Watson 133069bbb5b1SRobert Watson /* 133169bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 133269bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 133369bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 133469bbb5b1SRobert Watson */ 133569bbb5b1SRobert Watson void 133669bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 133769bbb5b1SRobert Watson { 133869bbb5b1SRobert Watson 133969bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 134069bbb5b1SRobert Watson } 134169bbb5b1SRobert Watson 134295fab37eSRobert Watson void 1343990b4b2dSRobert Watson mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de, 1344990b4b2dSRobert Watson struct vnode *vp) 134595fab37eSRobert Watson { 134695fab37eSRobert Watson 1347990b4b2dSRobert Watson MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp, 1348990b4b2dSRobert Watson &vp->v_label); 134995fab37eSRobert Watson } 135095fab37eSRobert Watson 135195fab37eSRobert Watson void 1352763bbd2fSRobert Watson mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1353763bbd2fSRobert Watson struct vnode *vp) 135495fab37eSRobert Watson { 135595fab37eSRobert Watson 1356763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1357763bbd2fSRobert Watson &de->de_label, vp, &vp->v_label); 135895fab37eSRobert Watson } 135995fab37eSRobert Watson 1360763bbd2fSRobert Watson int 1361763bbd2fSRobert Watson mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 136295fab37eSRobert Watson { 136395fab37eSRobert Watson int error; 136495fab37eSRobert Watson 1365763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1366763bbd2fSRobert Watson 1367763bbd2fSRobert Watson MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1368763bbd2fSRobert Watson &vp->v_label); 136995fab37eSRobert Watson 137095fab37eSRobert Watson return (error); 137195fab37eSRobert Watson } 137295fab37eSRobert Watson 137395fab37eSRobert Watson void 1374763bbd2fSRobert Watson mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 137595fab37eSRobert Watson { 137695fab37eSRobert Watson 1377763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1378763bbd2fSRobert Watson &vp->v_label); 137995fab37eSRobert Watson } 138095fab37eSRobert Watson 138195fab37eSRobert Watson int 1382763bbd2fSRobert Watson mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1383763bbd2fSRobert Watson struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 138495fab37eSRobert Watson { 1385763bbd2fSRobert Watson int error; 138695fab37eSRobert Watson 1387763bbd2fSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1388763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 138995fab37eSRobert Watson 1390763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1391763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1392763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1393763bbd2fSRobert Watson if (ea_warn_once == 0) { 1394763bbd2fSRobert Watson printf("Warning: transactions not supported " 1395763bbd2fSRobert Watson "in EA write.\n"); 1396763bbd2fSRobert Watson ea_warn_once = 1; 1397763bbd2fSRobert Watson } 1398763bbd2fSRobert Watson } else if (error) 139995fab37eSRobert Watson return (error); 140095fab37eSRobert Watson 1401763bbd2fSRobert Watson MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1402763bbd2fSRobert Watson dvp, &dvp->v_label, vp, &vp->v_label, cnp); 140395fab37eSRobert Watson 1404763bbd2fSRobert Watson if (error) { 1405763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 140695fab37eSRobert Watson return (error); 140795fab37eSRobert Watson } 140895fab37eSRobert Watson 1409763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 141095fab37eSRobert Watson 1411763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1412763bbd2fSRobert Watson error = 0; /* XXX */ 141395fab37eSRobert Watson 141495fab37eSRobert Watson return (error); 141595fab37eSRobert Watson } 141695fab37eSRobert Watson 141795fab37eSRobert Watson static int 1418763bbd2fSRobert Watson mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1419763bbd2fSRobert Watson struct label *intlabel) 142095fab37eSRobert Watson { 142195fab37eSRobert Watson int error; 142295fab37eSRobert Watson 1423763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 142495fab37eSRobert Watson 1425763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1426763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1427763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1428763bbd2fSRobert Watson if (ea_warn_once == 0) { 1429763bbd2fSRobert Watson printf("Warning: transactions not supported " 1430763bbd2fSRobert Watson "in EA write.\n"); 1431763bbd2fSRobert Watson ea_warn_once = 1; 143295fab37eSRobert Watson } 1433763bbd2fSRobert Watson } else if (error) 143495fab37eSRobert Watson return (error); 143595fab37eSRobert Watson 1436763bbd2fSRobert Watson MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 143795fab37eSRobert Watson 1438763bbd2fSRobert Watson if (error) { 1439763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 144095fab37eSRobert Watson return (error); 144195fab37eSRobert Watson } 144295fab37eSRobert Watson 1443763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1444763bbd2fSRobert Watson 1445763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1446763bbd2fSRobert Watson error = 0; /* XXX */ 1447763bbd2fSRobert Watson 1448763bbd2fSRobert Watson return (error); 144995fab37eSRobert Watson } 145095fab37eSRobert Watson 1451670cb89bSRobert Watson int 1452670cb89bSRobert Watson mac_execve_enter(struct image_params *imgp, struct mac *mac_p, 1453670cb89bSRobert Watson struct label *execlabelstorage) 1454670cb89bSRobert Watson { 1455670cb89bSRobert Watson struct mac mac; 1456670cb89bSRobert Watson char *buffer; 1457670cb89bSRobert Watson int error; 1458670cb89bSRobert Watson 1459670cb89bSRobert Watson if (mac_p == NULL) 1460670cb89bSRobert Watson return (0); 1461670cb89bSRobert Watson 1462670cb89bSRobert Watson error = copyin(mac_p, &mac, sizeof(mac)); 1463670cb89bSRobert Watson if (error) 1464670cb89bSRobert Watson return (error); 1465670cb89bSRobert Watson 1466670cb89bSRobert Watson error = mac_check_structmac_consistent(&mac); 1467670cb89bSRobert Watson if (error) 1468670cb89bSRobert Watson return (error); 1469670cb89bSRobert Watson 1470a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1471670cb89bSRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1472670cb89bSRobert Watson if (error) { 1473670cb89bSRobert Watson free(buffer, M_MACTEMP); 1474670cb89bSRobert Watson return (error); 1475670cb89bSRobert Watson } 1476670cb89bSRobert Watson 1477670cb89bSRobert Watson mac_init_cred_label(execlabelstorage); 1478670cb89bSRobert Watson error = mac_internalize_cred_label(execlabelstorage, buffer); 1479670cb89bSRobert Watson free(buffer, M_MACTEMP); 1480670cb89bSRobert Watson if (error) { 1481670cb89bSRobert Watson mac_destroy_cred_label(execlabelstorage); 1482670cb89bSRobert Watson return (error); 1483670cb89bSRobert Watson } 1484670cb89bSRobert Watson imgp->execlabel = execlabelstorage; 1485670cb89bSRobert Watson return (0); 1486670cb89bSRobert Watson } 1487670cb89bSRobert Watson 148895fab37eSRobert Watson void 1489670cb89bSRobert Watson mac_execve_exit(struct image_params *imgp) 1490670cb89bSRobert Watson { 1491670cb89bSRobert Watson if (imgp->execlabel != NULL) 1492670cb89bSRobert Watson mac_destroy_cred_label(imgp->execlabel); 1493670cb89bSRobert Watson } 1494670cb89bSRobert Watson 1495670cb89bSRobert Watson void 1496670cb89bSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 1497670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 149895fab37eSRobert Watson { 149995fab37eSRobert Watson 150095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 150195fab37eSRobert Watson 15024443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 15034443e9ffSRobert Watson return; 15044443e9ffSRobert Watson 1505670cb89bSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 15069fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 150795fab37eSRobert Watson } 150895fab37eSRobert Watson 150995fab37eSRobert Watson int 1510670cb89bSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp, 1511670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 151295fab37eSRobert Watson { 1513763bbd2fSRobert Watson int result; 151495fab37eSRobert Watson 15154443e9ffSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 15164443e9ffSRobert Watson 15174443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 15184443e9ffSRobert Watson return (0); 15194443e9ffSRobert Watson 152095fab37eSRobert Watson result = 0; 1521670cb89bSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 15229fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 152395fab37eSRobert Watson 152495fab37eSRobert Watson return (result); 152595fab37eSRobert Watson } 152695fab37eSRobert Watson 152795fab37eSRobert Watson int 1528b914de36SRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 152995fab37eSRobert Watson { 153095fab37eSRobert Watson int error; 153195fab37eSRobert Watson 153295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 153395fab37eSRobert Watson 153495fab37eSRobert Watson if (!mac_enforce_fs) 153595fab37eSRobert Watson return (0); 153695fab37eSRobert Watson 1537b914de36SRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 153895fab37eSRobert Watson return (error); 153995fab37eSRobert Watson } 154095fab37eSRobert Watson 154195fab37eSRobert Watson int 154295fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 154395fab37eSRobert Watson { 154495fab37eSRobert Watson int error; 154595fab37eSRobert Watson 154695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 154795fab37eSRobert Watson 154895fab37eSRobert Watson if (!mac_enforce_fs) 154995fab37eSRobert Watson return (0); 155095fab37eSRobert Watson 155195fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 155295fab37eSRobert Watson return (error); 155395fab37eSRobert Watson } 155495fab37eSRobert Watson 155595fab37eSRobert Watson int 155695fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 155795fab37eSRobert Watson { 155895fab37eSRobert Watson int error; 155995fab37eSRobert Watson 156095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 156195fab37eSRobert Watson 156295fab37eSRobert Watson if (!mac_enforce_fs) 156395fab37eSRobert Watson return (0); 156495fab37eSRobert Watson 156595fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 156695fab37eSRobert Watson return (error); 156795fab37eSRobert Watson } 156895fab37eSRobert Watson 156995fab37eSRobert Watson int 157095fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 157195fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 157295fab37eSRobert Watson { 157395fab37eSRobert Watson int error; 157495fab37eSRobert Watson 157595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 157695fab37eSRobert Watson 157795fab37eSRobert Watson if (!mac_enforce_fs) 157895fab37eSRobert Watson return (0); 157995fab37eSRobert Watson 158095fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 158195fab37eSRobert Watson return (error); 158295fab37eSRobert Watson } 158395fab37eSRobert Watson 158495fab37eSRobert Watson int 158595fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 158695fab37eSRobert Watson struct componentname *cnp) 158795fab37eSRobert Watson { 158895fab37eSRobert Watson int error; 158995fab37eSRobert Watson 159095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 159195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 159295fab37eSRobert Watson 159395fab37eSRobert Watson if (!mac_enforce_fs) 159495fab37eSRobert Watson return (0); 159595fab37eSRobert Watson 159695fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 159795fab37eSRobert Watson &vp->v_label, cnp); 159895fab37eSRobert Watson return (error); 159995fab37eSRobert Watson } 160095fab37eSRobert Watson 160195fab37eSRobert Watson int 160295fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 160395fab37eSRobert Watson acl_type_t type) 160495fab37eSRobert Watson { 160595fab37eSRobert Watson int error; 160695fab37eSRobert Watson 160795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 160895fab37eSRobert Watson 160995fab37eSRobert Watson if (!mac_enforce_fs) 161095fab37eSRobert Watson return (0); 161195fab37eSRobert Watson 161295fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 161395fab37eSRobert Watson return (error); 161495fab37eSRobert Watson } 161595fab37eSRobert Watson 161695fab37eSRobert Watson int 1617c096756cSRobert Watson mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, 1618c096756cSRobert Watson int attrnamespace, const char *name) 1619c096756cSRobert Watson { 1620c096756cSRobert Watson int error; 1621c096756cSRobert Watson 1622c096756cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr"); 1623c096756cSRobert Watson 1624c096756cSRobert Watson if (!mac_enforce_fs) 1625c096756cSRobert Watson return (0); 1626c096756cSRobert Watson 1627c096756cSRobert Watson MAC_CHECK(check_vnode_deleteextattr, cred, vp, &vp->v_label, 1628c096756cSRobert Watson attrnamespace, name); 1629c096756cSRobert Watson return (error); 1630c096756cSRobert Watson } 1631c096756cSRobert Watson 1632c096756cSRobert Watson int 1633670cb89bSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1634670cb89bSRobert Watson struct image_params *imgp) 163595fab37eSRobert Watson { 163695fab37eSRobert Watson int error; 163795fab37eSRobert Watson 1638851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1639851704bbSRobert Watson 164095fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 164195fab37eSRobert Watson return (0); 164295fab37eSRobert Watson 16439fa3506eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 16449fa3506eSRobert Watson imgp->execlabel); 164595fab37eSRobert Watson 164695fab37eSRobert Watson return (error); 164795fab37eSRobert Watson } 164895fab37eSRobert Watson 164995fab37eSRobert Watson int 165095fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 165195fab37eSRobert Watson { 165295fab37eSRobert Watson int error; 165395fab37eSRobert Watson 165495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 165595fab37eSRobert Watson 165695fab37eSRobert Watson if (!mac_enforce_fs) 165795fab37eSRobert Watson return (0); 165895fab37eSRobert Watson 165995fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 166095fab37eSRobert Watson return (error); 166195fab37eSRobert Watson } 166295fab37eSRobert Watson 166395fab37eSRobert Watson int 166495fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 166595fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 166695fab37eSRobert Watson { 166795fab37eSRobert Watson int error; 166895fab37eSRobert Watson 166995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 167095fab37eSRobert Watson 167195fab37eSRobert Watson if (!mac_enforce_fs) 167295fab37eSRobert Watson return (0); 167395fab37eSRobert Watson 167495fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 167595fab37eSRobert Watson attrnamespace, name, uio); 167695fab37eSRobert Watson return (error); 167795fab37eSRobert Watson } 167895fab37eSRobert Watson 167995fab37eSRobert Watson int 16800a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 16810a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 16820a694196SRobert Watson { 16830a694196SRobert Watson int error; 16840a694196SRobert Watson 16850a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 16860a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 16870a694196SRobert Watson 16880a694196SRobert Watson if (!mac_enforce_fs) 16890a694196SRobert Watson return (0); 16900a694196SRobert Watson 16910a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 16920a694196SRobert Watson &vp->v_label, cnp); 16930a694196SRobert Watson return (error); 16940a694196SRobert Watson } 16950a694196SRobert Watson 16960a694196SRobert Watson int 1697c096756cSRobert Watson mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, 1698c096756cSRobert Watson int attrnamespace) 1699c096756cSRobert Watson { 1700c096756cSRobert Watson int error; 1701c096756cSRobert Watson 1702c096756cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr"); 1703c096756cSRobert Watson 1704c096756cSRobert Watson if (!mac_enforce_fs) 1705c096756cSRobert Watson return (0); 1706c096756cSRobert Watson 1707c096756cSRobert Watson MAC_CHECK(check_vnode_listextattr, cred, vp, &vp->v_label, 1708c096756cSRobert Watson attrnamespace); 1709c096756cSRobert Watson return (error); 1710c096756cSRobert Watson } 1711c096756cSRobert Watson 1712c096756cSRobert Watson int 171395fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 171495fab37eSRobert Watson struct componentname *cnp) 171595fab37eSRobert Watson { 171695fab37eSRobert Watson int error; 171795fab37eSRobert Watson 171895fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 171995fab37eSRobert Watson 172095fab37eSRobert Watson if (!mac_enforce_fs) 172195fab37eSRobert Watson return (0); 172295fab37eSRobert Watson 172395fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 172495fab37eSRobert Watson return (error); 172595fab37eSRobert Watson } 172695fab37eSRobert Watson 1727e183f80eSRobert Watson int 1728e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 172995fab37eSRobert Watson { 1730e183f80eSRobert Watson int error; 173195fab37eSRobert Watson 1732e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1733ca7850c3SRobert Watson 1734e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1735e183f80eSRobert Watson return (0); 1736e183f80eSRobert Watson 1737e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1738e183f80eSRobert Watson return (error); 1739e183f80eSRobert Watson } 1740e183f80eSRobert Watson 1741e183f80eSRobert Watson void 1742e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1743e183f80eSRobert Watson { 1744e183f80eSRobert Watson int result = *prot; 1745e183f80eSRobert Watson 1746e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1747e183f80eSRobert Watson 1748e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1749e183f80eSRobert Watson return; 1750e183f80eSRobert Watson 1751e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1752e183f80eSRobert Watson &result); 1753e183f80eSRobert Watson 1754e183f80eSRobert Watson *prot = result; 1755e183f80eSRobert Watson } 1756e183f80eSRobert Watson 1757e183f80eSRobert Watson int 1758e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1759e183f80eSRobert Watson { 1760e183f80eSRobert Watson int error; 1761e183f80eSRobert Watson 1762e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1763e183f80eSRobert Watson 1764e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1765e183f80eSRobert Watson return (0); 1766e183f80eSRobert Watson 1767e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1768e183f80eSRobert Watson return (error); 176995fab37eSRobert Watson } 177095fab37eSRobert Watson 177195fab37eSRobert Watson int 1772b914de36SRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 177395fab37eSRobert Watson { 177495fab37eSRobert Watson int error; 177595fab37eSRobert Watson 177695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 177795fab37eSRobert Watson 177895fab37eSRobert Watson if (!mac_enforce_fs) 177995fab37eSRobert Watson return (0); 178095fab37eSRobert Watson 178195fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 178295fab37eSRobert Watson return (error); 178395fab37eSRobert Watson } 178495fab37eSRobert Watson 178595fab37eSRobert Watson int 1786177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1787177142e4SRobert Watson struct vnode *vp) 17887f724f8bSRobert Watson { 17897f724f8bSRobert Watson int error; 17907f724f8bSRobert Watson 17917f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 17927f724f8bSRobert Watson 17937f724f8bSRobert Watson if (!mac_enforce_fs) 17947f724f8bSRobert Watson return (0); 17957f724f8bSRobert Watson 1796177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1797177142e4SRobert Watson &vp->v_label); 17987f724f8bSRobert Watson 17997f724f8bSRobert Watson return (error); 18007f724f8bSRobert Watson } 18017f724f8bSRobert Watson 18027f724f8bSRobert Watson int 1803177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1804177142e4SRobert Watson struct vnode *vp) 18057f724f8bSRobert Watson { 18067f724f8bSRobert Watson int error; 18077f724f8bSRobert Watson 18087f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 18097f724f8bSRobert Watson 18107f724f8bSRobert Watson if (!mac_enforce_fs) 18117f724f8bSRobert Watson return (0); 18127f724f8bSRobert Watson 1813177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1814177142e4SRobert Watson &vp->v_label); 18157f724f8bSRobert Watson 18167f724f8bSRobert Watson return (error); 18177f724f8bSRobert Watson } 18187f724f8bSRobert Watson 18197f724f8bSRobert Watson int 182095fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 182195fab37eSRobert Watson { 182295fab37eSRobert Watson int error; 182395fab37eSRobert Watson 182495fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 182595fab37eSRobert Watson 182695fab37eSRobert Watson if (!mac_enforce_fs) 182795fab37eSRobert Watson return (0); 182895fab37eSRobert Watson 182995fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 183095fab37eSRobert Watson return (error); 183195fab37eSRobert Watson } 183295fab37eSRobert Watson 183395fab37eSRobert Watson int 183495fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 183595fab37eSRobert Watson { 183695fab37eSRobert Watson int error; 183795fab37eSRobert Watson 183895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 183995fab37eSRobert Watson 184095fab37eSRobert Watson if (!mac_enforce_fs) 184195fab37eSRobert Watson return (0); 184295fab37eSRobert Watson 184395fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 184495fab37eSRobert Watson return (error); 184595fab37eSRobert Watson } 184695fab37eSRobert Watson 184795fab37eSRobert Watson static int 184895fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 184995fab37eSRobert Watson struct label *newlabel) 185095fab37eSRobert Watson { 185195fab37eSRobert Watson int error; 185295fab37eSRobert Watson 185395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 185495fab37eSRobert Watson 185595fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 185695fab37eSRobert Watson 185795fab37eSRobert Watson return (error); 185895fab37eSRobert Watson } 185995fab37eSRobert Watson 186095fab37eSRobert Watson int 186195fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 186295fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 186395fab37eSRobert Watson { 186495fab37eSRobert Watson int error; 186595fab37eSRobert Watson 186695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 186795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 186895fab37eSRobert Watson 186995fab37eSRobert Watson if (!mac_enforce_fs) 187095fab37eSRobert Watson return (0); 187195fab37eSRobert Watson 187295fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 187395fab37eSRobert Watson &vp->v_label, cnp); 187495fab37eSRobert Watson return (error); 187595fab37eSRobert Watson } 187695fab37eSRobert Watson 187795fab37eSRobert Watson int 187895fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 187995fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 188095fab37eSRobert Watson { 188195fab37eSRobert Watson int error; 188295fab37eSRobert Watson 188395fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 188495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 188595fab37eSRobert Watson 188695fab37eSRobert Watson if (!mac_enforce_fs) 188795fab37eSRobert Watson return (0); 188895fab37eSRobert Watson 188995fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 189095fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 189195fab37eSRobert Watson return (error); 189295fab37eSRobert Watson } 189395fab37eSRobert Watson 189495fab37eSRobert Watson int 189595fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 189695fab37eSRobert Watson { 189795fab37eSRobert Watson int error; 189895fab37eSRobert Watson 189995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 190095fab37eSRobert Watson 190195fab37eSRobert Watson if (!mac_enforce_fs) 190295fab37eSRobert Watson return (0); 190395fab37eSRobert Watson 190495fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 190595fab37eSRobert Watson return (error); 190695fab37eSRobert Watson } 190795fab37eSRobert Watson 190895fab37eSRobert Watson int 190995fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 191095fab37eSRobert Watson struct acl *acl) 191195fab37eSRobert Watson { 191295fab37eSRobert Watson int error; 191395fab37eSRobert Watson 191495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 191595fab37eSRobert Watson 191695fab37eSRobert Watson if (!mac_enforce_fs) 191795fab37eSRobert Watson return (0); 191895fab37eSRobert Watson 191995fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 192095fab37eSRobert Watson return (error); 192195fab37eSRobert Watson } 192295fab37eSRobert Watson 192395fab37eSRobert Watson int 192495fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 192595fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 192695fab37eSRobert Watson { 192795fab37eSRobert Watson int error; 192895fab37eSRobert Watson 192995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 193095fab37eSRobert Watson 193195fab37eSRobert Watson if (!mac_enforce_fs) 193295fab37eSRobert Watson return (0); 193395fab37eSRobert Watson 193495fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 193595fab37eSRobert Watson attrnamespace, name, uio); 193695fab37eSRobert Watson return (error); 193795fab37eSRobert Watson } 193895fab37eSRobert Watson 193995fab37eSRobert Watson int 194095fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 194195fab37eSRobert Watson { 194295fab37eSRobert Watson int error; 194395fab37eSRobert Watson 194495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 194595fab37eSRobert Watson 194695fab37eSRobert Watson if (!mac_enforce_fs) 194795fab37eSRobert Watson return (0); 194895fab37eSRobert Watson 194995fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 195095fab37eSRobert Watson return (error); 195195fab37eSRobert Watson } 195295fab37eSRobert Watson 195395fab37eSRobert Watson int 195495fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 195595fab37eSRobert Watson { 195695fab37eSRobert Watson int error; 195795fab37eSRobert Watson 195895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 195995fab37eSRobert Watson 196095fab37eSRobert Watson if (!mac_enforce_fs) 196195fab37eSRobert Watson return (0); 196295fab37eSRobert Watson 196395fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 196495fab37eSRobert Watson return (error); 196595fab37eSRobert Watson } 196695fab37eSRobert Watson 196795fab37eSRobert Watson int 196895fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 196995fab37eSRobert Watson gid_t gid) 197095fab37eSRobert Watson { 197195fab37eSRobert Watson int error; 197295fab37eSRobert Watson 197395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 197495fab37eSRobert Watson 197595fab37eSRobert Watson if (!mac_enforce_fs) 197695fab37eSRobert Watson return (0); 197795fab37eSRobert Watson 197895fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 197995fab37eSRobert Watson return (error); 198095fab37eSRobert Watson } 198195fab37eSRobert Watson 198295fab37eSRobert Watson int 198395fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 198495fab37eSRobert Watson struct timespec atime, struct timespec mtime) 198595fab37eSRobert Watson { 198695fab37eSRobert Watson int error; 198795fab37eSRobert Watson 198895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 198995fab37eSRobert Watson 199095fab37eSRobert Watson if (!mac_enforce_fs) 199195fab37eSRobert Watson return (0); 199295fab37eSRobert Watson 199395fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 199495fab37eSRobert Watson mtime); 199595fab37eSRobert Watson return (error); 199695fab37eSRobert Watson } 199795fab37eSRobert Watson 199895fab37eSRobert Watson int 1999177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2000177142e4SRobert Watson struct vnode *vp) 200195fab37eSRobert Watson { 200295fab37eSRobert Watson int error; 200395fab37eSRobert Watson 200495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 200595fab37eSRobert Watson 200695fab37eSRobert Watson if (!mac_enforce_fs) 200795fab37eSRobert Watson return (0); 200895fab37eSRobert Watson 2009177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2010177142e4SRobert Watson &vp->v_label); 201195fab37eSRobert Watson return (error); 201295fab37eSRobert Watson } 201395fab37eSRobert Watson 20147f724f8bSRobert Watson int 2015177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2016177142e4SRobert Watson struct vnode *vp) 20177f724f8bSRobert Watson { 20187f724f8bSRobert Watson int error; 20197f724f8bSRobert Watson 20207f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 20217f724f8bSRobert Watson 20227f724f8bSRobert Watson if (!mac_enforce_fs) 20237f724f8bSRobert Watson return (0); 20247f724f8bSRobert Watson 2025177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2026177142e4SRobert Watson &vp->v_label); 20277f724f8bSRobert Watson 20287f724f8bSRobert Watson return (error); 20297f724f8bSRobert Watson } 20307f724f8bSRobert Watson 203195fab37eSRobert Watson /* 203295fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 203395fab37eSRobert Watson * permission allowed for each object type we know about in its 203495fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 203595fab37eSRobert Watson * know) when necessary. The process lock is not held here. 203695fab37eSRobert Watson */ 20374d10c0ceSRobert Watson void 203895fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 203995fab37eSRobert Watson { 204095fab37eSRobert Watson 204195fab37eSRobert Watson /* XXX freeze all other threads */ 204295fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 204395fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 204495fab37eSRobert Watson /* XXX allow other threads to continue */ 204595fab37eSRobert Watson } 204695fab37eSRobert Watson 204795fab37eSRobert Watson static __inline const char * 204895fab37eSRobert Watson prot2str(vm_prot_t prot) 204995fab37eSRobert Watson { 205095fab37eSRobert Watson 205195fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 205295fab37eSRobert Watson case VM_PROT_READ: 205395fab37eSRobert Watson return ("r--"); 205495fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 205595fab37eSRobert Watson return ("rw-"); 205695fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 205795fab37eSRobert Watson return ("r-x"); 205895fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 205995fab37eSRobert Watson return ("rwx"); 206095fab37eSRobert Watson case VM_PROT_WRITE: 206195fab37eSRobert Watson return ("-w-"); 206295fab37eSRobert Watson case VM_PROT_EXECUTE: 206395fab37eSRobert Watson return ("--x"); 206495fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 206595fab37eSRobert Watson return ("-wx"); 206695fab37eSRobert Watson default: 206795fab37eSRobert Watson return ("---"); 206895fab37eSRobert Watson } 206995fab37eSRobert Watson } 207095fab37eSRobert Watson 207195fab37eSRobert Watson static void 207295fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 207395fab37eSRobert Watson struct vm_map *map) 207495fab37eSRobert Watson { 207595fab37eSRobert Watson struct vm_map_entry *vme; 2076e183f80eSRobert Watson int result; 2077e183f80eSRobert Watson vm_prot_t revokeperms; 207895fab37eSRobert Watson vm_object_t object; 207995fab37eSRobert Watson vm_ooffset_t offset; 208095fab37eSRobert Watson struct vnode *vp; 208195fab37eSRobert Watson 2082c0f39905SRobert Watson if (!mac_mmap_revocation) 2083c0f39905SRobert Watson return; 2084c0f39905SRobert Watson 208595fab37eSRobert Watson vm_map_lock_read(map); 208695fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 208795fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 208895fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 208995fab37eSRobert Watson vme->object.sub_map); 209095fab37eSRobert Watson continue; 209195fab37eSRobert Watson } 209295fab37eSRobert Watson /* 209395fab37eSRobert Watson * Skip over entries that obviously are not shared. 209495fab37eSRobert Watson */ 209595fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 209695fab37eSRobert Watson !vme->max_protection) 209795fab37eSRobert Watson continue; 209895fab37eSRobert Watson /* 209995fab37eSRobert Watson * Drill down to the deepest backing object. 210095fab37eSRobert Watson */ 210195fab37eSRobert Watson offset = vme->offset; 210295fab37eSRobert Watson object = vme->object.vm_object; 210395fab37eSRobert Watson if (object == NULL) 210495fab37eSRobert Watson continue; 210595fab37eSRobert Watson while (object->backing_object != NULL) { 210695fab37eSRobert Watson object = object->backing_object; 210795fab37eSRobert Watson offset += object->backing_object_offset; 210895fab37eSRobert Watson } 210995fab37eSRobert Watson /* 211095fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 211195fab37eSRobert Watson * by the MAC system, so only things with backing by a 211295fab37eSRobert Watson * normal object (read: vnodes) are checked. 211395fab37eSRobert Watson */ 211495fab37eSRobert Watson if (object->type != OBJT_VNODE) 211595fab37eSRobert Watson continue; 211695fab37eSRobert Watson vp = (struct vnode *)object->handle; 211795fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2118e183f80eSRobert Watson result = vme->max_protection; 2119e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 212095fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 212195fab37eSRobert Watson /* 212295fab37eSRobert Watson * Find out what maximum protection we may be allowing 212395fab37eSRobert Watson * now but a policy needs to get removed. 212495fab37eSRobert Watson */ 212595fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 212695fab37eSRobert Watson if (!revokeperms) 212795fab37eSRobert Watson continue; 2128b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 2129b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2130b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 2131b656366bSBruce Evans (long)(vme->end - vme->start), 213295fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 213395fab37eSRobert Watson vm_map_lock_upgrade(map); 213495fab37eSRobert Watson /* 213595fab37eSRobert Watson * This is the really simple case: if a map has more 213695fab37eSRobert Watson * max_protection than is allowed, but it's not being 213795fab37eSRobert Watson * actually used (that is, the current protection is 213895fab37eSRobert Watson * still allowed), we can just wipe it out and do 213995fab37eSRobert Watson * nothing more. 214095fab37eSRobert Watson */ 214195fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 214295fab37eSRobert Watson vme->max_protection -= revokeperms; 214395fab37eSRobert Watson } else { 214495fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 214595fab37eSRobert Watson /* 214695fab37eSRobert Watson * In the more complicated case, flush out all 214795fab37eSRobert Watson * pending changes to the object then turn it 214895fab37eSRobert Watson * copy-on-write. 214995fab37eSRobert Watson */ 215095fab37eSRobert Watson vm_object_reference(object); 215195fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2152b6e48e03SAlan Cox VM_OBJECT_LOCK(object); 215395fab37eSRobert Watson vm_object_page_clean(object, 215495fab37eSRobert Watson OFF_TO_IDX(offset), 215595fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 215695fab37eSRobert Watson PAGE_MASK), 215795fab37eSRobert Watson OBJPC_SYNC); 2158b6e48e03SAlan Cox VM_OBJECT_UNLOCK(object); 215995fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 216095fab37eSRobert Watson vm_object_deallocate(object); 216195fab37eSRobert Watson /* 216295fab37eSRobert Watson * Why bother if there's no read permissions 216395fab37eSRobert Watson * anymore? For the rest, we need to leave 216495fab37eSRobert Watson * the write permissions on for COW, or 216595fab37eSRobert Watson * remove them entirely if configured to. 216695fab37eSRobert Watson */ 216795fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 216895fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 216995fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 217095fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 217195fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 217295fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 217395fab37eSRobert Watson } 217495fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 217595fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 217695fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 217795fab37eSRobert Watson } 217895fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 217995fab37eSRobert Watson vme->max_protection = 0; 218095fab37eSRobert Watson vme->protection = 0; 218195fab37eSRobert Watson } 218295fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 218395fab37eSRobert Watson vme->protection & ~revokeperms); 218495fab37eSRobert Watson vm_map_simplify_entry(map, vme); 218595fab37eSRobert Watson } 218695fab37eSRobert Watson vm_map_lock_downgrade(map); 218795fab37eSRobert Watson } 218895fab37eSRobert Watson vm_map_unlock_read(map); 218995fab37eSRobert Watson } 219095fab37eSRobert Watson 219195fab37eSRobert Watson /* 219295fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 219395fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 219495fab37eSRobert Watson * buffer cache. 219595fab37eSRobert Watson */ 219695fab37eSRobert Watson static void 219795fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 219895fab37eSRobert Watson { 219995fab37eSRobert Watson 220095fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 220195fab37eSRobert Watson } 220295fab37eSRobert Watson 220395fab37eSRobert Watson void 220495fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 220595fab37eSRobert Watson { 220695fab37eSRobert Watson 220795fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 220895fab37eSRobert Watson } 220995fab37eSRobert Watson 221095fab37eSRobert Watson void 221195fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 221295fab37eSRobert Watson { 221395fab37eSRobert Watson 221495fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 221595fab37eSRobert Watson } 221695fab37eSRobert Watson 221795fab37eSRobert Watson void 221895fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 221995fab37eSRobert Watson { 222095fab37eSRobert Watson 222195fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 222295fab37eSRobert Watson } 222395fab37eSRobert Watson 222495fab37eSRobert Watson void 222595fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 222695fab37eSRobert Watson { 222795fab37eSRobert Watson 222895fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 222995fab37eSRobert Watson } 223095fab37eSRobert Watson 223195fab37eSRobert Watson void 223295fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 223395fab37eSRobert Watson { 223495fab37eSRobert Watson 223595fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 223695fab37eSRobert Watson } 223795fab37eSRobert Watson 223895fab37eSRobert Watson void 223995fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 224095fab37eSRobert Watson struct socket *newsocket) 224195fab37eSRobert Watson { 224295fab37eSRobert Watson 224395fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 224495fab37eSRobert Watson newsocket, &newsocket->so_label); 224595fab37eSRobert Watson } 224695fab37eSRobert Watson 224795fab37eSRobert Watson static void 224895fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 224995fab37eSRobert Watson struct label *newlabel) 225095fab37eSRobert Watson { 225195fab37eSRobert Watson 225295fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 225395fab37eSRobert Watson } 225495fab37eSRobert Watson 225595fab37eSRobert Watson static void 225695fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 225795fab37eSRobert Watson { 225895fab37eSRobert Watson 225995fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 226095fab37eSRobert Watson } 226195fab37eSRobert Watson 226295fab37eSRobert Watson void 226395fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 226495fab37eSRobert Watson { 226510eeb10cSRobert Watson struct label *label; 226695fab37eSRobert Watson 226710eeb10cSRobert Watson label = mbuf_to_label(mbuf); 226810eeb10cSRobert Watson 226910eeb10cSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket, 227010eeb10cSRobert Watson &socket->so_peerlabel); 227195fab37eSRobert Watson } 227295fab37eSRobert Watson 227395fab37eSRobert Watson void 227495fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 227595fab37eSRobert Watson struct socket *newsocket) 227695fab37eSRobert Watson { 227795fab37eSRobert Watson 227895fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 227995fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 228095fab37eSRobert Watson } 228195fab37eSRobert Watson 228295fab37eSRobert Watson void 228395fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 228495fab37eSRobert Watson { 228510eeb10cSRobert Watson struct label *label; 228610eeb10cSRobert Watson 228710eeb10cSRobert Watson label = mbuf_to_label(datagram); 228895fab37eSRobert Watson 228995fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 229010eeb10cSRobert Watson datagram, label); 229195fab37eSRobert Watson } 229295fab37eSRobert Watson 229395fab37eSRobert Watson void 229495fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 229595fab37eSRobert Watson { 229610eeb10cSRobert Watson struct label *datagramlabel, *fragmentlabel; 229795fab37eSRobert Watson 229810eeb10cSRobert Watson datagramlabel = mbuf_to_label(datagram); 229910eeb10cSRobert Watson fragmentlabel = mbuf_to_label(fragment); 230010eeb10cSRobert Watson 230110eeb10cSRobert Watson MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment, 230210eeb10cSRobert Watson fragmentlabel); 230395fab37eSRobert Watson } 230495fab37eSRobert Watson 230595fab37eSRobert Watson void 230695fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 230795fab37eSRobert Watson { 230810eeb10cSRobert Watson struct label *label; 230995fab37eSRobert Watson 231010eeb10cSRobert Watson label = mbuf_to_label(fragment); 231110eeb10cSRobert Watson 231210eeb10cSRobert Watson MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label); 231395fab37eSRobert Watson } 231495fab37eSRobert Watson 231595fab37eSRobert Watson void 231695fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 231795fab37eSRobert Watson { 231810eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 231995fab37eSRobert Watson 232010eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 232110eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 232210eeb10cSRobert Watson 232310eeb10cSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf, 232410eeb10cSRobert Watson newmbuflabel); 232595fab37eSRobert Watson } 232695fab37eSRobert Watson 232795fab37eSRobert Watson void 232895fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 232995fab37eSRobert Watson { 233010eeb10cSRobert Watson struct label *label; 233110eeb10cSRobert Watson 233210eeb10cSRobert Watson label = mbuf_to_label(mbuf); 233395fab37eSRobert Watson 233495fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 233510eeb10cSRobert Watson label); 233695fab37eSRobert Watson } 233795fab37eSRobert Watson 233895fab37eSRobert Watson void 233995fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 234095fab37eSRobert Watson { 234110eeb10cSRobert Watson struct label *label; 234210eeb10cSRobert Watson 234310eeb10cSRobert Watson label = mbuf_to_label(mbuf); 234495fab37eSRobert Watson 234595fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 234610eeb10cSRobert Watson label); 234795fab37eSRobert Watson } 234895fab37eSRobert Watson 234995fab37eSRobert Watson void 235095fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 235195fab37eSRobert Watson { 235210eeb10cSRobert Watson struct label *label; 235310eeb10cSRobert Watson 235410eeb10cSRobert Watson label = mbuf_to_label(mbuf); 235595fab37eSRobert Watson 235695fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 235710eeb10cSRobert Watson label); 235895fab37eSRobert Watson } 235995fab37eSRobert Watson 236095fab37eSRobert Watson void 236195fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 236295fab37eSRobert Watson struct mbuf *newmbuf) 236395fab37eSRobert Watson { 236410eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 236595fab37eSRobert Watson 236610eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 236710eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 236810eeb10cSRobert Watson 236910eeb10cSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel, 237010eeb10cSRobert Watson ifnet, &ifnet->if_label, newmbuf, newmbuflabel); 237195fab37eSRobert Watson } 237295fab37eSRobert Watson 237395fab37eSRobert Watson void 237495fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 237595fab37eSRobert Watson { 237610eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 237795fab37eSRobert Watson 237810eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 237910eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 238010eeb10cSRobert Watson 238110eeb10cSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf, 238210eeb10cSRobert Watson newmbuflabel); 238395fab37eSRobert Watson } 238495fab37eSRobert Watson 238595fab37eSRobert Watson int 238695fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 238795fab37eSRobert Watson { 238810eeb10cSRobert Watson struct label *label; 238995fab37eSRobert Watson int result; 239095fab37eSRobert Watson 239110eeb10cSRobert Watson label = mbuf_to_label(fragment); 239210eeb10cSRobert Watson 239395fab37eSRobert Watson result = 1; 239410eeb10cSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq, 239510eeb10cSRobert Watson &ipq->ipq_label); 239695fab37eSRobert Watson 239795fab37eSRobert Watson return (result); 239895fab37eSRobert Watson } 239995fab37eSRobert Watson 240095fab37eSRobert Watson void 2401eb8c7f99SRobert Watson mac_reflect_mbuf_icmp(struct mbuf *m) 2402eb8c7f99SRobert Watson { 2403eb8c7f99SRobert Watson struct label *label; 2404eb8c7f99SRobert Watson 2405eb8c7f99SRobert Watson label = mbuf_to_label(m); 2406eb8c7f99SRobert Watson 2407eb8c7f99SRobert Watson MAC_PERFORM(reflect_mbuf_icmp, m, label); 2408eb8c7f99SRobert Watson } 2409eb8c7f99SRobert Watson void 2410eb8c7f99SRobert Watson mac_reflect_mbuf_tcp(struct mbuf *m) 2411eb8c7f99SRobert Watson { 2412eb8c7f99SRobert Watson struct label *label; 2413eb8c7f99SRobert Watson 2414eb8c7f99SRobert Watson label = mbuf_to_label(m); 2415eb8c7f99SRobert Watson 2416eb8c7f99SRobert Watson MAC_PERFORM(reflect_mbuf_tcp, m, label); 2417eb8c7f99SRobert Watson } 2418eb8c7f99SRobert Watson 2419eb8c7f99SRobert Watson void 242095fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 242195fab37eSRobert Watson { 242210eeb10cSRobert Watson struct label *label; 242395fab37eSRobert Watson 242410eeb10cSRobert Watson label = mbuf_to_label(fragment); 242510eeb10cSRobert Watson 242610eeb10cSRobert Watson MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label); 242795fab37eSRobert Watson } 242895fab37eSRobert Watson 242995fab37eSRobert Watson void 243095fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 243195fab37eSRobert Watson { 243210eeb10cSRobert Watson struct label *label; 243310eeb10cSRobert Watson 243410eeb10cSRobert Watson label = mbuf_to_label(mbuf); 243595fab37eSRobert Watson 243695fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 243710eeb10cSRobert Watson label); 243895fab37eSRobert Watson } 243995fab37eSRobert Watson 244095fab37eSRobert Watson void 244195fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 244295fab37eSRobert Watson { 244395fab37eSRobert Watson 244495fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 244595fab37eSRobert Watson &mp->mnt_fslabel); 244695fab37eSRobert Watson } 244795fab37eSRobert Watson 244895fab37eSRobert Watson void 244995fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 245095fab37eSRobert Watson { 245195fab37eSRobert Watson 245295fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 245395fab37eSRobert Watson &mp->mnt_fslabel); 245495fab37eSRobert Watson } 245595fab37eSRobert Watson 245695fab37eSRobert Watson int 245795fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 245895fab37eSRobert Watson { 245995fab37eSRobert Watson int error; 246095fab37eSRobert Watson 246195fab37eSRobert Watson if (!mac_enforce_network) 246295fab37eSRobert Watson return (0); 246395fab37eSRobert Watson 246495fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 246595fab37eSRobert Watson &ifnet->if_label); 246695fab37eSRobert Watson 246795fab37eSRobert Watson return (error); 246895fab37eSRobert Watson } 246995fab37eSRobert Watson 247095fab37eSRobert Watson static int 247195fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 247295fab37eSRobert Watson { 247395fab37eSRobert Watson int error; 247495fab37eSRobert Watson 247595fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 247695fab37eSRobert Watson 247795fab37eSRobert Watson return (error); 247895fab37eSRobert Watson } 247995fab37eSRobert Watson 248095fab37eSRobert Watson int 248195fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 248295fab37eSRobert Watson { 248395fab37eSRobert Watson int error; 248495fab37eSRobert Watson 248595fab37eSRobert Watson if (!mac_enforce_process) 248695fab37eSRobert Watson return (0); 248795fab37eSRobert Watson 248895fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 248995fab37eSRobert Watson 249095fab37eSRobert Watson return (error); 249195fab37eSRobert Watson } 249295fab37eSRobert Watson 249395fab37eSRobert Watson int 249495fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 249595fab37eSRobert Watson { 249610eeb10cSRobert Watson struct label *label; 249795fab37eSRobert Watson int error; 249895fab37eSRobert Watson 2499225bff6fSRobert Watson M_ASSERTPKTHDR(mbuf); 2500225bff6fSRobert Watson 250195fab37eSRobert Watson if (!mac_enforce_network) 250295fab37eSRobert Watson return (0); 250395fab37eSRobert Watson 250410eeb10cSRobert Watson label = mbuf_to_label(mbuf); 250595fab37eSRobert Watson 250695fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 250710eeb10cSRobert Watson label); 250895fab37eSRobert Watson 250995fab37eSRobert Watson return (error); 251095fab37eSRobert Watson } 251195fab37eSRobert Watson 251295fab37eSRobert Watson int 2513e686e5aeSRobert Watson mac_check_kenv_dump(struct ucred *cred) 2514e686e5aeSRobert Watson { 2515e686e5aeSRobert Watson int error; 2516e686e5aeSRobert Watson 2517e686e5aeSRobert Watson if (!mac_enforce_system) 2518e686e5aeSRobert Watson return (0); 2519e686e5aeSRobert Watson 2520e686e5aeSRobert Watson MAC_CHECK(check_kenv_dump, cred); 2521e686e5aeSRobert Watson 2522e686e5aeSRobert Watson return (error); 2523e686e5aeSRobert Watson } 2524e686e5aeSRobert Watson 2525e686e5aeSRobert Watson int 2526e686e5aeSRobert Watson mac_check_kenv_get(struct ucred *cred, char *name) 2527e686e5aeSRobert Watson { 2528e686e5aeSRobert Watson int error; 2529e686e5aeSRobert Watson 2530e686e5aeSRobert Watson if (!mac_enforce_system) 2531e686e5aeSRobert Watson return (0); 2532e686e5aeSRobert Watson 2533e686e5aeSRobert Watson MAC_CHECK(check_kenv_get, cred, name); 2534e686e5aeSRobert Watson 2535e686e5aeSRobert Watson return (error); 2536e686e5aeSRobert Watson } 2537e686e5aeSRobert Watson 2538e686e5aeSRobert Watson int 2539e686e5aeSRobert Watson mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2540e686e5aeSRobert Watson { 2541e686e5aeSRobert Watson int error; 2542e686e5aeSRobert Watson 2543e686e5aeSRobert Watson if (!mac_enforce_system) 2544e686e5aeSRobert Watson return (0); 2545e686e5aeSRobert Watson 2546e686e5aeSRobert Watson MAC_CHECK(check_kenv_set, cred, name, value); 2547e686e5aeSRobert Watson 2548e686e5aeSRobert Watson return (error); 2549e686e5aeSRobert Watson } 2550e686e5aeSRobert Watson 2551e686e5aeSRobert Watson int 2552e686e5aeSRobert Watson mac_check_kenv_unset(struct ucred *cred, char *name) 2553e686e5aeSRobert Watson { 2554e686e5aeSRobert Watson int error; 2555e686e5aeSRobert Watson 2556e686e5aeSRobert Watson if (!mac_enforce_system) 2557e686e5aeSRobert Watson return (0); 2558e686e5aeSRobert Watson 2559e686e5aeSRobert Watson MAC_CHECK(check_kenv_unset, cred, name); 2560e686e5aeSRobert Watson 2561e686e5aeSRobert Watson return (error); 2562e686e5aeSRobert Watson } 2563e686e5aeSRobert Watson 2564e686e5aeSRobert Watson int 2565a3df768bSRobert Watson mac_check_kld_load(struct ucred *cred, struct vnode *vp) 2566a3df768bSRobert Watson { 2567a3df768bSRobert Watson int error; 2568a3df768bSRobert Watson 2569a3df768bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_kld_load"); 2570a3df768bSRobert Watson 2571a3df768bSRobert Watson if (!mac_enforce_kld) 2572a3df768bSRobert Watson return (0); 2573a3df768bSRobert Watson 2574a3df768bSRobert Watson MAC_CHECK(check_kld_load, cred, vp, &vp->v_label); 2575a3df768bSRobert Watson 2576a3df768bSRobert Watson return (error); 2577a3df768bSRobert Watson } 2578a3df768bSRobert Watson 2579a3df768bSRobert Watson int 2580a3df768bSRobert Watson mac_check_kld_stat(struct ucred *cred) 2581a3df768bSRobert Watson { 2582a3df768bSRobert Watson int error; 2583a3df768bSRobert Watson 2584a3df768bSRobert Watson if (!mac_enforce_kld) 2585a3df768bSRobert Watson return (0); 2586a3df768bSRobert Watson 2587a3df768bSRobert Watson MAC_CHECK(check_kld_stat, cred); 2588a3df768bSRobert Watson 2589a3df768bSRobert Watson return (error); 2590a3df768bSRobert Watson } 2591a3df768bSRobert Watson 2592a3df768bSRobert Watson int 2593a3df768bSRobert Watson mac_check_kld_unload(struct ucred *cred) 2594a3df768bSRobert Watson { 2595a3df768bSRobert Watson int error; 2596a3df768bSRobert Watson 2597a3df768bSRobert Watson if (!mac_enforce_kld) 2598a3df768bSRobert Watson return (0); 2599a3df768bSRobert Watson 2600a3df768bSRobert Watson MAC_CHECK(check_kld_unload, cred); 2601a3df768bSRobert Watson 2602a3df768bSRobert Watson return (error); 2603a3df768bSRobert Watson } 2604a3df768bSRobert Watson 2605a3df768bSRobert Watson int 260695fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 260795fab37eSRobert Watson { 260895fab37eSRobert Watson int error; 260995fab37eSRobert Watson 261095fab37eSRobert Watson if (!mac_enforce_fs) 261195fab37eSRobert Watson return (0); 261295fab37eSRobert Watson 261395fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 261495fab37eSRobert Watson 261595fab37eSRobert Watson return (error); 261695fab37eSRobert Watson } 261795fab37eSRobert Watson 261895fab37eSRobert Watson int 261995fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 262095fab37eSRobert Watson void *data) 262195fab37eSRobert Watson { 262295fab37eSRobert Watson int error; 262395fab37eSRobert Watson 26241aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26251aa37f53SRobert Watson 26261aa37f53SRobert Watson if (!mac_enforce_pipe) 26271aa37f53SRobert Watson return (0); 26281aa37f53SRobert Watson 262995fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 263095fab37eSRobert Watson 263195fab37eSRobert Watson return (error); 263295fab37eSRobert Watson } 263395fab37eSRobert Watson 263495fab37eSRobert Watson int 2635c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 263695fab37eSRobert Watson { 263795fab37eSRobert Watson int error; 263895fab37eSRobert Watson 26391aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26401aa37f53SRobert Watson 26411aa37f53SRobert Watson if (!mac_enforce_pipe) 26421aa37f53SRobert Watson return (0); 26431aa37f53SRobert Watson 2644c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2645c024c3eeSRobert Watson 2646c024c3eeSRobert Watson return (error); 2647c024c3eeSRobert Watson } 2648c024c3eeSRobert Watson 2649c024c3eeSRobert Watson int 2650c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2651c024c3eeSRobert Watson { 2652c024c3eeSRobert Watson int error; 2653c024c3eeSRobert Watson 26541aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26551aa37f53SRobert Watson 26561aa37f53SRobert Watson if (!mac_enforce_pipe) 26571aa37f53SRobert Watson return (0); 26581aa37f53SRobert Watson 2659c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 266095fab37eSRobert Watson 266195fab37eSRobert Watson return (error); 266295fab37eSRobert Watson } 266395fab37eSRobert Watson 266495fab37eSRobert Watson static int 266595fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 266695fab37eSRobert Watson struct label *newlabel) 266795fab37eSRobert Watson { 266895fab37eSRobert Watson int error; 266995fab37eSRobert Watson 26701aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26711aa37f53SRobert Watson 26721aa37f53SRobert Watson if (!mac_enforce_pipe) 26731aa37f53SRobert Watson return (0); 26741aa37f53SRobert Watson 267595fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 267695fab37eSRobert Watson 267795fab37eSRobert Watson return (error); 267895fab37eSRobert Watson } 267995fab37eSRobert Watson 268095fab37eSRobert Watson int 2681c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2682c024c3eeSRobert Watson { 2683c024c3eeSRobert Watson int error; 2684c024c3eeSRobert Watson 26851aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26861aa37f53SRobert Watson 26871aa37f53SRobert Watson if (!mac_enforce_pipe) 26881aa37f53SRobert Watson return (0); 26891aa37f53SRobert Watson 2690c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2691c024c3eeSRobert Watson 2692c024c3eeSRobert Watson return (error); 2693c024c3eeSRobert Watson } 2694c024c3eeSRobert Watson 2695c024c3eeSRobert Watson int 2696c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2697c024c3eeSRobert Watson { 2698c024c3eeSRobert Watson int error; 2699c024c3eeSRobert Watson 27001aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 27011aa37f53SRobert Watson 27021aa37f53SRobert Watson if (!mac_enforce_pipe) 27031aa37f53SRobert Watson return (0); 27041aa37f53SRobert Watson 2705c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2706c024c3eeSRobert Watson 2707c024c3eeSRobert Watson return (error); 2708c024c3eeSRobert Watson } 2709c024c3eeSRobert Watson 2710c024c3eeSRobert Watson int 271195fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 271295fab37eSRobert Watson { 271395fab37eSRobert Watson int error; 271495fab37eSRobert Watson 2715b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2716b12baf55SRobert Watson 271795fab37eSRobert Watson if (!mac_enforce_process) 271895fab37eSRobert Watson return (0); 271995fab37eSRobert Watson 272095fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 272195fab37eSRobert Watson 272295fab37eSRobert Watson return (error); 272395fab37eSRobert Watson } 272495fab37eSRobert Watson 272595fab37eSRobert Watson int 272695fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 272795fab37eSRobert Watson { 272895fab37eSRobert Watson int error; 272995fab37eSRobert Watson 2730b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2731b12baf55SRobert Watson 273295fab37eSRobert Watson if (!mac_enforce_process) 273395fab37eSRobert Watson return (0); 273495fab37eSRobert Watson 273595fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 273695fab37eSRobert Watson 273795fab37eSRobert Watson return (error); 273895fab37eSRobert Watson } 273995fab37eSRobert Watson 274095fab37eSRobert Watson int 274195fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 274295fab37eSRobert Watson { 274395fab37eSRobert Watson int error; 274495fab37eSRobert Watson 2745b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2746b12baf55SRobert Watson 274795fab37eSRobert Watson if (!mac_enforce_process) 274895fab37eSRobert Watson return (0); 274995fab37eSRobert Watson 275095fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 275195fab37eSRobert Watson 275295fab37eSRobert Watson return (error); 275395fab37eSRobert Watson } 275495fab37eSRobert Watson 275595fab37eSRobert Watson int 275695fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 275795fab37eSRobert Watson struct sockaddr *sockaddr) 275895fab37eSRobert Watson { 275995fab37eSRobert Watson int error; 276095fab37eSRobert Watson 276195fab37eSRobert Watson if (!mac_enforce_socket) 276295fab37eSRobert Watson return (0); 276395fab37eSRobert Watson 276495fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 276595fab37eSRobert Watson sockaddr); 276695fab37eSRobert Watson 276795fab37eSRobert Watson return (error); 276895fab37eSRobert Watson } 276995fab37eSRobert Watson 277095fab37eSRobert Watson int 277195fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 277295fab37eSRobert Watson struct sockaddr *sockaddr) 277395fab37eSRobert Watson { 277495fab37eSRobert Watson int error; 277595fab37eSRobert Watson 277695fab37eSRobert Watson if (!mac_enforce_socket) 277795fab37eSRobert Watson return (0); 277895fab37eSRobert Watson 277995fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 278095fab37eSRobert Watson sockaddr); 278195fab37eSRobert Watson 278295fab37eSRobert Watson return (error); 278395fab37eSRobert Watson } 278495fab37eSRobert Watson 278595fab37eSRobert Watson int 2786d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2787d61198e4SRobert Watson { 278810eeb10cSRobert Watson struct label *label; 2789d61198e4SRobert Watson int error; 2790d61198e4SRobert Watson 2791d61198e4SRobert Watson if (!mac_enforce_socket) 2792d61198e4SRobert Watson return (0); 2793d61198e4SRobert Watson 279410eeb10cSRobert Watson label = mbuf_to_label(mbuf); 279510eeb10cSRobert Watson 2796d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 279710eeb10cSRobert Watson label); 2798d61198e4SRobert Watson 2799d61198e4SRobert Watson return (error); 2800d61198e4SRobert Watson } 2801d61198e4SRobert Watson 2802d61198e4SRobert Watson int 280395fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 280495fab37eSRobert Watson { 280595fab37eSRobert Watson int error; 280695fab37eSRobert Watson 280795fab37eSRobert Watson if (!mac_enforce_socket) 280895fab37eSRobert Watson return (0); 280995fab37eSRobert Watson 281095fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 281195fab37eSRobert Watson return (error); 281295fab37eSRobert Watson } 281395fab37eSRobert Watson 2814b371c939SRobert Watson int 2815b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 2816b371c939SRobert Watson { 2817b371c939SRobert Watson int error; 2818b371c939SRobert Watson 2819b371c939SRobert Watson if (!mac_enforce_socket) 2820b371c939SRobert Watson return (0); 2821b371c939SRobert Watson 2822b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2823b371c939SRobert Watson 2824b371c939SRobert Watson return (error); 2825b371c939SRobert Watson } 2826b371c939SRobert Watson 282795fab37eSRobert Watson static int 282895fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 282995fab37eSRobert Watson struct label *newlabel) 283095fab37eSRobert Watson { 283195fab37eSRobert Watson int error; 283295fab37eSRobert Watson 283395fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 283495fab37eSRobert Watson newlabel); 283595fab37eSRobert Watson 283695fab37eSRobert Watson return (error); 283795fab37eSRobert Watson } 283895fab37eSRobert Watson 283995fab37eSRobert Watson int 2840b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 2841b371c939SRobert Watson { 2842b371c939SRobert Watson int error; 2843b371c939SRobert Watson 2844b371c939SRobert Watson if (!mac_enforce_socket) 2845b371c939SRobert Watson return (0); 2846b371c939SRobert Watson 2847b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2848b371c939SRobert Watson 2849b371c939SRobert Watson return (error); 2850b371c939SRobert Watson } 2851b371c939SRobert Watson 2852b371c939SRobert Watson int 285395fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 285495fab37eSRobert Watson { 285595fab37eSRobert Watson int error; 285695fab37eSRobert Watson 285795fab37eSRobert Watson if (!mac_enforce_socket) 285895fab37eSRobert Watson return (0); 285995fab37eSRobert Watson 286095fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 286195fab37eSRobert Watson 286295fab37eSRobert Watson return (error); 286395fab37eSRobert Watson } 286495fab37eSRobert Watson 286595fab37eSRobert Watson int 286692835789SRobert Watson mac_check_sysarch_ioperm(struct ucred *cred) 286792835789SRobert Watson { 286892835789SRobert Watson int error; 286992835789SRobert Watson 287092835789SRobert Watson if (!mac_enforce_system) 287192835789SRobert Watson return (0); 287292835789SRobert Watson 287392835789SRobert Watson MAC_CHECK(check_sysarch_ioperm, cred); 287492835789SRobert Watson return (error); 287592835789SRobert Watson } 287692835789SRobert Watson 287792835789SRobert Watson int 2878e5e820fdSRobert Watson mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2879e5e820fdSRobert Watson { 2880e5e820fdSRobert Watson int error; 2881e5e820fdSRobert Watson 2882e5e820fdSRobert Watson if (vp != NULL) { 2883e5e820fdSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2884e5e820fdSRobert Watson } 2885e5e820fdSRobert Watson 2886e5e820fdSRobert Watson if (!mac_enforce_system) 2887e5e820fdSRobert Watson return (0); 2888e5e820fdSRobert Watson 2889e5e820fdSRobert Watson MAC_CHECK(check_system_acct, cred, vp, 2890e5e820fdSRobert Watson vp != NULL ? &vp->v_label : NULL); 2891e5e820fdSRobert Watson 2892e5e820fdSRobert Watson return (error); 2893e5e820fdSRobert Watson } 2894e5e820fdSRobert Watson 2895e5e820fdSRobert Watson int 2896e5e820fdSRobert Watson mac_check_system_nfsd(struct ucred *cred) 2897e5e820fdSRobert Watson { 2898e5e820fdSRobert Watson int error; 2899e5e820fdSRobert Watson 2900e5e820fdSRobert Watson if (!mac_enforce_system) 2901e5e820fdSRobert Watson return (0); 2902e5e820fdSRobert Watson 2903e5e820fdSRobert Watson MAC_CHECK(check_system_nfsd, cred); 2904e5e820fdSRobert Watson 2905e5e820fdSRobert Watson return (error); 2906e5e820fdSRobert Watson } 2907e5e820fdSRobert Watson 2908e5e820fdSRobert Watson int 2909a2ecb9b7SRobert Watson mac_check_system_reboot(struct ucred *cred, int howto) 2910a2ecb9b7SRobert Watson { 2911a2ecb9b7SRobert Watson int error; 2912a2ecb9b7SRobert Watson 29139e913ebdSRobert Watson if (!mac_enforce_system) 2914a2ecb9b7SRobert Watson return (0); 2915a2ecb9b7SRobert Watson 2916a2ecb9b7SRobert Watson MAC_CHECK(check_system_reboot, cred, howto); 29179e913ebdSRobert Watson 2918a2ecb9b7SRobert Watson return (error); 2919a2ecb9b7SRobert Watson } 2920a2ecb9b7SRobert Watson 2921a2ecb9b7SRobert Watson int 29224b8d5f2dSRobert Watson mac_check_system_settime(struct ucred *cred) 29234b8d5f2dSRobert Watson { 29244b8d5f2dSRobert Watson int error; 29254b8d5f2dSRobert Watson 29264b8d5f2dSRobert Watson if (!mac_enforce_system) 29274b8d5f2dSRobert Watson return (0); 29284b8d5f2dSRobert Watson 29294b8d5f2dSRobert Watson MAC_CHECK(check_system_settime, cred); 29304b8d5f2dSRobert Watson 29314b8d5f2dSRobert Watson return (error); 29324b8d5f2dSRobert Watson } 29334b8d5f2dSRobert Watson 29344b8d5f2dSRobert Watson int 293503ce2c0cSRobert Watson mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 293603ce2c0cSRobert Watson { 293703ce2c0cSRobert Watson int error; 293803ce2c0cSRobert Watson 293903ce2c0cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 294003ce2c0cSRobert Watson 29419e913ebdSRobert Watson if (!mac_enforce_system) 294203ce2c0cSRobert Watson return (0); 294303ce2c0cSRobert Watson 294403ce2c0cSRobert Watson MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 294503ce2c0cSRobert Watson return (error); 294603ce2c0cSRobert Watson } 294703ce2c0cSRobert Watson 294803ce2c0cSRobert Watson int 29491b2c2ab2SRobert Watson mac_check_system_swapoff(struct ucred *cred, struct vnode *vp) 29501b2c2ab2SRobert Watson { 29511b2c2ab2SRobert Watson int error; 29521b2c2ab2SRobert Watson 29531b2c2ab2SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff"); 29541b2c2ab2SRobert Watson 29551b2c2ab2SRobert Watson if (!mac_enforce_system) 29561b2c2ab2SRobert Watson return (0); 29571b2c2ab2SRobert Watson 29581b2c2ab2SRobert Watson MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label); 29591b2c2ab2SRobert Watson return (error); 29601b2c2ab2SRobert Watson } 29611b2c2ab2SRobert Watson 29621b2c2ab2SRobert Watson int 2963d3fc69eeSRobert Watson mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2964d3fc69eeSRobert Watson void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2965d3fc69eeSRobert Watson { 2966d3fc69eeSRobert Watson int error; 2967d3fc69eeSRobert Watson 2968d3fc69eeSRobert Watson /* 2969d3fc69eeSRobert Watson * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2970d3fc69eeSRobert Watson * but since it's not exported from kern_sysctl.c, we can't. 2971d3fc69eeSRobert Watson */ 29729e913ebdSRobert Watson if (!mac_enforce_system) 2973d3fc69eeSRobert Watson return (0); 2974d3fc69eeSRobert Watson 2975d3fc69eeSRobert Watson MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2976d3fc69eeSRobert Watson inkernel, new, newlen); 2977d3fc69eeSRobert Watson 2978d3fc69eeSRobert Watson return (error); 2979d3fc69eeSRobert Watson } 2980d3fc69eeSRobert Watson 2981d3fc69eeSRobert Watson int 298295fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 298395fab37eSRobert Watson struct ifnet *ifnet) 298495fab37eSRobert Watson { 2985f7b951a8SRobert Watson char *elements, *buffer; 2986f7b951a8SRobert Watson struct mac mac; 298795fab37eSRobert Watson int error; 298895fab37eSRobert Watson 2989f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 299095fab37eSRobert Watson if (error) 299195fab37eSRobert Watson return (error); 299295fab37eSRobert Watson 2993f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 2994f7b951a8SRobert Watson if (error) 2995f7b951a8SRobert Watson return (error); 2996f7b951a8SRobert Watson 2997a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2998f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2999f7b951a8SRobert Watson if (error) { 3000f7b951a8SRobert Watson free(elements, M_MACTEMP); 3001f7b951a8SRobert Watson return (error); 3002f7b951a8SRobert Watson } 3003f7b951a8SRobert Watson 3004a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3005f7b951a8SRobert Watson error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 3006a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3007f7b951a8SRobert Watson if (error == 0) 3008f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3009f7b951a8SRobert Watson 3010f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3011f7b951a8SRobert Watson free(elements, M_MACTEMP); 3012f7b951a8SRobert Watson 3013f7b951a8SRobert Watson return (error); 301495fab37eSRobert Watson } 301595fab37eSRobert Watson 301695fab37eSRobert Watson int 301795fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 301895fab37eSRobert Watson struct ifnet *ifnet) 301995fab37eSRobert Watson { 302095fab37eSRobert Watson struct label intlabel; 3021f7b951a8SRobert Watson struct mac mac; 3022f7b951a8SRobert Watson char *buffer; 302395fab37eSRobert Watson int error; 302495fab37eSRobert Watson 3025f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 302695fab37eSRobert Watson if (error) 302795fab37eSRobert Watson return (error); 302895fab37eSRobert Watson 3029f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 303095fab37eSRobert Watson if (error) 303195fab37eSRobert Watson return (error); 303295fab37eSRobert Watson 3033a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3034f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3035f7b951a8SRobert Watson if (error) { 3036f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3037f7b951a8SRobert Watson return (error); 3038f7b951a8SRobert Watson } 3039f7b951a8SRobert Watson 3040f7b951a8SRobert Watson mac_init_ifnet_label(&intlabel); 3041f7b951a8SRobert Watson error = mac_internalize_ifnet_label(&intlabel, buffer); 3042f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3043f7b951a8SRobert Watson if (error) { 3044f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3045f7b951a8SRobert Watson return (error); 3046f7b951a8SRobert Watson } 3047f7b951a8SRobert Watson 304895fab37eSRobert Watson /* 304995fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 305095fab37eSRobert Watson * policies impose this check themselves if required by the 305195fab37eSRobert Watson * policy. Eventually, this should go away. 305295fab37eSRobert Watson */ 305395fab37eSRobert Watson error = suser_cred(cred, 0); 3054f7b951a8SRobert Watson if (error) { 3055f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3056f7b951a8SRobert Watson return (error); 3057f7b951a8SRobert Watson } 305895fab37eSRobert Watson 305995fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 306095fab37eSRobert Watson &intlabel); 3061f7b951a8SRobert Watson if (error) { 3062f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3063f7b951a8SRobert Watson return (error); 3064f7b951a8SRobert Watson } 306595fab37eSRobert Watson 306695fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 306795fab37eSRobert Watson 3068f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3069f7b951a8SRobert Watson return (0); 307095fab37eSRobert Watson } 307195fab37eSRobert Watson 307295fab37eSRobert Watson void 3073990b4b2dSRobert Watson mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de) 307495fab37eSRobert Watson { 307595fab37eSRobert Watson 3076990b4b2dSRobert Watson MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label); 307795fab37eSRobert Watson } 307895fab37eSRobert Watson 307974e62b1bSRobert Watson void 3080990b4b2dSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct mount *mp, 3081990b4b2dSRobert Watson struct devfs_dirent *dd, struct devfs_dirent *de) 308274e62b1bSRobert Watson { 308374e62b1bSRobert Watson 3084990b4b2dSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de, 308574e62b1bSRobert Watson &de->de_label); 308674e62b1bSRobert Watson } 308774e62b1bSRobert Watson 308895fab37eSRobert Watson void 3089990b4b2dSRobert Watson mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, 309095fab37eSRobert Watson struct devfs_dirent *de) 309195fab37eSRobert Watson { 309295fab37eSRobert Watson 3093990b4b2dSRobert Watson MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de, 309495fab37eSRobert Watson &de->de_label); 309595fab37eSRobert Watson } 309695fab37eSRobert Watson 309795fab37eSRobert Watson int 309895fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 3099f7b951a8SRobert Watson struct mac *mac) 310095fab37eSRobert Watson { 310195fab37eSRobert Watson struct label intlabel; 3102f7b951a8SRobert Watson char *buffer; 310395fab37eSRobert Watson int error; 310495fab37eSRobert Watson 3105f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 310695fab37eSRobert Watson if (error) 310795fab37eSRobert Watson return (error); 310895fab37eSRobert Watson 3109a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3110f7b951a8SRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 3111f7b951a8SRobert Watson if (error) { 3112f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3113f7b951a8SRobert Watson return (error); 3114f7b951a8SRobert Watson } 3115f7b951a8SRobert Watson 3116a163d034SWarner Losh mac_init_socket_label(&intlabel, M_WAITOK); 3117f7b951a8SRobert Watson error = mac_internalize_socket_label(&intlabel, buffer); 3118f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3119f7b951a8SRobert Watson if (error) { 3120f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 3121f7b951a8SRobert Watson return (error); 3122f7b951a8SRobert Watson } 3123f7b951a8SRobert Watson 312495fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 312595fab37eSRobert Watson if (error) { 3126f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 312795fab37eSRobert Watson return (error); 312895fab37eSRobert Watson } 312995fab37eSRobert Watson 313095fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 313195fab37eSRobert Watson 3132f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 313395fab37eSRobert Watson return (0); 313495fab37eSRobert Watson } 313595fab37eSRobert Watson 313695fab37eSRobert Watson int 313795fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 313895fab37eSRobert Watson { 313995fab37eSRobert Watson int error; 314095fab37eSRobert Watson 31411aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31421aa37f53SRobert Watson 314395fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 314495fab37eSRobert Watson if (error) 314595fab37eSRobert Watson return (error); 314695fab37eSRobert Watson 314795fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 314895fab37eSRobert Watson 314995fab37eSRobert Watson return (0); 315095fab37eSRobert Watson } 315195fab37eSRobert Watson 315295fab37eSRobert Watson int 315395fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 3154f7b951a8SRobert Watson struct mac *mac) 315595fab37eSRobert Watson { 3156f7b951a8SRobert Watson char *buffer, *elements; 3157f7b951a8SRobert Watson int error; 315895fab37eSRobert Watson 3159f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3160f7b951a8SRobert Watson if (error) 3161f7b951a8SRobert Watson return (error); 3162f7b951a8SRobert Watson 3163a163d034SWarner Losh elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3164f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3165f7b951a8SRobert Watson if (error) { 3166f7b951a8SRobert Watson free(elements, M_MACTEMP); 3167f7b951a8SRobert Watson return (error); 3168f7b951a8SRobert Watson } 3169f7b951a8SRobert Watson 3170a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3171f7b951a8SRobert Watson error = mac_externalize_socket_label(&so->so_label, elements, 3172a163d034SWarner Losh buffer, mac->m_buflen, M_WAITOK); 3173f7b951a8SRobert Watson if (error == 0) 3174f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3175f7b951a8SRobert Watson 3176f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3177f7b951a8SRobert Watson free(elements, M_MACTEMP); 3178f7b951a8SRobert Watson 3179f7b951a8SRobert Watson return (error); 318095fab37eSRobert Watson } 318195fab37eSRobert Watson 318295fab37eSRobert Watson int 318395fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 3184f7b951a8SRobert Watson struct mac *mac) 318595fab37eSRobert Watson { 3186f7b951a8SRobert Watson char *elements, *buffer; 3187f7b951a8SRobert Watson int error; 318895fab37eSRobert Watson 3189f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3190f7b951a8SRobert Watson if (error) 3191f7b951a8SRobert Watson return (error); 3192f7b951a8SRobert Watson 3193a163d034SWarner Losh elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3194f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3195f7b951a8SRobert Watson if (error) { 3196f7b951a8SRobert Watson free(elements, M_MACTEMP); 3197f7b951a8SRobert Watson return (error); 3198f7b951a8SRobert Watson } 3199f7b951a8SRobert Watson 3200a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3201f7b951a8SRobert Watson error = mac_externalize_socket_peer_label(&so->so_peerlabel, 3202a163d034SWarner Losh elements, buffer, mac->m_buflen, M_WAITOK); 3203f7b951a8SRobert Watson if (error == 0) 3204f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3205f7b951a8SRobert Watson 3206f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3207f7b951a8SRobert Watson free(elements, M_MACTEMP); 3208f7b951a8SRobert Watson 3209f7b951a8SRobert Watson return (error); 321095fab37eSRobert Watson } 321195fab37eSRobert Watson 321295fab37eSRobert Watson /* 321395fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 321495fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 321595fab37eSRobert Watson * extended attributes. 321695fab37eSRobert Watson */ 321795fab37eSRobert Watson int 321895fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 321995fab37eSRobert Watson { 322095fab37eSRobert Watson struct vnode *vp = ap->a_vp; 322195fab37eSRobert Watson struct label *intlabel = ap->a_label; 322295fab37eSRobert Watson int error; 322395fab37eSRobert Watson 322495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 322595fab37eSRobert Watson 3226763bbd2fSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 3227763bbd2fSRobert Watson return (EOPNOTSUPP); 322895fab37eSRobert Watson 3229763bbd2fSRobert Watson error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 323095fab37eSRobert Watson if (error) 323195fab37eSRobert Watson return (error); 323295fab37eSRobert Watson 323395fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 323495fab37eSRobert Watson 323595fab37eSRobert Watson return (0); 323695fab37eSRobert Watson } 323795fab37eSRobert Watson 323895fab37eSRobert Watson static int 323995fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 324095fab37eSRobert Watson { 324195fab37eSRobert Watson int error; 324295fab37eSRobert Watson 324395fab37eSRobert Watson if (vp->v_mount == NULL) { 324495fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 324506be2aaaSNate Lawson if (vp->v_type != VNON) 324606be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 324795fab37eSRobert Watson return (EBADF); 324895fab37eSRobert Watson } 324995fab37eSRobert Watson 325095fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 325195fab37eSRobert Watson return (EOPNOTSUPP); 325295fab37eSRobert Watson 325395fab37eSRobert Watson /* 325495fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 325595fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 325695fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 325795fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 325895fab37eSRobert Watson */ 325995fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 326095fab37eSRobert Watson if (error) 326195fab37eSRobert Watson return (error); 326295fab37eSRobert Watson 326395fab37eSRobert Watson /* 326495fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 326595fab37eSRobert Watson * decisions about who is and is not able to modify labels 326695fab37eSRobert Watson * and protections on files. This might not be right. We can't 326795fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 326895fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 326995fab37eSRobert Watson */ 327095fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 327195fab37eSRobert Watson if (error) 327295fab37eSRobert Watson return (error); 327395fab37eSRobert Watson 327495fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 327595fab37eSRobert Watson if (error) 327695fab37eSRobert Watson return (error); 327795fab37eSRobert Watson 327895fab37eSRobert Watson return (0); 327995fab37eSRobert Watson } 328095fab37eSRobert Watson 3281f7b951a8SRobert Watson int 3282f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3283f7b951a8SRobert Watson { 3284f7b951a8SRobert Watson char *elements, *buffer; 3285f7b951a8SRobert Watson struct mac mac; 3286f7b951a8SRobert Watson struct proc *tproc; 3287f7b951a8SRobert Watson struct ucred *tcred; 3288f7b951a8SRobert Watson int error; 3289f7b951a8SRobert Watson 3290d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 3291f7b951a8SRobert Watson if (error) 3292f7b951a8SRobert Watson return (error); 3293f7b951a8SRobert Watson 3294f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3295f7b951a8SRobert Watson if (error) 3296f7b951a8SRobert Watson return (error); 3297f7b951a8SRobert Watson 3298f7b951a8SRobert Watson tproc = pfind(uap->pid); 3299f7b951a8SRobert Watson if (tproc == NULL) 3300f7b951a8SRobert Watson return (ESRCH); 3301f7b951a8SRobert Watson 3302f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 3303f7b951a8SRobert Watson error = p_cansee(td, tproc); 3304f7b951a8SRobert Watson if (error == 0) 3305f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 3306f7b951a8SRobert Watson PROC_UNLOCK(tproc); 3307f7b951a8SRobert Watson if (error) 3308f7b951a8SRobert Watson return (error); 3309f7b951a8SRobert Watson 3310a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3311f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3312f7b951a8SRobert Watson if (error) { 3313f7b951a8SRobert Watson free(elements, M_MACTEMP); 3314f7b951a8SRobert Watson crfree(tcred); 3315f7b951a8SRobert Watson return (error); 3316f7b951a8SRobert Watson } 3317f7b951a8SRobert Watson 3318a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3319f7b951a8SRobert Watson error = mac_externalize_cred_label(&tcred->cr_label, elements, 3320a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3321f7b951a8SRobert Watson if (error == 0) 3322f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3323f7b951a8SRobert Watson 3324f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3325f7b951a8SRobert Watson free(elements, M_MACTEMP); 3326f7b951a8SRobert Watson crfree(tcred); 3327f7b951a8SRobert Watson return (error); 3328f7b951a8SRobert Watson } 3329f7b951a8SRobert Watson 333095fab37eSRobert Watson /* 333195fab37eSRobert Watson * MPSAFE 333295fab37eSRobert Watson */ 333395fab37eSRobert Watson int 333495fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 333595fab37eSRobert Watson { 3336f7b951a8SRobert Watson char *elements, *buffer; 3337f7b951a8SRobert Watson struct mac mac; 333895fab37eSRobert Watson int error; 333995fab37eSRobert Watson 3340f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3341f7b951a8SRobert Watson if (error) 3342f7b951a8SRobert Watson return (error); 334395fab37eSRobert Watson 3344f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3345f7b951a8SRobert Watson if (error) 3346f7b951a8SRobert Watson return (error); 3347f7b951a8SRobert Watson 3348a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3349f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3350f7b951a8SRobert Watson if (error) { 3351f7b951a8SRobert Watson free(elements, M_MACTEMP); 3352f7b951a8SRobert Watson return (error); 3353f7b951a8SRobert Watson } 3354f7b951a8SRobert Watson 3355a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3356f7b951a8SRobert Watson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3357a163d034SWarner Losh elements, buffer, mac.m_buflen, M_WAITOK); 3358f7b951a8SRobert Watson if (error == 0) 3359f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3360f7b951a8SRobert Watson 3361f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3362f7b951a8SRobert Watson free(elements, M_MACTEMP); 336395fab37eSRobert Watson return (error); 336495fab37eSRobert Watson } 336595fab37eSRobert Watson 336695fab37eSRobert Watson /* 336795fab37eSRobert Watson * MPSAFE 336895fab37eSRobert Watson */ 336995fab37eSRobert Watson int 337095fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 337195fab37eSRobert Watson { 337295fab37eSRobert Watson struct ucred *newcred, *oldcred; 337395fab37eSRobert Watson struct label intlabel; 3374f7b951a8SRobert Watson struct proc *p; 3375f7b951a8SRobert Watson struct mac mac; 3376f7b951a8SRobert Watson char *buffer; 337795fab37eSRobert Watson int error; 337895fab37eSRobert Watson 3379f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 338095fab37eSRobert Watson if (error) 338195fab37eSRobert Watson return (error); 338295fab37eSRobert Watson 3383f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 338495fab37eSRobert Watson if (error) 338595fab37eSRobert Watson return (error); 338695fab37eSRobert Watson 3387a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3388f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3389f7b951a8SRobert Watson if (error) { 3390f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3391f7b951a8SRobert Watson return (error); 3392f7b951a8SRobert Watson } 3393f7b951a8SRobert Watson 3394f7b951a8SRobert Watson mac_init_cred_label(&intlabel); 3395f7b951a8SRobert Watson error = mac_internalize_cred_label(&intlabel, buffer); 3396f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3397f7b951a8SRobert Watson if (error) { 3398f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3399f7b951a8SRobert Watson return (error); 3400f7b951a8SRobert Watson } 3401f7b951a8SRobert Watson 340295fab37eSRobert Watson newcred = crget(); 340395fab37eSRobert Watson 340495fab37eSRobert Watson p = td->td_proc; 340595fab37eSRobert Watson PROC_LOCK(p); 340695fab37eSRobert Watson oldcred = p->p_ucred; 340795fab37eSRobert Watson 340895fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 340995fab37eSRobert Watson if (error) { 341095fab37eSRobert Watson PROC_UNLOCK(p); 341195fab37eSRobert Watson crfree(newcred); 3412f7b951a8SRobert Watson goto out; 341395fab37eSRobert Watson } 341495fab37eSRobert Watson 341595fab37eSRobert Watson setsugid(p); 341695fab37eSRobert Watson crcopy(newcred, oldcred); 341795fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 341895fab37eSRobert Watson p->p_ucred = newcred; 3419e5cb5e37SRobert Watson 3420e5cb5e37SRobert Watson /* 3421e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3422e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3423e5cb5e37SRobert Watson */ 3424e5cb5e37SRobert Watson crhold(newcred); 342595fab37eSRobert Watson PROC_UNLOCK(p); 3426e5cb5e37SRobert Watson 3427f7b951a8SRobert Watson if (mac_enforce_vm) { 342816140035SRobert Watson mtx_lock(&Giant); 3429e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 343016140035SRobert Watson mtx_unlock(&Giant); 3431f7b951a8SRobert Watson } 3432e5cb5e37SRobert Watson 3433e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 343495fab37eSRobert Watson crfree(oldcred); 3435f7b951a8SRobert Watson 3436f7b951a8SRobert Watson out: 3437f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3438f7b951a8SRobert Watson return (error); 343995fab37eSRobert Watson } 344095fab37eSRobert Watson 344195fab37eSRobert Watson /* 344295fab37eSRobert Watson * MPSAFE 344395fab37eSRobert Watson */ 344495fab37eSRobert Watson int 344595fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 344695fab37eSRobert Watson { 3447f7b951a8SRobert Watson char *elements, *buffer; 3448f7b951a8SRobert Watson struct label intlabel; 344995fab37eSRobert Watson struct file *fp; 3450f7b951a8SRobert Watson struct mac mac; 345195fab37eSRobert Watson struct vnode *vp; 345295fab37eSRobert Watson struct pipe *pipe; 3453f7b951a8SRobert Watson short label_type; 345495fab37eSRobert Watson int error; 345595fab37eSRobert Watson 3456f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3457f7b951a8SRobert Watson if (error) 3458f7b951a8SRobert Watson return (error); 345995fab37eSRobert Watson 3460f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3461f7b951a8SRobert Watson if (error) 3462f7b951a8SRobert Watson return (error); 3463f7b951a8SRobert Watson 3464a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3465f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3466f7b951a8SRobert Watson if (error) { 3467f7b951a8SRobert Watson free(elements, M_MACTEMP); 3468f7b951a8SRobert Watson return (error); 3469f7b951a8SRobert Watson } 3470f7b951a8SRobert Watson 3471a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3472f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3473d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 347495fab37eSRobert Watson if (error) 347595fab37eSRobert Watson goto out; 347695fab37eSRobert Watson 3477f7b951a8SRobert Watson label_type = fp->f_type; 347895fab37eSRobert Watson switch (fp->f_type) { 347995fab37eSRobert Watson case DTYPE_FIFO: 348095fab37eSRobert Watson case DTYPE_VNODE: 34813b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 348295fab37eSRobert Watson 3483f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3484f7b951a8SRobert Watson 348595fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3486f7b951a8SRobert Watson mac_copy_vnode_label(&vp->v_label, &intlabel); 348795fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 3488f7b951a8SRobert Watson 348995fab37eSRobert Watson break; 349095fab37eSRobert Watson case DTYPE_PIPE: 349148e3128bSMatthew Dillon pipe = fp->f_data; 3492f7b951a8SRobert Watson 3493f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3494f7b951a8SRobert Watson 3495f7b951a8SRobert Watson PIPE_LOCK(pipe); 3496f7b951a8SRobert Watson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3497f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 349895fab37eSRobert Watson break; 349995fab37eSRobert Watson default: 350095fab37eSRobert Watson error = EINVAL; 3501f7b951a8SRobert Watson fdrop(fp, td); 3502f7b951a8SRobert Watson goto out; 3503f7b951a8SRobert Watson } 3504f7b951a8SRobert Watson fdrop(fp, td); 3505f7b951a8SRobert Watson 3506f7b951a8SRobert Watson switch (label_type) { 3507f7b951a8SRobert Watson case DTYPE_FIFO: 3508f7b951a8SRobert Watson case DTYPE_VNODE: 3509f7b951a8SRobert Watson if (error == 0) 3510f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, 3511a163d034SWarner Losh elements, buffer, mac.m_buflen, M_WAITOK); 3512f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3513f7b951a8SRobert Watson break; 3514f7b951a8SRobert Watson case DTYPE_PIPE: 3515f7b951a8SRobert Watson error = mac_externalize_pipe_label(&intlabel, elements, 3516a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3517f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 3518f7b951a8SRobert Watson break; 3519f7b951a8SRobert Watson default: 3520f7b951a8SRobert Watson panic("__mac_get_fd: corrupted label_type"); 352195fab37eSRobert Watson } 352295fab37eSRobert Watson 352395fab37eSRobert Watson if (error == 0) 3524f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 352595fab37eSRobert Watson 352695fab37eSRobert Watson out: 3527f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3528f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3529f7b951a8SRobert Watson free(elements, M_MACTEMP); 3530f7b951a8SRobert Watson 353195fab37eSRobert Watson return (error); 353295fab37eSRobert Watson } 353395fab37eSRobert Watson 353495fab37eSRobert Watson /* 353595fab37eSRobert Watson * MPSAFE 353695fab37eSRobert Watson */ 353795fab37eSRobert Watson int 353895fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 353995fab37eSRobert Watson { 3540f7b951a8SRobert Watson char *elements, *buffer; 354195fab37eSRobert Watson struct nameidata nd; 3542f7b951a8SRobert Watson struct label intlabel; 3543f7b951a8SRobert Watson struct mac mac; 354495fab37eSRobert Watson int error; 354595fab37eSRobert Watson 3546f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3547f7b951a8SRobert Watson if (error) 3548f7b951a8SRobert Watson return (error); 3549f7b951a8SRobert Watson 3550f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3551f7b951a8SRobert Watson if (error) 3552f7b951a8SRobert Watson return (error); 3553f7b951a8SRobert Watson 3554a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3555f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3556f7b951a8SRobert Watson if (error) { 3557f7b951a8SRobert Watson free(elements, M_MACTEMP); 3558f7b951a8SRobert Watson return (error); 3559f7b951a8SRobert Watson } 3560f7b951a8SRobert Watson 3561a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3562f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3563f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3564f7b951a8SRobert Watson td); 356595fab37eSRobert Watson error = namei(&nd); 356695fab37eSRobert Watson if (error) 356795fab37eSRobert Watson goto out; 356895fab37eSRobert Watson 3569f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3570f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3571763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3572a163d034SWarner Losh mac.m_buflen, M_WAITOK); 3573f7b951a8SRobert Watson 357495fab37eSRobert Watson NDFREE(&nd, 0); 3575f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3576f7b951a8SRobert Watson 3577f7b951a8SRobert Watson if (error == 0) 3578f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3579f7b951a8SRobert Watson 3580f7b951a8SRobert Watson out: 3581f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3582f7b951a8SRobert Watson 3583f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3584f7b951a8SRobert Watson free(elements, M_MACTEMP); 3585f7b951a8SRobert Watson 3586f7b951a8SRobert Watson return (error); 3587f7b951a8SRobert Watson } 3588f7b951a8SRobert Watson 3589f7b951a8SRobert Watson /* 3590f7b951a8SRobert Watson * MPSAFE 3591f7b951a8SRobert Watson */ 3592f7b951a8SRobert Watson int 3593f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3594f7b951a8SRobert Watson { 3595f7b951a8SRobert Watson char *elements, *buffer; 3596f7b951a8SRobert Watson struct nameidata nd; 3597f7b951a8SRobert Watson struct label intlabel; 3598f7b951a8SRobert Watson struct mac mac; 3599f7b951a8SRobert Watson int error; 3600f7b951a8SRobert Watson 3601f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3602f7b951a8SRobert Watson if (error) 3603f7b951a8SRobert Watson return (error); 3604f7b951a8SRobert Watson 3605f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3606f7b951a8SRobert Watson if (error) 3607f7b951a8SRobert Watson return (error); 3608f7b951a8SRobert Watson 3609a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3610f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3611f7b951a8SRobert Watson if (error) { 3612f7b951a8SRobert Watson free(elements, M_MACTEMP); 3613f7b951a8SRobert Watson return (error); 3614f7b951a8SRobert Watson } 3615f7b951a8SRobert Watson 3616a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3617f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3618f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3619f7b951a8SRobert Watson td); 3620f7b951a8SRobert Watson error = namei(&nd); 362195fab37eSRobert Watson if (error) 362295fab37eSRobert Watson goto out; 362395fab37eSRobert Watson 3624f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3625f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3626763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3627a163d034SWarner Losh mac.m_buflen, M_WAITOK); 3628f7b951a8SRobert Watson NDFREE(&nd, 0); 3629f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3630f7b951a8SRobert Watson 3631f7b951a8SRobert Watson if (error == 0) 3632f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 363395fab37eSRobert Watson 363495fab37eSRobert Watson out: 3635f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3636f7b951a8SRobert Watson 3637f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3638f7b951a8SRobert Watson free(elements, M_MACTEMP); 3639f7b951a8SRobert Watson 364095fab37eSRobert Watson return (error); 364195fab37eSRobert Watson } 364295fab37eSRobert Watson 364395fab37eSRobert Watson /* 364495fab37eSRobert Watson * MPSAFE 364595fab37eSRobert Watson */ 364695fab37eSRobert Watson int 364795fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 364895fab37eSRobert Watson { 364995fab37eSRobert Watson struct label intlabel; 3650f7b951a8SRobert Watson struct pipe *pipe; 3651f7b951a8SRobert Watson struct file *fp; 365295fab37eSRobert Watson struct mount *mp; 365395fab37eSRobert Watson struct vnode *vp; 3654f7b951a8SRobert Watson struct mac mac; 3655f7b951a8SRobert Watson char *buffer; 365695fab37eSRobert Watson int error; 365795fab37eSRobert Watson 3658f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3659f7b951a8SRobert Watson if (error) 3660f7b951a8SRobert Watson return (error); 3661f7b951a8SRobert Watson 3662f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3663f7b951a8SRobert Watson if (error) 3664f7b951a8SRobert Watson return (error); 3665f7b951a8SRobert Watson 3666a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3667f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3668f7b951a8SRobert Watson if (error) { 3669f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3670f7b951a8SRobert Watson return (error); 3671f7b951a8SRobert Watson } 3672f7b951a8SRobert Watson 3673f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3674f7b951a8SRobert Watson 3675d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 367695fab37eSRobert Watson if (error) 3677f7b951a8SRobert Watson goto out; 367895fab37eSRobert Watson 367995fab37eSRobert Watson switch (fp->f_type) { 368095fab37eSRobert Watson case DTYPE_FIFO: 368195fab37eSRobert Watson case DTYPE_VNODE: 3682f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3683f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3684f7b951a8SRobert Watson if (error) { 3685f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3686f7b951a8SRobert Watson break; 3687f7b951a8SRobert Watson } 3688f7b951a8SRobert Watson 36893b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 369095fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3691f7b951a8SRobert Watson if (error != 0) { 3692f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 369395fab37eSRobert Watson break; 3694f7b951a8SRobert Watson } 369595fab37eSRobert Watson 369695fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 369795fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 369895fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 369995fab37eSRobert Watson vn_finished_write(mp); 3700f7b951a8SRobert Watson 3701f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 370295fab37eSRobert Watson break; 3703f7b951a8SRobert Watson 370495fab37eSRobert Watson case DTYPE_PIPE: 3705f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3706f7b951a8SRobert Watson error = mac_internalize_pipe_label(&intlabel, buffer); 3707f7b951a8SRobert Watson if (error == 0) { 370848e3128bSMatthew Dillon pipe = fp->f_data; 37091aa37f53SRobert Watson PIPE_LOCK(pipe); 3710f7b951a8SRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, 3711f7b951a8SRobert Watson &intlabel); 37121aa37f53SRobert Watson PIPE_UNLOCK(pipe); 3713f7b951a8SRobert Watson } 3714f7b951a8SRobert Watson 3715f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 371695fab37eSRobert Watson break; 3717f7b951a8SRobert Watson 371895fab37eSRobert Watson default: 371995fab37eSRobert Watson error = EINVAL; 372095fab37eSRobert Watson } 372195fab37eSRobert Watson 372295fab37eSRobert Watson fdrop(fp, td); 3723f7b951a8SRobert Watson out: 3724f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3725f7b951a8SRobert Watson 3726f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3727f7b951a8SRobert Watson 372895fab37eSRobert Watson return (error); 372995fab37eSRobert Watson } 373095fab37eSRobert Watson 373195fab37eSRobert Watson /* 373295fab37eSRobert Watson * MPSAFE 373395fab37eSRobert Watson */ 373495fab37eSRobert Watson int 373595fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 373695fab37eSRobert Watson { 373795fab37eSRobert Watson struct label intlabel; 3738f7b951a8SRobert Watson struct nameidata nd; 373995fab37eSRobert Watson struct mount *mp; 3740f7b951a8SRobert Watson struct mac mac; 3741f7b951a8SRobert Watson char *buffer; 374295fab37eSRobert Watson int error; 374395fab37eSRobert Watson 3744f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 374595fab37eSRobert Watson if (error) 3746f7b951a8SRobert Watson return (error); 374795fab37eSRobert Watson 3748f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 374995fab37eSRobert Watson if (error) 3750f7b951a8SRobert Watson return (error); 375195fab37eSRobert Watson 3752a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3753f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3754f7b951a8SRobert Watson if (error) { 3755f7b951a8SRobert Watson free(buffer, M_MACTEMP); 375695fab37eSRobert Watson return (error); 375795fab37eSRobert Watson } 375895fab37eSRobert Watson 3759f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3760f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3761f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3762f7b951a8SRobert Watson if (error) { 3763f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3764f7b951a8SRobert Watson return (error); 3765f7b951a8SRobert Watson } 3766f7b951a8SRobert Watson 3767f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3768f7b951a8SRobert Watson 3769f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3770f7b951a8SRobert Watson td); 3771f7b951a8SRobert Watson error = namei(&nd); 3772f7b951a8SRobert Watson if (error == 0) { 3773f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3774f7b951a8SRobert Watson if (error == 0) 3775f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3776f7b951a8SRobert Watson td->td_ucred); 3777f7b951a8SRobert Watson vn_finished_write(mp); 3778f7b951a8SRobert Watson } 3779f7b951a8SRobert Watson 3780f7b951a8SRobert Watson NDFREE(&nd, 0); 3781f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3782f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3783f7b951a8SRobert Watson 3784f7b951a8SRobert Watson return (error); 3785f7b951a8SRobert Watson } 3786f7b951a8SRobert Watson 3787f7b951a8SRobert Watson /* 3788f7b951a8SRobert Watson * MPSAFE 3789f7b951a8SRobert Watson */ 3790f7b951a8SRobert Watson int 3791f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3792f7b951a8SRobert Watson { 3793f7b951a8SRobert Watson struct label intlabel; 3794f7b951a8SRobert Watson struct nameidata nd; 3795f7b951a8SRobert Watson struct mount *mp; 3796f7b951a8SRobert Watson struct mac mac; 3797f7b951a8SRobert Watson char *buffer; 3798f7b951a8SRobert Watson int error; 3799f7b951a8SRobert Watson 3800f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3801f7b951a8SRobert Watson if (error) 3802f7b951a8SRobert Watson return (error); 3803f7b951a8SRobert Watson 3804f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3805f7b951a8SRobert Watson if (error) 3806f7b951a8SRobert Watson return (error); 3807f7b951a8SRobert Watson 3808a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3809f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3810f7b951a8SRobert Watson if (error) { 3811f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3812f7b951a8SRobert Watson return (error); 3813f7b951a8SRobert Watson } 3814f7b951a8SRobert Watson 3815f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3816f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3817f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3818f7b951a8SRobert Watson if (error) { 3819f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3820f7b951a8SRobert Watson return (error); 3821f7b951a8SRobert Watson } 3822f7b951a8SRobert Watson 3823f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3824f7b951a8SRobert Watson 3825f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3826f7b951a8SRobert Watson td); 3827f7b951a8SRobert Watson error = namei(&nd); 3828f7b951a8SRobert Watson if (error == 0) { 3829f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3830f7b951a8SRobert Watson if (error == 0) 3831f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3832f7b951a8SRobert Watson td->td_ucred); 3833f7b951a8SRobert Watson vn_finished_write(mp); 3834f7b951a8SRobert Watson } 3835f7b951a8SRobert Watson 3836f7b951a8SRobert Watson NDFREE(&nd, 0); 3837f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3838f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3839f7b951a8SRobert Watson 3840f7b951a8SRobert Watson return (error); 3841f7b951a8SRobert Watson } 3842f7b951a8SRobert Watson 3843f7b951a8SRobert Watson /* 3844f7b951a8SRobert Watson * MPSAFE 3845f7b951a8SRobert Watson */ 384627f2eac7SRobert Watson int 384727f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 384827f2eac7SRobert Watson { 384927f2eac7SRobert Watson struct mac_policy_conf *mpc; 385027f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 385141a17fe3SRobert Watson int entrycount, error; 385227f2eac7SRobert Watson 3853d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 385427f2eac7SRobert Watson if (error) 385527f2eac7SRobert Watson return (error); 385627f2eac7SRobert Watson 385727f2eac7SRobert Watson error = ENOSYS; 3858a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 385927f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 386027f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 386127f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 3862d1e405c5SAlfred Perlstein uap->call, uap->arg); 386327f2eac7SRobert Watson goto out; 386427f2eac7SRobert Watson } 386527f2eac7SRobert Watson } 386627f2eac7SRobert Watson 386741a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 386841a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 386941a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 387041a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 387141a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 387241a17fe3SRobert Watson uap->call, uap->arg); 387341a17fe3SRobert Watson break; 387441a17fe3SRobert Watson } 387541a17fe3SRobert Watson } 387641a17fe3SRobert Watson mac_policy_list_unbusy(); 387741a17fe3SRobert Watson } 387827f2eac7SRobert Watson out: 387927f2eac7SRobert Watson return (error); 388027f2eac7SRobert Watson } 388127f2eac7SRobert Watson 388295fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 388395fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 388495fab37eSRobert Watson 388595fab37eSRobert Watson #else /* !MAC */ 38867bc82500SRobert Watson 38877bc82500SRobert Watson int 3888f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3889f7b951a8SRobert Watson { 3890f7b951a8SRobert Watson 3891f7b951a8SRobert Watson return (ENOSYS); 3892f7b951a8SRobert Watson } 3893f7b951a8SRobert Watson 3894f7b951a8SRobert Watson int 38957bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 38967bc82500SRobert Watson { 38977bc82500SRobert Watson 38987bc82500SRobert Watson return (ENOSYS); 38997bc82500SRobert Watson } 39007bc82500SRobert Watson 39017bc82500SRobert Watson int 39027bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 39037bc82500SRobert Watson { 39047bc82500SRobert Watson 39057bc82500SRobert Watson return (ENOSYS); 39067bc82500SRobert Watson } 39077bc82500SRobert Watson 39087bc82500SRobert Watson int 39097bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 39107bc82500SRobert Watson { 39117bc82500SRobert Watson 39127bc82500SRobert Watson return (ENOSYS); 39137bc82500SRobert Watson } 39147bc82500SRobert Watson 39157bc82500SRobert Watson int 39167bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 39177bc82500SRobert Watson { 39187bc82500SRobert Watson 39197bc82500SRobert Watson return (ENOSYS); 39207bc82500SRobert Watson } 39217bc82500SRobert Watson 39227bc82500SRobert Watson int 3923f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3924f7b951a8SRobert Watson { 3925f7b951a8SRobert Watson 3926f7b951a8SRobert Watson return (ENOSYS); 3927f7b951a8SRobert Watson } 3928f7b951a8SRobert Watson 3929f7b951a8SRobert Watson int 39307bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 39317bc82500SRobert Watson { 39327bc82500SRobert Watson 39337bc82500SRobert Watson return (ENOSYS); 39347bc82500SRobert Watson } 39357bc82500SRobert Watson 39367bc82500SRobert Watson int 39377bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 39387bc82500SRobert Watson { 39397bc82500SRobert Watson 39407bc82500SRobert Watson return (ENOSYS); 39417bc82500SRobert Watson } 394295fab37eSRobert Watson 394327f2eac7SRobert Watson int 3944f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3945f7b951a8SRobert Watson { 3946f7b951a8SRobert Watson 3947f7b951a8SRobert Watson return (ENOSYS); 3948f7b951a8SRobert Watson } 3949f7b951a8SRobert Watson 3950f7b951a8SRobert Watson int 395127f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 395227f2eac7SRobert Watson { 395327f2eac7SRobert Watson 395427f2eac7SRobert Watson return (ENOSYS); 395527f2eac7SRobert Watson } 395627f2eac7SRobert Watson 3957f7b951a8SRobert Watson #endif 3958