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 */ 116089c1bdaSRobert Watson int mac_late = 0; 117763bbd2fSRobert Watson 118225bff6fSRobert Watson /* 119225bff6fSRobert Watson * Flag to indicate whether or not we should allocate label storage for 120225bff6fSRobert Watson * new mbufs. Since most dynamic policies we currently work with don't 121225bff6fSRobert Watson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 122225bff6fSRobert Watson * unless specifically notified of interest. One result of this is 123225bff6fSRobert Watson * that if a dynamically loaded policy requests mbuf labels, it must 124225bff6fSRobert Watson * be able to deal with a NULL label being returned on any mbufs that 125225bff6fSRobert Watson * were already in flight when the policy was loaded. Since the policy 126225bff6fSRobert Watson * already has to deal with uninitialized labels, this probably won't 127225bff6fSRobert Watson * be a problem. Note: currently no locking. Will this be a problem? 128225bff6fSRobert Watson */ 12919c3e120SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 130089c1bdaSRobert Watson int mac_labelmbufs = 0; 131225bff6fSRobert Watson #endif 132225bff6fSRobert Watson 13395fab37eSRobert Watson static int mac_enforce_fs = 1; 13495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 13595fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 13695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 13795fab37eSRobert Watson 138a3df768bSRobert Watson static int mac_enforce_kld = 1; 139a3df768bSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW, 140a3df768bSRobert Watson &mac_enforce_kld, 0, "Enforce MAC policy on kld operations"); 141a3df768bSRobert Watson TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld); 142a3df768bSRobert Watson 14395fab37eSRobert Watson static int mac_enforce_network = 1; 14495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 14595fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 14695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 14795fab37eSRobert Watson 148b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 149b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 150b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 151c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 152b88c98f6SRobert Watson 15395fab37eSRobert Watson static int mac_enforce_process = 1; 15495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 15595fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 15695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 15795fab37eSRobert Watson 15895fab37eSRobert Watson static int mac_enforce_socket = 1; 15995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 16095fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 16195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 16295fab37eSRobert Watson 1639e913ebdSRobert Watson static int mac_enforce_system = 1; 1649e913ebdSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 1659e913ebdSRobert Watson &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 1669e913ebdSRobert Watson TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 167d3fc69eeSRobert Watson 168ca7850c3SRobert Watson static int mac_enforce_vm = 1; 169ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 170ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 171c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 172ca7850c3SRobert Watson 173c0f39905SRobert Watson static int mac_mmap_revocation = 1; 174c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 175c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 176c0f39905SRobert Watson "relabel"); 17799fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 17895fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 17995fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 18095fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 18195fab37eSRobert Watson 182f050add5SRobert Watson #ifdef MAC_DEBUG 1836be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1846be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1856be0c25eSRobert Watson 1866be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1876be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1886be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1896be0c25eSRobert Watson "when label is corrupted."); 1906be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1916be0c25eSRobert Watson &mac_debug_label_fallback); 1926be0c25eSRobert Watson 193b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 194b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 195b2f0927aSRobert Watson 19695fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 19795fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 1982555374cSRobert Watson nmacipqs, nmacpipes, nmacprocs; 199b2f0927aSRobert Watson 2008d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_INC(x) atomic_add_int(x, 1); 2018d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_DEC(x) atomic_subtract_int(x, 1); 2028d8d5ea8SRobert Watson 203b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 20495fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 205b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 20695fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 207b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 20895fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 209b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 21095fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 211b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 21295fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 213b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 21495fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 215b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 21695fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 2172555374cSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD, 2182555374cSRobert Watson &nmacprocs, 0, "number of procs in use"); 219b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 22095fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 221b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 22295fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 223b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 22495fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 225b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 22695fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 2278d8d5ea8SRobert Watson #else 2288d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_INC(x) 2298d8d5ea8SRobert Watson #define MAC_DEBUG_COUNTER_DEC(x) 230f050add5SRobert Watson #endif 23195fab37eSRobert Watson 23295fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 23395fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 23495fab37eSRobert Watson 235e183f80eSRobert Watson static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 236e183f80eSRobert Watson struct vnode *vp, int *prot); 23795fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 23895fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 23995fab37eSRobert Watson 24083985c26SRobert Watson static void mac_destroy_socket_label(struct label *label); 24183985c26SRobert Watson 242763bbd2fSRobert Watson static int mac_setlabel_vnode_extattr(struct ucred *cred, 243763bbd2fSRobert Watson struct vnode *vp, struct label *intlabel); 244763bbd2fSRobert Watson 24595fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 246f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 24795fab37eSRobert Watson 24895fab37eSRobert Watson /* 24941a17fe3SRobert Watson * mac_static_policy_list holds a list of policy modules that are not 25041a17fe3SRobert Watson * loaded while the system is "live", and cannot be unloaded. These 25141a17fe3SRobert Watson * policies can be invoked without holding the busy count. 25241a17fe3SRobert Watson * 25341a17fe3SRobert Watson * mac_policy_list stores the list of dynamic policies. A busy count is 254a96acd1aSRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count 25541a17fe3SRobert Watson * is protected by mac_policy_mtx; the list may be modified only 256a96acd1aSRobert Watson * while the busy count is 0, requiring that the lock be held to 257a96acd1aSRobert Watson * prevent new references to the list from being acquired. For almost 258a96acd1aSRobert Watson * all operations, incrementing the busy count is sufficient to 259a96acd1aSRobert Watson * guarantee consistency, as the list cannot be modified while the 260a96acd1aSRobert Watson * busy count is elevated. For a few special operations involving a 26141a17fe3SRobert Watson * change to the list of active policies, the mtx itself must be held. 26241a17fe3SRobert Watson * A condition variable, mac_policy_cv, is used to signal potential 26341a17fe3SRobert Watson * exclusive consumers that they should try to acquire the lock if a 26441a17fe3SRobert Watson * first attempt at exclusive access fails. 26595fab37eSRobert Watson */ 26641a17fe3SRobert Watson static struct mtx mac_policy_mtx; 26741a17fe3SRobert Watson static struct cv mac_policy_cv; 26841a17fe3SRobert Watson static int mac_policy_count; 269089c1bdaSRobert Watson struct mac_policy_list_head mac_policy_list; 270089c1bdaSRobert Watson struct mac_policy_list_head mac_static_policy_list; 271a96acd1aSRobert Watson 272a96acd1aSRobert Watson /* 27326306795SJohn Baldwin * We manually invoke WITNESS_WARN() to allow Witness to generate 274a96acd1aSRobert Watson * warnings even if we don't end up ever triggering the wait at 275a96acd1aSRobert Watson * run-time. The consumer of the exclusive interface must not hold 276a96acd1aSRobert Watson * any locks (other than potentially Giant) since we may sleep for 277a96acd1aSRobert Watson * long (potentially indefinite) periods of time waiting for the 278a96acd1aSRobert Watson * framework to become quiescent so that a policy list change may 279a96acd1aSRobert Watson * be made. 280a96acd1aSRobert Watson */ 281089c1bdaSRobert Watson void 28241a17fe3SRobert Watson mac_policy_grab_exclusive(void) 28341a17fe3SRobert Watson { 28441a17fe3SRobert Watson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 28541a17fe3SRobert Watson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 28641a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 28741a17fe3SRobert Watson while (mac_policy_count != 0) 28841a17fe3SRobert Watson cv_wait(&mac_policy_cv, &mac_policy_mtx); 28941a17fe3SRobert Watson } 29095fab37eSRobert Watson 291089c1bdaSRobert Watson void 29241a17fe3SRobert Watson mac_policy_assert_exclusive(void) 29341a17fe3SRobert Watson { 29441a17fe3SRobert Watson mtx_assert(&mac_policy_mtx, MA_OWNED); 29541a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 29641a17fe3SRobert Watson ("mac_policy_assert_exclusive(): not exclusive")); 29741a17fe3SRobert Watson } 298225bff6fSRobert Watson 299089c1bdaSRobert Watson void 30041a17fe3SRobert Watson mac_policy_release_exclusive(void) 30141a17fe3SRobert Watson { 30295fab37eSRobert Watson 30341a17fe3SRobert Watson KASSERT(mac_policy_count == 0, 30441a17fe3SRobert Watson ("mac_policy_release_exclusive(): not exclusive")); 30541a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 30641a17fe3SRobert Watson cv_signal(&mac_policy_cv); 30741a17fe3SRobert Watson } 30841a17fe3SRobert Watson 309089c1bdaSRobert Watson void 31041a17fe3SRobert Watson mac_policy_list_busy(void) 31141a17fe3SRobert Watson { 31241a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 31341a17fe3SRobert Watson mac_policy_count++; 31441a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 31541a17fe3SRobert Watson } 31641a17fe3SRobert Watson 317089c1bdaSRobert Watson int 31841a17fe3SRobert Watson mac_policy_list_conditional_busy(void) 31941a17fe3SRobert Watson { 32041a17fe3SRobert Watson int ret; 32141a17fe3SRobert Watson 32241a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 32341a17fe3SRobert Watson if (!LIST_EMPTY(&mac_policy_list)) { 32441a17fe3SRobert Watson mac_policy_count++; 32541a17fe3SRobert Watson ret = 1; 32641a17fe3SRobert Watson } else 32741a17fe3SRobert Watson ret = 0; 32841a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 32941a17fe3SRobert Watson return (ret); 33041a17fe3SRobert Watson } 33141a17fe3SRobert Watson 332089c1bdaSRobert Watson void 33341a17fe3SRobert Watson mac_policy_list_unbusy(void) 33441a17fe3SRobert Watson { 33541a17fe3SRobert Watson mtx_lock(&mac_policy_mtx); 33641a17fe3SRobert Watson mac_policy_count--; 33741a17fe3SRobert Watson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 33841a17fe3SRobert Watson if (mac_policy_count == 0) 33941a17fe3SRobert Watson cv_signal(&mac_policy_cv); 34041a17fe3SRobert Watson mtx_unlock(&mac_policy_mtx); 34141a17fe3SRobert Watson } 34295fab37eSRobert Watson 34395fab37eSRobert Watson /* 34495fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 34595fab37eSRobert Watson * module list and checking with each as to how it feels about the 34695fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 34795fab37eSRobert Watson * of the caller. 34895fab37eSRobert Watson */ 34995fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 35095fab37eSRobert Watson struct mac_policy_conf *mpc; \ 35141a17fe3SRobert Watson int entrycount; \ 35295fab37eSRobert Watson \ 35395fab37eSRobert Watson error = 0; \ 35441a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 35541a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 3569e7bf51cSRobert Watson error = mac_error_select( \ 35741a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 35841a17fe3SRobert Watson error); \ 35941a17fe3SRobert Watson } \ 36041a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 36195fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 36295fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 3639e7bf51cSRobert Watson error = mac_error_select( \ 36495fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 36595fab37eSRobert Watson error); \ 36695fab37eSRobert Watson } \ 36741a17fe3SRobert Watson mac_policy_list_unbusy(); \ 36841a17fe3SRobert Watson } \ 36995fab37eSRobert Watson } while (0) 37095fab37eSRobert Watson 37195fab37eSRobert Watson /* 37295fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 37395fab37eSRobert Watson * the module list, invoking each instance of the operation, and 37495fab37eSRobert Watson * combining the results using the passed C operator. Note that it 37595fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 37695fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 37795fab37eSRobert Watson * a meaningful result. 37895fab37eSRobert Watson */ 37995fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 38095fab37eSRobert Watson struct mac_policy_conf *mpc; \ 38141a17fe3SRobert Watson int entrycount; \ 38295fab37eSRobert Watson \ 38341a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 38495fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 38595fab37eSRobert Watson result = result composition \ 38695fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 38795fab37eSRobert Watson } \ 38841a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 38941a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 39041a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 39141a17fe3SRobert Watson result = result composition \ 39241a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## operation \ 39341a17fe3SRobert Watson (args); \ 39441a17fe3SRobert Watson } \ 39541a17fe3SRobert Watson mac_policy_list_unbusy(); \ 39641a17fe3SRobert Watson } \ 39795fab37eSRobert Watson } while (0) 39895fab37eSRobert Watson 399f7b951a8SRobert Watson #define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 400f7b951a8SRobert Watson outbuflen) do { \ 401f51e5803SRobert Watson int claimed, first, ignorenotfound, savedlen; \ 402f51e5803SRobert Watson char *element_name, *element_temp; \ 403f51e5803SRobert Watson struct sbuf sb; \ 404f7b951a8SRobert Watson \ 405f7b951a8SRobert Watson error = 0; \ 406f7b951a8SRobert Watson first = 1; \ 407f51e5803SRobert Watson sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN); \ 408f51e5803SRobert Watson element_temp = elementlist; \ 409f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 410f7b951a8SRobert Watson if (element_name[0] == '?') { \ 411f7b951a8SRobert Watson element_name++; \ 412f7b951a8SRobert Watson ignorenotfound = 1; \ 413f7b951a8SRobert Watson } else \ 414f7b951a8SRobert Watson ignorenotfound = 0; \ 415f51e5803SRobert Watson savedlen = sbuf_len(&sb); \ 416f7b951a8SRobert Watson if (first) { \ 417f51e5803SRobert Watson error = sbuf_printf(&sb, "%s/", element_name); \ 418f7b951a8SRobert Watson first = 0; \ 419f7b951a8SRobert Watson } else \ 420f51e5803SRobert Watson error = sbuf_printf(&sb, ",%s/", element_name); \ 421f51e5803SRobert Watson if (error == -1) { \ 422f51e5803SRobert Watson error = EINVAL; /* XXX: E2BIG? */ \ 423f7b951a8SRobert Watson break; \ 424f7b951a8SRobert Watson } \ 425f51e5803SRobert Watson claimed = 0; \ 426f7b951a8SRobert Watson MAC_CHECK(externalize_ ## type, label, element_name, \ 427f51e5803SRobert Watson &sb, &claimed); \ 428f7b951a8SRobert Watson if (error) \ 429f7b951a8SRobert Watson break; \ 430f51e5803SRobert Watson if (claimed == 0 && ignorenotfound) { \ 431f51e5803SRobert Watson /* Revert last label name. */ \ 432f51e5803SRobert Watson sbuf_setpos(&sb, savedlen); \ 433f51e5803SRobert Watson } else if (claimed != 1) { \ 434f51e5803SRobert Watson error = EINVAL; /* XXX: ENOLABEL? */ \ 435f7b951a8SRobert Watson break; \ 436f7b951a8SRobert Watson } \ 437f7b951a8SRobert Watson } \ 438f51e5803SRobert Watson sbuf_finish(&sb); \ 439f7b951a8SRobert Watson } while (0) 440f7b951a8SRobert Watson 441f7b951a8SRobert Watson #define MAC_INTERNALIZE(type, label, instring) do { \ 442f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 443f7b951a8SRobert Watson int claimed; \ 444f7b951a8SRobert Watson \ 445f7b951a8SRobert Watson error = 0; \ 446f7b951a8SRobert Watson element = instring; \ 447f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 448f7b951a8SRobert Watson element_data = element_name; \ 449f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 450f7b951a8SRobert Watson if (element_data == NULL) { \ 451f7b951a8SRobert Watson error = EINVAL; \ 452f7b951a8SRobert Watson break; \ 453f7b951a8SRobert Watson } \ 454f7b951a8SRobert Watson claimed = 0; \ 455f7b951a8SRobert Watson MAC_CHECK(internalize_ ## type, label, element_name, \ 456f7b951a8SRobert Watson element_data, &claimed); \ 457f7b951a8SRobert Watson if (error) \ 458f7b951a8SRobert Watson break; \ 459f7b951a8SRobert Watson if (claimed != 1) { \ 460f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 461f7b951a8SRobert Watson error = EINVAL; \ 462f7b951a8SRobert Watson break; \ 463f7b951a8SRobert Watson } \ 464f7b951a8SRobert Watson } \ 465f7b951a8SRobert Watson } while (0) 466f7b951a8SRobert Watson 46795fab37eSRobert Watson /* 46895fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 46995fab37eSRobert Watson * module list and invoking that operation for each policy. 47095fab37eSRobert Watson */ 47195fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 47295fab37eSRobert Watson struct mac_policy_conf *mpc; \ 47341a17fe3SRobert Watson int entrycount; \ 47495fab37eSRobert Watson \ 47541a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 47641a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 47741a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 47841a17fe3SRobert Watson } \ 47941a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 48095fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 48195fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 48295fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 48395fab37eSRobert Watson } \ 48441a17fe3SRobert Watson mac_policy_list_unbusy(); \ 48541a17fe3SRobert Watson } \ 48695fab37eSRobert Watson } while (0) 48795fab37eSRobert Watson 48895fab37eSRobert Watson /* 48995fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 49095fab37eSRobert Watson */ 49195fab37eSRobert Watson static void 49295fab37eSRobert Watson mac_init(void) 49395fab37eSRobert Watson { 49495fab37eSRobert Watson 49541a17fe3SRobert Watson LIST_INIT(&mac_static_policy_list); 49695fab37eSRobert Watson LIST_INIT(&mac_policy_list); 49741a17fe3SRobert Watson 49841a17fe3SRobert Watson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 49941a17fe3SRobert Watson cv_init(&mac_policy_cv, "mac_policy_cv"); 50095fab37eSRobert Watson } 50195fab37eSRobert Watson 50295fab37eSRobert Watson /* 50395fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 50495fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 50595fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 50695fab37eSRobert Watson */ 50795fab37eSRobert Watson static void 50895fab37eSRobert Watson mac_late_init(void) 50995fab37eSRobert Watson { 51095fab37eSRobert Watson 51195fab37eSRobert Watson mac_late = 1; 51295fab37eSRobert Watson } 51395fab37eSRobert Watson 51495fab37eSRobert Watson /* 515225bff6fSRobert Watson * After the policy list has changed, walk the list to update any global 51619c3e120SRobert Watson * flags. Currently, we support only one flag, and it's conditionally 51719c3e120SRobert Watson * defined; as a result, the entire function is conditional. Eventually, 51819c3e120SRobert Watson * the #else case might also iterate across the policies. 519225bff6fSRobert Watson */ 520225bff6fSRobert Watson static void 521225bff6fSRobert Watson mac_policy_updateflags(void) 522225bff6fSRobert Watson { 523225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 52419c3e120SRobert Watson struct mac_policy_conf *tmpc; 525225bff6fSRobert Watson int labelmbufs; 526225bff6fSRobert Watson 52741a17fe3SRobert Watson mac_policy_assert_exclusive(); 528225bff6fSRobert Watson 529225bff6fSRobert Watson labelmbufs = 0; 53041a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 53141a17fe3SRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 53241a17fe3SRobert Watson labelmbufs++; 53341a17fe3SRobert Watson } 534225bff6fSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 535225bff6fSRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 536225bff6fSRobert Watson labelmbufs++; 537225bff6fSRobert Watson } 538225bff6fSRobert Watson mac_labelmbufs = (labelmbufs != 0); 539225bff6fSRobert Watson #endif 540225bff6fSRobert Watson } 541225bff6fSRobert Watson 542225bff6fSRobert Watson /* 54395fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 54495fab37eSRobert Watson */ 54595fab37eSRobert Watson int 54695fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 54795fab37eSRobert Watson { 54895fab37eSRobert Watson struct mac_policy_conf *mpc; 54995fab37eSRobert Watson int error; 55095fab37eSRobert Watson 55195fab37eSRobert Watson error = 0; 55295fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 55395fab37eSRobert Watson 55495fab37eSRobert Watson switch (type) { 55595fab37eSRobert Watson case MOD_LOAD: 55695fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 55795fab37eSRobert Watson mac_late) { 55895fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 55995fab37eSRobert Watson "after booting\n", mpc->mpc_name); 56095fab37eSRobert Watson error = EBUSY; 56195fab37eSRobert Watson break; 56295fab37eSRobert Watson } 56395fab37eSRobert Watson error = mac_policy_register(mpc); 56495fab37eSRobert Watson break; 56595fab37eSRobert Watson case MOD_UNLOAD: 56695fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 56795fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 56895fab37eSRobert Watson != 0) 56995fab37eSRobert Watson error = mac_policy_unregister(mpc); 57095fab37eSRobert Watson else 57195fab37eSRobert Watson error = 0; 57295fab37eSRobert Watson break; 57395fab37eSRobert Watson default: 57495fab37eSRobert Watson break; 57595fab37eSRobert Watson } 57695fab37eSRobert Watson 57795fab37eSRobert Watson return (error); 57895fab37eSRobert Watson } 57995fab37eSRobert Watson 58095fab37eSRobert Watson static int 58195fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 58295fab37eSRobert Watson { 58395fab37eSRobert Watson struct mac_policy_conf *tmpc; 58441a17fe3SRobert Watson int error, slot, static_entry; 58595fab37eSRobert Watson 58641a17fe3SRobert Watson error = 0; 58741a17fe3SRobert Watson 58841a17fe3SRobert Watson /* 58941a17fe3SRobert Watson * We don't technically need exclusive access while !mac_late, 59041a17fe3SRobert Watson * but hold it for assertion consistency. 59141a17fe3SRobert Watson */ 59241a17fe3SRobert Watson mac_policy_grab_exclusive(); 59341a17fe3SRobert Watson 59441a17fe3SRobert Watson /* 59541a17fe3SRobert Watson * If the module can potentially be unloaded, or we're loading 59641a17fe3SRobert Watson * late, we have to stick it in the non-static list and pay 59741a17fe3SRobert Watson * an extra performance overhead. Otherwise, we can pay a 59841a17fe3SRobert Watson * light locking cost and stick it in the static list. 59941a17fe3SRobert Watson */ 60041a17fe3SRobert Watson static_entry = (!mac_late && 60141a17fe3SRobert Watson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 60241a17fe3SRobert Watson 60341a17fe3SRobert Watson if (static_entry) { 60441a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 60541a17fe3SRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 60641a17fe3SRobert Watson error = EEXIST; 60741a17fe3SRobert Watson goto out; 60841a17fe3SRobert Watson } 60941a17fe3SRobert Watson } 61041a17fe3SRobert Watson } else { 61195fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 61295fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 61341a17fe3SRobert Watson error = EEXIST; 61441a17fe3SRobert Watson goto out; 61541a17fe3SRobert Watson } 61695fab37eSRobert Watson } 61795fab37eSRobert Watson } 61895fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 619b2aef571SRobert Watson slot = ffs(mac_slot_offsets_free); 62095fab37eSRobert Watson if (slot == 0) { 62141a17fe3SRobert Watson error = ENOMEM; 62241a17fe3SRobert Watson goto out; 62395fab37eSRobert Watson } 62495fab37eSRobert Watson slot--; 625b2aef571SRobert Watson mac_slot_offsets_free &= ~(1 << slot); 62695fab37eSRobert Watson *mpc->mpc_field_off = slot; 62795fab37eSRobert Watson } 62895fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 62941a17fe3SRobert Watson 63041a17fe3SRobert Watson /* 63141a17fe3SRobert Watson * If we're loading a MAC module after the framework has 63241a17fe3SRobert Watson * initialized, it has to go into the dynamic list. If 63341a17fe3SRobert Watson * we're loading it before we've finished initializing, 63441a17fe3SRobert Watson * it can go into the static list with weaker locker 63541a17fe3SRobert Watson * requirements. 63641a17fe3SRobert Watson */ 63741a17fe3SRobert Watson if (static_entry) 63841a17fe3SRobert Watson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 63941a17fe3SRobert Watson else 64095fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 64195fab37eSRobert Watson 64295fab37eSRobert Watson /* Per-policy initialization. */ 64395fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 64495fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 645225bff6fSRobert Watson mac_policy_updateflags(); 64695fab37eSRobert Watson 64795fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 64895fab37eSRobert Watson mpc->mpc_name); 64995fab37eSRobert Watson 65041a17fe3SRobert Watson out: 65141a17fe3SRobert Watson mac_policy_release_exclusive(); 65241a17fe3SRobert Watson return (error); 65395fab37eSRobert Watson } 65495fab37eSRobert Watson 65595fab37eSRobert Watson static int 65695fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 65795fab37eSRobert Watson { 65895fab37eSRobert Watson 659ea599aa0SRobert Watson /* 660ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 661ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 662ea599aa0SRobert Watson * silently succeed. 663ea599aa0SRobert Watson */ 66441a17fe3SRobert Watson mac_policy_grab_exclusive(); 665ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 66641a17fe3SRobert Watson mac_policy_release_exclusive(); 667ea599aa0SRobert Watson return (0); 668ea599aa0SRobert Watson } 66995fab37eSRobert Watson #if 0 67095fab37eSRobert Watson /* 67195fab37eSRobert Watson * Don't allow unloading modules with private data. 67295fab37eSRobert Watson */ 673ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 674ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 67595fab37eSRobert Watson return (EBUSY); 676ea599aa0SRobert Watson } 67795fab37eSRobert Watson #endif 678ea599aa0SRobert Watson /* 679ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 680ea599aa0SRobert Watson * by its own definition. 681ea599aa0SRobert Watson */ 682ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 68341a17fe3SRobert Watson mac_policy_release_exclusive(); 68495fab37eSRobert Watson return (EBUSY); 685ea599aa0SRobert Watson } 68695fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 68795fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 68895fab37eSRobert Watson 68995fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 6909aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 691225bff6fSRobert Watson mac_policy_updateflags(); 69241a17fe3SRobert Watson 69341a17fe3SRobert Watson mac_policy_release_exclusive(); 694a96acd1aSRobert Watson 69595fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 69695fab37eSRobert Watson mpc->mpc_name); 69795fab37eSRobert Watson 69895fab37eSRobert Watson return (0); 69995fab37eSRobert Watson } 70095fab37eSRobert Watson 70195fab37eSRobert Watson /* 70295fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 70395fab37eSRobert Watson * value with the higher precedence. 70495fab37eSRobert Watson */ 7059e7bf51cSRobert Watson int 7069e7bf51cSRobert Watson mac_error_select(int error1, int error2) 70795fab37eSRobert Watson { 70895fab37eSRobert Watson 70995fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 71095fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 71195fab37eSRobert Watson return (EDEADLK); 71295fab37eSRobert Watson 71395fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 71495fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 71595fab37eSRobert Watson return (EINVAL); 71695fab37eSRobert Watson 71795fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 71895fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 71995fab37eSRobert Watson return (ESRCH); 72095fab37eSRobert Watson 72195fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 72295fab37eSRobert Watson return (ENOENT); 72395fab37eSRobert Watson 72495fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 72595fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 72695fab37eSRobert Watson return (EACCES); 72795fab37eSRobert Watson 72895fab37eSRobert Watson /* Precedence goes to privilege. */ 72995fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 73095fab37eSRobert Watson return (EPERM); 73195fab37eSRobert Watson 73295fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 73395fab37eSRobert Watson if (error1 != 0) 73495fab37eSRobert Watson return (error1); 73595fab37eSRobert Watson return (error2); 73695fab37eSRobert Watson } 73795fab37eSRobert Watson 73810eeb10cSRobert Watson static struct label * 73910eeb10cSRobert Watson mbuf_to_label(struct mbuf *mbuf) 74010eeb10cSRobert Watson { 741225bff6fSRobert Watson struct m_tag *tag; 74210eeb10cSRobert Watson struct label *label; 74310eeb10cSRobert Watson 744225bff6fSRobert Watson tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL); 745225bff6fSRobert Watson label = (struct label *)(tag+1); 74610eeb10cSRobert Watson 74710eeb10cSRobert Watson return (label); 74810eeb10cSRobert Watson } 74910eeb10cSRobert Watson 75008bcdc58SRobert Watson static void 75108bcdc58SRobert Watson mac_init_label(struct label *label) 75208bcdc58SRobert Watson { 75308bcdc58SRobert Watson 75408bcdc58SRobert Watson bzero(label, sizeof(*label)); 75508bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 75608bcdc58SRobert Watson } 75708bcdc58SRobert Watson 75808bcdc58SRobert Watson static void 75908bcdc58SRobert Watson mac_destroy_label(struct label *label) 76008bcdc58SRobert Watson { 76108bcdc58SRobert Watson 76208bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 76308bcdc58SRobert Watson ("destroying uninitialized label")); 76408bcdc58SRobert Watson 76508bcdc58SRobert Watson bzero(label, sizeof(*label)); 76608bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 76708bcdc58SRobert Watson } 76808bcdc58SRobert Watson 76908bcdc58SRobert Watson void 77087807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 77108bcdc58SRobert Watson { 77208bcdc58SRobert Watson 77387807196SRobert Watson mac_init_label(&bpf_d->bd_label); 77487807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 7758d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacbpfdescs); 77608bcdc58SRobert Watson } 77708bcdc58SRobert Watson 778f7b951a8SRobert Watson static void 779f7b951a8SRobert Watson mac_init_cred_label(struct label *label) 78008bcdc58SRobert Watson { 78108bcdc58SRobert Watson 782f7b951a8SRobert Watson mac_init_label(label); 783f7b951a8SRobert Watson MAC_PERFORM(init_cred_label, label); 7848d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmaccreds); 78508bcdc58SRobert Watson } 78608bcdc58SRobert Watson 78708bcdc58SRobert Watson void 788f7b951a8SRobert Watson mac_init_cred(struct ucred *cred) 789f7b951a8SRobert Watson { 790f7b951a8SRobert Watson 791f7b951a8SRobert Watson mac_init_cred_label(&cred->cr_label); 792f7b951a8SRobert Watson } 793f7b951a8SRobert Watson 794f7b951a8SRobert Watson void 79587807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 79608bcdc58SRobert Watson { 79708bcdc58SRobert Watson 79887807196SRobert Watson mac_init_label(&de->de_label); 79987807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 8008d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents); 80108bcdc58SRobert Watson } 80208bcdc58SRobert Watson 803f7b951a8SRobert Watson static void 804f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label) 805f7b951a8SRobert Watson { 806f7b951a8SRobert Watson 807f7b951a8SRobert Watson mac_init_label(label); 808f7b951a8SRobert Watson MAC_PERFORM(init_ifnet_label, label); 8098d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacifnets); 810f7b951a8SRobert Watson } 811f7b951a8SRobert Watson 81208bcdc58SRobert Watson void 81308bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 81408bcdc58SRobert Watson { 81508bcdc58SRobert Watson 816f7b951a8SRobert Watson mac_init_ifnet_label(&ifp->if_label); 81708bcdc58SRobert Watson } 81808bcdc58SRobert Watson 8195e7ce478SRobert Watson int 8205e7ce478SRobert Watson mac_init_ipq(struct ipq *ipq, int flag) 82108bcdc58SRobert Watson { 8225e7ce478SRobert Watson int error; 82308bcdc58SRobert Watson 82408bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 8255e7ce478SRobert Watson 8265e7ce478SRobert Watson MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag); 8275e7ce478SRobert Watson if (error) { 8285e7ce478SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 8295e7ce478SRobert Watson mac_destroy_label(&ipq->ipq_label); 8308d8d5ea8SRobert Watson } else { 8318d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacipqs); 8325e7ce478SRobert Watson } 8335e7ce478SRobert Watson return (error); 83408bcdc58SRobert Watson } 83508bcdc58SRobert Watson 83687807196SRobert Watson int 837225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag) 83808bcdc58SRobert Watson { 839225bff6fSRobert Watson struct label *label; 8406d1a6a9aSRobert Watson int error; 84156c15412SRobert Watson 842225bff6fSRobert Watson label = (struct label *) (tag + 1); 843225bff6fSRobert Watson mac_init_label(label); 84408bcdc58SRobert Watson 8456d1a6a9aSRobert Watson MAC_CHECK(init_mbuf_label, label, flag); 84656c15412SRobert Watson if (error) { 847225bff6fSRobert Watson MAC_PERFORM(destroy_mbuf_label, label); 848225bff6fSRobert Watson mac_destroy_label(label); 8498d8d5ea8SRobert Watson } else { 8508d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacmbufs); 85156c15412SRobert Watson } 85256c15412SRobert Watson return (error); 85308bcdc58SRobert Watson } 85408bcdc58SRobert Watson 855225bff6fSRobert Watson int 856225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 857225bff6fSRobert Watson { 858225bff6fSRobert Watson struct m_tag *tag; 859225bff6fSRobert Watson int error; 860225bff6fSRobert Watson 861225bff6fSRobert Watson M_ASSERTPKTHDR(m); 862225bff6fSRobert Watson 863225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 864225bff6fSRobert Watson /* 86519c3e120SRobert Watson * If conditionally allocating mbuf labels, don't allocate unless 86619c3e120SRobert Watson * they are required. 867225bff6fSRobert Watson */ 86819c3e120SRobert Watson if (!mac_labelmbufs) 86919c3e120SRobert Watson return (0); 870225bff6fSRobert Watson #endif 871225bff6fSRobert Watson tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label), 872225bff6fSRobert Watson flag); 873225bff6fSRobert Watson if (tag == NULL) 874225bff6fSRobert Watson return (ENOMEM); 875225bff6fSRobert Watson error = mac_init_mbuf_tag(tag, flag); 876225bff6fSRobert Watson if (error) { 877225bff6fSRobert Watson m_tag_free(tag); 878225bff6fSRobert Watson return (error); 879225bff6fSRobert Watson } 880225bff6fSRobert Watson m_tag_prepend(m, tag); 881225bff6fSRobert Watson return (0); 882225bff6fSRobert Watson } 883225bff6fSRobert Watson 88408bcdc58SRobert Watson void 88587807196SRobert Watson mac_init_mount(struct mount *mp) 88608bcdc58SRobert Watson { 88708bcdc58SRobert Watson 88887807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 88987807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 89087807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 89187807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 8928d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacmounts); 89308bcdc58SRobert Watson } 89408bcdc58SRobert Watson 895f7b951a8SRobert Watson static void 896f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 897f7b951a8SRobert Watson { 898f7b951a8SRobert Watson 899f7b951a8SRobert Watson mac_init_label(label); 900f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 9018d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacpipes); 902f7b951a8SRobert Watson } 903f7b951a8SRobert Watson 90408bcdc58SRobert Watson void 90508bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 90608bcdc58SRobert Watson { 90708bcdc58SRobert Watson struct label *label; 90808bcdc58SRobert Watson 909a163d034SWarner Losh label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 91008bcdc58SRobert Watson pipe->pipe_label = label; 91108bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 912f7b951a8SRobert Watson mac_init_pipe_label(label); 91308bcdc58SRobert Watson } 91408bcdc58SRobert Watson 9152555374cSRobert Watson void 9162555374cSRobert Watson mac_init_proc(struct proc *p) 9172555374cSRobert Watson { 9182555374cSRobert Watson 9192555374cSRobert Watson mac_init_label(&p->p_label); 9202555374cSRobert Watson MAC_PERFORM(init_proc_label, &p->p_label); 9218d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacprocs); 9222555374cSRobert Watson } 9232555374cSRobert Watson 92483985c26SRobert Watson static int 92583985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 92608bcdc58SRobert Watson { 92783985c26SRobert Watson int error; 92808bcdc58SRobert Watson 92983985c26SRobert Watson mac_init_label(label); 93083985c26SRobert Watson 93183985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 93283985c26SRobert Watson if (error) { 93383985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 93483985c26SRobert Watson mac_destroy_label(label); 9358d8d5ea8SRobert Watson } else { 9368d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacsockets); 93783985c26SRobert Watson } 93883985c26SRobert Watson 93983985c26SRobert Watson return (error); 94083985c26SRobert Watson } 94183985c26SRobert Watson 94283985c26SRobert Watson static int 94383985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 94483985c26SRobert Watson { 94583985c26SRobert Watson int error; 94683985c26SRobert Watson 94783985c26SRobert Watson mac_init_label(label); 94883985c26SRobert Watson 94983985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 95083985c26SRobert Watson if (error) { 95183985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 95283985c26SRobert Watson mac_destroy_label(label); 95383985c26SRobert Watson } 95483985c26SRobert Watson 95583985c26SRobert Watson return (error); 95683985c26SRobert Watson } 95783985c26SRobert Watson 95883985c26SRobert Watson int 95983985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 96083985c26SRobert Watson { 96183985c26SRobert Watson int error; 96283985c26SRobert Watson 96383985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 96483985c26SRobert Watson if (error) 96583985c26SRobert Watson return (error); 96683985c26SRobert Watson 96783985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 96883985c26SRobert Watson if (error) 96983985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 97083985c26SRobert Watson 97183985c26SRobert Watson return (error); 97287807196SRobert Watson } 97387807196SRobert Watson 974763bbd2fSRobert Watson void 975f7b951a8SRobert Watson mac_init_vnode_label(struct label *label) 97687807196SRobert Watson { 97787807196SRobert Watson 97887807196SRobert Watson mac_init_label(label); 979f7b951a8SRobert Watson MAC_PERFORM(init_vnode_label, label); 9808d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacvnodes); 98108bcdc58SRobert Watson } 98208bcdc58SRobert Watson 98308bcdc58SRobert Watson void 98487807196SRobert Watson mac_init_vnode(struct vnode *vp) 98508bcdc58SRobert Watson { 98608bcdc58SRobert Watson 987f7b951a8SRobert Watson mac_init_vnode_label(&vp->v_label); 98808bcdc58SRobert Watson } 98908bcdc58SRobert Watson 99008bcdc58SRobert Watson void 99108bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 99208bcdc58SRobert Watson { 99308bcdc58SRobert Watson 99408bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 99508bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 9968d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs); 99708bcdc58SRobert Watson } 99808bcdc58SRobert Watson 999f7b951a8SRobert Watson static void 1000f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label) 100108bcdc58SRobert Watson { 100208bcdc58SRobert Watson 1003f7b951a8SRobert Watson MAC_PERFORM(destroy_cred_label, label); 1004f7b951a8SRobert Watson mac_destroy_label(label); 10058d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmaccreds); 100687807196SRobert Watson } 100787807196SRobert Watson 100887807196SRobert Watson void 1009f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred) 1010f7b951a8SRobert Watson { 1011f7b951a8SRobert Watson 1012f7b951a8SRobert Watson mac_destroy_cred_label(&cred->cr_label); 1013f7b951a8SRobert Watson } 1014f7b951a8SRobert Watson 1015f7b951a8SRobert Watson void 101687807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 101787807196SRobert Watson { 101887807196SRobert Watson 101987807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 102087807196SRobert Watson mac_destroy_label(&de->de_label); 10218d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents); 102287807196SRobert Watson } 102387807196SRobert Watson 1024f7b951a8SRobert Watson static void 1025f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label) 1026f7b951a8SRobert Watson { 1027f7b951a8SRobert Watson 1028f7b951a8SRobert Watson MAC_PERFORM(destroy_ifnet_label, label); 1029f7b951a8SRobert Watson mac_destroy_label(label); 10308d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacifnets); 1031f7b951a8SRobert Watson } 1032f7b951a8SRobert Watson 103387807196SRobert Watson void 103487807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 103587807196SRobert Watson { 103687807196SRobert Watson 1037f7b951a8SRobert Watson mac_destroy_ifnet_label(&ifp->if_label); 103887807196SRobert Watson } 103987807196SRobert Watson 104087807196SRobert Watson void 104187807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 104287807196SRobert Watson { 104387807196SRobert Watson 104487807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 104587807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 10468d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacipqs); 104787807196SRobert Watson } 104887807196SRobert Watson 104987807196SRobert Watson void 1050225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag) 105187807196SRobert Watson { 1052225bff6fSRobert Watson struct label *label; 105387807196SRobert Watson 1054225bff6fSRobert Watson label = (struct label *)(tag+1); 1055225bff6fSRobert Watson 1056225bff6fSRobert Watson MAC_PERFORM(destroy_mbuf_label, label); 1057225bff6fSRobert Watson mac_destroy_label(label); 10588d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacmbufs); 105908bcdc58SRobert Watson } 106008bcdc58SRobert Watson 106108bcdc58SRobert Watson void 106208bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 106308bcdc58SRobert Watson { 106408bcdc58SRobert Watson 106508bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 106608bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 106708bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 106808bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 10698d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacmounts); 107008bcdc58SRobert Watson } 107108bcdc58SRobert Watson 1072f7b951a8SRobert Watson static void 1073f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 1074f7b951a8SRobert Watson { 1075f7b951a8SRobert Watson 1076f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 1077f7b951a8SRobert Watson mac_destroy_label(label); 10788d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacpipes); 1079f7b951a8SRobert Watson } 1080f7b951a8SRobert Watson 108187807196SRobert Watson void 108287807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 108308bcdc58SRobert Watson { 108408bcdc58SRobert Watson 1085f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 108687807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 108787807196SRobert Watson } 108887807196SRobert Watson 10892555374cSRobert Watson void 10902555374cSRobert Watson mac_destroy_proc(struct proc *p) 10912555374cSRobert Watson { 10922555374cSRobert Watson 10932555374cSRobert Watson MAC_PERFORM(destroy_proc_label, &p->p_label); 10942555374cSRobert Watson mac_destroy_label(&p->p_label); 10958d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacprocs); 10962555374cSRobert Watson } 10972555374cSRobert Watson 109883985c26SRobert Watson static void 109983985c26SRobert Watson mac_destroy_socket_label(struct label *label) 110083985c26SRobert Watson { 110183985c26SRobert Watson 110283985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 110383985c26SRobert Watson mac_destroy_label(label); 11048d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacsockets); 110583985c26SRobert Watson } 110683985c26SRobert Watson 110783985c26SRobert Watson static void 110883985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 110983985c26SRobert Watson { 111083985c26SRobert Watson 111183985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 111283985c26SRobert Watson mac_destroy_label(label); 111383985c26SRobert Watson } 111483985c26SRobert Watson 111587807196SRobert Watson void 111687807196SRobert Watson mac_destroy_socket(struct socket *socket) 111787807196SRobert Watson { 111887807196SRobert Watson 111983985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 112083985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 112108bcdc58SRobert Watson } 112208bcdc58SRobert Watson 1123763bbd2fSRobert Watson void 1124f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label) 112508bcdc58SRobert Watson { 112608bcdc58SRobert Watson 1127f7b951a8SRobert Watson MAC_PERFORM(destroy_vnode_label, label); 112808bcdc58SRobert Watson mac_destroy_label(label); 11298d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacvnodes); 113008bcdc58SRobert Watson } 113108bcdc58SRobert Watson 113208bcdc58SRobert Watson void 113308bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 113408bcdc58SRobert Watson { 113508bcdc58SRobert Watson 1136f7b951a8SRobert Watson mac_destroy_vnode_label(&vp->v_label); 1137f7b951a8SRobert Watson } 1138f7b951a8SRobert Watson 1139225bff6fSRobert Watson void 1140225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest) 1141225bff6fSRobert Watson { 1142225bff6fSRobert Watson struct label *src_label, *dest_label; 1143225bff6fSRobert Watson 1144225bff6fSRobert Watson src_label = (struct label *)(src+1); 1145225bff6fSRobert Watson dest_label = (struct label *)(dest+1); 1146225bff6fSRobert Watson 1147225bff6fSRobert Watson /* 1148225bff6fSRobert Watson * mac_init_mbuf_tag() is called on the target tag in 1149225bff6fSRobert Watson * m_tag_copy(), so we don't need to call it here. 1150225bff6fSRobert Watson */ 1151225bff6fSRobert Watson MAC_PERFORM(copy_mbuf_label, src_label, dest_label); 1152225bff6fSRobert Watson } 1153225bff6fSRobert Watson 1154f7b951a8SRobert Watson static void 1155f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 1156f7b951a8SRobert Watson { 1157f7b951a8SRobert Watson 1158f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 1159f7b951a8SRobert Watson } 1160f7b951a8SRobert Watson 1161763bbd2fSRobert Watson void 1162f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest) 1163f7b951a8SRobert Watson { 1164f7b951a8SRobert Watson 1165f7b951a8SRobert Watson MAC_PERFORM(copy_vnode_label, src, dest); 116608bcdc58SRobert Watson } 116708bcdc58SRobert Watson 116869bbb5b1SRobert Watson static int 1169f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 1170f7b951a8SRobert Watson { 1171f7b951a8SRobert Watson 1172cc7b13bfSRobert Watson if (mac->m_buflen < 0 || 1173cc7b13bfSRobert Watson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1174f7b951a8SRobert Watson return (EINVAL); 1175f7b951a8SRobert Watson 1176f7b951a8SRobert Watson return (0); 1177f7b951a8SRobert Watson } 1178f7b951a8SRobert Watson 1179f7b951a8SRobert Watson static int 1180f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements, 1181f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 118269bbb5b1SRobert Watson { 118369bbb5b1SRobert Watson int error; 118469bbb5b1SRobert Watson 1185f7b951a8SRobert Watson MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 118669bbb5b1SRobert Watson 118769bbb5b1SRobert Watson return (error); 118869bbb5b1SRobert Watson } 118969bbb5b1SRobert Watson 119069bbb5b1SRobert Watson static int 1191f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements, 1192f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 119369bbb5b1SRobert Watson { 119469bbb5b1SRobert Watson int error; 119569bbb5b1SRobert Watson 1196f7b951a8SRobert Watson MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1197f7b951a8SRobert Watson 1198f7b951a8SRobert Watson return (error); 1199f7b951a8SRobert Watson } 1200f7b951a8SRobert Watson 1201f7b951a8SRobert Watson static int 1202f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 1203f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1204f7b951a8SRobert Watson { 1205f7b951a8SRobert Watson int error; 1206f7b951a8SRobert Watson 1207f7b951a8SRobert Watson MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1208f7b951a8SRobert Watson 1209f7b951a8SRobert Watson return (error); 1210f7b951a8SRobert Watson } 1211f7b951a8SRobert Watson 1212f7b951a8SRobert Watson static int 1213f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 1214f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1215f7b951a8SRobert Watson { 1216f7b951a8SRobert Watson int error; 1217f7b951a8SRobert Watson 1218f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1219f7b951a8SRobert Watson 1220f7b951a8SRobert Watson return (error); 1221f7b951a8SRobert Watson } 1222f7b951a8SRobert Watson 1223f7b951a8SRobert Watson static int 1224f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 1225f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1226f7b951a8SRobert Watson { 1227f7b951a8SRobert Watson int error; 1228f7b951a8SRobert Watson 1229f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1230f7b951a8SRobert Watson 1231f7b951a8SRobert Watson return (error); 1232f7b951a8SRobert Watson } 1233f7b951a8SRobert Watson 1234f7b951a8SRobert Watson static int 1235f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements, 1236f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1237f7b951a8SRobert Watson { 1238f7b951a8SRobert Watson int error; 1239f7b951a8SRobert Watson 1240f7b951a8SRobert Watson MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1241f7b951a8SRobert Watson 1242f7b951a8SRobert Watson return (error); 1243f7b951a8SRobert Watson } 1244f7b951a8SRobert Watson 1245f7b951a8SRobert Watson static int 1246f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string) 1247f7b951a8SRobert Watson { 1248f7b951a8SRobert Watson int error; 1249f7b951a8SRobert Watson 1250f7b951a8SRobert Watson MAC_INTERNALIZE(cred_label, label, string); 1251f7b951a8SRobert Watson 1252f7b951a8SRobert Watson return (error); 1253f7b951a8SRobert Watson } 1254f7b951a8SRobert Watson 1255f7b951a8SRobert Watson static int 1256f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string) 1257f7b951a8SRobert Watson { 1258f7b951a8SRobert Watson int error; 1259f7b951a8SRobert Watson 1260f7b951a8SRobert Watson MAC_INTERNALIZE(ifnet_label, label, string); 1261f7b951a8SRobert Watson 1262f7b951a8SRobert Watson return (error); 1263f7b951a8SRobert Watson } 1264f7b951a8SRobert Watson 1265f7b951a8SRobert Watson static int 1266f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 1267f7b951a8SRobert Watson { 1268f7b951a8SRobert Watson int error; 1269f7b951a8SRobert Watson 1270f7b951a8SRobert Watson MAC_INTERNALIZE(pipe_label, label, string); 1271f7b951a8SRobert Watson 1272f7b951a8SRobert Watson return (error); 1273f7b951a8SRobert Watson } 1274f7b951a8SRobert Watson 1275f7b951a8SRobert Watson static int 1276f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string) 1277f7b951a8SRobert Watson { 1278f7b951a8SRobert Watson int error; 1279f7b951a8SRobert Watson 1280f7b951a8SRobert Watson MAC_INTERNALIZE(socket_label, label, string); 1281f7b951a8SRobert Watson 1282f7b951a8SRobert Watson return (error); 1283f7b951a8SRobert Watson } 1284f7b951a8SRobert Watson 1285f7b951a8SRobert Watson static int 1286f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string) 1287f7b951a8SRobert Watson { 1288f7b951a8SRobert Watson int error; 1289f7b951a8SRobert Watson 1290f7b951a8SRobert Watson MAC_INTERNALIZE(vnode_label, label, string); 129169bbb5b1SRobert Watson 129269bbb5b1SRobert Watson return (error); 129369bbb5b1SRobert Watson } 129469bbb5b1SRobert Watson 129569bbb5b1SRobert Watson /* 129669bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 129769bbb5b1SRobert Watson * kernel processes and threads are spawned. 129869bbb5b1SRobert Watson */ 129969bbb5b1SRobert Watson void 130069bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 130169bbb5b1SRobert Watson { 130269bbb5b1SRobert Watson 130369bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 130469bbb5b1SRobert Watson } 130569bbb5b1SRobert Watson 130669bbb5b1SRobert Watson /* 130769bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 130869bbb5b1SRobert Watson * userland processes and threads are spawned. 130969bbb5b1SRobert Watson */ 131069bbb5b1SRobert Watson void 131169bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 131269bbb5b1SRobert Watson { 131369bbb5b1SRobert Watson 131469bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 131569bbb5b1SRobert Watson } 131669bbb5b1SRobert Watson 131769bbb5b1SRobert Watson void 131869bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 131969bbb5b1SRobert Watson { 132069bbb5b1SRobert Watson 132169bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 132269bbb5b1SRobert Watson } 132369bbb5b1SRobert Watson 132469bbb5b1SRobert Watson /* 132569bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 132669bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 132769bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 132869bbb5b1SRobert Watson */ 132969bbb5b1SRobert Watson void 133069bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 133169bbb5b1SRobert Watson { 133269bbb5b1SRobert Watson 133369bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 133469bbb5b1SRobert Watson } 133569bbb5b1SRobert Watson 133695fab37eSRobert Watson void 1337990b4b2dSRobert Watson mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de, 1338990b4b2dSRobert Watson struct vnode *vp) 133995fab37eSRobert Watson { 134095fab37eSRobert Watson 1341990b4b2dSRobert Watson MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp, 1342990b4b2dSRobert Watson &vp->v_label); 134395fab37eSRobert Watson } 134495fab37eSRobert Watson 134595fab37eSRobert Watson void 1346763bbd2fSRobert Watson mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1347763bbd2fSRobert Watson struct vnode *vp) 134895fab37eSRobert Watson { 134995fab37eSRobert Watson 1350763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1351763bbd2fSRobert Watson &de->de_label, vp, &vp->v_label); 135295fab37eSRobert Watson } 135395fab37eSRobert Watson 1354763bbd2fSRobert Watson int 1355763bbd2fSRobert Watson mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 135695fab37eSRobert Watson { 135795fab37eSRobert Watson int error; 135895fab37eSRobert Watson 1359763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1360763bbd2fSRobert Watson 1361763bbd2fSRobert Watson MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1362763bbd2fSRobert Watson &vp->v_label); 136395fab37eSRobert Watson 136495fab37eSRobert Watson return (error); 136595fab37eSRobert Watson } 136695fab37eSRobert Watson 136795fab37eSRobert Watson void 1368763bbd2fSRobert Watson mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 136995fab37eSRobert Watson { 137095fab37eSRobert Watson 1371763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1372763bbd2fSRobert Watson &vp->v_label); 137395fab37eSRobert Watson } 137495fab37eSRobert Watson 137595fab37eSRobert Watson int 1376763bbd2fSRobert Watson mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1377763bbd2fSRobert Watson struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 137895fab37eSRobert Watson { 1379763bbd2fSRobert Watson int error; 138095fab37eSRobert Watson 1381763bbd2fSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1382763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 138395fab37eSRobert Watson 1384763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1385763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1386763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1387763bbd2fSRobert Watson if (ea_warn_once == 0) { 1388763bbd2fSRobert Watson printf("Warning: transactions not supported " 1389763bbd2fSRobert Watson "in EA write.\n"); 1390763bbd2fSRobert Watson ea_warn_once = 1; 1391763bbd2fSRobert Watson } 1392763bbd2fSRobert Watson } else if (error) 139395fab37eSRobert Watson return (error); 139495fab37eSRobert Watson 1395763bbd2fSRobert Watson MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1396763bbd2fSRobert Watson dvp, &dvp->v_label, vp, &vp->v_label, cnp); 139795fab37eSRobert Watson 1398763bbd2fSRobert Watson if (error) { 1399763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 140095fab37eSRobert Watson return (error); 140195fab37eSRobert Watson } 140295fab37eSRobert Watson 1403763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 140495fab37eSRobert Watson 1405763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1406763bbd2fSRobert Watson error = 0; /* XXX */ 140795fab37eSRobert Watson 140895fab37eSRobert Watson return (error); 140995fab37eSRobert Watson } 141095fab37eSRobert Watson 141195fab37eSRobert Watson static int 1412763bbd2fSRobert Watson mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1413763bbd2fSRobert Watson struct label *intlabel) 141495fab37eSRobert Watson { 141595fab37eSRobert Watson int error; 141695fab37eSRobert Watson 1417763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 141895fab37eSRobert Watson 1419763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1420763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1421763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1422763bbd2fSRobert Watson if (ea_warn_once == 0) { 1423763bbd2fSRobert Watson printf("Warning: transactions not supported " 1424763bbd2fSRobert Watson "in EA write.\n"); 1425763bbd2fSRobert Watson ea_warn_once = 1; 142695fab37eSRobert Watson } 1427763bbd2fSRobert Watson } else if (error) 142895fab37eSRobert Watson return (error); 142995fab37eSRobert Watson 1430763bbd2fSRobert Watson MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 143195fab37eSRobert Watson 1432763bbd2fSRobert Watson if (error) { 1433763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 143495fab37eSRobert Watson return (error); 143595fab37eSRobert Watson } 143695fab37eSRobert Watson 1437763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1438763bbd2fSRobert Watson 1439763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1440763bbd2fSRobert Watson error = 0; /* XXX */ 1441763bbd2fSRobert Watson 1442763bbd2fSRobert Watson return (error); 144395fab37eSRobert Watson } 144495fab37eSRobert Watson 1445670cb89bSRobert Watson int 1446670cb89bSRobert Watson mac_execve_enter(struct image_params *imgp, struct mac *mac_p, 1447670cb89bSRobert Watson struct label *execlabelstorage) 1448670cb89bSRobert Watson { 1449670cb89bSRobert Watson struct mac mac; 1450670cb89bSRobert Watson char *buffer; 1451670cb89bSRobert Watson int error; 1452670cb89bSRobert Watson 1453670cb89bSRobert Watson if (mac_p == NULL) 1454670cb89bSRobert Watson return (0); 1455670cb89bSRobert Watson 1456670cb89bSRobert Watson error = copyin(mac_p, &mac, sizeof(mac)); 1457670cb89bSRobert Watson if (error) 1458670cb89bSRobert Watson return (error); 1459670cb89bSRobert Watson 1460670cb89bSRobert Watson error = mac_check_structmac_consistent(&mac); 1461670cb89bSRobert Watson if (error) 1462670cb89bSRobert Watson return (error); 1463670cb89bSRobert Watson 1464a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1465670cb89bSRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1466670cb89bSRobert Watson if (error) { 1467670cb89bSRobert Watson free(buffer, M_MACTEMP); 1468670cb89bSRobert Watson return (error); 1469670cb89bSRobert Watson } 1470670cb89bSRobert Watson 1471670cb89bSRobert Watson mac_init_cred_label(execlabelstorage); 1472670cb89bSRobert Watson error = mac_internalize_cred_label(execlabelstorage, buffer); 1473670cb89bSRobert Watson free(buffer, M_MACTEMP); 1474670cb89bSRobert Watson if (error) { 1475670cb89bSRobert Watson mac_destroy_cred_label(execlabelstorage); 1476670cb89bSRobert Watson return (error); 1477670cb89bSRobert Watson } 1478670cb89bSRobert Watson imgp->execlabel = execlabelstorage; 1479670cb89bSRobert Watson return (0); 1480670cb89bSRobert Watson } 1481670cb89bSRobert Watson 148295fab37eSRobert Watson void 1483670cb89bSRobert Watson mac_execve_exit(struct image_params *imgp) 1484670cb89bSRobert Watson { 1485670cb89bSRobert Watson if (imgp->execlabel != NULL) 1486670cb89bSRobert Watson mac_destroy_cred_label(imgp->execlabel); 1487670cb89bSRobert Watson } 1488670cb89bSRobert Watson 1489670cb89bSRobert Watson void 1490670cb89bSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 1491670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 149295fab37eSRobert Watson { 149395fab37eSRobert Watson 149495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 149595fab37eSRobert Watson 14964443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 14974443e9ffSRobert Watson return; 14984443e9ffSRobert Watson 1499670cb89bSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 15009fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 150195fab37eSRobert Watson } 150295fab37eSRobert Watson 150395fab37eSRobert Watson int 1504670cb89bSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp, 1505670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 150695fab37eSRobert Watson { 1507763bbd2fSRobert Watson int result; 150895fab37eSRobert Watson 15094443e9ffSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 15104443e9ffSRobert Watson 15114443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 15124443e9ffSRobert Watson return (0); 15134443e9ffSRobert Watson 151495fab37eSRobert Watson result = 0; 1515670cb89bSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 15169fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 151795fab37eSRobert Watson 151895fab37eSRobert Watson return (result); 151995fab37eSRobert Watson } 152095fab37eSRobert Watson 152195fab37eSRobert Watson int 1522b914de36SRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 152395fab37eSRobert Watson { 152495fab37eSRobert Watson int error; 152595fab37eSRobert Watson 152695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 152795fab37eSRobert Watson 152895fab37eSRobert Watson if (!mac_enforce_fs) 152995fab37eSRobert Watson return (0); 153095fab37eSRobert Watson 1531b914de36SRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 153295fab37eSRobert Watson return (error); 153395fab37eSRobert Watson } 153495fab37eSRobert Watson 153595fab37eSRobert Watson int 153695fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 153795fab37eSRobert Watson { 153895fab37eSRobert Watson int error; 153995fab37eSRobert Watson 154095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 154195fab37eSRobert Watson 154295fab37eSRobert Watson if (!mac_enforce_fs) 154395fab37eSRobert Watson return (0); 154495fab37eSRobert Watson 154595fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 154695fab37eSRobert Watson return (error); 154795fab37eSRobert Watson } 154895fab37eSRobert Watson 154995fab37eSRobert Watson int 155095fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 155195fab37eSRobert Watson { 155295fab37eSRobert Watson int error; 155395fab37eSRobert Watson 155495fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 155595fab37eSRobert Watson 155695fab37eSRobert Watson if (!mac_enforce_fs) 155795fab37eSRobert Watson return (0); 155895fab37eSRobert Watson 155995fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 156095fab37eSRobert Watson return (error); 156195fab37eSRobert Watson } 156295fab37eSRobert Watson 156395fab37eSRobert Watson int 156495fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 156595fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 156695fab37eSRobert Watson { 156795fab37eSRobert Watson int error; 156895fab37eSRobert Watson 156995fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 157095fab37eSRobert Watson 157195fab37eSRobert Watson if (!mac_enforce_fs) 157295fab37eSRobert Watson return (0); 157395fab37eSRobert Watson 157495fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 157595fab37eSRobert Watson return (error); 157695fab37eSRobert Watson } 157795fab37eSRobert Watson 157895fab37eSRobert Watson int 157995fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 158095fab37eSRobert Watson struct componentname *cnp) 158195fab37eSRobert Watson { 158295fab37eSRobert Watson int error; 158395fab37eSRobert Watson 158495fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 158595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 158695fab37eSRobert Watson 158795fab37eSRobert Watson if (!mac_enforce_fs) 158895fab37eSRobert Watson return (0); 158995fab37eSRobert Watson 159095fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 159195fab37eSRobert Watson &vp->v_label, cnp); 159295fab37eSRobert Watson return (error); 159395fab37eSRobert Watson } 159495fab37eSRobert Watson 159595fab37eSRobert Watson int 159695fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 159795fab37eSRobert Watson acl_type_t type) 159895fab37eSRobert Watson { 159995fab37eSRobert Watson int error; 160095fab37eSRobert Watson 160195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 160295fab37eSRobert Watson 160395fab37eSRobert Watson if (!mac_enforce_fs) 160495fab37eSRobert Watson return (0); 160595fab37eSRobert Watson 160695fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 160795fab37eSRobert Watson return (error); 160895fab37eSRobert Watson } 160995fab37eSRobert Watson 161095fab37eSRobert Watson int 1611c096756cSRobert Watson mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp, 1612c096756cSRobert Watson int attrnamespace, const char *name) 1613c096756cSRobert Watson { 1614c096756cSRobert Watson int error; 1615c096756cSRobert Watson 1616c096756cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr"); 1617c096756cSRobert Watson 1618c096756cSRobert Watson if (!mac_enforce_fs) 1619c096756cSRobert Watson return (0); 1620c096756cSRobert Watson 1621c096756cSRobert Watson MAC_CHECK(check_vnode_deleteextattr, cred, vp, &vp->v_label, 1622c096756cSRobert Watson attrnamespace, name); 1623c096756cSRobert Watson return (error); 1624c096756cSRobert Watson } 1625c096756cSRobert Watson 1626c096756cSRobert Watson int 1627670cb89bSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1628670cb89bSRobert Watson struct image_params *imgp) 162995fab37eSRobert Watson { 163095fab37eSRobert Watson int error; 163195fab37eSRobert Watson 1632851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1633851704bbSRobert Watson 163495fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 163595fab37eSRobert Watson return (0); 163695fab37eSRobert Watson 16379fa3506eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 16389fa3506eSRobert Watson imgp->execlabel); 163995fab37eSRobert Watson 164095fab37eSRobert Watson return (error); 164195fab37eSRobert Watson } 164295fab37eSRobert Watson 164395fab37eSRobert Watson int 164495fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 164595fab37eSRobert Watson { 164695fab37eSRobert Watson int error; 164795fab37eSRobert Watson 164895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 164995fab37eSRobert Watson 165095fab37eSRobert Watson if (!mac_enforce_fs) 165195fab37eSRobert Watson return (0); 165295fab37eSRobert Watson 165395fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 165495fab37eSRobert Watson return (error); 165595fab37eSRobert Watson } 165695fab37eSRobert Watson 165795fab37eSRobert Watson int 165895fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 165995fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 166095fab37eSRobert Watson { 166195fab37eSRobert Watson int error; 166295fab37eSRobert Watson 166395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 166495fab37eSRobert Watson 166595fab37eSRobert Watson if (!mac_enforce_fs) 166695fab37eSRobert Watson return (0); 166795fab37eSRobert Watson 166895fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 166995fab37eSRobert Watson attrnamespace, name, uio); 167095fab37eSRobert Watson return (error); 167195fab37eSRobert Watson } 167295fab37eSRobert Watson 167395fab37eSRobert Watson int 16740a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 16750a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 16760a694196SRobert Watson { 16770a694196SRobert Watson int error; 16780a694196SRobert Watson 16790a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 16800a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 16810a694196SRobert Watson 16820a694196SRobert Watson if (!mac_enforce_fs) 16830a694196SRobert Watson return (0); 16840a694196SRobert Watson 16850a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 16860a694196SRobert Watson &vp->v_label, cnp); 16870a694196SRobert Watson return (error); 16880a694196SRobert Watson } 16890a694196SRobert Watson 16900a694196SRobert Watson int 1691c096756cSRobert Watson mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp, 1692c096756cSRobert Watson int attrnamespace) 1693c096756cSRobert Watson { 1694c096756cSRobert Watson int error; 1695c096756cSRobert Watson 1696c096756cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr"); 1697c096756cSRobert Watson 1698c096756cSRobert Watson if (!mac_enforce_fs) 1699c096756cSRobert Watson return (0); 1700c096756cSRobert Watson 1701c096756cSRobert Watson MAC_CHECK(check_vnode_listextattr, cred, vp, &vp->v_label, 1702c096756cSRobert Watson attrnamespace); 1703c096756cSRobert Watson return (error); 1704c096756cSRobert Watson } 1705c096756cSRobert Watson 1706c096756cSRobert Watson int 170795fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 170895fab37eSRobert Watson struct componentname *cnp) 170995fab37eSRobert Watson { 171095fab37eSRobert Watson int error; 171195fab37eSRobert Watson 171295fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 171395fab37eSRobert Watson 171495fab37eSRobert Watson if (!mac_enforce_fs) 171595fab37eSRobert Watson return (0); 171695fab37eSRobert Watson 171795fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 171895fab37eSRobert Watson return (error); 171995fab37eSRobert Watson } 172095fab37eSRobert Watson 1721e183f80eSRobert Watson int 1722e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 172395fab37eSRobert Watson { 1724e183f80eSRobert Watson int error; 172595fab37eSRobert Watson 1726e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1727ca7850c3SRobert Watson 1728e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1729e183f80eSRobert Watson return (0); 1730e183f80eSRobert Watson 1731e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1732e183f80eSRobert Watson return (error); 1733e183f80eSRobert Watson } 1734e183f80eSRobert Watson 1735e183f80eSRobert Watson void 1736e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1737e183f80eSRobert Watson { 1738e183f80eSRobert Watson int result = *prot; 1739e183f80eSRobert Watson 1740e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1741e183f80eSRobert Watson 1742e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1743e183f80eSRobert Watson return; 1744e183f80eSRobert Watson 1745e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1746e183f80eSRobert Watson &result); 1747e183f80eSRobert Watson 1748e183f80eSRobert Watson *prot = result; 1749e183f80eSRobert Watson } 1750e183f80eSRobert Watson 1751e183f80eSRobert Watson int 1752e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1753e183f80eSRobert Watson { 1754e183f80eSRobert Watson int error; 1755e183f80eSRobert Watson 1756e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1757e183f80eSRobert Watson 1758e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1759e183f80eSRobert Watson return (0); 1760e183f80eSRobert Watson 1761e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1762e183f80eSRobert Watson return (error); 176395fab37eSRobert Watson } 176495fab37eSRobert Watson 176595fab37eSRobert Watson int 1766b914de36SRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 176795fab37eSRobert Watson { 176895fab37eSRobert Watson int error; 176995fab37eSRobert Watson 177095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 177195fab37eSRobert Watson 177295fab37eSRobert Watson if (!mac_enforce_fs) 177395fab37eSRobert Watson return (0); 177495fab37eSRobert Watson 177595fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 177695fab37eSRobert Watson return (error); 177795fab37eSRobert Watson } 177895fab37eSRobert Watson 177995fab37eSRobert Watson int 1780177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1781177142e4SRobert Watson struct vnode *vp) 17827f724f8bSRobert Watson { 17837f724f8bSRobert Watson int error; 17847f724f8bSRobert Watson 17857f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 17867f724f8bSRobert Watson 17877f724f8bSRobert Watson if (!mac_enforce_fs) 17887f724f8bSRobert Watson return (0); 17897f724f8bSRobert Watson 1790177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1791177142e4SRobert Watson &vp->v_label); 17927f724f8bSRobert Watson 17937f724f8bSRobert Watson return (error); 17947f724f8bSRobert Watson } 17957f724f8bSRobert Watson 17967f724f8bSRobert Watson int 1797177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1798177142e4SRobert Watson struct vnode *vp) 17997f724f8bSRobert Watson { 18007f724f8bSRobert Watson int error; 18017f724f8bSRobert Watson 18027f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 18037f724f8bSRobert Watson 18047f724f8bSRobert Watson if (!mac_enforce_fs) 18057f724f8bSRobert Watson return (0); 18067f724f8bSRobert Watson 1807177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1808177142e4SRobert Watson &vp->v_label); 18097f724f8bSRobert Watson 18107f724f8bSRobert Watson return (error); 18117f724f8bSRobert Watson } 18127f724f8bSRobert Watson 18137f724f8bSRobert Watson int 181495fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 181595fab37eSRobert Watson { 181695fab37eSRobert Watson int error; 181795fab37eSRobert Watson 181895fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 181995fab37eSRobert Watson 182095fab37eSRobert Watson if (!mac_enforce_fs) 182195fab37eSRobert Watson return (0); 182295fab37eSRobert Watson 182395fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 182495fab37eSRobert Watson return (error); 182595fab37eSRobert Watson } 182695fab37eSRobert Watson 182795fab37eSRobert Watson int 182895fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 182995fab37eSRobert Watson { 183095fab37eSRobert Watson int error; 183195fab37eSRobert Watson 183295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 183395fab37eSRobert Watson 183495fab37eSRobert Watson if (!mac_enforce_fs) 183595fab37eSRobert Watson return (0); 183695fab37eSRobert Watson 183795fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 183895fab37eSRobert Watson return (error); 183995fab37eSRobert Watson } 184095fab37eSRobert Watson 184195fab37eSRobert Watson static int 184295fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 184395fab37eSRobert Watson struct label *newlabel) 184495fab37eSRobert Watson { 184595fab37eSRobert Watson int error; 184695fab37eSRobert Watson 184795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 184895fab37eSRobert Watson 184995fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 185095fab37eSRobert Watson 185195fab37eSRobert Watson return (error); 185295fab37eSRobert Watson } 185395fab37eSRobert Watson 185495fab37eSRobert Watson int 185595fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 185695fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 185795fab37eSRobert Watson { 185895fab37eSRobert Watson int error; 185995fab37eSRobert Watson 186095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 186195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 186295fab37eSRobert Watson 186395fab37eSRobert Watson if (!mac_enforce_fs) 186495fab37eSRobert Watson return (0); 186595fab37eSRobert Watson 186695fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 186795fab37eSRobert Watson &vp->v_label, cnp); 186895fab37eSRobert Watson return (error); 186995fab37eSRobert Watson } 187095fab37eSRobert Watson 187195fab37eSRobert Watson int 187295fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 187395fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 187495fab37eSRobert Watson { 187595fab37eSRobert Watson int error; 187695fab37eSRobert Watson 187795fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 187895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 187995fab37eSRobert Watson 188095fab37eSRobert Watson if (!mac_enforce_fs) 188195fab37eSRobert Watson return (0); 188295fab37eSRobert Watson 188395fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 188495fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 188595fab37eSRobert Watson return (error); 188695fab37eSRobert Watson } 188795fab37eSRobert Watson 188895fab37eSRobert Watson int 188995fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 189095fab37eSRobert Watson { 189195fab37eSRobert Watson int error; 189295fab37eSRobert Watson 189395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 189495fab37eSRobert Watson 189595fab37eSRobert Watson if (!mac_enforce_fs) 189695fab37eSRobert Watson return (0); 189795fab37eSRobert Watson 189895fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 189995fab37eSRobert Watson return (error); 190095fab37eSRobert Watson } 190195fab37eSRobert Watson 190295fab37eSRobert Watson int 190395fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 190495fab37eSRobert Watson struct acl *acl) 190595fab37eSRobert Watson { 190695fab37eSRobert Watson int error; 190795fab37eSRobert Watson 190895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 190995fab37eSRobert Watson 191095fab37eSRobert Watson if (!mac_enforce_fs) 191195fab37eSRobert Watson return (0); 191295fab37eSRobert Watson 191395fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 191495fab37eSRobert Watson return (error); 191595fab37eSRobert Watson } 191695fab37eSRobert Watson 191795fab37eSRobert Watson int 191895fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 191995fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 192095fab37eSRobert Watson { 192195fab37eSRobert Watson int error; 192295fab37eSRobert Watson 192395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 192495fab37eSRobert Watson 192595fab37eSRobert Watson if (!mac_enforce_fs) 192695fab37eSRobert Watson return (0); 192795fab37eSRobert Watson 192895fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 192995fab37eSRobert Watson attrnamespace, name, uio); 193095fab37eSRobert Watson return (error); 193195fab37eSRobert Watson } 193295fab37eSRobert Watson 193395fab37eSRobert Watson int 193495fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 193595fab37eSRobert Watson { 193695fab37eSRobert Watson int error; 193795fab37eSRobert Watson 193895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 193995fab37eSRobert Watson 194095fab37eSRobert Watson if (!mac_enforce_fs) 194195fab37eSRobert Watson return (0); 194295fab37eSRobert Watson 194395fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 194495fab37eSRobert Watson return (error); 194595fab37eSRobert Watson } 194695fab37eSRobert Watson 194795fab37eSRobert Watson int 194895fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 194995fab37eSRobert Watson { 195095fab37eSRobert Watson int error; 195195fab37eSRobert Watson 195295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 195395fab37eSRobert Watson 195495fab37eSRobert Watson if (!mac_enforce_fs) 195595fab37eSRobert Watson return (0); 195695fab37eSRobert Watson 195795fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 195895fab37eSRobert Watson return (error); 195995fab37eSRobert Watson } 196095fab37eSRobert Watson 196195fab37eSRobert Watson int 196295fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 196395fab37eSRobert Watson gid_t gid) 196495fab37eSRobert Watson { 196595fab37eSRobert Watson int error; 196695fab37eSRobert Watson 196795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 196895fab37eSRobert Watson 196995fab37eSRobert Watson if (!mac_enforce_fs) 197095fab37eSRobert Watson return (0); 197195fab37eSRobert Watson 197295fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 197395fab37eSRobert Watson return (error); 197495fab37eSRobert Watson } 197595fab37eSRobert Watson 197695fab37eSRobert Watson int 197795fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 197895fab37eSRobert Watson struct timespec atime, struct timespec mtime) 197995fab37eSRobert Watson { 198095fab37eSRobert Watson int error; 198195fab37eSRobert Watson 198295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 198395fab37eSRobert Watson 198495fab37eSRobert Watson if (!mac_enforce_fs) 198595fab37eSRobert Watson return (0); 198695fab37eSRobert Watson 198795fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 198895fab37eSRobert Watson mtime); 198995fab37eSRobert Watson return (error); 199095fab37eSRobert Watson } 199195fab37eSRobert Watson 199295fab37eSRobert Watson int 1993177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 1994177142e4SRobert Watson struct vnode *vp) 199595fab37eSRobert Watson { 199695fab37eSRobert Watson int error; 199795fab37eSRobert Watson 199895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 199995fab37eSRobert Watson 200095fab37eSRobert Watson if (!mac_enforce_fs) 200195fab37eSRobert Watson return (0); 200295fab37eSRobert Watson 2003177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2004177142e4SRobert Watson &vp->v_label); 200595fab37eSRobert Watson return (error); 200695fab37eSRobert Watson } 200795fab37eSRobert Watson 20087f724f8bSRobert Watson int 2009177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2010177142e4SRobert Watson struct vnode *vp) 20117f724f8bSRobert Watson { 20127f724f8bSRobert Watson int error; 20137f724f8bSRobert Watson 20147f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 20157f724f8bSRobert Watson 20167f724f8bSRobert Watson if (!mac_enforce_fs) 20177f724f8bSRobert Watson return (0); 20187f724f8bSRobert Watson 2019177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2020177142e4SRobert Watson &vp->v_label); 20217f724f8bSRobert Watson 20227f724f8bSRobert Watson return (error); 20237f724f8bSRobert Watson } 20247f724f8bSRobert Watson 202595fab37eSRobert Watson /* 202695fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 202795fab37eSRobert Watson * permission allowed for each object type we know about in its 202895fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 202995fab37eSRobert Watson * know) when necessary. The process lock is not held here. 203095fab37eSRobert Watson */ 20314d10c0ceSRobert Watson void 203295fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 203395fab37eSRobert Watson { 203495fab37eSRobert Watson 203595fab37eSRobert Watson /* XXX freeze all other threads */ 203695fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 203795fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 203895fab37eSRobert Watson /* XXX allow other threads to continue */ 203995fab37eSRobert Watson } 204095fab37eSRobert Watson 204195fab37eSRobert Watson static __inline const char * 204295fab37eSRobert Watson prot2str(vm_prot_t prot) 204395fab37eSRobert Watson { 204495fab37eSRobert Watson 204595fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 204695fab37eSRobert Watson case VM_PROT_READ: 204795fab37eSRobert Watson return ("r--"); 204895fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 204995fab37eSRobert Watson return ("rw-"); 205095fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 205195fab37eSRobert Watson return ("r-x"); 205295fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 205395fab37eSRobert Watson return ("rwx"); 205495fab37eSRobert Watson case VM_PROT_WRITE: 205595fab37eSRobert Watson return ("-w-"); 205695fab37eSRobert Watson case VM_PROT_EXECUTE: 205795fab37eSRobert Watson return ("--x"); 205895fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 205995fab37eSRobert Watson return ("-wx"); 206095fab37eSRobert Watson default: 206195fab37eSRobert Watson return ("---"); 206295fab37eSRobert Watson } 206395fab37eSRobert Watson } 206495fab37eSRobert Watson 206595fab37eSRobert Watson static void 206695fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 206795fab37eSRobert Watson struct vm_map *map) 206895fab37eSRobert Watson { 206995fab37eSRobert Watson struct vm_map_entry *vme; 2070e183f80eSRobert Watson int result; 2071e183f80eSRobert Watson vm_prot_t revokeperms; 207295fab37eSRobert Watson vm_object_t object; 207395fab37eSRobert Watson vm_ooffset_t offset; 207495fab37eSRobert Watson struct vnode *vp; 207595fab37eSRobert Watson 2076c0f39905SRobert Watson if (!mac_mmap_revocation) 2077c0f39905SRobert Watson return; 2078c0f39905SRobert Watson 207995fab37eSRobert Watson vm_map_lock_read(map); 208095fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 208195fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 208295fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 208395fab37eSRobert Watson vme->object.sub_map); 208495fab37eSRobert Watson continue; 208595fab37eSRobert Watson } 208695fab37eSRobert Watson /* 208795fab37eSRobert Watson * Skip over entries that obviously are not shared. 208895fab37eSRobert Watson */ 208995fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 209095fab37eSRobert Watson !vme->max_protection) 209195fab37eSRobert Watson continue; 209295fab37eSRobert Watson /* 209395fab37eSRobert Watson * Drill down to the deepest backing object. 209495fab37eSRobert Watson */ 209595fab37eSRobert Watson offset = vme->offset; 209695fab37eSRobert Watson object = vme->object.vm_object; 209795fab37eSRobert Watson if (object == NULL) 209895fab37eSRobert Watson continue; 209995fab37eSRobert Watson while (object->backing_object != NULL) { 210095fab37eSRobert Watson object = object->backing_object; 210195fab37eSRobert Watson offset += object->backing_object_offset; 210295fab37eSRobert Watson } 210395fab37eSRobert Watson /* 210495fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 210595fab37eSRobert Watson * by the MAC system, so only things with backing by a 210695fab37eSRobert Watson * normal object (read: vnodes) are checked. 210795fab37eSRobert Watson */ 210895fab37eSRobert Watson if (object->type != OBJT_VNODE) 210995fab37eSRobert Watson continue; 211095fab37eSRobert Watson vp = (struct vnode *)object->handle; 211195fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2112e183f80eSRobert Watson result = vme->max_protection; 2113e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 211495fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 211595fab37eSRobert Watson /* 211695fab37eSRobert Watson * Find out what maximum protection we may be allowing 211795fab37eSRobert Watson * now but a policy needs to get removed. 211895fab37eSRobert Watson */ 211995fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 212095fab37eSRobert Watson if (!revokeperms) 212195fab37eSRobert Watson continue; 2122b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 2123b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2124b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 2125b656366bSBruce Evans (long)(vme->end - vme->start), 212695fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 212795fab37eSRobert Watson vm_map_lock_upgrade(map); 212895fab37eSRobert Watson /* 212995fab37eSRobert Watson * This is the really simple case: if a map has more 213095fab37eSRobert Watson * max_protection than is allowed, but it's not being 213195fab37eSRobert Watson * actually used (that is, the current protection is 213295fab37eSRobert Watson * still allowed), we can just wipe it out and do 213395fab37eSRobert Watson * nothing more. 213495fab37eSRobert Watson */ 213595fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 213695fab37eSRobert Watson vme->max_protection -= revokeperms; 213795fab37eSRobert Watson } else { 213895fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 213995fab37eSRobert Watson /* 214095fab37eSRobert Watson * In the more complicated case, flush out all 214195fab37eSRobert Watson * pending changes to the object then turn it 214295fab37eSRobert Watson * copy-on-write. 214395fab37eSRobert Watson */ 214495fab37eSRobert Watson vm_object_reference(object); 214595fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2146b6e48e03SAlan Cox VM_OBJECT_LOCK(object); 214795fab37eSRobert Watson vm_object_page_clean(object, 214895fab37eSRobert Watson OFF_TO_IDX(offset), 214995fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 215095fab37eSRobert Watson PAGE_MASK), 215195fab37eSRobert Watson OBJPC_SYNC); 2152b6e48e03SAlan Cox VM_OBJECT_UNLOCK(object); 215395fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 215495fab37eSRobert Watson vm_object_deallocate(object); 215595fab37eSRobert Watson /* 215695fab37eSRobert Watson * Why bother if there's no read permissions 215795fab37eSRobert Watson * anymore? For the rest, we need to leave 215895fab37eSRobert Watson * the write permissions on for COW, or 215995fab37eSRobert Watson * remove them entirely if configured to. 216095fab37eSRobert Watson */ 216195fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 216295fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 216395fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 216495fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 216595fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 216695fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 216795fab37eSRobert Watson } 216895fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 216995fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 217095fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 217195fab37eSRobert Watson } 217295fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 217395fab37eSRobert Watson vme->max_protection = 0; 217495fab37eSRobert Watson vme->protection = 0; 217595fab37eSRobert Watson } 217695fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 217795fab37eSRobert Watson vme->protection & ~revokeperms); 217895fab37eSRobert Watson vm_map_simplify_entry(map, vme); 217995fab37eSRobert Watson } 218095fab37eSRobert Watson vm_map_lock_downgrade(map); 218195fab37eSRobert Watson } 218295fab37eSRobert Watson vm_map_unlock_read(map); 218395fab37eSRobert Watson } 218495fab37eSRobert Watson 218595fab37eSRobert Watson /* 218695fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 218795fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 218895fab37eSRobert Watson * buffer cache. 218995fab37eSRobert Watson */ 219095fab37eSRobert Watson static void 219195fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 219295fab37eSRobert Watson { 219395fab37eSRobert Watson 219495fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 219595fab37eSRobert Watson } 219695fab37eSRobert Watson 219795fab37eSRobert Watson void 219895fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 219995fab37eSRobert Watson { 220095fab37eSRobert Watson 220195fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 220295fab37eSRobert Watson } 220395fab37eSRobert Watson 220495fab37eSRobert Watson void 220595fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 220695fab37eSRobert Watson { 220795fab37eSRobert Watson 220895fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 220995fab37eSRobert Watson } 221095fab37eSRobert Watson 221195fab37eSRobert Watson void 221295fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 221395fab37eSRobert Watson { 221495fab37eSRobert Watson 221595fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 221695fab37eSRobert Watson } 221795fab37eSRobert Watson 221895fab37eSRobert Watson void 221995fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 222095fab37eSRobert Watson { 222195fab37eSRobert Watson 222295fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 222395fab37eSRobert Watson } 222495fab37eSRobert Watson 222595fab37eSRobert Watson void 222695fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 222795fab37eSRobert Watson { 222895fab37eSRobert Watson 222995fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 223095fab37eSRobert Watson } 223195fab37eSRobert Watson 223295fab37eSRobert Watson void 223395fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 223495fab37eSRobert Watson struct socket *newsocket) 223595fab37eSRobert Watson { 223695fab37eSRobert Watson 223795fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 223895fab37eSRobert Watson newsocket, &newsocket->so_label); 223995fab37eSRobert Watson } 224095fab37eSRobert Watson 224195fab37eSRobert Watson static void 224295fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 224395fab37eSRobert Watson struct label *newlabel) 224495fab37eSRobert Watson { 224595fab37eSRobert Watson 224695fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 224795fab37eSRobert Watson } 224895fab37eSRobert Watson 224995fab37eSRobert Watson static void 225095fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 225195fab37eSRobert Watson { 225295fab37eSRobert Watson 225395fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 225495fab37eSRobert Watson } 225595fab37eSRobert Watson 225695fab37eSRobert Watson void 225795fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 225895fab37eSRobert Watson { 225910eeb10cSRobert Watson struct label *label; 226095fab37eSRobert Watson 226110eeb10cSRobert Watson label = mbuf_to_label(mbuf); 226210eeb10cSRobert Watson 226310eeb10cSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket, 226410eeb10cSRobert Watson &socket->so_peerlabel); 226595fab37eSRobert Watson } 226695fab37eSRobert Watson 226795fab37eSRobert Watson void 226895fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 226995fab37eSRobert Watson struct socket *newsocket) 227095fab37eSRobert Watson { 227195fab37eSRobert Watson 227295fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 227395fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 227495fab37eSRobert Watson } 227595fab37eSRobert Watson 227695fab37eSRobert Watson void 227795fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 227895fab37eSRobert Watson { 227910eeb10cSRobert Watson struct label *label; 228010eeb10cSRobert Watson 228110eeb10cSRobert Watson label = mbuf_to_label(datagram); 228295fab37eSRobert Watson 228395fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 228410eeb10cSRobert Watson datagram, label); 228595fab37eSRobert Watson } 228695fab37eSRobert Watson 228795fab37eSRobert Watson void 228895fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 228995fab37eSRobert Watson { 229010eeb10cSRobert Watson struct label *datagramlabel, *fragmentlabel; 229195fab37eSRobert Watson 229210eeb10cSRobert Watson datagramlabel = mbuf_to_label(datagram); 229310eeb10cSRobert Watson fragmentlabel = mbuf_to_label(fragment); 229410eeb10cSRobert Watson 229510eeb10cSRobert Watson MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment, 229610eeb10cSRobert Watson fragmentlabel); 229795fab37eSRobert Watson } 229895fab37eSRobert Watson 229995fab37eSRobert Watson void 230095fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 230195fab37eSRobert Watson { 230210eeb10cSRobert Watson struct label *label; 230395fab37eSRobert Watson 230410eeb10cSRobert Watson label = mbuf_to_label(fragment); 230510eeb10cSRobert Watson 230610eeb10cSRobert Watson MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label); 230795fab37eSRobert Watson } 230895fab37eSRobert Watson 230995fab37eSRobert Watson void 231095fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 231195fab37eSRobert Watson { 231210eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 231395fab37eSRobert Watson 231410eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 231510eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 231610eeb10cSRobert Watson 231710eeb10cSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf, 231810eeb10cSRobert Watson newmbuflabel); 231995fab37eSRobert Watson } 232095fab37eSRobert Watson 232195fab37eSRobert Watson void 232295fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 232395fab37eSRobert Watson { 232410eeb10cSRobert Watson struct label *label; 232510eeb10cSRobert Watson 232610eeb10cSRobert Watson label = mbuf_to_label(mbuf); 232795fab37eSRobert Watson 232895fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 232910eeb10cSRobert Watson label); 233095fab37eSRobert Watson } 233195fab37eSRobert Watson 233295fab37eSRobert Watson void 233395fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 233495fab37eSRobert Watson { 233510eeb10cSRobert Watson struct label *label; 233610eeb10cSRobert Watson 233710eeb10cSRobert Watson label = mbuf_to_label(mbuf); 233895fab37eSRobert Watson 233995fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 234010eeb10cSRobert Watson label); 234195fab37eSRobert Watson } 234295fab37eSRobert Watson 234395fab37eSRobert Watson void 234495fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 234595fab37eSRobert Watson { 234610eeb10cSRobert Watson struct label *label; 234710eeb10cSRobert Watson 234810eeb10cSRobert Watson label = mbuf_to_label(mbuf); 234995fab37eSRobert Watson 235095fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 235110eeb10cSRobert Watson label); 235295fab37eSRobert Watson } 235395fab37eSRobert Watson 235495fab37eSRobert Watson void 235595fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 235695fab37eSRobert Watson struct mbuf *newmbuf) 235795fab37eSRobert Watson { 235810eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 235995fab37eSRobert Watson 236010eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 236110eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 236210eeb10cSRobert Watson 236310eeb10cSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel, 236410eeb10cSRobert Watson ifnet, &ifnet->if_label, newmbuf, newmbuflabel); 236595fab37eSRobert Watson } 236695fab37eSRobert Watson 236795fab37eSRobert Watson void 236895fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 236995fab37eSRobert Watson { 237010eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 237195fab37eSRobert Watson 237210eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 237310eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 237410eeb10cSRobert Watson 237510eeb10cSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf, 237610eeb10cSRobert Watson newmbuflabel); 237795fab37eSRobert Watson } 237895fab37eSRobert Watson 237995fab37eSRobert Watson int 238095fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 238195fab37eSRobert Watson { 238210eeb10cSRobert Watson struct label *label; 238395fab37eSRobert Watson int result; 238495fab37eSRobert Watson 238510eeb10cSRobert Watson label = mbuf_to_label(fragment); 238610eeb10cSRobert Watson 238795fab37eSRobert Watson result = 1; 238810eeb10cSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq, 238910eeb10cSRobert Watson &ipq->ipq_label); 239095fab37eSRobert Watson 239195fab37eSRobert Watson return (result); 239295fab37eSRobert Watson } 239395fab37eSRobert Watson 239495fab37eSRobert Watson void 2395eb8c7f99SRobert Watson mac_reflect_mbuf_icmp(struct mbuf *m) 2396eb8c7f99SRobert Watson { 2397eb8c7f99SRobert Watson struct label *label; 2398eb8c7f99SRobert Watson 2399eb8c7f99SRobert Watson label = mbuf_to_label(m); 2400eb8c7f99SRobert Watson 2401eb8c7f99SRobert Watson MAC_PERFORM(reflect_mbuf_icmp, m, label); 2402eb8c7f99SRobert Watson } 2403eb8c7f99SRobert Watson void 2404eb8c7f99SRobert Watson mac_reflect_mbuf_tcp(struct mbuf *m) 2405eb8c7f99SRobert Watson { 2406eb8c7f99SRobert Watson struct label *label; 2407eb8c7f99SRobert Watson 2408eb8c7f99SRobert Watson label = mbuf_to_label(m); 2409eb8c7f99SRobert Watson 2410eb8c7f99SRobert Watson MAC_PERFORM(reflect_mbuf_tcp, m, label); 2411eb8c7f99SRobert Watson } 2412eb8c7f99SRobert Watson 2413eb8c7f99SRobert Watson void 241495fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 241595fab37eSRobert Watson { 241610eeb10cSRobert Watson struct label *label; 241795fab37eSRobert Watson 241810eeb10cSRobert Watson label = mbuf_to_label(fragment); 241910eeb10cSRobert Watson 242010eeb10cSRobert Watson MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label); 242195fab37eSRobert Watson } 242295fab37eSRobert Watson 242395fab37eSRobert Watson void 242495fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 242595fab37eSRobert Watson { 242610eeb10cSRobert Watson struct label *label; 242710eeb10cSRobert Watson 242810eeb10cSRobert Watson label = mbuf_to_label(mbuf); 242995fab37eSRobert Watson 243095fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 243110eeb10cSRobert Watson label); 243295fab37eSRobert Watson } 243395fab37eSRobert Watson 243495fab37eSRobert Watson void 243595fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 243695fab37eSRobert Watson { 243795fab37eSRobert Watson 243895fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 243995fab37eSRobert Watson &mp->mnt_fslabel); 244095fab37eSRobert Watson } 244195fab37eSRobert Watson 244295fab37eSRobert Watson void 244395fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 244495fab37eSRobert Watson { 244595fab37eSRobert Watson 244695fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 244795fab37eSRobert Watson &mp->mnt_fslabel); 244895fab37eSRobert Watson } 244995fab37eSRobert Watson 245095fab37eSRobert Watson int 245195fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 245295fab37eSRobert Watson { 245395fab37eSRobert Watson int error; 245495fab37eSRobert Watson 245595fab37eSRobert Watson if (!mac_enforce_network) 245695fab37eSRobert Watson return (0); 245795fab37eSRobert Watson 245895fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 245995fab37eSRobert Watson &ifnet->if_label); 246095fab37eSRobert Watson 246195fab37eSRobert Watson return (error); 246295fab37eSRobert Watson } 246395fab37eSRobert Watson 246495fab37eSRobert Watson static int 246595fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 246695fab37eSRobert Watson { 246795fab37eSRobert Watson int error; 246895fab37eSRobert Watson 246995fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 247095fab37eSRobert Watson 247195fab37eSRobert Watson return (error); 247295fab37eSRobert Watson } 247395fab37eSRobert Watson 247495fab37eSRobert Watson int 247595fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 247695fab37eSRobert Watson { 247795fab37eSRobert Watson int error; 247895fab37eSRobert Watson 247995fab37eSRobert Watson if (!mac_enforce_process) 248095fab37eSRobert Watson return (0); 248195fab37eSRobert Watson 248295fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 248395fab37eSRobert Watson 248495fab37eSRobert Watson return (error); 248595fab37eSRobert Watson } 248695fab37eSRobert Watson 248795fab37eSRobert Watson int 248895fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 248995fab37eSRobert Watson { 249010eeb10cSRobert Watson struct label *label; 249195fab37eSRobert Watson int error; 249295fab37eSRobert Watson 2493225bff6fSRobert Watson M_ASSERTPKTHDR(mbuf); 2494225bff6fSRobert Watson 249595fab37eSRobert Watson if (!mac_enforce_network) 249695fab37eSRobert Watson return (0); 249795fab37eSRobert Watson 249810eeb10cSRobert Watson label = mbuf_to_label(mbuf); 249995fab37eSRobert Watson 250095fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 250110eeb10cSRobert Watson label); 250295fab37eSRobert Watson 250395fab37eSRobert Watson return (error); 250495fab37eSRobert Watson } 250595fab37eSRobert Watson 250695fab37eSRobert Watson int 2507e686e5aeSRobert Watson mac_check_kenv_dump(struct ucred *cred) 2508e686e5aeSRobert Watson { 2509e686e5aeSRobert Watson int error; 2510e686e5aeSRobert Watson 2511e686e5aeSRobert Watson if (!mac_enforce_system) 2512e686e5aeSRobert Watson return (0); 2513e686e5aeSRobert Watson 2514e686e5aeSRobert Watson MAC_CHECK(check_kenv_dump, cred); 2515e686e5aeSRobert Watson 2516e686e5aeSRobert Watson return (error); 2517e686e5aeSRobert Watson } 2518e686e5aeSRobert Watson 2519e686e5aeSRobert Watson int 2520e686e5aeSRobert Watson mac_check_kenv_get(struct ucred *cred, char *name) 2521e686e5aeSRobert Watson { 2522e686e5aeSRobert Watson int error; 2523e686e5aeSRobert Watson 2524e686e5aeSRobert Watson if (!mac_enforce_system) 2525e686e5aeSRobert Watson return (0); 2526e686e5aeSRobert Watson 2527e686e5aeSRobert Watson MAC_CHECK(check_kenv_get, cred, name); 2528e686e5aeSRobert Watson 2529e686e5aeSRobert Watson return (error); 2530e686e5aeSRobert Watson } 2531e686e5aeSRobert Watson 2532e686e5aeSRobert Watson int 2533e686e5aeSRobert Watson mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2534e686e5aeSRobert Watson { 2535e686e5aeSRobert Watson int error; 2536e686e5aeSRobert Watson 2537e686e5aeSRobert Watson if (!mac_enforce_system) 2538e686e5aeSRobert Watson return (0); 2539e686e5aeSRobert Watson 2540e686e5aeSRobert Watson MAC_CHECK(check_kenv_set, cred, name, value); 2541e686e5aeSRobert Watson 2542e686e5aeSRobert Watson return (error); 2543e686e5aeSRobert Watson } 2544e686e5aeSRobert Watson 2545e686e5aeSRobert Watson int 2546e686e5aeSRobert Watson mac_check_kenv_unset(struct ucred *cred, char *name) 2547e686e5aeSRobert Watson { 2548e686e5aeSRobert Watson int error; 2549e686e5aeSRobert Watson 2550e686e5aeSRobert Watson if (!mac_enforce_system) 2551e686e5aeSRobert Watson return (0); 2552e686e5aeSRobert Watson 2553e686e5aeSRobert Watson MAC_CHECK(check_kenv_unset, cred, name); 2554e686e5aeSRobert Watson 2555e686e5aeSRobert Watson return (error); 2556e686e5aeSRobert Watson } 2557e686e5aeSRobert Watson 2558e686e5aeSRobert Watson int 2559a3df768bSRobert Watson mac_check_kld_load(struct ucred *cred, struct vnode *vp) 2560a3df768bSRobert Watson { 2561a3df768bSRobert Watson int error; 2562a3df768bSRobert Watson 2563a3df768bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_kld_load"); 2564a3df768bSRobert Watson 2565a3df768bSRobert Watson if (!mac_enforce_kld) 2566a3df768bSRobert Watson return (0); 2567a3df768bSRobert Watson 2568a3df768bSRobert Watson MAC_CHECK(check_kld_load, cred, vp, &vp->v_label); 2569a3df768bSRobert Watson 2570a3df768bSRobert Watson return (error); 2571a3df768bSRobert Watson } 2572a3df768bSRobert Watson 2573a3df768bSRobert Watson int 2574a3df768bSRobert Watson mac_check_kld_stat(struct ucred *cred) 2575a3df768bSRobert Watson { 2576a3df768bSRobert Watson int error; 2577a3df768bSRobert Watson 2578a3df768bSRobert Watson if (!mac_enforce_kld) 2579a3df768bSRobert Watson return (0); 2580a3df768bSRobert Watson 2581a3df768bSRobert Watson MAC_CHECK(check_kld_stat, cred); 2582a3df768bSRobert Watson 2583a3df768bSRobert Watson return (error); 2584a3df768bSRobert Watson } 2585a3df768bSRobert Watson 2586a3df768bSRobert Watson int 2587a3df768bSRobert Watson mac_check_kld_unload(struct ucred *cred) 2588a3df768bSRobert Watson { 2589a3df768bSRobert Watson int error; 2590a3df768bSRobert Watson 2591a3df768bSRobert Watson if (!mac_enforce_kld) 2592a3df768bSRobert Watson return (0); 2593a3df768bSRobert Watson 2594a3df768bSRobert Watson MAC_CHECK(check_kld_unload, cred); 2595a3df768bSRobert Watson 2596a3df768bSRobert Watson return (error); 2597a3df768bSRobert Watson } 2598a3df768bSRobert Watson 2599a3df768bSRobert Watson int 260095fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 260195fab37eSRobert Watson { 260295fab37eSRobert Watson int error; 260395fab37eSRobert Watson 260495fab37eSRobert Watson if (!mac_enforce_fs) 260595fab37eSRobert Watson return (0); 260695fab37eSRobert Watson 260795fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 260895fab37eSRobert Watson 260995fab37eSRobert Watson return (error); 261095fab37eSRobert Watson } 261195fab37eSRobert Watson 261295fab37eSRobert Watson int 261395fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 261495fab37eSRobert Watson void *data) 261595fab37eSRobert Watson { 261695fab37eSRobert Watson int error; 261795fab37eSRobert Watson 26181aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26191aa37f53SRobert Watson 26201aa37f53SRobert Watson if (!mac_enforce_pipe) 26211aa37f53SRobert Watson return (0); 26221aa37f53SRobert Watson 262395fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 262495fab37eSRobert Watson 262595fab37eSRobert Watson return (error); 262695fab37eSRobert Watson } 262795fab37eSRobert Watson 262895fab37eSRobert Watson int 2629c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 263095fab37eSRobert Watson { 263195fab37eSRobert Watson int error; 263295fab37eSRobert Watson 26331aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26341aa37f53SRobert Watson 26351aa37f53SRobert Watson if (!mac_enforce_pipe) 26361aa37f53SRobert Watson return (0); 26371aa37f53SRobert Watson 2638c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2639c024c3eeSRobert Watson 2640c024c3eeSRobert Watson return (error); 2641c024c3eeSRobert Watson } 2642c024c3eeSRobert Watson 2643c024c3eeSRobert Watson int 2644c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2645c024c3eeSRobert Watson { 2646c024c3eeSRobert Watson int error; 2647c024c3eeSRobert Watson 26481aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26491aa37f53SRobert Watson 26501aa37f53SRobert Watson if (!mac_enforce_pipe) 26511aa37f53SRobert Watson return (0); 26521aa37f53SRobert Watson 2653c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 265495fab37eSRobert Watson 265595fab37eSRobert Watson return (error); 265695fab37eSRobert Watson } 265795fab37eSRobert Watson 265895fab37eSRobert Watson static int 265995fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 266095fab37eSRobert Watson struct label *newlabel) 266195fab37eSRobert Watson { 266295fab37eSRobert Watson int error; 266395fab37eSRobert Watson 26641aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26651aa37f53SRobert Watson 26661aa37f53SRobert Watson if (!mac_enforce_pipe) 26671aa37f53SRobert Watson return (0); 26681aa37f53SRobert Watson 266995fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 267095fab37eSRobert Watson 267195fab37eSRobert Watson return (error); 267295fab37eSRobert Watson } 267395fab37eSRobert Watson 267495fab37eSRobert Watson int 2675c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2676c024c3eeSRobert Watson { 2677c024c3eeSRobert Watson int error; 2678c024c3eeSRobert Watson 26791aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26801aa37f53SRobert Watson 26811aa37f53SRobert Watson if (!mac_enforce_pipe) 26821aa37f53SRobert Watson return (0); 26831aa37f53SRobert Watson 2684c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2685c024c3eeSRobert Watson 2686c024c3eeSRobert Watson return (error); 2687c024c3eeSRobert Watson } 2688c024c3eeSRobert Watson 2689c024c3eeSRobert Watson int 2690c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2691c024c3eeSRobert Watson { 2692c024c3eeSRobert Watson int error; 2693c024c3eeSRobert Watson 26941aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26951aa37f53SRobert Watson 26961aa37f53SRobert Watson if (!mac_enforce_pipe) 26971aa37f53SRobert Watson return (0); 26981aa37f53SRobert Watson 2699c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2700c024c3eeSRobert Watson 2701c024c3eeSRobert Watson return (error); 2702c024c3eeSRobert Watson } 2703c024c3eeSRobert Watson 2704c024c3eeSRobert Watson int 270595fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 270695fab37eSRobert Watson { 270795fab37eSRobert Watson int error; 270895fab37eSRobert Watson 2709b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2710b12baf55SRobert Watson 271195fab37eSRobert Watson if (!mac_enforce_process) 271295fab37eSRobert Watson return (0); 271395fab37eSRobert Watson 271495fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 271595fab37eSRobert Watson 271695fab37eSRobert Watson return (error); 271795fab37eSRobert Watson } 271895fab37eSRobert Watson 271995fab37eSRobert Watson int 272095fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 272195fab37eSRobert Watson { 272295fab37eSRobert Watson int error; 272395fab37eSRobert Watson 2724b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2725b12baf55SRobert Watson 272695fab37eSRobert Watson if (!mac_enforce_process) 272795fab37eSRobert Watson return (0); 272895fab37eSRobert Watson 272995fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 273095fab37eSRobert Watson 273195fab37eSRobert Watson return (error); 273295fab37eSRobert Watson } 273395fab37eSRobert Watson 273495fab37eSRobert Watson int 273595fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 273695fab37eSRobert Watson { 273795fab37eSRobert Watson int error; 273895fab37eSRobert Watson 2739b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2740b12baf55SRobert Watson 274195fab37eSRobert Watson if (!mac_enforce_process) 274295fab37eSRobert Watson return (0); 274395fab37eSRobert Watson 274495fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 274595fab37eSRobert Watson 274695fab37eSRobert Watson return (error); 274795fab37eSRobert Watson } 274895fab37eSRobert Watson 274995fab37eSRobert Watson int 275095fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 275195fab37eSRobert Watson struct sockaddr *sockaddr) 275295fab37eSRobert Watson { 275395fab37eSRobert Watson int error; 275495fab37eSRobert Watson 275595fab37eSRobert Watson if (!mac_enforce_socket) 275695fab37eSRobert Watson return (0); 275795fab37eSRobert Watson 275895fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 275995fab37eSRobert Watson sockaddr); 276095fab37eSRobert Watson 276195fab37eSRobert Watson return (error); 276295fab37eSRobert Watson } 276395fab37eSRobert Watson 276495fab37eSRobert Watson int 276595fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 276695fab37eSRobert Watson struct sockaddr *sockaddr) 276795fab37eSRobert Watson { 276895fab37eSRobert Watson int error; 276995fab37eSRobert Watson 277095fab37eSRobert Watson if (!mac_enforce_socket) 277195fab37eSRobert Watson return (0); 277295fab37eSRobert Watson 277395fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 277495fab37eSRobert Watson sockaddr); 277595fab37eSRobert Watson 277695fab37eSRobert Watson return (error); 277795fab37eSRobert Watson } 277895fab37eSRobert Watson 277995fab37eSRobert Watson int 2780d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2781d61198e4SRobert Watson { 278210eeb10cSRobert Watson struct label *label; 2783d61198e4SRobert Watson int error; 2784d61198e4SRobert Watson 2785d61198e4SRobert Watson if (!mac_enforce_socket) 2786d61198e4SRobert Watson return (0); 2787d61198e4SRobert Watson 278810eeb10cSRobert Watson label = mbuf_to_label(mbuf); 278910eeb10cSRobert Watson 2790d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 279110eeb10cSRobert Watson label); 2792d61198e4SRobert Watson 2793d61198e4SRobert Watson return (error); 2794d61198e4SRobert Watson } 2795d61198e4SRobert Watson 2796d61198e4SRobert Watson int 279795fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 279895fab37eSRobert Watson { 279995fab37eSRobert Watson int error; 280095fab37eSRobert Watson 280195fab37eSRobert Watson if (!mac_enforce_socket) 280295fab37eSRobert Watson return (0); 280395fab37eSRobert Watson 280495fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 280595fab37eSRobert Watson return (error); 280695fab37eSRobert Watson } 280795fab37eSRobert Watson 2808b371c939SRobert Watson int 2809b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 2810b371c939SRobert Watson { 2811b371c939SRobert Watson int error; 2812b371c939SRobert Watson 2813b371c939SRobert Watson if (!mac_enforce_socket) 2814b371c939SRobert Watson return (0); 2815b371c939SRobert Watson 2816b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2817b371c939SRobert Watson 2818b371c939SRobert Watson return (error); 2819b371c939SRobert Watson } 2820b371c939SRobert Watson 282195fab37eSRobert Watson static int 282295fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 282395fab37eSRobert Watson struct label *newlabel) 282495fab37eSRobert Watson { 282595fab37eSRobert Watson int error; 282695fab37eSRobert Watson 282795fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 282895fab37eSRobert Watson newlabel); 282995fab37eSRobert Watson 283095fab37eSRobert Watson return (error); 283195fab37eSRobert Watson } 283295fab37eSRobert Watson 283395fab37eSRobert Watson int 2834b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 2835b371c939SRobert Watson { 2836b371c939SRobert Watson int error; 2837b371c939SRobert Watson 2838b371c939SRobert Watson if (!mac_enforce_socket) 2839b371c939SRobert Watson return (0); 2840b371c939SRobert Watson 2841b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2842b371c939SRobert Watson 2843b371c939SRobert Watson return (error); 2844b371c939SRobert Watson } 2845b371c939SRobert Watson 2846b371c939SRobert Watson int 284795fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 284895fab37eSRobert Watson { 284995fab37eSRobert Watson int error; 285095fab37eSRobert Watson 285195fab37eSRobert Watson if (!mac_enforce_socket) 285295fab37eSRobert Watson return (0); 285395fab37eSRobert Watson 285495fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 285595fab37eSRobert Watson 285695fab37eSRobert Watson return (error); 285795fab37eSRobert Watson } 285895fab37eSRobert Watson 285995fab37eSRobert Watson int 286092835789SRobert Watson mac_check_sysarch_ioperm(struct ucred *cred) 286192835789SRobert Watson { 286292835789SRobert Watson int error; 286392835789SRobert Watson 286492835789SRobert Watson if (!mac_enforce_system) 286592835789SRobert Watson return (0); 286692835789SRobert Watson 286792835789SRobert Watson MAC_CHECK(check_sysarch_ioperm, cred); 286892835789SRobert Watson return (error); 286992835789SRobert Watson } 287092835789SRobert Watson 287192835789SRobert Watson int 2872e5e820fdSRobert Watson mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2873e5e820fdSRobert Watson { 2874e5e820fdSRobert Watson int error; 2875e5e820fdSRobert Watson 2876e5e820fdSRobert Watson if (vp != NULL) { 2877e5e820fdSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2878e5e820fdSRobert Watson } 2879e5e820fdSRobert Watson 2880e5e820fdSRobert Watson if (!mac_enforce_system) 2881e5e820fdSRobert Watson return (0); 2882e5e820fdSRobert Watson 2883e5e820fdSRobert Watson MAC_CHECK(check_system_acct, cred, vp, 2884e5e820fdSRobert Watson vp != NULL ? &vp->v_label : NULL); 2885e5e820fdSRobert Watson 2886e5e820fdSRobert Watson return (error); 2887e5e820fdSRobert Watson } 2888e5e820fdSRobert Watson 2889e5e820fdSRobert Watson int 2890e5e820fdSRobert Watson mac_check_system_nfsd(struct ucred *cred) 2891e5e820fdSRobert Watson { 2892e5e820fdSRobert Watson int error; 2893e5e820fdSRobert Watson 2894e5e820fdSRobert Watson if (!mac_enforce_system) 2895e5e820fdSRobert Watson return (0); 2896e5e820fdSRobert Watson 2897e5e820fdSRobert Watson MAC_CHECK(check_system_nfsd, cred); 2898e5e820fdSRobert Watson 2899e5e820fdSRobert Watson return (error); 2900e5e820fdSRobert Watson } 2901e5e820fdSRobert Watson 2902e5e820fdSRobert Watson int 2903a2ecb9b7SRobert Watson mac_check_system_reboot(struct ucred *cred, int howto) 2904a2ecb9b7SRobert Watson { 2905a2ecb9b7SRobert Watson int error; 2906a2ecb9b7SRobert Watson 29079e913ebdSRobert Watson if (!mac_enforce_system) 2908a2ecb9b7SRobert Watson return (0); 2909a2ecb9b7SRobert Watson 2910a2ecb9b7SRobert Watson MAC_CHECK(check_system_reboot, cred, howto); 29119e913ebdSRobert Watson 2912a2ecb9b7SRobert Watson return (error); 2913a2ecb9b7SRobert Watson } 2914a2ecb9b7SRobert Watson 2915a2ecb9b7SRobert Watson int 29164b8d5f2dSRobert Watson mac_check_system_settime(struct ucred *cred) 29174b8d5f2dSRobert Watson { 29184b8d5f2dSRobert Watson int error; 29194b8d5f2dSRobert Watson 29204b8d5f2dSRobert Watson if (!mac_enforce_system) 29214b8d5f2dSRobert Watson return (0); 29224b8d5f2dSRobert Watson 29234b8d5f2dSRobert Watson MAC_CHECK(check_system_settime, cred); 29244b8d5f2dSRobert Watson 29254b8d5f2dSRobert Watson return (error); 29264b8d5f2dSRobert Watson } 29274b8d5f2dSRobert Watson 29284b8d5f2dSRobert Watson int 292903ce2c0cSRobert Watson mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 293003ce2c0cSRobert Watson { 293103ce2c0cSRobert Watson int error; 293203ce2c0cSRobert Watson 293303ce2c0cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 293403ce2c0cSRobert Watson 29359e913ebdSRobert Watson if (!mac_enforce_system) 293603ce2c0cSRobert Watson return (0); 293703ce2c0cSRobert Watson 293803ce2c0cSRobert Watson MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 293903ce2c0cSRobert Watson return (error); 294003ce2c0cSRobert Watson } 294103ce2c0cSRobert Watson 294203ce2c0cSRobert Watson int 29431b2c2ab2SRobert Watson mac_check_system_swapoff(struct ucred *cred, struct vnode *vp) 29441b2c2ab2SRobert Watson { 29451b2c2ab2SRobert Watson int error; 29461b2c2ab2SRobert Watson 29471b2c2ab2SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff"); 29481b2c2ab2SRobert Watson 29491b2c2ab2SRobert Watson if (!mac_enforce_system) 29501b2c2ab2SRobert Watson return (0); 29511b2c2ab2SRobert Watson 29521b2c2ab2SRobert Watson MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label); 29531b2c2ab2SRobert Watson return (error); 29541b2c2ab2SRobert Watson } 29551b2c2ab2SRobert Watson 29561b2c2ab2SRobert Watson int 2957d3fc69eeSRobert Watson mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2958d3fc69eeSRobert Watson void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2959d3fc69eeSRobert Watson { 2960d3fc69eeSRobert Watson int error; 2961d3fc69eeSRobert Watson 2962d3fc69eeSRobert Watson /* 2963d3fc69eeSRobert Watson * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2964d3fc69eeSRobert Watson * but since it's not exported from kern_sysctl.c, we can't. 2965d3fc69eeSRobert Watson */ 29669e913ebdSRobert Watson if (!mac_enforce_system) 2967d3fc69eeSRobert Watson return (0); 2968d3fc69eeSRobert Watson 2969d3fc69eeSRobert Watson MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2970d3fc69eeSRobert Watson inkernel, new, newlen); 2971d3fc69eeSRobert Watson 2972d3fc69eeSRobert Watson return (error); 2973d3fc69eeSRobert Watson } 2974d3fc69eeSRobert Watson 2975d3fc69eeSRobert Watson int 297695fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 297795fab37eSRobert Watson struct ifnet *ifnet) 297895fab37eSRobert Watson { 2979f7b951a8SRobert Watson char *elements, *buffer; 2980f7b951a8SRobert Watson struct mac mac; 298195fab37eSRobert Watson int error; 298295fab37eSRobert Watson 2983f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 298495fab37eSRobert Watson if (error) 298595fab37eSRobert Watson return (error); 298695fab37eSRobert Watson 2987f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 2988f7b951a8SRobert Watson if (error) 2989f7b951a8SRobert Watson return (error); 2990f7b951a8SRobert Watson 2991a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2992f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2993f7b951a8SRobert Watson if (error) { 2994f7b951a8SRobert Watson free(elements, M_MACTEMP); 2995f7b951a8SRobert Watson return (error); 2996f7b951a8SRobert Watson } 2997f7b951a8SRobert Watson 2998a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2999f7b951a8SRobert Watson error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 3000a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3001f7b951a8SRobert Watson if (error == 0) 3002f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3003f7b951a8SRobert Watson 3004f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3005f7b951a8SRobert Watson free(elements, M_MACTEMP); 3006f7b951a8SRobert Watson 3007f7b951a8SRobert Watson return (error); 300895fab37eSRobert Watson } 300995fab37eSRobert Watson 301095fab37eSRobert Watson int 301195fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 301295fab37eSRobert Watson struct ifnet *ifnet) 301395fab37eSRobert Watson { 301495fab37eSRobert Watson struct label intlabel; 3015f7b951a8SRobert Watson struct mac mac; 3016f7b951a8SRobert Watson char *buffer; 301795fab37eSRobert Watson int error; 301895fab37eSRobert Watson 3019f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 302095fab37eSRobert Watson if (error) 302195fab37eSRobert Watson return (error); 302295fab37eSRobert Watson 3023f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 302495fab37eSRobert Watson if (error) 302595fab37eSRobert Watson return (error); 302695fab37eSRobert Watson 3027a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3028f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3029f7b951a8SRobert Watson if (error) { 3030f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3031f7b951a8SRobert Watson return (error); 3032f7b951a8SRobert Watson } 3033f7b951a8SRobert Watson 3034f7b951a8SRobert Watson mac_init_ifnet_label(&intlabel); 3035f7b951a8SRobert Watson error = mac_internalize_ifnet_label(&intlabel, buffer); 3036f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3037f7b951a8SRobert Watson if (error) { 3038f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3039f7b951a8SRobert Watson return (error); 3040f7b951a8SRobert Watson } 3041f7b951a8SRobert Watson 304295fab37eSRobert Watson /* 304395fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 304495fab37eSRobert Watson * policies impose this check themselves if required by the 304595fab37eSRobert Watson * policy. Eventually, this should go away. 304695fab37eSRobert Watson */ 304795fab37eSRobert Watson error = suser_cred(cred, 0); 3048f7b951a8SRobert Watson if (error) { 3049f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3050f7b951a8SRobert Watson return (error); 3051f7b951a8SRobert Watson } 305295fab37eSRobert Watson 305395fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 305495fab37eSRobert Watson &intlabel); 3055f7b951a8SRobert Watson if (error) { 3056f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3057f7b951a8SRobert Watson return (error); 3058f7b951a8SRobert Watson } 305995fab37eSRobert Watson 306095fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 306195fab37eSRobert Watson 3062f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3063f7b951a8SRobert Watson return (0); 306495fab37eSRobert Watson } 306595fab37eSRobert Watson 306695fab37eSRobert Watson void 3067990b4b2dSRobert Watson mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de) 306895fab37eSRobert Watson { 306995fab37eSRobert Watson 3070990b4b2dSRobert Watson MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label); 307195fab37eSRobert Watson } 307295fab37eSRobert Watson 307374e62b1bSRobert Watson void 3074990b4b2dSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct mount *mp, 3075990b4b2dSRobert Watson struct devfs_dirent *dd, struct devfs_dirent *de) 307674e62b1bSRobert Watson { 307774e62b1bSRobert Watson 3078990b4b2dSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de, 307974e62b1bSRobert Watson &de->de_label); 308074e62b1bSRobert Watson } 308174e62b1bSRobert Watson 308295fab37eSRobert Watson void 3083990b4b2dSRobert Watson mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, 308495fab37eSRobert Watson struct devfs_dirent *de) 308595fab37eSRobert Watson { 308695fab37eSRobert Watson 3087990b4b2dSRobert Watson MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de, 308895fab37eSRobert Watson &de->de_label); 308995fab37eSRobert Watson } 309095fab37eSRobert Watson 309195fab37eSRobert Watson int 309295fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 3093f7b951a8SRobert Watson struct mac *mac) 309495fab37eSRobert Watson { 309595fab37eSRobert Watson struct label intlabel; 3096f7b951a8SRobert Watson char *buffer; 309795fab37eSRobert Watson int error; 309895fab37eSRobert Watson 3099f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 310095fab37eSRobert Watson if (error) 310195fab37eSRobert Watson return (error); 310295fab37eSRobert Watson 3103a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3104f7b951a8SRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 3105f7b951a8SRobert Watson if (error) { 3106f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3107f7b951a8SRobert Watson return (error); 3108f7b951a8SRobert Watson } 3109f7b951a8SRobert Watson 3110a163d034SWarner Losh mac_init_socket_label(&intlabel, M_WAITOK); 3111f7b951a8SRobert Watson error = mac_internalize_socket_label(&intlabel, buffer); 3112f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3113f7b951a8SRobert Watson if (error) { 3114f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 3115f7b951a8SRobert Watson return (error); 3116f7b951a8SRobert Watson } 3117f7b951a8SRobert Watson 311895fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 311995fab37eSRobert Watson if (error) { 3120f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 312195fab37eSRobert Watson return (error); 312295fab37eSRobert Watson } 312395fab37eSRobert Watson 312495fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 312595fab37eSRobert Watson 3126f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 312795fab37eSRobert Watson return (0); 312895fab37eSRobert Watson } 312995fab37eSRobert Watson 313095fab37eSRobert Watson int 313195fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 313295fab37eSRobert Watson { 313395fab37eSRobert Watson int error; 313495fab37eSRobert Watson 31351aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31361aa37f53SRobert Watson 313795fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 313895fab37eSRobert Watson if (error) 313995fab37eSRobert Watson return (error); 314095fab37eSRobert Watson 314195fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 314295fab37eSRobert Watson 314395fab37eSRobert Watson return (0); 314495fab37eSRobert Watson } 314595fab37eSRobert Watson 314695fab37eSRobert Watson int 314795fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 3148f7b951a8SRobert Watson struct mac *mac) 314995fab37eSRobert Watson { 3150f7b951a8SRobert Watson char *buffer, *elements; 3151f7b951a8SRobert Watson int error; 315295fab37eSRobert Watson 3153f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3154f7b951a8SRobert Watson if (error) 3155f7b951a8SRobert Watson return (error); 3156f7b951a8SRobert Watson 3157a163d034SWarner Losh elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3158f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3159f7b951a8SRobert Watson if (error) { 3160f7b951a8SRobert Watson free(elements, M_MACTEMP); 3161f7b951a8SRobert Watson return (error); 3162f7b951a8SRobert Watson } 3163f7b951a8SRobert Watson 3164a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3165f7b951a8SRobert Watson error = mac_externalize_socket_label(&so->so_label, elements, 3166a163d034SWarner Losh buffer, mac->m_buflen, M_WAITOK); 3167f7b951a8SRobert Watson if (error == 0) 3168f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3169f7b951a8SRobert Watson 3170f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3171f7b951a8SRobert Watson free(elements, M_MACTEMP); 3172f7b951a8SRobert Watson 3173f7b951a8SRobert Watson return (error); 317495fab37eSRobert Watson } 317595fab37eSRobert Watson 317695fab37eSRobert Watson int 317795fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 3178f7b951a8SRobert Watson struct mac *mac) 317995fab37eSRobert Watson { 3180f7b951a8SRobert Watson char *elements, *buffer; 3181f7b951a8SRobert Watson int error; 318295fab37eSRobert Watson 3183f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3184f7b951a8SRobert Watson if (error) 3185f7b951a8SRobert Watson return (error); 3186f7b951a8SRobert Watson 3187a163d034SWarner Losh elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3188f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3189f7b951a8SRobert Watson if (error) { 3190f7b951a8SRobert Watson free(elements, M_MACTEMP); 3191f7b951a8SRobert Watson return (error); 3192f7b951a8SRobert Watson } 3193f7b951a8SRobert Watson 3194a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3195f7b951a8SRobert Watson error = mac_externalize_socket_peer_label(&so->so_peerlabel, 3196a163d034SWarner Losh elements, buffer, mac->m_buflen, M_WAITOK); 3197f7b951a8SRobert Watson if (error == 0) 3198f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3199f7b951a8SRobert Watson 3200f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3201f7b951a8SRobert Watson free(elements, M_MACTEMP); 3202f7b951a8SRobert Watson 3203f7b951a8SRobert Watson return (error); 320495fab37eSRobert Watson } 320595fab37eSRobert Watson 320695fab37eSRobert Watson /* 320795fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 320895fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 320995fab37eSRobert Watson * extended attributes. 321095fab37eSRobert Watson */ 321195fab37eSRobert Watson int 321295fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 321395fab37eSRobert Watson { 321495fab37eSRobert Watson struct vnode *vp = ap->a_vp; 321595fab37eSRobert Watson struct label *intlabel = ap->a_label; 321695fab37eSRobert Watson int error; 321795fab37eSRobert Watson 321895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 321995fab37eSRobert Watson 3220763bbd2fSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 3221763bbd2fSRobert Watson return (EOPNOTSUPP); 322295fab37eSRobert Watson 3223763bbd2fSRobert Watson error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 322495fab37eSRobert Watson if (error) 322595fab37eSRobert Watson return (error); 322695fab37eSRobert Watson 322795fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 322895fab37eSRobert Watson 322995fab37eSRobert Watson return (0); 323095fab37eSRobert Watson } 323195fab37eSRobert Watson 323295fab37eSRobert Watson static int 323395fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 323495fab37eSRobert Watson { 323595fab37eSRobert Watson int error; 323695fab37eSRobert Watson 323795fab37eSRobert Watson if (vp->v_mount == NULL) { 323895fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 323906be2aaaSNate Lawson if (vp->v_type != VNON) 324006be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 324195fab37eSRobert Watson return (EBADF); 324295fab37eSRobert Watson } 324395fab37eSRobert Watson 324495fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 324595fab37eSRobert Watson return (EOPNOTSUPP); 324695fab37eSRobert Watson 324795fab37eSRobert Watson /* 324895fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 324995fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 325095fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 325195fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 325295fab37eSRobert Watson */ 325395fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 325495fab37eSRobert Watson if (error) 325595fab37eSRobert Watson return (error); 325695fab37eSRobert Watson 325795fab37eSRobert Watson /* 325895fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 325995fab37eSRobert Watson * decisions about who is and is not able to modify labels 326095fab37eSRobert Watson * and protections on files. This might not be right. We can't 326195fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 326295fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 326395fab37eSRobert Watson */ 326495fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 326595fab37eSRobert Watson if (error) 326695fab37eSRobert Watson return (error); 326795fab37eSRobert Watson 326895fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 326995fab37eSRobert Watson if (error) 327095fab37eSRobert Watson return (error); 327195fab37eSRobert Watson 327295fab37eSRobert Watson return (0); 327395fab37eSRobert Watson } 327495fab37eSRobert Watson 3275f7b951a8SRobert Watson int 3276f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3277f7b951a8SRobert Watson { 3278f7b951a8SRobert Watson char *elements, *buffer; 3279f7b951a8SRobert Watson struct mac mac; 3280f7b951a8SRobert Watson struct proc *tproc; 3281f7b951a8SRobert Watson struct ucred *tcred; 3282f7b951a8SRobert Watson int error; 3283f7b951a8SRobert Watson 3284d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 3285f7b951a8SRobert Watson if (error) 3286f7b951a8SRobert Watson return (error); 3287f7b951a8SRobert Watson 3288f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3289f7b951a8SRobert Watson if (error) 3290f7b951a8SRobert Watson return (error); 3291f7b951a8SRobert Watson 3292f7b951a8SRobert Watson tproc = pfind(uap->pid); 3293f7b951a8SRobert Watson if (tproc == NULL) 3294f7b951a8SRobert Watson return (ESRCH); 3295f7b951a8SRobert Watson 3296f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 3297f7b951a8SRobert Watson error = p_cansee(td, tproc); 3298f7b951a8SRobert Watson if (error == 0) 3299f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 3300f7b951a8SRobert Watson PROC_UNLOCK(tproc); 3301f7b951a8SRobert Watson if (error) 3302f7b951a8SRobert Watson return (error); 3303f7b951a8SRobert Watson 3304a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3305f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3306f7b951a8SRobert Watson if (error) { 3307f7b951a8SRobert Watson free(elements, M_MACTEMP); 3308f7b951a8SRobert Watson crfree(tcred); 3309f7b951a8SRobert Watson return (error); 3310f7b951a8SRobert Watson } 3311f7b951a8SRobert Watson 3312a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3313f7b951a8SRobert Watson error = mac_externalize_cred_label(&tcred->cr_label, elements, 3314a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3315f7b951a8SRobert Watson if (error == 0) 3316f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3317f7b951a8SRobert Watson 3318f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3319f7b951a8SRobert Watson free(elements, M_MACTEMP); 3320f7b951a8SRobert Watson crfree(tcred); 3321f7b951a8SRobert Watson return (error); 3322f7b951a8SRobert Watson } 3323f7b951a8SRobert Watson 332495fab37eSRobert Watson /* 332595fab37eSRobert Watson * MPSAFE 332695fab37eSRobert Watson */ 332795fab37eSRobert Watson int 332895fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 332995fab37eSRobert Watson { 3330f7b951a8SRobert Watson char *elements, *buffer; 3331f7b951a8SRobert Watson struct mac mac; 333295fab37eSRobert Watson int error; 333395fab37eSRobert Watson 3334f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3335f7b951a8SRobert Watson if (error) 3336f7b951a8SRobert Watson return (error); 333795fab37eSRobert Watson 3338f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3339f7b951a8SRobert Watson if (error) 3340f7b951a8SRobert Watson return (error); 3341f7b951a8SRobert Watson 3342a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3343f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3344f7b951a8SRobert Watson if (error) { 3345f7b951a8SRobert Watson free(elements, M_MACTEMP); 3346f7b951a8SRobert Watson return (error); 3347f7b951a8SRobert Watson } 3348f7b951a8SRobert Watson 3349a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3350f7b951a8SRobert Watson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3351a163d034SWarner Losh elements, buffer, mac.m_buflen, M_WAITOK); 3352f7b951a8SRobert Watson if (error == 0) 3353f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3354f7b951a8SRobert Watson 3355f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3356f7b951a8SRobert Watson free(elements, M_MACTEMP); 335795fab37eSRobert Watson return (error); 335895fab37eSRobert Watson } 335995fab37eSRobert Watson 336095fab37eSRobert Watson /* 336195fab37eSRobert Watson * MPSAFE 336295fab37eSRobert Watson */ 336395fab37eSRobert Watson int 336495fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 336595fab37eSRobert Watson { 336695fab37eSRobert Watson struct ucred *newcred, *oldcred; 336795fab37eSRobert Watson struct label intlabel; 3368f7b951a8SRobert Watson struct proc *p; 3369f7b951a8SRobert Watson struct mac mac; 3370f7b951a8SRobert Watson char *buffer; 337195fab37eSRobert Watson int error; 337295fab37eSRobert Watson 3373f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 337495fab37eSRobert Watson if (error) 337595fab37eSRobert Watson return (error); 337695fab37eSRobert Watson 3377f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 337895fab37eSRobert Watson if (error) 337995fab37eSRobert Watson return (error); 338095fab37eSRobert Watson 3381a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3382f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3383f7b951a8SRobert Watson if (error) { 3384f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3385f7b951a8SRobert Watson return (error); 3386f7b951a8SRobert Watson } 3387f7b951a8SRobert Watson 3388f7b951a8SRobert Watson mac_init_cred_label(&intlabel); 3389f7b951a8SRobert Watson error = mac_internalize_cred_label(&intlabel, buffer); 3390f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3391f7b951a8SRobert Watson if (error) { 3392f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3393f7b951a8SRobert Watson return (error); 3394f7b951a8SRobert Watson } 3395f7b951a8SRobert Watson 339695fab37eSRobert Watson newcred = crget(); 339795fab37eSRobert Watson 339895fab37eSRobert Watson p = td->td_proc; 339995fab37eSRobert Watson PROC_LOCK(p); 340095fab37eSRobert Watson oldcred = p->p_ucred; 340195fab37eSRobert Watson 340295fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 340395fab37eSRobert Watson if (error) { 340495fab37eSRobert Watson PROC_UNLOCK(p); 340595fab37eSRobert Watson crfree(newcred); 3406f7b951a8SRobert Watson goto out; 340795fab37eSRobert Watson } 340895fab37eSRobert Watson 340995fab37eSRobert Watson setsugid(p); 341095fab37eSRobert Watson crcopy(newcred, oldcred); 341195fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 341295fab37eSRobert Watson p->p_ucred = newcred; 3413e5cb5e37SRobert Watson 3414e5cb5e37SRobert Watson /* 3415e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3416e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3417e5cb5e37SRobert Watson */ 3418e5cb5e37SRobert Watson crhold(newcred); 341995fab37eSRobert Watson PROC_UNLOCK(p); 3420e5cb5e37SRobert Watson 3421f7b951a8SRobert Watson if (mac_enforce_vm) { 342216140035SRobert Watson mtx_lock(&Giant); 3423e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 342416140035SRobert Watson mtx_unlock(&Giant); 3425f7b951a8SRobert Watson } 3426e5cb5e37SRobert Watson 3427e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 342895fab37eSRobert Watson crfree(oldcred); 3429f7b951a8SRobert Watson 3430f7b951a8SRobert Watson out: 3431f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3432f7b951a8SRobert Watson return (error); 343395fab37eSRobert Watson } 343495fab37eSRobert Watson 343595fab37eSRobert Watson /* 343695fab37eSRobert Watson * MPSAFE 343795fab37eSRobert Watson */ 343895fab37eSRobert Watson int 343995fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 344095fab37eSRobert Watson { 3441f7b951a8SRobert Watson char *elements, *buffer; 3442f7b951a8SRobert Watson struct label intlabel; 344395fab37eSRobert Watson struct file *fp; 3444f7b951a8SRobert Watson struct mac mac; 344595fab37eSRobert Watson struct vnode *vp; 344695fab37eSRobert Watson struct pipe *pipe; 3447f7b951a8SRobert Watson short label_type; 344895fab37eSRobert Watson int error; 344995fab37eSRobert Watson 3450f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3451f7b951a8SRobert Watson if (error) 3452f7b951a8SRobert Watson return (error); 345395fab37eSRobert Watson 3454f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3455f7b951a8SRobert Watson if (error) 3456f7b951a8SRobert Watson return (error); 3457f7b951a8SRobert Watson 3458a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3459f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3460f7b951a8SRobert Watson if (error) { 3461f7b951a8SRobert Watson free(elements, M_MACTEMP); 3462f7b951a8SRobert Watson return (error); 3463f7b951a8SRobert Watson } 3464f7b951a8SRobert Watson 3465a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3466f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3467d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 346895fab37eSRobert Watson if (error) 346995fab37eSRobert Watson goto out; 347095fab37eSRobert Watson 3471f7b951a8SRobert Watson label_type = fp->f_type; 347295fab37eSRobert Watson switch (fp->f_type) { 347395fab37eSRobert Watson case DTYPE_FIFO: 347495fab37eSRobert Watson case DTYPE_VNODE: 34753b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 347695fab37eSRobert Watson 3477f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3478f7b951a8SRobert Watson 347995fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3480f7b951a8SRobert Watson mac_copy_vnode_label(&vp->v_label, &intlabel); 348195fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 3482f7b951a8SRobert Watson 348395fab37eSRobert Watson break; 348495fab37eSRobert Watson case DTYPE_PIPE: 348548e3128bSMatthew Dillon pipe = fp->f_data; 3486f7b951a8SRobert Watson 3487f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3488f7b951a8SRobert Watson 3489f7b951a8SRobert Watson PIPE_LOCK(pipe); 3490f7b951a8SRobert Watson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3491f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 349295fab37eSRobert Watson break; 349395fab37eSRobert Watson default: 349495fab37eSRobert Watson error = EINVAL; 3495f7b951a8SRobert Watson fdrop(fp, td); 3496f7b951a8SRobert Watson goto out; 3497f7b951a8SRobert Watson } 3498f7b951a8SRobert Watson fdrop(fp, td); 3499f7b951a8SRobert Watson 3500f7b951a8SRobert Watson switch (label_type) { 3501f7b951a8SRobert Watson case DTYPE_FIFO: 3502f7b951a8SRobert Watson case DTYPE_VNODE: 3503f7b951a8SRobert Watson if (error == 0) 3504f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, 3505a163d034SWarner Losh elements, buffer, mac.m_buflen, M_WAITOK); 3506f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3507f7b951a8SRobert Watson break; 3508f7b951a8SRobert Watson case DTYPE_PIPE: 3509f7b951a8SRobert Watson error = mac_externalize_pipe_label(&intlabel, elements, 3510a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3511f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 3512f7b951a8SRobert Watson break; 3513f7b951a8SRobert Watson default: 3514f7b951a8SRobert Watson panic("__mac_get_fd: corrupted label_type"); 351595fab37eSRobert Watson } 351695fab37eSRobert Watson 351795fab37eSRobert Watson if (error == 0) 3518f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 351995fab37eSRobert Watson 352095fab37eSRobert Watson out: 3521f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3522f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3523f7b951a8SRobert Watson free(elements, M_MACTEMP); 3524f7b951a8SRobert Watson 352595fab37eSRobert Watson return (error); 352695fab37eSRobert Watson } 352795fab37eSRobert Watson 352895fab37eSRobert Watson /* 352995fab37eSRobert Watson * MPSAFE 353095fab37eSRobert Watson */ 353195fab37eSRobert Watson int 353295fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 353395fab37eSRobert Watson { 3534f7b951a8SRobert Watson char *elements, *buffer; 353595fab37eSRobert Watson struct nameidata nd; 3536f7b951a8SRobert Watson struct label intlabel; 3537f7b951a8SRobert Watson struct mac mac; 353895fab37eSRobert Watson int error; 353995fab37eSRobert Watson 3540f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3541f7b951a8SRobert Watson if (error) 3542f7b951a8SRobert Watson return (error); 3543f7b951a8SRobert Watson 3544f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3545f7b951a8SRobert Watson if (error) 3546f7b951a8SRobert Watson return (error); 3547f7b951a8SRobert Watson 3548a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3549f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3550f7b951a8SRobert Watson if (error) { 3551f7b951a8SRobert Watson free(elements, M_MACTEMP); 3552f7b951a8SRobert Watson return (error); 3553f7b951a8SRobert Watson } 3554f7b951a8SRobert Watson 3555a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3556f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3557f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3558f7b951a8SRobert Watson td); 355995fab37eSRobert Watson error = namei(&nd); 356095fab37eSRobert Watson if (error) 356195fab37eSRobert Watson goto out; 356295fab37eSRobert Watson 3563f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3564f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3565763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3566a163d034SWarner Losh mac.m_buflen, M_WAITOK); 3567f7b951a8SRobert Watson 356895fab37eSRobert Watson NDFREE(&nd, 0); 3569f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3570f7b951a8SRobert Watson 3571f7b951a8SRobert Watson if (error == 0) 3572f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3573f7b951a8SRobert Watson 3574f7b951a8SRobert Watson out: 3575f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3576f7b951a8SRobert Watson 3577f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3578f7b951a8SRobert Watson free(elements, M_MACTEMP); 3579f7b951a8SRobert Watson 3580f7b951a8SRobert Watson return (error); 3581f7b951a8SRobert Watson } 3582f7b951a8SRobert Watson 3583f7b951a8SRobert Watson /* 3584f7b951a8SRobert Watson * MPSAFE 3585f7b951a8SRobert Watson */ 3586f7b951a8SRobert Watson int 3587f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3588f7b951a8SRobert Watson { 3589f7b951a8SRobert Watson char *elements, *buffer; 3590f7b951a8SRobert Watson struct nameidata nd; 3591f7b951a8SRobert Watson struct label intlabel; 3592f7b951a8SRobert Watson struct mac mac; 3593f7b951a8SRobert Watson int error; 3594f7b951a8SRobert Watson 3595f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3596f7b951a8SRobert Watson if (error) 3597f7b951a8SRobert Watson return (error); 3598f7b951a8SRobert Watson 3599f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3600f7b951a8SRobert Watson if (error) 3601f7b951a8SRobert Watson return (error); 3602f7b951a8SRobert Watson 3603a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3604f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3605f7b951a8SRobert Watson if (error) { 3606f7b951a8SRobert Watson free(elements, M_MACTEMP); 3607f7b951a8SRobert Watson return (error); 3608f7b951a8SRobert Watson } 3609f7b951a8SRobert Watson 3610a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3611f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3612f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3613f7b951a8SRobert Watson td); 3614f7b951a8SRobert Watson error = namei(&nd); 361595fab37eSRobert Watson if (error) 361695fab37eSRobert Watson goto out; 361795fab37eSRobert Watson 3618f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3619f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3620763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3621a163d034SWarner Losh mac.m_buflen, M_WAITOK); 3622f7b951a8SRobert Watson NDFREE(&nd, 0); 3623f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3624f7b951a8SRobert Watson 3625f7b951a8SRobert Watson if (error == 0) 3626f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 362795fab37eSRobert Watson 362895fab37eSRobert Watson out: 3629f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3630f7b951a8SRobert Watson 3631f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3632f7b951a8SRobert Watson free(elements, M_MACTEMP); 3633f7b951a8SRobert Watson 363495fab37eSRobert Watson return (error); 363595fab37eSRobert Watson } 363695fab37eSRobert Watson 363795fab37eSRobert Watson /* 363895fab37eSRobert Watson * MPSAFE 363995fab37eSRobert Watson */ 364095fab37eSRobert Watson int 364195fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 364295fab37eSRobert Watson { 364395fab37eSRobert Watson struct label intlabel; 3644f7b951a8SRobert Watson struct pipe *pipe; 3645f7b951a8SRobert Watson struct file *fp; 364695fab37eSRobert Watson struct mount *mp; 364795fab37eSRobert Watson struct vnode *vp; 3648f7b951a8SRobert Watson struct mac mac; 3649f7b951a8SRobert Watson char *buffer; 365095fab37eSRobert Watson int error; 365195fab37eSRobert Watson 3652f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3653f7b951a8SRobert Watson if (error) 3654f7b951a8SRobert Watson return (error); 3655f7b951a8SRobert Watson 3656f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3657f7b951a8SRobert Watson if (error) 3658f7b951a8SRobert Watson return (error); 3659f7b951a8SRobert Watson 3660a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3661f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3662f7b951a8SRobert Watson if (error) { 3663f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3664f7b951a8SRobert Watson return (error); 3665f7b951a8SRobert Watson } 3666f7b951a8SRobert Watson 3667f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3668f7b951a8SRobert Watson 3669d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 367095fab37eSRobert Watson if (error) 3671f7b951a8SRobert Watson goto out; 367295fab37eSRobert Watson 367395fab37eSRobert Watson switch (fp->f_type) { 367495fab37eSRobert Watson case DTYPE_FIFO: 367595fab37eSRobert Watson case DTYPE_VNODE: 3676f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3677f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3678f7b951a8SRobert Watson if (error) { 3679f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3680f7b951a8SRobert Watson break; 3681f7b951a8SRobert Watson } 3682f7b951a8SRobert Watson 36833b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 368495fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3685f7b951a8SRobert Watson if (error != 0) { 3686f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 368795fab37eSRobert Watson break; 3688f7b951a8SRobert Watson } 368995fab37eSRobert Watson 369095fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 369195fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 369295fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 369395fab37eSRobert Watson vn_finished_write(mp); 3694f7b951a8SRobert Watson 3695f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 369695fab37eSRobert Watson break; 3697f7b951a8SRobert Watson 369895fab37eSRobert Watson case DTYPE_PIPE: 3699f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3700f7b951a8SRobert Watson error = mac_internalize_pipe_label(&intlabel, buffer); 3701f7b951a8SRobert Watson if (error == 0) { 370248e3128bSMatthew Dillon pipe = fp->f_data; 37031aa37f53SRobert Watson PIPE_LOCK(pipe); 3704f7b951a8SRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, 3705f7b951a8SRobert Watson &intlabel); 37061aa37f53SRobert Watson PIPE_UNLOCK(pipe); 3707f7b951a8SRobert Watson } 3708f7b951a8SRobert Watson 3709f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 371095fab37eSRobert Watson break; 3711f7b951a8SRobert Watson 371295fab37eSRobert Watson default: 371395fab37eSRobert Watson error = EINVAL; 371495fab37eSRobert Watson } 371595fab37eSRobert Watson 371695fab37eSRobert Watson fdrop(fp, td); 3717f7b951a8SRobert Watson out: 3718f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3719f7b951a8SRobert Watson 3720f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3721f7b951a8SRobert Watson 372295fab37eSRobert Watson return (error); 372395fab37eSRobert Watson } 372495fab37eSRobert Watson 372595fab37eSRobert Watson /* 372695fab37eSRobert Watson * MPSAFE 372795fab37eSRobert Watson */ 372895fab37eSRobert Watson int 372995fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 373095fab37eSRobert Watson { 373195fab37eSRobert Watson struct label intlabel; 3732f7b951a8SRobert Watson struct nameidata nd; 373395fab37eSRobert Watson struct mount *mp; 3734f7b951a8SRobert Watson struct mac mac; 3735f7b951a8SRobert Watson char *buffer; 373695fab37eSRobert Watson int error; 373795fab37eSRobert Watson 3738f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 373995fab37eSRobert Watson if (error) 3740f7b951a8SRobert Watson return (error); 374195fab37eSRobert Watson 3742f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 374395fab37eSRobert Watson if (error) 3744f7b951a8SRobert Watson return (error); 374595fab37eSRobert Watson 3746a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3747f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3748f7b951a8SRobert Watson if (error) { 3749f7b951a8SRobert Watson free(buffer, M_MACTEMP); 375095fab37eSRobert Watson return (error); 375195fab37eSRobert Watson } 375295fab37eSRobert Watson 3753f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3754f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3755f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3756f7b951a8SRobert Watson if (error) { 3757f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3758f7b951a8SRobert Watson return (error); 3759f7b951a8SRobert Watson } 3760f7b951a8SRobert Watson 3761f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3762f7b951a8SRobert Watson 3763f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3764f7b951a8SRobert Watson td); 3765f7b951a8SRobert Watson error = namei(&nd); 3766f7b951a8SRobert Watson if (error == 0) { 3767f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3768f7b951a8SRobert Watson if (error == 0) 3769f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3770f7b951a8SRobert Watson td->td_ucred); 3771f7b951a8SRobert Watson vn_finished_write(mp); 3772f7b951a8SRobert Watson } 3773f7b951a8SRobert Watson 3774f7b951a8SRobert Watson NDFREE(&nd, 0); 3775f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3776f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3777f7b951a8SRobert Watson 3778f7b951a8SRobert Watson return (error); 3779f7b951a8SRobert Watson } 3780f7b951a8SRobert Watson 3781f7b951a8SRobert Watson /* 3782f7b951a8SRobert Watson * MPSAFE 3783f7b951a8SRobert Watson */ 3784f7b951a8SRobert Watson int 3785f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3786f7b951a8SRobert Watson { 3787f7b951a8SRobert Watson struct label intlabel; 3788f7b951a8SRobert Watson struct nameidata nd; 3789f7b951a8SRobert Watson struct mount *mp; 3790f7b951a8SRobert Watson struct mac mac; 3791f7b951a8SRobert Watson char *buffer; 3792f7b951a8SRobert Watson int error; 3793f7b951a8SRobert Watson 3794f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3795f7b951a8SRobert Watson if (error) 3796f7b951a8SRobert Watson return (error); 3797f7b951a8SRobert Watson 3798f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3799f7b951a8SRobert Watson if (error) 3800f7b951a8SRobert Watson return (error); 3801f7b951a8SRobert Watson 3802a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3803f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3804f7b951a8SRobert Watson if (error) { 3805f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3806f7b951a8SRobert Watson return (error); 3807f7b951a8SRobert Watson } 3808f7b951a8SRobert Watson 3809f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3810f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3811f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3812f7b951a8SRobert Watson if (error) { 3813f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3814f7b951a8SRobert Watson return (error); 3815f7b951a8SRobert Watson } 3816f7b951a8SRobert Watson 3817f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3818f7b951a8SRobert Watson 3819f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3820f7b951a8SRobert Watson td); 3821f7b951a8SRobert Watson error = namei(&nd); 3822f7b951a8SRobert Watson if (error == 0) { 3823f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3824f7b951a8SRobert Watson if (error == 0) 3825f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3826f7b951a8SRobert Watson td->td_ucred); 3827f7b951a8SRobert Watson vn_finished_write(mp); 3828f7b951a8SRobert Watson } 3829f7b951a8SRobert Watson 3830f7b951a8SRobert Watson NDFREE(&nd, 0); 3831f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3832f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3833f7b951a8SRobert Watson 3834f7b951a8SRobert Watson return (error); 3835f7b951a8SRobert Watson } 3836f7b951a8SRobert Watson 3837f7b951a8SRobert Watson /* 3838f7b951a8SRobert Watson * MPSAFE 3839f7b951a8SRobert Watson */ 384027f2eac7SRobert Watson int 384127f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 384227f2eac7SRobert Watson { 384327f2eac7SRobert Watson struct mac_policy_conf *mpc; 384427f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 384541a17fe3SRobert Watson int entrycount, error; 384627f2eac7SRobert Watson 3847d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 384827f2eac7SRobert Watson if (error) 384927f2eac7SRobert Watson return (error); 385027f2eac7SRobert Watson 385127f2eac7SRobert Watson error = ENOSYS; 3852a6a65b05SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 385327f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 385427f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 385527f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 3856d1e405c5SAlfred Perlstein uap->call, uap->arg); 385727f2eac7SRobert Watson goto out; 385827f2eac7SRobert Watson } 385927f2eac7SRobert Watson } 386027f2eac7SRobert Watson 386141a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 386241a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 386341a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 386441a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 386541a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 386641a17fe3SRobert Watson uap->call, uap->arg); 386741a17fe3SRobert Watson break; 386841a17fe3SRobert Watson } 386941a17fe3SRobert Watson } 387041a17fe3SRobert Watson mac_policy_list_unbusy(); 387141a17fe3SRobert Watson } 387227f2eac7SRobert Watson out: 387327f2eac7SRobert Watson return (error); 387427f2eac7SRobert Watson } 387527f2eac7SRobert Watson 387695fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 387795fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 387895fab37eSRobert Watson 387995fab37eSRobert Watson #else /* !MAC */ 38807bc82500SRobert Watson 38817bc82500SRobert Watson int 3882f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3883f7b951a8SRobert Watson { 3884f7b951a8SRobert Watson 3885f7b951a8SRobert Watson return (ENOSYS); 3886f7b951a8SRobert Watson } 3887f7b951a8SRobert Watson 3888f7b951a8SRobert Watson int 38897bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 38907bc82500SRobert Watson { 38917bc82500SRobert Watson 38927bc82500SRobert Watson return (ENOSYS); 38937bc82500SRobert Watson } 38947bc82500SRobert Watson 38957bc82500SRobert Watson int 38967bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 38977bc82500SRobert Watson { 38987bc82500SRobert Watson 38997bc82500SRobert Watson return (ENOSYS); 39007bc82500SRobert Watson } 39017bc82500SRobert Watson 39027bc82500SRobert Watson int 39037bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 39047bc82500SRobert Watson { 39057bc82500SRobert Watson 39067bc82500SRobert Watson return (ENOSYS); 39077bc82500SRobert Watson } 39087bc82500SRobert Watson 39097bc82500SRobert Watson int 39107bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 39117bc82500SRobert Watson { 39127bc82500SRobert Watson 39137bc82500SRobert Watson return (ENOSYS); 39147bc82500SRobert Watson } 39157bc82500SRobert Watson 39167bc82500SRobert Watson int 3917f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3918f7b951a8SRobert Watson { 3919f7b951a8SRobert Watson 3920f7b951a8SRobert Watson return (ENOSYS); 3921f7b951a8SRobert Watson } 3922f7b951a8SRobert Watson 3923f7b951a8SRobert Watson int 39247bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 39257bc82500SRobert Watson { 39267bc82500SRobert Watson 39277bc82500SRobert Watson return (ENOSYS); 39287bc82500SRobert Watson } 39297bc82500SRobert Watson 39307bc82500SRobert Watson int 39317bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 39327bc82500SRobert Watson { 39337bc82500SRobert Watson 39347bc82500SRobert Watson return (ENOSYS); 39357bc82500SRobert Watson } 393695fab37eSRobert Watson 393727f2eac7SRobert Watson int 3938f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3939f7b951a8SRobert Watson { 3940f7b951a8SRobert Watson 3941f7b951a8SRobert Watson return (ENOSYS); 3942f7b951a8SRobert Watson } 3943f7b951a8SRobert Watson 3944f7b951a8SRobert Watson int 394527f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 394627f2eac7SRobert Watson { 394727f2eac7SRobert Watson 394827f2eac7SRobert Watson return (ENOSYS); 394927f2eac7SRobert Watson } 395027f2eac7SRobert Watson 3951f7b951a8SRobert Watson #endif 3952