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 * 367bc82500SRobert Watson * $FreeBSD$ 377bc82500SRobert Watson */ 387bc82500SRobert Watson /* 397bc82500SRobert Watson * Developed by the TrustedBSD Project. 407bc82500SRobert Watson * 417bc82500SRobert Watson * Framework for extensible kernel access control. Kernel and userland 427bc82500SRobert Watson * interface to the framework, policy registration and composition. 437bc82500SRobert Watson */ 447bc82500SRobert Watson 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> 5995fab37eSRobert Watson #include <sys/systm.h> 607bc82500SRobert Watson #include <sys/sysproto.h> 617bc82500SRobert Watson #include <sys/sysent.h> 6295fab37eSRobert Watson #include <sys/vnode.h> 6395fab37eSRobert Watson #include <sys/mount.h> 6495fab37eSRobert Watson #include <sys/file.h> 6595fab37eSRobert Watson #include <sys/namei.h> 6695fab37eSRobert Watson #include <sys/socket.h> 6795fab37eSRobert Watson #include <sys/pipe.h> 6895fab37eSRobert Watson #include <sys/socketvar.h> 6995fab37eSRobert Watson #include <sys/sysctl.h> 7095fab37eSRobert Watson 7195fab37eSRobert Watson #include <vm/vm.h> 7295fab37eSRobert Watson #include <vm/pmap.h> 7395fab37eSRobert Watson #include <vm/vm_map.h> 7495fab37eSRobert Watson #include <vm/vm_object.h> 7595fab37eSRobert Watson 7695fab37eSRobert Watson #include <sys/mac_policy.h> 7795fab37eSRobert Watson 7895fab37eSRobert Watson #include <fs/devfs/devfs.h> 7995fab37eSRobert Watson 8095fab37eSRobert Watson #include <net/bpfdesc.h> 8195fab37eSRobert Watson #include <net/if.h> 8295fab37eSRobert Watson #include <net/if_var.h> 8395fab37eSRobert Watson 8495fab37eSRobert Watson #include <netinet/in.h> 8595fab37eSRobert Watson #include <netinet/ip_var.h> 8695fab37eSRobert Watson 8795fab37eSRobert Watson #ifdef MAC 8895fab37eSRobert Watson 897ba28492SRobert Watson /* 907ba28492SRobert Watson * Declare that the kernel provides MAC support, version 1. This permits 917ba28492SRobert Watson * modules to refuse to be loaded if the necessary support isn't present, 927ba28492SRobert Watson * even if it's pre-boot. 937ba28492SRobert Watson */ 947ba28492SRobert Watson MODULE_VERSION(kernel_mac_support, 1); 957ba28492SRobert Watson 9695fab37eSRobert Watson SYSCTL_DECL(_security); 9795fab37eSRobert Watson 9895fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 9995fab37eSRobert Watson "TrustedBSD MAC policy controls"); 100b2f0927aSRobert Watson 101b2aef571SRobert Watson #if MAC_MAX_SLOTS > 32 102b2aef571SRobert Watson #error "MAC_MAX_SLOTS too large" 10395fab37eSRobert Watson #endif 104a13c67daSRobert Watson 105b2aef571SRobert Watson static unsigned int mac_max_slots = MAC_MAX_SLOTS; 106b2aef571SRobert Watson static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 107b2aef571SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 108b2aef571SRobert Watson &mac_max_slots, 0, ""); 10995fab37eSRobert Watson 110a67fe518SRobert Watson /* 111a67fe518SRobert Watson * Has the kernel started generating labeled objects yet? All read/write 112a67fe518SRobert Watson * access to this variable is serialized during the boot process. Following 113a67fe518SRobert Watson * the end of serialization, we don't update this flag; no locking. 114a67fe518SRobert Watson */ 11595fab37eSRobert Watson static int mac_late = 0; 11695fab37eSRobert Watson 117763bbd2fSRobert Watson /* 118763bbd2fSRobert Watson * Warn about EA transactions only the first time they happen. 119763bbd2fSRobert Watson * Weak coherency, no locking. 120763bbd2fSRobert Watson */ 121763bbd2fSRobert Watson static int ea_warn_once = 0; 122763bbd2fSRobert Watson 123225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 124225bff6fSRobert Watson /* 125225bff6fSRobert Watson * Flag to indicate whether or not we should allocate label storage for 126225bff6fSRobert Watson * new mbufs. Since most dynamic policies we currently work with don't 127225bff6fSRobert Watson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 128225bff6fSRobert Watson * unless specifically notified of interest. One result of this is 129225bff6fSRobert Watson * that if a dynamically loaded policy requests mbuf labels, it must 130225bff6fSRobert Watson * be able to deal with a NULL label being returned on any mbufs that 131225bff6fSRobert Watson * were already in flight when the policy was loaded. Since the policy 132225bff6fSRobert Watson * already has to deal with uninitialized labels, this probably won't 133225bff6fSRobert Watson * be a problem. Note: currently no locking. Will this be a problem? 134225bff6fSRobert Watson */ 135225bff6fSRobert Watson static int mac_labelmbufs = 0; 136225bff6fSRobert Watson #endif 137225bff6fSRobert Watson 13895fab37eSRobert Watson static int mac_enforce_fs = 1; 13995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 14095fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 14195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 14295fab37eSRobert Watson 143a3df768bSRobert Watson static int mac_enforce_kld = 1; 144a3df768bSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW, 145a3df768bSRobert Watson &mac_enforce_kld, 0, "Enforce MAC policy on kld operations"); 146a3df768bSRobert Watson TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld); 147a3df768bSRobert Watson 14895fab37eSRobert Watson static int mac_enforce_network = 1; 14995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 15095fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 15195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 15295fab37eSRobert Watson 153b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 154b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 155b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 156c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 157b88c98f6SRobert Watson 15895fab37eSRobert Watson static int mac_enforce_process = 1; 15995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 16095fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 16195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 16295fab37eSRobert Watson 16395fab37eSRobert Watson static int mac_enforce_socket = 1; 16495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 16595fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 16695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 16795fab37eSRobert Watson 1689e913ebdSRobert Watson static int mac_enforce_system = 1; 1699e913ebdSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 1709e913ebdSRobert Watson &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 1719e913ebdSRobert Watson TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 172d3fc69eeSRobert Watson 173ca7850c3SRobert Watson static int mac_enforce_vm = 1; 174ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 175ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 176c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 177ca7850c3SRobert Watson 178c0f39905SRobert Watson static int mac_mmap_revocation = 1; 179c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 180c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 181c0f39905SRobert Watson "relabel"); 18299fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 18395fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 18495fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 18595fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 18695fab37eSRobert Watson 187f050add5SRobert Watson #ifdef MAC_DEBUG 1886be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1896be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1906be0c25eSRobert Watson 1916be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1926be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1936be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1946be0c25eSRobert Watson "when label is corrupted."); 1956be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1966be0c25eSRobert Watson &mac_debug_label_fallback); 1976be0c25eSRobert Watson 198b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 199b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 200b2f0927aSRobert Watson 20195fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 20295fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 2032555374cSRobert Watson nmacipqs, nmacpipes, nmacprocs; 204b2f0927aSRobert Watson 205b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 20695fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 207b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 20895fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 209b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 21095fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 211b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 21295fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 213b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 21495fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 215b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 21695fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 217b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 21895fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 2192555374cSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD, 2202555374cSRobert Watson &nmacprocs, 0, "number of procs in use"); 221b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 22295fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 223b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 22495fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 225b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 22695fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 227b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 22895fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 229f050add5SRobert Watson #endif 23095fab37eSRobert Watson 23195fab37eSRobert Watson static int error_select(int error1, int error2); 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; 26995fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 27041a17fe3SRobert Watson static LIST_HEAD(, mac_policy_conf) 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 */ 28141a17fe3SRobert Watson static __inline 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 29141a17fe3SRobert Watson static __inline 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 29941a17fe3SRobert Watson static __inline 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 30941a17fe3SRobert Watson static __inline 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 31741a17fe3SRobert Watson static __inline 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 33241a17fe3SRobert Watson static __inline 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) \ 35641a17fe3SRobert Watson error = 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) \ 36395fab37eSRobert Watson error = 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 { \ 401f7b951a8SRobert Watson char *curptr, *curptr_start, *element_name, *element_temp; \ 402f7b951a8SRobert Watson size_t left, left_start, len; \ 403f7b951a8SRobert Watson int claimed, first, first_start, ignorenotfound; \ 404f7b951a8SRobert Watson \ 405f7b951a8SRobert Watson error = 0; \ 406f7b951a8SRobert Watson element_temp = elementlist; \ 407f7b951a8SRobert Watson curptr = outbuf; \ 408f7b951a8SRobert Watson curptr[0] = '\0'; \ 409f7b951a8SRobert Watson left = outbuflen; \ 410f7b951a8SRobert Watson first = 1; \ 411f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 412f7b951a8SRobert Watson curptr_start = curptr; \ 413f7b951a8SRobert Watson left_start = left; \ 414f7b951a8SRobert Watson first_start = first; \ 415f7b951a8SRobert Watson if (element_name[0] == '?') { \ 416f7b951a8SRobert Watson element_name++; \ 417f7b951a8SRobert Watson ignorenotfound = 1; \ 418f7b951a8SRobert Watson } else \ 419f7b951a8SRobert Watson ignorenotfound = 0; \ 420f7b951a8SRobert Watson claimed = 0; \ 421f7b951a8SRobert Watson if (first) { \ 422f7b951a8SRobert Watson len = snprintf(curptr, left, "%s/", \ 423f7b951a8SRobert Watson element_name); \ 424f7b951a8SRobert Watson first = 0; \ 425f7b951a8SRobert Watson } else \ 426f7b951a8SRobert Watson len = snprintf(curptr, left, ",%s/", \ 427f7b951a8SRobert Watson element_name); \ 428f7b951a8SRobert Watson if (len >= left) { \ 429f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 430f7b951a8SRobert Watson break; \ 431f7b951a8SRobert Watson } \ 432f7b951a8SRobert Watson curptr += len; \ 433f7b951a8SRobert Watson left -= len; \ 434f7b951a8SRobert Watson \ 435f7b951a8SRobert Watson MAC_CHECK(externalize_ ## type, label, element_name, \ 436f7b951a8SRobert Watson curptr, left, &len, &claimed); \ 437f7b951a8SRobert Watson if (error) \ 438f7b951a8SRobert Watson break; \ 439f7b951a8SRobert Watson if (claimed == 1) { \ 440f7b951a8SRobert Watson if (len >= outbuflen) { \ 441f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 442f7b951a8SRobert Watson break; \ 443f7b951a8SRobert Watson } \ 444f7b951a8SRobert Watson curptr += len; \ 445f7b951a8SRobert Watson left -= len; \ 446f7b951a8SRobert Watson } else if (claimed == 0 && ignorenotfound) { \ 447f7b951a8SRobert Watson /* \ 448f7b951a8SRobert Watson * Revert addition of the label element \ 449f7b951a8SRobert Watson * name. \ 450f7b951a8SRobert Watson */ \ 451f7b951a8SRobert Watson curptr = curptr_start; \ 452f7b951a8SRobert Watson *curptr = '\0'; \ 453f7b951a8SRobert Watson left = left_start; \ 454f7b951a8SRobert Watson first = first_start; \ 455f7b951a8SRobert Watson } else { \ 456f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: ENOLABEL */ \ 457f7b951a8SRobert Watson break; \ 458f7b951a8SRobert Watson } \ 459f7b951a8SRobert Watson } \ 460f7b951a8SRobert Watson } while (0) 461f7b951a8SRobert Watson 462f7b951a8SRobert Watson #define MAC_INTERNALIZE(type, label, instring) do { \ 463f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 464f7b951a8SRobert Watson int claimed; \ 465f7b951a8SRobert Watson \ 466f7b951a8SRobert Watson error = 0; \ 467f7b951a8SRobert Watson element = instring; \ 468f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 469f7b951a8SRobert Watson element_data = element_name; \ 470f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 471f7b951a8SRobert Watson if (element_data == NULL) { \ 472f7b951a8SRobert Watson error = EINVAL; \ 473f7b951a8SRobert Watson break; \ 474f7b951a8SRobert Watson } \ 475f7b951a8SRobert Watson claimed = 0; \ 476f7b951a8SRobert Watson MAC_CHECK(internalize_ ## type, label, element_name, \ 477f7b951a8SRobert Watson element_data, &claimed); \ 478f7b951a8SRobert Watson if (error) \ 479f7b951a8SRobert Watson break; \ 480f7b951a8SRobert Watson if (claimed != 1) { \ 481f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 482f7b951a8SRobert Watson error = EINVAL; \ 483f7b951a8SRobert Watson break; \ 484f7b951a8SRobert Watson } \ 485f7b951a8SRobert Watson } \ 486f7b951a8SRobert Watson } while (0) 487f7b951a8SRobert Watson 48895fab37eSRobert Watson /* 48995fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 49095fab37eSRobert Watson * module list and invoking that operation for each policy. 49195fab37eSRobert Watson */ 49295fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 49395fab37eSRobert Watson struct mac_policy_conf *mpc; \ 49441a17fe3SRobert Watson int entrycount; \ 49595fab37eSRobert Watson \ 49641a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \ 49741a17fe3SRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 49841a17fe3SRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 49941a17fe3SRobert Watson } \ 50041a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \ 50195fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 50295fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 50395fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 50495fab37eSRobert Watson } \ 50541a17fe3SRobert Watson mac_policy_list_unbusy(); \ 50641a17fe3SRobert Watson } \ 50795fab37eSRobert Watson } while (0) 50895fab37eSRobert Watson 50995fab37eSRobert Watson /* 51095fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 51195fab37eSRobert Watson */ 51295fab37eSRobert Watson static void 51395fab37eSRobert Watson mac_init(void) 51495fab37eSRobert Watson { 51595fab37eSRobert Watson 51641a17fe3SRobert Watson LIST_INIT(&mac_static_policy_list); 51795fab37eSRobert Watson LIST_INIT(&mac_policy_list); 51841a17fe3SRobert Watson 51941a17fe3SRobert Watson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 52041a17fe3SRobert Watson cv_init(&mac_policy_cv, "mac_policy_cv"); 52195fab37eSRobert Watson } 52295fab37eSRobert Watson 52395fab37eSRobert Watson /* 52495fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 52595fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 52695fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 52795fab37eSRobert Watson */ 52895fab37eSRobert Watson static void 52995fab37eSRobert Watson mac_late_init(void) 53095fab37eSRobert Watson { 53195fab37eSRobert Watson 53295fab37eSRobert Watson mac_late = 1; 53395fab37eSRobert Watson } 53495fab37eSRobert Watson 53595fab37eSRobert Watson /* 536225bff6fSRobert Watson * After the policy list has changed, walk the list to update any global 537225bff6fSRobert Watson * flags. 538225bff6fSRobert Watson */ 539225bff6fSRobert Watson static void 540225bff6fSRobert Watson mac_policy_updateflags(void) 541225bff6fSRobert Watson { 542225bff6fSRobert Watson struct mac_policy_conf *tmpc; 543225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 544225bff6fSRobert Watson int labelmbufs; 545225bff6fSRobert Watson #endif 546225bff6fSRobert Watson 54741a17fe3SRobert Watson mac_policy_assert_exclusive(); 548225bff6fSRobert Watson 549225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 550225bff6fSRobert Watson labelmbufs = 0; 551225bff6fSRobert Watson #endif 55241a17fe3SRobert Watson 55341a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 55441a17fe3SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 55541a17fe3SRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 55641a17fe3SRobert Watson labelmbufs++; 55741a17fe3SRobert Watson #endif 55841a17fe3SRobert Watson } 559225bff6fSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 560225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 561225bff6fSRobert Watson if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 562225bff6fSRobert Watson labelmbufs++; 563225bff6fSRobert Watson #endif 564225bff6fSRobert Watson } 565225bff6fSRobert Watson 566225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 567225bff6fSRobert Watson mac_labelmbufs = (labelmbufs != 0); 568225bff6fSRobert Watson #endif 569225bff6fSRobert Watson } 570225bff6fSRobert Watson 571225bff6fSRobert Watson /* 57295fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 57395fab37eSRobert Watson */ 57495fab37eSRobert Watson int 57595fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 57695fab37eSRobert Watson { 57795fab37eSRobert Watson struct mac_policy_conf *mpc; 57895fab37eSRobert Watson int error; 57995fab37eSRobert Watson 58095fab37eSRobert Watson error = 0; 58195fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 58295fab37eSRobert Watson 58395fab37eSRobert Watson switch (type) { 58495fab37eSRobert Watson case MOD_LOAD: 58595fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 58695fab37eSRobert Watson mac_late) { 58795fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 58895fab37eSRobert Watson "after booting\n", mpc->mpc_name); 58995fab37eSRobert Watson error = EBUSY; 59095fab37eSRobert Watson break; 59195fab37eSRobert Watson } 59295fab37eSRobert Watson error = mac_policy_register(mpc); 59395fab37eSRobert Watson break; 59495fab37eSRobert Watson case MOD_UNLOAD: 59595fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 59695fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 59795fab37eSRobert Watson != 0) 59895fab37eSRobert Watson error = mac_policy_unregister(mpc); 59995fab37eSRobert Watson else 60095fab37eSRobert Watson error = 0; 60195fab37eSRobert Watson break; 60295fab37eSRobert Watson default: 60395fab37eSRobert Watson break; 60495fab37eSRobert Watson } 60595fab37eSRobert Watson 60695fab37eSRobert Watson return (error); 60795fab37eSRobert Watson } 60895fab37eSRobert Watson 60995fab37eSRobert Watson static int 61095fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 61195fab37eSRobert Watson { 61295fab37eSRobert Watson struct mac_policy_conf *tmpc; 61341a17fe3SRobert Watson int error, slot, static_entry; 61495fab37eSRobert Watson 61541a17fe3SRobert Watson error = 0; 61641a17fe3SRobert Watson 61741a17fe3SRobert Watson /* 61841a17fe3SRobert Watson * We don't technically need exclusive access while !mac_late, 61941a17fe3SRobert Watson * but hold it for assertion consistency. 62041a17fe3SRobert Watson */ 62141a17fe3SRobert Watson mac_policy_grab_exclusive(); 62241a17fe3SRobert Watson 62341a17fe3SRobert Watson /* 62441a17fe3SRobert Watson * If the module can potentially be unloaded, or we're loading 62541a17fe3SRobert Watson * late, we have to stick it in the non-static list and pay 62641a17fe3SRobert Watson * an extra performance overhead. Otherwise, we can pay a 62741a17fe3SRobert Watson * light locking cost and stick it in the static list. 62841a17fe3SRobert Watson */ 62941a17fe3SRobert Watson static_entry = (!mac_late && 63041a17fe3SRobert Watson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 63141a17fe3SRobert Watson 63241a17fe3SRobert Watson if (static_entry) { 63341a17fe3SRobert Watson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 63441a17fe3SRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 63541a17fe3SRobert Watson error = EEXIST; 63641a17fe3SRobert Watson goto out; 63741a17fe3SRobert Watson } 63841a17fe3SRobert Watson } 63941a17fe3SRobert Watson } else { 64095fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 64195fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 64241a17fe3SRobert Watson error = EEXIST; 64341a17fe3SRobert Watson goto out; 64441a17fe3SRobert Watson } 64595fab37eSRobert Watson } 64695fab37eSRobert Watson } 64795fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 648b2aef571SRobert Watson slot = ffs(mac_slot_offsets_free); 64995fab37eSRobert Watson if (slot == 0) { 65041a17fe3SRobert Watson error = ENOMEM; 65141a17fe3SRobert Watson goto out; 65295fab37eSRobert Watson } 65395fab37eSRobert Watson slot--; 654b2aef571SRobert Watson mac_slot_offsets_free &= ~(1 << slot); 65595fab37eSRobert Watson *mpc->mpc_field_off = slot; 65695fab37eSRobert Watson } 65795fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 65841a17fe3SRobert Watson 65941a17fe3SRobert Watson /* 66041a17fe3SRobert Watson * If we're loading a MAC module after the framework has 66141a17fe3SRobert Watson * initialized, it has to go into the dynamic list. If 66241a17fe3SRobert Watson * we're loading it before we've finished initializing, 66341a17fe3SRobert Watson * it can go into the static list with weaker locker 66441a17fe3SRobert Watson * requirements. 66541a17fe3SRobert Watson */ 66641a17fe3SRobert Watson if (static_entry) 66741a17fe3SRobert Watson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 66841a17fe3SRobert Watson else 66995fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 67095fab37eSRobert Watson 67195fab37eSRobert Watson /* Per-policy initialization. */ 67295fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 67395fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 674225bff6fSRobert Watson mac_policy_updateflags(); 67595fab37eSRobert Watson 67695fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 67795fab37eSRobert Watson mpc->mpc_name); 67895fab37eSRobert Watson 67941a17fe3SRobert Watson out: 68041a17fe3SRobert Watson mac_policy_release_exclusive(); 68141a17fe3SRobert Watson return (error); 68295fab37eSRobert Watson } 68395fab37eSRobert Watson 68495fab37eSRobert Watson static int 68595fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 68695fab37eSRobert Watson { 68795fab37eSRobert Watson 688ea599aa0SRobert Watson /* 689ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 690ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 691ea599aa0SRobert Watson * silently succeed. 692ea599aa0SRobert Watson */ 69341a17fe3SRobert Watson mac_policy_grab_exclusive(); 694ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 69541a17fe3SRobert Watson mac_policy_release_exclusive(); 696ea599aa0SRobert Watson return (0); 697ea599aa0SRobert Watson } 69895fab37eSRobert Watson #if 0 69995fab37eSRobert Watson /* 70095fab37eSRobert Watson * Don't allow unloading modules with private data. 70195fab37eSRobert Watson */ 702ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 703ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 70495fab37eSRobert Watson return (EBUSY); 705ea599aa0SRobert Watson } 70695fab37eSRobert Watson #endif 707ea599aa0SRobert Watson /* 708ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 709ea599aa0SRobert Watson * by its own definition. 710ea599aa0SRobert Watson */ 711ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 71241a17fe3SRobert Watson mac_policy_release_exclusive(); 71395fab37eSRobert Watson return (EBUSY); 714ea599aa0SRobert Watson } 71595fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 71695fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 71795fab37eSRobert Watson 71895fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 7199aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 720225bff6fSRobert Watson mac_policy_updateflags(); 72141a17fe3SRobert Watson 72241a17fe3SRobert Watson mac_policy_release_exclusive(); 723a96acd1aSRobert Watson 72495fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 72595fab37eSRobert Watson mpc->mpc_name); 72695fab37eSRobert Watson 72795fab37eSRobert Watson return (0); 72895fab37eSRobert Watson } 72995fab37eSRobert Watson 73095fab37eSRobert Watson /* 73195fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 73295fab37eSRobert Watson * value with the higher precedence. 73395fab37eSRobert Watson */ 73495fab37eSRobert Watson static int 73595fab37eSRobert Watson error_select(int error1, int error2) 73695fab37eSRobert Watson { 73795fab37eSRobert Watson 73895fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 73995fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 74095fab37eSRobert Watson return (EDEADLK); 74195fab37eSRobert Watson 74295fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 74395fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 74495fab37eSRobert Watson return (EINVAL); 74595fab37eSRobert Watson 74695fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 74795fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 74895fab37eSRobert Watson return (ESRCH); 74995fab37eSRobert Watson 75095fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 75195fab37eSRobert Watson return (ENOENT); 75295fab37eSRobert Watson 75395fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 75495fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 75595fab37eSRobert Watson return (EACCES); 75695fab37eSRobert Watson 75795fab37eSRobert Watson /* Precedence goes to privilege. */ 75895fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 75995fab37eSRobert Watson return (EPERM); 76095fab37eSRobert Watson 76195fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 76295fab37eSRobert Watson if (error1 != 0) 76395fab37eSRobert Watson return (error1); 76495fab37eSRobert Watson return (error2); 76595fab37eSRobert Watson } 76695fab37eSRobert Watson 76710eeb10cSRobert Watson static struct label * 76810eeb10cSRobert Watson mbuf_to_label(struct mbuf *mbuf) 76910eeb10cSRobert Watson { 770225bff6fSRobert Watson struct m_tag *tag; 77110eeb10cSRobert Watson struct label *label; 77210eeb10cSRobert Watson 773225bff6fSRobert Watson tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL); 774225bff6fSRobert Watson label = (struct label *)(tag+1); 77510eeb10cSRobert Watson 77610eeb10cSRobert Watson return (label); 77710eeb10cSRobert Watson } 77810eeb10cSRobert Watson 77908bcdc58SRobert Watson static void 78008bcdc58SRobert Watson mac_init_label(struct label *label) 78108bcdc58SRobert Watson { 78208bcdc58SRobert Watson 78308bcdc58SRobert Watson bzero(label, sizeof(*label)); 78408bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 78508bcdc58SRobert Watson } 78608bcdc58SRobert Watson 78708bcdc58SRobert Watson static void 78808bcdc58SRobert Watson mac_destroy_label(struct label *label) 78908bcdc58SRobert Watson { 79008bcdc58SRobert Watson 79108bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 79208bcdc58SRobert Watson ("destroying uninitialized label")); 79308bcdc58SRobert Watson 79408bcdc58SRobert Watson bzero(label, sizeof(*label)); 79508bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 79608bcdc58SRobert Watson } 79708bcdc58SRobert Watson 79808bcdc58SRobert Watson void 79987807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 80008bcdc58SRobert Watson { 80108bcdc58SRobert Watson 80287807196SRobert Watson mac_init_label(&bpf_d->bd_label); 80387807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 80408bcdc58SRobert Watson #ifdef MAC_DEBUG 80587807196SRobert Watson atomic_add_int(&nmacbpfdescs, 1); 80608bcdc58SRobert Watson #endif 80708bcdc58SRobert Watson } 80808bcdc58SRobert Watson 809f7b951a8SRobert Watson static void 810f7b951a8SRobert Watson mac_init_cred_label(struct label *label) 81108bcdc58SRobert Watson { 81208bcdc58SRobert Watson 813f7b951a8SRobert Watson mac_init_label(label); 814f7b951a8SRobert Watson MAC_PERFORM(init_cred_label, label); 81508bcdc58SRobert Watson #ifdef MAC_DEBUG 81608bcdc58SRobert Watson atomic_add_int(&nmaccreds, 1); 81708bcdc58SRobert Watson #endif 81808bcdc58SRobert Watson } 81908bcdc58SRobert Watson 82008bcdc58SRobert Watson void 821f7b951a8SRobert Watson mac_init_cred(struct ucred *cred) 822f7b951a8SRobert Watson { 823f7b951a8SRobert Watson 824f7b951a8SRobert Watson mac_init_cred_label(&cred->cr_label); 825f7b951a8SRobert Watson } 826f7b951a8SRobert Watson 827f7b951a8SRobert Watson void 82887807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 82908bcdc58SRobert Watson { 83008bcdc58SRobert Watson 83187807196SRobert Watson mac_init_label(&de->de_label); 83287807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 83308bcdc58SRobert Watson #ifdef MAC_DEBUG 83487807196SRobert Watson atomic_add_int(&nmacdevfsdirents, 1); 83508bcdc58SRobert Watson #endif 83608bcdc58SRobert Watson } 83708bcdc58SRobert Watson 838f7b951a8SRobert Watson static void 839f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label) 840f7b951a8SRobert Watson { 841f7b951a8SRobert Watson 842f7b951a8SRobert Watson mac_init_label(label); 843f7b951a8SRobert Watson MAC_PERFORM(init_ifnet_label, label); 844f7b951a8SRobert Watson #ifdef MAC_DEBUG 845f7b951a8SRobert Watson atomic_add_int(&nmacifnets, 1); 846f7b951a8SRobert Watson #endif 847f7b951a8SRobert Watson } 848f7b951a8SRobert Watson 84908bcdc58SRobert Watson void 85008bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 85108bcdc58SRobert Watson { 85208bcdc58SRobert Watson 853f7b951a8SRobert Watson mac_init_ifnet_label(&ifp->if_label); 85408bcdc58SRobert Watson } 85508bcdc58SRobert Watson 8565e7ce478SRobert Watson int 8575e7ce478SRobert Watson mac_init_ipq(struct ipq *ipq, int flag) 85808bcdc58SRobert Watson { 8595e7ce478SRobert Watson int error; 86008bcdc58SRobert Watson 86108bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 8625e7ce478SRobert Watson 8635e7ce478SRobert Watson MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag); 8645e7ce478SRobert Watson if (error) { 8655e7ce478SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 8665e7ce478SRobert Watson mac_destroy_label(&ipq->ipq_label); 8675e7ce478SRobert Watson } 86808bcdc58SRobert Watson #ifdef MAC_DEBUG 8695e7ce478SRobert Watson if (error == 0) 87008bcdc58SRobert Watson atomic_add_int(&nmacipqs, 1); 87108bcdc58SRobert Watson #endif 8725e7ce478SRobert Watson return (error); 87308bcdc58SRobert Watson } 87408bcdc58SRobert Watson 87587807196SRobert Watson int 876225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag) 87708bcdc58SRobert Watson { 878225bff6fSRobert Watson struct label *label; 8796d1a6a9aSRobert Watson int error; 88056c15412SRobert Watson 881225bff6fSRobert Watson label = (struct label *) (tag + 1); 882225bff6fSRobert Watson mac_init_label(label); 88308bcdc58SRobert Watson 8846d1a6a9aSRobert Watson MAC_CHECK(init_mbuf_label, label, flag); 88556c15412SRobert Watson if (error) { 886225bff6fSRobert Watson MAC_PERFORM(destroy_mbuf_label, label); 887225bff6fSRobert Watson mac_destroy_label(label); 88856c15412SRobert Watson } 88908bcdc58SRobert Watson #ifdef MAC_DEBUG 89056c15412SRobert Watson if (error == 0) 89187807196SRobert Watson atomic_add_int(&nmacmbufs, 1); 89208bcdc58SRobert Watson #endif 89356c15412SRobert Watson return (error); 89408bcdc58SRobert Watson } 89508bcdc58SRobert Watson 896225bff6fSRobert Watson int 897225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 898225bff6fSRobert Watson { 899225bff6fSRobert Watson struct m_tag *tag; 900225bff6fSRobert Watson int error; 901225bff6fSRobert Watson 902225bff6fSRobert Watson M_ASSERTPKTHDR(m); 903225bff6fSRobert Watson 904225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 905225bff6fSRobert Watson /* 906225bff6fSRobert Watson * Don't reserve space for labels on mbufs unless we have a policy 907225bff6fSRobert Watson * that uses the labels. 908225bff6fSRobert Watson */ 909225bff6fSRobert Watson if (mac_labelmbufs) { 910225bff6fSRobert Watson #endif 911225bff6fSRobert Watson tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label), 912225bff6fSRobert Watson flag); 913225bff6fSRobert Watson if (tag == NULL) 914225bff6fSRobert Watson return (ENOMEM); 915225bff6fSRobert Watson error = mac_init_mbuf_tag(tag, flag); 916225bff6fSRobert Watson if (error) { 917225bff6fSRobert Watson m_tag_free(tag); 918225bff6fSRobert Watson return (error); 919225bff6fSRobert Watson } 920225bff6fSRobert Watson m_tag_prepend(m, tag); 921225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF 922225bff6fSRobert Watson } 923225bff6fSRobert Watson #endif 924225bff6fSRobert Watson return (0); 925225bff6fSRobert Watson } 926225bff6fSRobert Watson 92708bcdc58SRobert Watson void 92887807196SRobert Watson mac_init_mount(struct mount *mp) 92908bcdc58SRobert Watson { 93008bcdc58SRobert Watson 93187807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 93287807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 93387807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 93487807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 93508bcdc58SRobert Watson #ifdef MAC_DEBUG 93687807196SRobert Watson atomic_add_int(&nmacmounts, 1); 93708bcdc58SRobert Watson #endif 93808bcdc58SRobert Watson } 93908bcdc58SRobert Watson 940f7b951a8SRobert Watson static void 941f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 942f7b951a8SRobert Watson { 943f7b951a8SRobert Watson 944f7b951a8SRobert Watson mac_init_label(label); 945f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 946f7b951a8SRobert Watson #ifdef MAC_DEBUG 947f7b951a8SRobert Watson atomic_add_int(&nmacpipes, 1); 948f7b951a8SRobert Watson #endif 949f7b951a8SRobert Watson } 950f7b951a8SRobert Watson 95108bcdc58SRobert Watson void 95208bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 95308bcdc58SRobert Watson { 95408bcdc58SRobert Watson struct label *label; 95508bcdc58SRobert Watson 956a163d034SWarner Losh label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 95708bcdc58SRobert Watson pipe->pipe_label = label; 95808bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 959f7b951a8SRobert Watson mac_init_pipe_label(label); 96008bcdc58SRobert Watson } 96108bcdc58SRobert Watson 9622555374cSRobert Watson void 9632555374cSRobert Watson mac_init_proc(struct proc *p) 9642555374cSRobert Watson { 9652555374cSRobert Watson 9662555374cSRobert Watson mac_init_label(&p->p_label); 9672555374cSRobert Watson MAC_PERFORM(init_proc_label, &p->p_label); 9682555374cSRobert Watson #ifdef MAC_DEBUG 9692555374cSRobert Watson atomic_add_int(&nmacprocs, 1); 9702555374cSRobert Watson #endif 9712555374cSRobert Watson } 9722555374cSRobert Watson 97383985c26SRobert Watson static int 97483985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 97508bcdc58SRobert Watson { 97683985c26SRobert Watson int error; 97708bcdc58SRobert Watson 97883985c26SRobert Watson mac_init_label(label); 97983985c26SRobert Watson 98083985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 98183985c26SRobert Watson if (error) { 98283985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 98383985c26SRobert Watson mac_destroy_label(label); 98483985c26SRobert Watson } 98583985c26SRobert Watson 98608bcdc58SRobert Watson #ifdef MAC_DEBUG 98783985c26SRobert Watson if (error == 0) 98887807196SRobert Watson atomic_add_int(&nmacsockets, 1); 98987807196SRobert Watson #endif 99083985c26SRobert Watson 99183985c26SRobert Watson return (error); 99283985c26SRobert Watson } 99383985c26SRobert Watson 99483985c26SRobert Watson static int 99583985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 99683985c26SRobert Watson { 99783985c26SRobert Watson int error; 99883985c26SRobert Watson 99983985c26SRobert Watson mac_init_label(label); 100083985c26SRobert Watson 100183985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 100283985c26SRobert Watson if (error) { 100383985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 100483985c26SRobert Watson mac_destroy_label(label); 100583985c26SRobert Watson } 100683985c26SRobert Watson 100783985c26SRobert Watson return (error); 100883985c26SRobert Watson } 100983985c26SRobert Watson 101083985c26SRobert Watson int 101183985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 101283985c26SRobert Watson { 101383985c26SRobert Watson int error; 101483985c26SRobert Watson 101583985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 101683985c26SRobert Watson if (error) 101783985c26SRobert Watson return (error); 101883985c26SRobert Watson 101983985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 102083985c26SRobert Watson if (error) 102183985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 102283985c26SRobert Watson 102383985c26SRobert Watson return (error); 102487807196SRobert Watson } 102587807196SRobert Watson 1026763bbd2fSRobert Watson void 1027f7b951a8SRobert Watson mac_init_vnode_label(struct label *label) 102887807196SRobert Watson { 102987807196SRobert Watson 103087807196SRobert Watson mac_init_label(label); 1031f7b951a8SRobert Watson MAC_PERFORM(init_vnode_label, label); 103287807196SRobert Watson #ifdef MAC_DEBUG 1033f7b951a8SRobert Watson atomic_add_int(&nmacvnodes, 1); 103408bcdc58SRobert Watson #endif 103508bcdc58SRobert Watson } 103608bcdc58SRobert Watson 103708bcdc58SRobert Watson void 103887807196SRobert Watson mac_init_vnode(struct vnode *vp) 103908bcdc58SRobert Watson { 104008bcdc58SRobert Watson 1041f7b951a8SRobert Watson mac_init_vnode_label(&vp->v_label); 104208bcdc58SRobert Watson } 104308bcdc58SRobert Watson 104408bcdc58SRobert Watson void 104508bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 104608bcdc58SRobert Watson { 104708bcdc58SRobert Watson 104808bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 104908bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 105008bcdc58SRobert Watson #ifdef MAC_DEBUG 105108bcdc58SRobert Watson atomic_subtract_int(&nmacbpfdescs, 1); 105208bcdc58SRobert Watson #endif 105308bcdc58SRobert Watson } 105408bcdc58SRobert Watson 1055f7b951a8SRobert Watson static void 1056f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label) 105708bcdc58SRobert Watson { 105808bcdc58SRobert Watson 1059f7b951a8SRobert Watson MAC_PERFORM(destroy_cred_label, label); 1060f7b951a8SRobert Watson mac_destroy_label(label); 106108bcdc58SRobert Watson #ifdef MAC_DEBUG 106287807196SRobert Watson atomic_subtract_int(&nmaccreds, 1); 106387807196SRobert Watson #endif 106487807196SRobert Watson } 106587807196SRobert Watson 106687807196SRobert Watson void 1067f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred) 1068f7b951a8SRobert Watson { 1069f7b951a8SRobert Watson 1070f7b951a8SRobert Watson mac_destroy_cred_label(&cred->cr_label); 1071f7b951a8SRobert Watson } 1072f7b951a8SRobert Watson 1073f7b951a8SRobert Watson void 107487807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 107587807196SRobert Watson { 107687807196SRobert Watson 107787807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 107887807196SRobert Watson mac_destroy_label(&de->de_label); 107987807196SRobert Watson #ifdef MAC_DEBUG 108087807196SRobert Watson atomic_subtract_int(&nmacdevfsdirents, 1); 108187807196SRobert Watson #endif 108287807196SRobert Watson } 108387807196SRobert Watson 1084f7b951a8SRobert Watson static void 1085f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label) 1086f7b951a8SRobert Watson { 1087f7b951a8SRobert Watson 1088f7b951a8SRobert Watson MAC_PERFORM(destroy_ifnet_label, label); 1089f7b951a8SRobert Watson mac_destroy_label(label); 1090f7b951a8SRobert Watson #ifdef MAC_DEBUG 1091f7b951a8SRobert Watson atomic_subtract_int(&nmacifnets, 1); 1092f7b951a8SRobert Watson #endif 1093f7b951a8SRobert Watson } 1094f7b951a8SRobert Watson 109587807196SRobert Watson void 109687807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 109787807196SRobert Watson { 109887807196SRobert Watson 1099f7b951a8SRobert Watson mac_destroy_ifnet_label(&ifp->if_label); 110087807196SRobert Watson } 110187807196SRobert Watson 110287807196SRobert Watson void 110387807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 110487807196SRobert Watson { 110587807196SRobert Watson 110687807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 110787807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 110887807196SRobert Watson #ifdef MAC_DEBUG 110987807196SRobert Watson atomic_subtract_int(&nmacipqs, 1); 111087807196SRobert Watson #endif 111187807196SRobert Watson } 111287807196SRobert Watson 111387807196SRobert Watson void 1114225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag) 111587807196SRobert Watson { 1116225bff6fSRobert Watson struct label *label; 111787807196SRobert Watson 1118225bff6fSRobert Watson label = (struct label *)(tag+1); 1119225bff6fSRobert Watson 1120225bff6fSRobert Watson MAC_PERFORM(destroy_mbuf_label, label); 1121225bff6fSRobert Watson mac_destroy_label(label); 112287807196SRobert Watson #ifdef MAC_DEBUG 112387807196SRobert Watson atomic_subtract_int(&nmacmbufs, 1); 112408bcdc58SRobert Watson #endif 112508bcdc58SRobert Watson } 112608bcdc58SRobert Watson 112708bcdc58SRobert Watson void 112808bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 112908bcdc58SRobert Watson { 113008bcdc58SRobert Watson 113108bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 113208bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 113308bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 113408bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 113508bcdc58SRobert Watson #ifdef MAC_DEBUG 113608bcdc58SRobert Watson atomic_subtract_int(&nmacmounts, 1); 113708bcdc58SRobert Watson #endif 113808bcdc58SRobert Watson } 113908bcdc58SRobert Watson 1140f7b951a8SRobert Watson static void 1141f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 1142f7b951a8SRobert Watson { 1143f7b951a8SRobert Watson 1144f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 1145f7b951a8SRobert Watson mac_destroy_label(label); 1146f7b951a8SRobert Watson #ifdef MAC_DEBUG 1147f7b951a8SRobert Watson atomic_subtract_int(&nmacpipes, 1); 1148f7b951a8SRobert Watson #endif 1149f7b951a8SRobert Watson } 1150f7b951a8SRobert Watson 115187807196SRobert Watson void 115287807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 115308bcdc58SRobert Watson { 115408bcdc58SRobert Watson 1155f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 115687807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 115787807196SRobert Watson } 115887807196SRobert Watson 11592555374cSRobert Watson void 11602555374cSRobert Watson mac_destroy_proc(struct proc *p) 11612555374cSRobert Watson { 11622555374cSRobert Watson 11632555374cSRobert Watson MAC_PERFORM(destroy_proc_label, &p->p_label); 11642555374cSRobert Watson mac_destroy_label(&p->p_label); 11652555374cSRobert Watson #ifdef MAC_DEBUG 11662555374cSRobert Watson atomic_subtract_int(&nmacprocs, 1); 11672555374cSRobert Watson #endif 11682555374cSRobert Watson } 11692555374cSRobert Watson 117083985c26SRobert Watson static void 117183985c26SRobert Watson mac_destroy_socket_label(struct label *label) 117283985c26SRobert Watson { 117383985c26SRobert Watson 117483985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 117583985c26SRobert Watson mac_destroy_label(label); 117683985c26SRobert Watson #ifdef MAC_DEBUG 117783985c26SRobert Watson atomic_subtract_int(&nmacsockets, 1); 117883985c26SRobert Watson #endif 117983985c26SRobert Watson } 118083985c26SRobert Watson 118183985c26SRobert Watson static void 118283985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 118383985c26SRobert Watson { 118483985c26SRobert Watson 118583985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 118683985c26SRobert Watson mac_destroy_label(label); 118783985c26SRobert Watson } 118883985c26SRobert Watson 118987807196SRobert Watson void 119087807196SRobert Watson mac_destroy_socket(struct socket *socket) 119187807196SRobert Watson { 119287807196SRobert Watson 119383985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 119483985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 119508bcdc58SRobert Watson } 119608bcdc58SRobert Watson 1197763bbd2fSRobert Watson void 1198f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label) 119908bcdc58SRobert Watson { 120008bcdc58SRobert Watson 1201f7b951a8SRobert Watson MAC_PERFORM(destroy_vnode_label, label); 120208bcdc58SRobert Watson mac_destroy_label(label); 120308bcdc58SRobert Watson #ifdef MAC_DEBUG 1204f7b951a8SRobert Watson atomic_subtract_int(&nmacvnodes, 1); 120508bcdc58SRobert Watson #endif 120608bcdc58SRobert Watson } 120708bcdc58SRobert Watson 120808bcdc58SRobert Watson void 120908bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 121008bcdc58SRobert Watson { 121108bcdc58SRobert Watson 1212f7b951a8SRobert Watson mac_destroy_vnode_label(&vp->v_label); 1213f7b951a8SRobert Watson } 1214f7b951a8SRobert Watson 1215225bff6fSRobert Watson void 1216225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest) 1217225bff6fSRobert Watson { 1218225bff6fSRobert Watson struct label *src_label, *dest_label; 1219225bff6fSRobert Watson 1220225bff6fSRobert Watson src_label = (struct label *)(src+1); 1221225bff6fSRobert Watson dest_label = (struct label *)(dest+1); 1222225bff6fSRobert Watson 1223225bff6fSRobert Watson /* 1224225bff6fSRobert Watson * mac_init_mbuf_tag() is called on the target tag in 1225225bff6fSRobert Watson * m_tag_copy(), so we don't need to call it here. 1226225bff6fSRobert Watson */ 1227225bff6fSRobert Watson MAC_PERFORM(copy_mbuf_label, src_label, dest_label); 1228225bff6fSRobert Watson } 1229225bff6fSRobert Watson 1230f7b951a8SRobert Watson static void 1231f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 1232f7b951a8SRobert Watson { 1233f7b951a8SRobert Watson 1234f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 1235f7b951a8SRobert Watson } 1236f7b951a8SRobert Watson 1237763bbd2fSRobert Watson void 1238f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest) 1239f7b951a8SRobert Watson { 1240f7b951a8SRobert Watson 1241f7b951a8SRobert Watson MAC_PERFORM(copy_vnode_label, src, dest); 124208bcdc58SRobert Watson } 124308bcdc58SRobert Watson 124469bbb5b1SRobert Watson static int 1245f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 1246f7b951a8SRobert Watson { 1247f7b951a8SRobert Watson 1248f7b951a8SRobert Watson if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1249f7b951a8SRobert Watson return (EINVAL); 1250f7b951a8SRobert Watson 1251f7b951a8SRobert Watson return (0); 1252f7b951a8SRobert Watson } 1253f7b951a8SRobert Watson 1254f7b951a8SRobert Watson static int 1255f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements, 1256f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 125769bbb5b1SRobert Watson { 125869bbb5b1SRobert Watson int error; 125969bbb5b1SRobert Watson 1260f7b951a8SRobert Watson MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 126169bbb5b1SRobert Watson 126269bbb5b1SRobert Watson return (error); 126369bbb5b1SRobert Watson } 126469bbb5b1SRobert Watson 126569bbb5b1SRobert Watson static int 1266f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements, 1267f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 126869bbb5b1SRobert Watson { 126969bbb5b1SRobert Watson int error; 127069bbb5b1SRobert Watson 1271f7b951a8SRobert Watson MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1272f7b951a8SRobert Watson 1273f7b951a8SRobert Watson return (error); 1274f7b951a8SRobert Watson } 1275f7b951a8SRobert Watson 1276f7b951a8SRobert Watson static int 1277f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 1278f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1279f7b951a8SRobert Watson { 1280f7b951a8SRobert Watson int error; 1281f7b951a8SRobert Watson 1282f7b951a8SRobert Watson MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1283f7b951a8SRobert Watson 1284f7b951a8SRobert Watson return (error); 1285f7b951a8SRobert Watson } 1286f7b951a8SRobert Watson 1287f7b951a8SRobert Watson static int 1288f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 1289f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1290f7b951a8SRobert Watson { 1291f7b951a8SRobert Watson int error; 1292f7b951a8SRobert Watson 1293f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1294f7b951a8SRobert Watson 1295f7b951a8SRobert Watson return (error); 1296f7b951a8SRobert Watson } 1297f7b951a8SRobert Watson 1298f7b951a8SRobert Watson static int 1299f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 1300f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1301f7b951a8SRobert Watson { 1302f7b951a8SRobert Watson int error; 1303f7b951a8SRobert Watson 1304f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1305f7b951a8SRobert Watson 1306f7b951a8SRobert Watson return (error); 1307f7b951a8SRobert Watson } 1308f7b951a8SRobert Watson 1309f7b951a8SRobert Watson static int 1310f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements, 1311f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1312f7b951a8SRobert Watson { 1313f7b951a8SRobert Watson int error; 1314f7b951a8SRobert Watson 1315f7b951a8SRobert Watson MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1316f7b951a8SRobert Watson 1317f7b951a8SRobert Watson return (error); 1318f7b951a8SRobert Watson } 1319f7b951a8SRobert Watson 1320f7b951a8SRobert Watson static int 1321f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string) 1322f7b951a8SRobert Watson { 1323f7b951a8SRobert Watson int error; 1324f7b951a8SRobert Watson 1325f7b951a8SRobert Watson MAC_INTERNALIZE(cred_label, label, string); 1326f7b951a8SRobert Watson 1327f7b951a8SRobert Watson return (error); 1328f7b951a8SRobert Watson } 1329f7b951a8SRobert Watson 1330f7b951a8SRobert Watson static int 1331f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string) 1332f7b951a8SRobert Watson { 1333f7b951a8SRobert Watson int error; 1334f7b951a8SRobert Watson 1335f7b951a8SRobert Watson MAC_INTERNALIZE(ifnet_label, label, string); 1336f7b951a8SRobert Watson 1337f7b951a8SRobert Watson return (error); 1338f7b951a8SRobert Watson } 1339f7b951a8SRobert Watson 1340f7b951a8SRobert Watson static int 1341f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 1342f7b951a8SRobert Watson { 1343f7b951a8SRobert Watson int error; 1344f7b951a8SRobert Watson 1345f7b951a8SRobert Watson MAC_INTERNALIZE(pipe_label, label, string); 1346f7b951a8SRobert Watson 1347f7b951a8SRobert Watson return (error); 1348f7b951a8SRobert Watson } 1349f7b951a8SRobert Watson 1350f7b951a8SRobert Watson static int 1351f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string) 1352f7b951a8SRobert Watson { 1353f7b951a8SRobert Watson int error; 1354f7b951a8SRobert Watson 1355f7b951a8SRobert Watson MAC_INTERNALIZE(socket_label, label, string); 1356f7b951a8SRobert Watson 1357f7b951a8SRobert Watson return (error); 1358f7b951a8SRobert Watson } 1359f7b951a8SRobert Watson 1360f7b951a8SRobert Watson static int 1361f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string) 1362f7b951a8SRobert Watson { 1363f7b951a8SRobert Watson int error; 1364f7b951a8SRobert Watson 1365f7b951a8SRobert Watson MAC_INTERNALIZE(vnode_label, label, string); 136669bbb5b1SRobert Watson 136769bbb5b1SRobert Watson return (error); 136869bbb5b1SRobert Watson } 136969bbb5b1SRobert Watson 137069bbb5b1SRobert Watson /* 137169bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 137269bbb5b1SRobert Watson * kernel processes and threads are spawned. 137369bbb5b1SRobert Watson */ 137469bbb5b1SRobert Watson void 137569bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 137669bbb5b1SRobert Watson { 137769bbb5b1SRobert Watson 137869bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 137969bbb5b1SRobert Watson } 138069bbb5b1SRobert Watson 138169bbb5b1SRobert Watson /* 138269bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 138369bbb5b1SRobert Watson * userland processes and threads are spawned. 138469bbb5b1SRobert Watson */ 138569bbb5b1SRobert Watson void 138669bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 138769bbb5b1SRobert Watson { 138869bbb5b1SRobert Watson 138969bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 139069bbb5b1SRobert Watson } 139169bbb5b1SRobert Watson 139269bbb5b1SRobert Watson void 139369bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 139469bbb5b1SRobert Watson { 139569bbb5b1SRobert Watson 139669bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 139769bbb5b1SRobert Watson } 139869bbb5b1SRobert Watson 139969bbb5b1SRobert Watson /* 140069bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 140169bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 140269bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 140369bbb5b1SRobert Watson */ 140469bbb5b1SRobert Watson void 140569bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 140669bbb5b1SRobert Watson { 140769bbb5b1SRobert Watson 140869bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 140969bbb5b1SRobert Watson } 141069bbb5b1SRobert Watson 141195fab37eSRobert Watson void 1412990b4b2dSRobert Watson mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de, 1413990b4b2dSRobert Watson struct vnode *vp) 141495fab37eSRobert Watson { 141595fab37eSRobert Watson 1416990b4b2dSRobert Watson MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp, 1417990b4b2dSRobert Watson &vp->v_label); 141895fab37eSRobert Watson } 141995fab37eSRobert Watson 142095fab37eSRobert Watson void 1421763bbd2fSRobert Watson mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1422763bbd2fSRobert Watson struct vnode *vp) 142395fab37eSRobert Watson { 142495fab37eSRobert Watson 1425763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1426763bbd2fSRobert Watson &de->de_label, vp, &vp->v_label); 142795fab37eSRobert Watson } 142895fab37eSRobert Watson 1429763bbd2fSRobert Watson int 1430763bbd2fSRobert Watson mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 143195fab37eSRobert Watson { 143295fab37eSRobert Watson int error; 143395fab37eSRobert Watson 1434763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1435763bbd2fSRobert Watson 1436763bbd2fSRobert Watson MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1437763bbd2fSRobert Watson &vp->v_label); 143895fab37eSRobert Watson 143995fab37eSRobert Watson return (error); 144095fab37eSRobert Watson } 144195fab37eSRobert Watson 144295fab37eSRobert Watson void 1443763bbd2fSRobert Watson mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 144495fab37eSRobert Watson { 144595fab37eSRobert Watson 1446763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1447763bbd2fSRobert Watson &vp->v_label); 144895fab37eSRobert Watson } 144995fab37eSRobert Watson 145095fab37eSRobert Watson int 1451763bbd2fSRobert Watson mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1452763bbd2fSRobert Watson struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 145395fab37eSRobert Watson { 1454763bbd2fSRobert Watson int error; 145595fab37eSRobert Watson 1456763bbd2fSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1457763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 145895fab37eSRobert Watson 1459763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1460763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1461763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1462763bbd2fSRobert Watson if (ea_warn_once == 0) { 1463763bbd2fSRobert Watson printf("Warning: transactions not supported " 1464763bbd2fSRobert Watson "in EA write.\n"); 1465763bbd2fSRobert Watson ea_warn_once = 1; 1466763bbd2fSRobert Watson } 1467763bbd2fSRobert Watson } else if (error) 146895fab37eSRobert Watson return (error); 146995fab37eSRobert Watson 1470763bbd2fSRobert Watson MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1471763bbd2fSRobert Watson dvp, &dvp->v_label, vp, &vp->v_label, cnp); 147295fab37eSRobert Watson 1473763bbd2fSRobert Watson if (error) { 1474763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 147595fab37eSRobert Watson return (error); 147695fab37eSRobert Watson } 147795fab37eSRobert Watson 1478763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 147995fab37eSRobert Watson 1480763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1481763bbd2fSRobert Watson error = 0; /* XXX */ 148295fab37eSRobert Watson 148395fab37eSRobert Watson return (error); 148495fab37eSRobert Watson } 148595fab37eSRobert Watson 148695fab37eSRobert Watson static int 1487763bbd2fSRobert Watson mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1488763bbd2fSRobert Watson struct label *intlabel) 148995fab37eSRobert Watson { 149095fab37eSRobert Watson int error; 149195fab37eSRobert Watson 1492763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 149395fab37eSRobert Watson 1494763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1495763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1496763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1497763bbd2fSRobert Watson if (ea_warn_once == 0) { 1498763bbd2fSRobert Watson printf("Warning: transactions not supported " 1499763bbd2fSRobert Watson "in EA write.\n"); 1500763bbd2fSRobert Watson ea_warn_once = 1; 150195fab37eSRobert Watson } 1502763bbd2fSRobert Watson } else if (error) 150395fab37eSRobert Watson return (error); 150495fab37eSRobert Watson 1505763bbd2fSRobert Watson MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 150695fab37eSRobert Watson 1507763bbd2fSRobert Watson if (error) { 1508763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 150995fab37eSRobert Watson return (error); 151095fab37eSRobert Watson } 151195fab37eSRobert Watson 1512763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1513763bbd2fSRobert Watson 1514763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1515763bbd2fSRobert Watson error = 0; /* XXX */ 1516763bbd2fSRobert Watson 1517763bbd2fSRobert Watson return (error); 151895fab37eSRobert Watson } 151995fab37eSRobert Watson 1520670cb89bSRobert Watson int 1521670cb89bSRobert Watson mac_execve_enter(struct image_params *imgp, struct mac *mac_p, 1522670cb89bSRobert Watson struct label *execlabelstorage) 1523670cb89bSRobert Watson { 1524670cb89bSRobert Watson struct mac mac; 1525670cb89bSRobert Watson char *buffer; 1526670cb89bSRobert Watson int error; 1527670cb89bSRobert Watson 1528670cb89bSRobert Watson if (mac_p == NULL) 1529670cb89bSRobert Watson return (0); 1530670cb89bSRobert Watson 1531670cb89bSRobert Watson error = copyin(mac_p, &mac, sizeof(mac)); 1532670cb89bSRobert Watson if (error) 1533670cb89bSRobert Watson return (error); 1534670cb89bSRobert Watson 1535670cb89bSRobert Watson error = mac_check_structmac_consistent(&mac); 1536670cb89bSRobert Watson if (error) 1537670cb89bSRobert Watson return (error); 1538670cb89bSRobert Watson 1539a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1540670cb89bSRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1541670cb89bSRobert Watson if (error) { 1542670cb89bSRobert Watson free(buffer, M_MACTEMP); 1543670cb89bSRobert Watson return (error); 1544670cb89bSRobert Watson } 1545670cb89bSRobert Watson 1546670cb89bSRobert Watson mac_init_cred_label(execlabelstorage); 1547670cb89bSRobert Watson error = mac_internalize_cred_label(execlabelstorage, buffer); 1548670cb89bSRobert Watson free(buffer, M_MACTEMP); 1549670cb89bSRobert Watson if (error) { 1550670cb89bSRobert Watson mac_destroy_cred_label(execlabelstorage); 1551670cb89bSRobert Watson return (error); 1552670cb89bSRobert Watson } 1553670cb89bSRobert Watson imgp->execlabel = execlabelstorage; 1554670cb89bSRobert Watson return (0); 1555670cb89bSRobert Watson } 1556670cb89bSRobert Watson 155795fab37eSRobert Watson void 1558670cb89bSRobert Watson mac_execve_exit(struct image_params *imgp) 1559670cb89bSRobert Watson { 1560670cb89bSRobert Watson if (imgp->execlabel != NULL) 1561670cb89bSRobert Watson mac_destroy_cred_label(imgp->execlabel); 1562670cb89bSRobert Watson } 1563670cb89bSRobert Watson 1564670cb89bSRobert Watson void 1565670cb89bSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 1566670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 156795fab37eSRobert Watson { 156895fab37eSRobert Watson 156995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 157095fab37eSRobert Watson 15714443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 15724443e9ffSRobert Watson return; 15734443e9ffSRobert Watson 1574670cb89bSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 15759fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 157695fab37eSRobert Watson } 157795fab37eSRobert Watson 157895fab37eSRobert Watson int 1579670cb89bSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp, 1580670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 158195fab37eSRobert Watson { 1582763bbd2fSRobert Watson int result; 158395fab37eSRobert Watson 15844443e9ffSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 15854443e9ffSRobert Watson 15864443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 15874443e9ffSRobert Watson return (0); 15884443e9ffSRobert Watson 158995fab37eSRobert Watson result = 0; 1590670cb89bSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 15919fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 159295fab37eSRobert Watson 159395fab37eSRobert Watson return (result); 159495fab37eSRobert Watson } 159595fab37eSRobert Watson 159695fab37eSRobert Watson int 1597b914de36SRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 159895fab37eSRobert Watson { 159995fab37eSRobert Watson int error; 160095fab37eSRobert Watson 160195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 160295fab37eSRobert Watson 160395fab37eSRobert Watson if (!mac_enforce_fs) 160495fab37eSRobert Watson return (0); 160595fab37eSRobert Watson 1606b914de36SRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 160795fab37eSRobert Watson return (error); 160895fab37eSRobert Watson } 160995fab37eSRobert Watson 161095fab37eSRobert Watson int 161195fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 161295fab37eSRobert Watson { 161395fab37eSRobert Watson int error; 161495fab37eSRobert Watson 161595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 161695fab37eSRobert Watson 161795fab37eSRobert Watson if (!mac_enforce_fs) 161895fab37eSRobert Watson return (0); 161995fab37eSRobert Watson 162095fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 162195fab37eSRobert Watson return (error); 162295fab37eSRobert Watson } 162395fab37eSRobert Watson 162495fab37eSRobert Watson int 162595fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 162695fab37eSRobert Watson { 162795fab37eSRobert Watson int error; 162895fab37eSRobert Watson 162995fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 163095fab37eSRobert Watson 163195fab37eSRobert Watson if (!mac_enforce_fs) 163295fab37eSRobert Watson return (0); 163395fab37eSRobert Watson 163495fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 163595fab37eSRobert Watson return (error); 163695fab37eSRobert Watson } 163795fab37eSRobert Watson 163895fab37eSRobert Watson int 163995fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 164095fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 164195fab37eSRobert Watson { 164295fab37eSRobert Watson int error; 164395fab37eSRobert Watson 164495fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 164595fab37eSRobert Watson 164695fab37eSRobert Watson if (!mac_enforce_fs) 164795fab37eSRobert Watson return (0); 164895fab37eSRobert Watson 164995fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 165095fab37eSRobert Watson return (error); 165195fab37eSRobert Watson } 165295fab37eSRobert Watson 165395fab37eSRobert Watson int 165495fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 165595fab37eSRobert Watson struct componentname *cnp) 165695fab37eSRobert Watson { 165795fab37eSRobert Watson int error; 165895fab37eSRobert Watson 165995fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 166095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 166195fab37eSRobert Watson 166295fab37eSRobert Watson if (!mac_enforce_fs) 166395fab37eSRobert Watson return (0); 166495fab37eSRobert Watson 166595fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 166695fab37eSRobert Watson &vp->v_label, cnp); 166795fab37eSRobert Watson return (error); 166895fab37eSRobert Watson } 166995fab37eSRobert Watson 167095fab37eSRobert Watson int 167195fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 167295fab37eSRobert Watson acl_type_t type) 167395fab37eSRobert Watson { 167495fab37eSRobert Watson int error; 167595fab37eSRobert Watson 167695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 167795fab37eSRobert Watson 167895fab37eSRobert Watson if (!mac_enforce_fs) 167995fab37eSRobert Watson return (0); 168095fab37eSRobert Watson 168195fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 168295fab37eSRobert Watson return (error); 168395fab37eSRobert Watson } 168495fab37eSRobert Watson 168595fab37eSRobert Watson int 1686670cb89bSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1687670cb89bSRobert Watson struct image_params *imgp) 168895fab37eSRobert Watson { 168995fab37eSRobert Watson int error; 169095fab37eSRobert Watson 1691851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1692851704bbSRobert Watson 169395fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 169495fab37eSRobert Watson return (0); 169595fab37eSRobert Watson 16969fa3506eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 16979fa3506eSRobert Watson imgp->execlabel); 169895fab37eSRobert Watson 169995fab37eSRobert Watson return (error); 170095fab37eSRobert Watson } 170195fab37eSRobert Watson 170295fab37eSRobert Watson int 170395fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 170495fab37eSRobert Watson { 170595fab37eSRobert Watson int error; 170695fab37eSRobert Watson 170795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 170895fab37eSRobert Watson 170995fab37eSRobert Watson if (!mac_enforce_fs) 171095fab37eSRobert Watson return (0); 171195fab37eSRobert Watson 171295fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 171395fab37eSRobert Watson return (error); 171495fab37eSRobert Watson } 171595fab37eSRobert Watson 171695fab37eSRobert Watson int 171795fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 171895fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 171995fab37eSRobert Watson { 172095fab37eSRobert Watson int error; 172195fab37eSRobert Watson 172295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 172395fab37eSRobert Watson 172495fab37eSRobert Watson if (!mac_enforce_fs) 172595fab37eSRobert Watson return (0); 172695fab37eSRobert Watson 172795fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 172895fab37eSRobert Watson attrnamespace, name, uio); 172995fab37eSRobert Watson return (error); 173095fab37eSRobert Watson } 173195fab37eSRobert Watson 173295fab37eSRobert Watson int 17330a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 17340a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 17350a694196SRobert Watson { 17360a694196SRobert Watson int error; 17370a694196SRobert Watson 17380a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 17390a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 17400a694196SRobert Watson 17410a694196SRobert Watson if (!mac_enforce_fs) 17420a694196SRobert Watson return (0); 17430a694196SRobert Watson 17440a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 17450a694196SRobert Watson &vp->v_label, cnp); 17460a694196SRobert Watson return (error); 17470a694196SRobert Watson } 17480a694196SRobert Watson 17490a694196SRobert Watson int 175095fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 175195fab37eSRobert Watson struct componentname *cnp) 175295fab37eSRobert Watson { 175395fab37eSRobert Watson int error; 175495fab37eSRobert Watson 175595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 175695fab37eSRobert Watson 175795fab37eSRobert Watson if (!mac_enforce_fs) 175895fab37eSRobert Watson return (0); 175995fab37eSRobert Watson 176095fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 176195fab37eSRobert Watson return (error); 176295fab37eSRobert Watson } 176395fab37eSRobert Watson 1764e183f80eSRobert Watson int 1765e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 176695fab37eSRobert Watson { 1767e183f80eSRobert Watson int error; 176895fab37eSRobert Watson 1769e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1770ca7850c3SRobert Watson 1771e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1772e183f80eSRobert Watson return (0); 1773e183f80eSRobert Watson 1774e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1775e183f80eSRobert Watson return (error); 1776e183f80eSRobert Watson } 1777e183f80eSRobert Watson 1778e183f80eSRobert Watson void 1779e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1780e183f80eSRobert Watson { 1781e183f80eSRobert Watson int result = *prot; 1782e183f80eSRobert Watson 1783e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1784e183f80eSRobert Watson 1785e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1786e183f80eSRobert Watson return; 1787e183f80eSRobert Watson 1788e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1789e183f80eSRobert Watson &result); 1790e183f80eSRobert Watson 1791e183f80eSRobert Watson *prot = result; 1792e183f80eSRobert Watson } 1793e183f80eSRobert Watson 1794e183f80eSRobert Watson int 1795e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1796e183f80eSRobert Watson { 1797e183f80eSRobert Watson int error; 1798e183f80eSRobert Watson 1799e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1800e183f80eSRobert Watson 1801e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1802e183f80eSRobert Watson return (0); 1803e183f80eSRobert Watson 1804e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1805e183f80eSRobert Watson return (error); 180695fab37eSRobert Watson } 180795fab37eSRobert Watson 180895fab37eSRobert Watson int 1809b914de36SRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 181095fab37eSRobert Watson { 181195fab37eSRobert Watson int error; 181295fab37eSRobert Watson 181395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 181495fab37eSRobert Watson 181595fab37eSRobert Watson if (!mac_enforce_fs) 181695fab37eSRobert Watson return (0); 181795fab37eSRobert Watson 181895fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 181995fab37eSRobert Watson return (error); 182095fab37eSRobert Watson } 182195fab37eSRobert Watson 182295fab37eSRobert Watson int 1823177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1824177142e4SRobert Watson struct vnode *vp) 18257f724f8bSRobert Watson { 18267f724f8bSRobert Watson int error; 18277f724f8bSRobert Watson 18287f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 18297f724f8bSRobert Watson 18307f724f8bSRobert Watson if (!mac_enforce_fs) 18317f724f8bSRobert Watson return (0); 18327f724f8bSRobert Watson 1833177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1834177142e4SRobert Watson &vp->v_label); 18357f724f8bSRobert Watson 18367f724f8bSRobert Watson return (error); 18377f724f8bSRobert Watson } 18387f724f8bSRobert Watson 18397f724f8bSRobert Watson int 1840177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1841177142e4SRobert Watson struct vnode *vp) 18427f724f8bSRobert Watson { 18437f724f8bSRobert Watson int error; 18447f724f8bSRobert Watson 18457f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 18467f724f8bSRobert Watson 18477f724f8bSRobert Watson if (!mac_enforce_fs) 18487f724f8bSRobert Watson return (0); 18497f724f8bSRobert Watson 1850177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1851177142e4SRobert Watson &vp->v_label); 18527f724f8bSRobert Watson 18537f724f8bSRobert Watson return (error); 18547f724f8bSRobert Watson } 18557f724f8bSRobert Watson 18567f724f8bSRobert Watson int 185795fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 185895fab37eSRobert Watson { 185995fab37eSRobert Watson int error; 186095fab37eSRobert Watson 186195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 186295fab37eSRobert Watson 186395fab37eSRobert Watson if (!mac_enforce_fs) 186495fab37eSRobert Watson return (0); 186595fab37eSRobert Watson 186695fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 186795fab37eSRobert Watson return (error); 186895fab37eSRobert Watson } 186995fab37eSRobert Watson 187095fab37eSRobert Watson int 187195fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 187295fab37eSRobert Watson { 187395fab37eSRobert Watson int error; 187495fab37eSRobert Watson 187595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 187695fab37eSRobert Watson 187795fab37eSRobert Watson if (!mac_enforce_fs) 187895fab37eSRobert Watson return (0); 187995fab37eSRobert Watson 188095fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 188195fab37eSRobert Watson return (error); 188295fab37eSRobert Watson } 188395fab37eSRobert Watson 188495fab37eSRobert Watson static int 188595fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 188695fab37eSRobert Watson struct label *newlabel) 188795fab37eSRobert Watson { 188895fab37eSRobert Watson int error; 188995fab37eSRobert Watson 189095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 189195fab37eSRobert Watson 189295fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 189395fab37eSRobert Watson 189495fab37eSRobert Watson return (error); 189595fab37eSRobert Watson } 189695fab37eSRobert Watson 189795fab37eSRobert Watson int 189895fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 189995fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 190095fab37eSRobert Watson { 190195fab37eSRobert Watson int error; 190295fab37eSRobert Watson 190395fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 190495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 190595fab37eSRobert Watson 190695fab37eSRobert Watson if (!mac_enforce_fs) 190795fab37eSRobert Watson return (0); 190895fab37eSRobert Watson 190995fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 191095fab37eSRobert Watson &vp->v_label, cnp); 191195fab37eSRobert Watson return (error); 191295fab37eSRobert Watson } 191395fab37eSRobert Watson 191495fab37eSRobert Watson int 191595fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 191695fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 191795fab37eSRobert Watson { 191895fab37eSRobert Watson int error; 191995fab37eSRobert Watson 192095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 192195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 192295fab37eSRobert Watson 192395fab37eSRobert Watson if (!mac_enforce_fs) 192495fab37eSRobert Watson return (0); 192595fab37eSRobert Watson 192695fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 192795fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 192895fab37eSRobert Watson return (error); 192995fab37eSRobert Watson } 193095fab37eSRobert Watson 193195fab37eSRobert Watson int 193295fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 193395fab37eSRobert Watson { 193495fab37eSRobert Watson int error; 193595fab37eSRobert Watson 193695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 193795fab37eSRobert Watson 193895fab37eSRobert Watson if (!mac_enforce_fs) 193995fab37eSRobert Watson return (0); 194095fab37eSRobert Watson 194195fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 194295fab37eSRobert Watson return (error); 194395fab37eSRobert Watson } 194495fab37eSRobert Watson 194595fab37eSRobert Watson int 194695fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 194795fab37eSRobert Watson struct acl *acl) 194895fab37eSRobert Watson { 194995fab37eSRobert Watson int error; 195095fab37eSRobert Watson 195195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 195295fab37eSRobert Watson 195395fab37eSRobert Watson if (!mac_enforce_fs) 195495fab37eSRobert Watson return (0); 195595fab37eSRobert Watson 195695fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 195795fab37eSRobert Watson return (error); 195895fab37eSRobert Watson } 195995fab37eSRobert Watson 196095fab37eSRobert Watson int 196195fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 196295fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 196395fab37eSRobert Watson { 196495fab37eSRobert Watson int error; 196595fab37eSRobert Watson 196695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 196795fab37eSRobert Watson 196895fab37eSRobert Watson if (!mac_enforce_fs) 196995fab37eSRobert Watson return (0); 197095fab37eSRobert Watson 197195fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 197295fab37eSRobert Watson attrnamespace, name, uio); 197395fab37eSRobert Watson return (error); 197495fab37eSRobert Watson } 197595fab37eSRobert Watson 197695fab37eSRobert Watson int 197795fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 197895fab37eSRobert Watson { 197995fab37eSRobert Watson int error; 198095fab37eSRobert Watson 198195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 198295fab37eSRobert Watson 198395fab37eSRobert Watson if (!mac_enforce_fs) 198495fab37eSRobert Watson return (0); 198595fab37eSRobert Watson 198695fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 198795fab37eSRobert Watson return (error); 198895fab37eSRobert Watson } 198995fab37eSRobert Watson 199095fab37eSRobert Watson int 199195fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 199295fab37eSRobert Watson { 199395fab37eSRobert Watson int error; 199495fab37eSRobert Watson 199595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 199695fab37eSRobert Watson 199795fab37eSRobert Watson if (!mac_enforce_fs) 199895fab37eSRobert Watson return (0); 199995fab37eSRobert Watson 200095fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 200195fab37eSRobert Watson return (error); 200295fab37eSRobert Watson } 200395fab37eSRobert Watson 200495fab37eSRobert Watson int 200595fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 200695fab37eSRobert Watson gid_t gid) 200795fab37eSRobert Watson { 200895fab37eSRobert Watson int error; 200995fab37eSRobert Watson 201095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 201195fab37eSRobert Watson 201295fab37eSRobert Watson if (!mac_enforce_fs) 201395fab37eSRobert Watson return (0); 201495fab37eSRobert Watson 201595fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 201695fab37eSRobert Watson return (error); 201795fab37eSRobert Watson } 201895fab37eSRobert Watson 201995fab37eSRobert Watson int 202095fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 202195fab37eSRobert Watson struct timespec atime, struct timespec mtime) 202295fab37eSRobert Watson { 202395fab37eSRobert Watson int error; 202495fab37eSRobert Watson 202595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 202695fab37eSRobert Watson 202795fab37eSRobert Watson if (!mac_enforce_fs) 202895fab37eSRobert Watson return (0); 202995fab37eSRobert Watson 203095fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 203195fab37eSRobert Watson mtime); 203295fab37eSRobert Watson return (error); 203395fab37eSRobert Watson } 203495fab37eSRobert Watson 203595fab37eSRobert Watson int 2036177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2037177142e4SRobert Watson struct vnode *vp) 203895fab37eSRobert Watson { 203995fab37eSRobert Watson int error; 204095fab37eSRobert Watson 204195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 204295fab37eSRobert Watson 204395fab37eSRobert Watson if (!mac_enforce_fs) 204495fab37eSRobert Watson return (0); 204595fab37eSRobert Watson 2046177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 2047177142e4SRobert Watson &vp->v_label); 204895fab37eSRobert Watson return (error); 204995fab37eSRobert Watson } 205095fab37eSRobert Watson 20517f724f8bSRobert Watson int 2052177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2053177142e4SRobert Watson struct vnode *vp) 20547f724f8bSRobert Watson { 20557f724f8bSRobert Watson int error; 20567f724f8bSRobert Watson 20577f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 20587f724f8bSRobert Watson 20597f724f8bSRobert Watson if (!mac_enforce_fs) 20607f724f8bSRobert Watson return (0); 20617f724f8bSRobert Watson 2062177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 2063177142e4SRobert Watson &vp->v_label); 20647f724f8bSRobert Watson 20657f724f8bSRobert Watson return (error); 20667f724f8bSRobert Watson } 20677f724f8bSRobert Watson 206895fab37eSRobert Watson /* 206995fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 207095fab37eSRobert Watson * permission allowed for each object type we know about in its 207195fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 207295fab37eSRobert Watson * know) when necessary. The process lock is not held here. 207395fab37eSRobert Watson */ 20744d10c0ceSRobert Watson void 207595fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 207695fab37eSRobert Watson { 207795fab37eSRobert Watson 207895fab37eSRobert Watson /* XXX freeze all other threads */ 207995fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 208095fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 208195fab37eSRobert Watson /* XXX allow other threads to continue */ 208295fab37eSRobert Watson } 208395fab37eSRobert Watson 208495fab37eSRobert Watson static __inline const char * 208595fab37eSRobert Watson prot2str(vm_prot_t prot) 208695fab37eSRobert Watson { 208795fab37eSRobert Watson 208895fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 208995fab37eSRobert Watson case VM_PROT_READ: 209095fab37eSRobert Watson return ("r--"); 209195fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 209295fab37eSRobert Watson return ("rw-"); 209395fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 209495fab37eSRobert Watson return ("r-x"); 209595fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 209695fab37eSRobert Watson return ("rwx"); 209795fab37eSRobert Watson case VM_PROT_WRITE: 209895fab37eSRobert Watson return ("-w-"); 209995fab37eSRobert Watson case VM_PROT_EXECUTE: 210095fab37eSRobert Watson return ("--x"); 210195fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 210295fab37eSRobert Watson return ("-wx"); 210395fab37eSRobert Watson default: 210495fab37eSRobert Watson return ("---"); 210595fab37eSRobert Watson } 210695fab37eSRobert Watson } 210795fab37eSRobert Watson 210895fab37eSRobert Watson static void 210995fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 211095fab37eSRobert Watson struct vm_map *map) 211195fab37eSRobert Watson { 211295fab37eSRobert Watson struct vm_map_entry *vme; 2113e183f80eSRobert Watson int result; 2114e183f80eSRobert Watson vm_prot_t revokeperms; 211595fab37eSRobert Watson vm_object_t object; 211695fab37eSRobert Watson vm_ooffset_t offset; 211795fab37eSRobert Watson struct vnode *vp; 211895fab37eSRobert Watson 2119c0f39905SRobert Watson if (!mac_mmap_revocation) 2120c0f39905SRobert Watson return; 2121c0f39905SRobert Watson 212295fab37eSRobert Watson vm_map_lock_read(map); 212395fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 212495fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 212595fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 212695fab37eSRobert Watson vme->object.sub_map); 212795fab37eSRobert Watson continue; 212895fab37eSRobert Watson } 212995fab37eSRobert Watson /* 213095fab37eSRobert Watson * Skip over entries that obviously are not shared. 213195fab37eSRobert Watson */ 213295fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 213395fab37eSRobert Watson !vme->max_protection) 213495fab37eSRobert Watson continue; 213595fab37eSRobert Watson /* 213695fab37eSRobert Watson * Drill down to the deepest backing object. 213795fab37eSRobert Watson */ 213895fab37eSRobert Watson offset = vme->offset; 213995fab37eSRobert Watson object = vme->object.vm_object; 214095fab37eSRobert Watson if (object == NULL) 214195fab37eSRobert Watson continue; 214295fab37eSRobert Watson while (object->backing_object != NULL) { 214395fab37eSRobert Watson object = object->backing_object; 214495fab37eSRobert Watson offset += object->backing_object_offset; 214595fab37eSRobert Watson } 214695fab37eSRobert Watson /* 214795fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 214895fab37eSRobert Watson * by the MAC system, so only things with backing by a 214995fab37eSRobert Watson * normal object (read: vnodes) are checked. 215095fab37eSRobert Watson */ 215195fab37eSRobert Watson if (object->type != OBJT_VNODE) 215295fab37eSRobert Watson continue; 215395fab37eSRobert Watson vp = (struct vnode *)object->handle; 215495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2155e183f80eSRobert Watson result = vme->max_protection; 2156e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 215795fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 215895fab37eSRobert Watson /* 215995fab37eSRobert Watson * Find out what maximum protection we may be allowing 216095fab37eSRobert Watson * now but a policy needs to get removed. 216195fab37eSRobert Watson */ 216295fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 216395fab37eSRobert Watson if (!revokeperms) 216495fab37eSRobert Watson continue; 2165b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 2166b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 2167b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 2168b656366bSBruce Evans (long)(vme->end - vme->start), 216995fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 217095fab37eSRobert Watson vm_map_lock_upgrade(map); 217195fab37eSRobert Watson /* 217295fab37eSRobert Watson * This is the really simple case: if a map has more 217395fab37eSRobert Watson * max_protection than is allowed, but it's not being 217495fab37eSRobert Watson * actually used (that is, the current protection is 217595fab37eSRobert Watson * still allowed), we can just wipe it out and do 217695fab37eSRobert Watson * nothing more. 217795fab37eSRobert Watson */ 217895fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 217995fab37eSRobert Watson vme->max_protection -= revokeperms; 218095fab37eSRobert Watson } else { 218195fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 218295fab37eSRobert Watson /* 218395fab37eSRobert Watson * In the more complicated case, flush out all 218495fab37eSRobert Watson * pending changes to the object then turn it 218595fab37eSRobert Watson * copy-on-write. 218695fab37eSRobert Watson */ 218795fab37eSRobert Watson vm_object_reference(object); 218895fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2189b6e48e03SAlan Cox VM_OBJECT_LOCK(object); 219095fab37eSRobert Watson vm_object_page_clean(object, 219195fab37eSRobert Watson OFF_TO_IDX(offset), 219295fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 219395fab37eSRobert Watson PAGE_MASK), 219495fab37eSRobert Watson OBJPC_SYNC); 2195b6e48e03SAlan Cox VM_OBJECT_UNLOCK(object); 219695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 219795fab37eSRobert Watson vm_object_deallocate(object); 219895fab37eSRobert Watson /* 219995fab37eSRobert Watson * Why bother if there's no read permissions 220095fab37eSRobert Watson * anymore? For the rest, we need to leave 220195fab37eSRobert Watson * the write permissions on for COW, or 220295fab37eSRobert Watson * remove them entirely if configured to. 220395fab37eSRobert Watson */ 220495fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 220595fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 220695fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 220795fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 220895fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 220995fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 221095fab37eSRobert Watson } 221195fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 221295fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 221395fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 221495fab37eSRobert Watson } 221595fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 221695fab37eSRobert Watson vme->max_protection = 0; 221795fab37eSRobert Watson vme->protection = 0; 221895fab37eSRobert Watson } 221995fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 222095fab37eSRobert Watson vme->protection & ~revokeperms); 222195fab37eSRobert Watson vm_map_simplify_entry(map, vme); 222295fab37eSRobert Watson } 222395fab37eSRobert Watson vm_map_lock_downgrade(map); 222495fab37eSRobert Watson } 222595fab37eSRobert Watson vm_map_unlock_read(map); 222695fab37eSRobert Watson } 222795fab37eSRobert Watson 222895fab37eSRobert Watson /* 222995fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 223095fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 223195fab37eSRobert Watson * buffer cache. 223295fab37eSRobert Watson */ 223395fab37eSRobert Watson static void 223495fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 223595fab37eSRobert Watson { 223695fab37eSRobert Watson 223795fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 223895fab37eSRobert Watson } 223995fab37eSRobert Watson 224095fab37eSRobert Watson void 224195fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 224295fab37eSRobert Watson { 224395fab37eSRobert Watson 224495fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 224595fab37eSRobert Watson } 224695fab37eSRobert Watson 224795fab37eSRobert Watson void 224895fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 224995fab37eSRobert Watson { 225095fab37eSRobert Watson 225195fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 225295fab37eSRobert Watson } 225395fab37eSRobert Watson 225495fab37eSRobert Watson void 225595fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 225695fab37eSRobert Watson { 225795fab37eSRobert Watson 225895fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 225995fab37eSRobert Watson } 226095fab37eSRobert Watson 226195fab37eSRobert Watson void 226295fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 226395fab37eSRobert Watson { 226495fab37eSRobert Watson 226595fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 226695fab37eSRobert Watson } 226795fab37eSRobert Watson 226895fab37eSRobert Watson void 226995fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 227095fab37eSRobert Watson { 227195fab37eSRobert Watson 227295fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 227395fab37eSRobert Watson } 227495fab37eSRobert Watson 227595fab37eSRobert Watson void 227695fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 227795fab37eSRobert Watson struct socket *newsocket) 227895fab37eSRobert Watson { 227995fab37eSRobert Watson 228095fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 228195fab37eSRobert Watson newsocket, &newsocket->so_label); 228295fab37eSRobert Watson } 228395fab37eSRobert Watson 228495fab37eSRobert Watson static void 228595fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 228695fab37eSRobert Watson struct label *newlabel) 228795fab37eSRobert Watson { 228895fab37eSRobert Watson 228995fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 229095fab37eSRobert Watson } 229195fab37eSRobert Watson 229295fab37eSRobert Watson static void 229395fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 229495fab37eSRobert Watson { 229595fab37eSRobert Watson 229695fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 229795fab37eSRobert Watson } 229895fab37eSRobert Watson 229995fab37eSRobert Watson void 230095fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 230195fab37eSRobert Watson { 230210eeb10cSRobert Watson struct label *label; 230395fab37eSRobert Watson 230410eeb10cSRobert Watson label = mbuf_to_label(mbuf); 230510eeb10cSRobert Watson 230610eeb10cSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket, 230710eeb10cSRobert Watson &socket->so_peerlabel); 230895fab37eSRobert Watson } 230995fab37eSRobert Watson 231095fab37eSRobert Watson void 231195fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 231295fab37eSRobert Watson struct socket *newsocket) 231395fab37eSRobert Watson { 231495fab37eSRobert Watson 231595fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 231695fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 231795fab37eSRobert Watson } 231895fab37eSRobert Watson 231995fab37eSRobert Watson void 232095fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 232195fab37eSRobert Watson { 232210eeb10cSRobert Watson struct label *label; 232310eeb10cSRobert Watson 232410eeb10cSRobert Watson label = mbuf_to_label(datagram); 232595fab37eSRobert Watson 232695fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 232710eeb10cSRobert Watson datagram, label); 232895fab37eSRobert Watson } 232995fab37eSRobert Watson 233095fab37eSRobert Watson void 233195fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 233295fab37eSRobert Watson { 233310eeb10cSRobert Watson struct label *datagramlabel, *fragmentlabel; 233495fab37eSRobert Watson 233510eeb10cSRobert Watson datagramlabel = mbuf_to_label(datagram); 233610eeb10cSRobert Watson fragmentlabel = mbuf_to_label(fragment); 233710eeb10cSRobert Watson 233810eeb10cSRobert Watson MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment, 233910eeb10cSRobert Watson fragmentlabel); 234095fab37eSRobert Watson } 234195fab37eSRobert Watson 234295fab37eSRobert Watson void 234395fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 234495fab37eSRobert Watson { 234510eeb10cSRobert Watson struct label *label; 234695fab37eSRobert Watson 234710eeb10cSRobert Watson label = mbuf_to_label(fragment); 234810eeb10cSRobert Watson 234910eeb10cSRobert Watson MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label); 235095fab37eSRobert Watson } 235195fab37eSRobert Watson 235295fab37eSRobert Watson void 235395fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 235495fab37eSRobert Watson { 235510eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 235695fab37eSRobert Watson 235710eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 235810eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 235910eeb10cSRobert Watson 236010eeb10cSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf, 236110eeb10cSRobert Watson newmbuflabel); 236295fab37eSRobert Watson } 236395fab37eSRobert Watson 236495fab37eSRobert Watson void 236595fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 236695fab37eSRobert Watson { 236710eeb10cSRobert Watson struct label *label; 236810eeb10cSRobert Watson 236910eeb10cSRobert Watson label = mbuf_to_label(mbuf); 237095fab37eSRobert Watson 237195fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 237210eeb10cSRobert Watson label); 237395fab37eSRobert Watson } 237495fab37eSRobert Watson 237595fab37eSRobert Watson void 237695fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 237795fab37eSRobert Watson { 237810eeb10cSRobert Watson struct label *label; 237910eeb10cSRobert Watson 238010eeb10cSRobert Watson label = mbuf_to_label(mbuf); 238195fab37eSRobert Watson 238295fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 238310eeb10cSRobert Watson label); 238495fab37eSRobert Watson } 238595fab37eSRobert Watson 238695fab37eSRobert Watson void 238795fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 238895fab37eSRobert Watson { 238910eeb10cSRobert Watson struct label *label; 239010eeb10cSRobert Watson 239110eeb10cSRobert Watson label = mbuf_to_label(mbuf); 239295fab37eSRobert Watson 239395fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 239410eeb10cSRobert Watson label); 239595fab37eSRobert Watson } 239695fab37eSRobert Watson 239795fab37eSRobert Watson void 239895fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 239995fab37eSRobert Watson struct mbuf *newmbuf) 240095fab37eSRobert Watson { 240110eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 240295fab37eSRobert Watson 240310eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 240410eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 240510eeb10cSRobert Watson 240610eeb10cSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel, 240710eeb10cSRobert Watson ifnet, &ifnet->if_label, newmbuf, newmbuflabel); 240895fab37eSRobert Watson } 240995fab37eSRobert Watson 241095fab37eSRobert Watson void 241195fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 241295fab37eSRobert Watson { 241310eeb10cSRobert Watson struct label *oldmbuflabel, *newmbuflabel; 241495fab37eSRobert Watson 241510eeb10cSRobert Watson oldmbuflabel = mbuf_to_label(oldmbuf); 241610eeb10cSRobert Watson newmbuflabel = mbuf_to_label(newmbuf); 241710eeb10cSRobert Watson 241810eeb10cSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf, 241910eeb10cSRobert Watson newmbuflabel); 242095fab37eSRobert Watson } 242195fab37eSRobert Watson 242295fab37eSRobert Watson int 242395fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 242495fab37eSRobert Watson { 242510eeb10cSRobert Watson struct label *label; 242695fab37eSRobert Watson int result; 242795fab37eSRobert Watson 242810eeb10cSRobert Watson label = mbuf_to_label(fragment); 242910eeb10cSRobert Watson 243095fab37eSRobert Watson result = 1; 243110eeb10cSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq, 243210eeb10cSRobert Watson &ipq->ipq_label); 243395fab37eSRobert Watson 243495fab37eSRobert Watson return (result); 243595fab37eSRobert Watson } 243695fab37eSRobert Watson 243795fab37eSRobert Watson void 243895fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 243995fab37eSRobert Watson { 244010eeb10cSRobert Watson struct label *label; 244195fab37eSRobert Watson 244210eeb10cSRobert Watson label = mbuf_to_label(fragment); 244310eeb10cSRobert Watson 244410eeb10cSRobert Watson MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label); 244595fab37eSRobert Watson } 244695fab37eSRobert Watson 244795fab37eSRobert Watson void 244895fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 244995fab37eSRobert Watson { 245010eeb10cSRobert Watson struct label *label; 245110eeb10cSRobert Watson 245210eeb10cSRobert Watson label = mbuf_to_label(mbuf); 245395fab37eSRobert Watson 245495fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 245510eeb10cSRobert Watson label); 245695fab37eSRobert Watson } 245795fab37eSRobert Watson 245895fab37eSRobert Watson void 245995fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 246095fab37eSRobert Watson { 246195fab37eSRobert Watson 246295fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 246395fab37eSRobert Watson &mp->mnt_fslabel); 246495fab37eSRobert Watson } 246595fab37eSRobert Watson 246695fab37eSRobert Watson void 246795fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 246895fab37eSRobert Watson { 246995fab37eSRobert Watson 247095fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 247195fab37eSRobert Watson &mp->mnt_fslabel); 247295fab37eSRobert Watson } 247395fab37eSRobert Watson 247495fab37eSRobert Watson int 247595fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 247695fab37eSRobert Watson { 247795fab37eSRobert Watson int error; 247895fab37eSRobert Watson 247995fab37eSRobert Watson if (!mac_enforce_network) 248095fab37eSRobert Watson return (0); 248195fab37eSRobert Watson 248295fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 248395fab37eSRobert Watson &ifnet->if_label); 248495fab37eSRobert Watson 248595fab37eSRobert Watson return (error); 248695fab37eSRobert Watson } 248795fab37eSRobert Watson 248895fab37eSRobert Watson static int 248995fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 249095fab37eSRobert Watson { 249195fab37eSRobert Watson int error; 249295fab37eSRobert Watson 249395fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 249495fab37eSRobert Watson 249595fab37eSRobert Watson return (error); 249695fab37eSRobert Watson } 249795fab37eSRobert Watson 249895fab37eSRobert Watson int 249995fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 250095fab37eSRobert Watson { 250195fab37eSRobert Watson int error; 250295fab37eSRobert Watson 250395fab37eSRobert Watson if (!mac_enforce_process) 250495fab37eSRobert Watson return (0); 250595fab37eSRobert Watson 250695fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 250795fab37eSRobert Watson 250895fab37eSRobert Watson return (error); 250995fab37eSRobert Watson } 251095fab37eSRobert Watson 251195fab37eSRobert Watson int 251295fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 251395fab37eSRobert Watson { 251410eeb10cSRobert Watson struct label *label; 251595fab37eSRobert Watson int error; 251695fab37eSRobert Watson 2517225bff6fSRobert Watson M_ASSERTPKTHDR(mbuf); 2518225bff6fSRobert Watson 251995fab37eSRobert Watson if (!mac_enforce_network) 252095fab37eSRobert Watson return (0); 252195fab37eSRobert Watson 252210eeb10cSRobert Watson label = mbuf_to_label(mbuf); 252395fab37eSRobert Watson 252495fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 252510eeb10cSRobert Watson label); 252695fab37eSRobert Watson 252795fab37eSRobert Watson return (error); 252895fab37eSRobert Watson } 252995fab37eSRobert Watson 253095fab37eSRobert Watson int 2531e686e5aeSRobert Watson mac_check_kenv_dump(struct ucred *cred) 2532e686e5aeSRobert Watson { 2533e686e5aeSRobert Watson int error; 2534e686e5aeSRobert Watson 2535e686e5aeSRobert Watson if (!mac_enforce_system) 2536e686e5aeSRobert Watson return (0); 2537e686e5aeSRobert Watson 2538e686e5aeSRobert Watson MAC_CHECK(check_kenv_dump, cred); 2539e686e5aeSRobert Watson 2540e686e5aeSRobert Watson return (error); 2541e686e5aeSRobert Watson } 2542e686e5aeSRobert Watson 2543e686e5aeSRobert Watson int 2544e686e5aeSRobert Watson mac_check_kenv_get(struct ucred *cred, char *name) 2545e686e5aeSRobert Watson { 2546e686e5aeSRobert Watson int error; 2547e686e5aeSRobert Watson 2548e686e5aeSRobert Watson if (!mac_enforce_system) 2549e686e5aeSRobert Watson return (0); 2550e686e5aeSRobert Watson 2551e686e5aeSRobert Watson MAC_CHECK(check_kenv_get, cred, name); 2552e686e5aeSRobert Watson 2553e686e5aeSRobert Watson return (error); 2554e686e5aeSRobert Watson } 2555e686e5aeSRobert Watson 2556e686e5aeSRobert Watson int 2557e686e5aeSRobert Watson mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2558e686e5aeSRobert Watson { 2559e686e5aeSRobert Watson int error; 2560e686e5aeSRobert Watson 2561e686e5aeSRobert Watson if (!mac_enforce_system) 2562e686e5aeSRobert Watson return (0); 2563e686e5aeSRobert Watson 2564e686e5aeSRobert Watson MAC_CHECK(check_kenv_set, cred, name, value); 2565e686e5aeSRobert Watson 2566e686e5aeSRobert Watson return (error); 2567e686e5aeSRobert Watson } 2568e686e5aeSRobert Watson 2569e686e5aeSRobert Watson int 2570e686e5aeSRobert Watson mac_check_kenv_unset(struct ucred *cred, char *name) 2571e686e5aeSRobert Watson { 2572e686e5aeSRobert Watson int error; 2573e686e5aeSRobert Watson 2574e686e5aeSRobert Watson if (!mac_enforce_system) 2575e686e5aeSRobert Watson return (0); 2576e686e5aeSRobert Watson 2577e686e5aeSRobert Watson MAC_CHECK(check_kenv_unset, cred, name); 2578e686e5aeSRobert Watson 2579e686e5aeSRobert Watson return (error); 2580e686e5aeSRobert Watson } 2581e686e5aeSRobert Watson 2582e686e5aeSRobert Watson int 2583a3df768bSRobert Watson mac_check_kld_load(struct ucred *cred, struct vnode *vp) 2584a3df768bSRobert Watson { 2585a3df768bSRobert Watson int error; 2586a3df768bSRobert Watson 2587a3df768bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_kld_load"); 2588a3df768bSRobert Watson 2589a3df768bSRobert Watson if (!mac_enforce_kld) 2590a3df768bSRobert Watson return (0); 2591a3df768bSRobert Watson 2592a3df768bSRobert Watson MAC_CHECK(check_kld_load, cred, vp, &vp->v_label); 2593a3df768bSRobert Watson 2594a3df768bSRobert Watson return (error); 2595a3df768bSRobert Watson } 2596a3df768bSRobert Watson 2597a3df768bSRobert Watson int 2598a3df768bSRobert Watson mac_check_kld_stat(struct ucred *cred) 2599a3df768bSRobert Watson { 2600a3df768bSRobert Watson int error; 2601a3df768bSRobert Watson 2602a3df768bSRobert Watson if (!mac_enforce_kld) 2603a3df768bSRobert Watson return (0); 2604a3df768bSRobert Watson 2605a3df768bSRobert Watson MAC_CHECK(check_kld_stat, cred); 2606a3df768bSRobert Watson 2607a3df768bSRobert Watson return (error); 2608a3df768bSRobert Watson } 2609a3df768bSRobert Watson 2610a3df768bSRobert Watson int 2611a3df768bSRobert Watson mac_check_kld_unload(struct ucred *cred) 2612a3df768bSRobert Watson { 2613a3df768bSRobert Watson int error; 2614a3df768bSRobert Watson 2615a3df768bSRobert Watson if (!mac_enforce_kld) 2616a3df768bSRobert Watson return (0); 2617a3df768bSRobert Watson 2618a3df768bSRobert Watson MAC_CHECK(check_kld_unload, cred); 2619a3df768bSRobert Watson 2620a3df768bSRobert Watson return (error); 2621a3df768bSRobert Watson } 2622a3df768bSRobert Watson 2623a3df768bSRobert Watson int 262495fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 262595fab37eSRobert Watson { 262695fab37eSRobert Watson int error; 262795fab37eSRobert Watson 262895fab37eSRobert Watson if (!mac_enforce_fs) 262995fab37eSRobert Watson return (0); 263095fab37eSRobert Watson 263195fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 263295fab37eSRobert Watson 263395fab37eSRobert Watson return (error); 263495fab37eSRobert Watson } 263595fab37eSRobert Watson 263695fab37eSRobert Watson int 263795fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 263895fab37eSRobert Watson void *data) 263995fab37eSRobert Watson { 264095fab37eSRobert Watson int error; 264195fab37eSRobert Watson 26421aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26431aa37f53SRobert Watson 26441aa37f53SRobert Watson if (!mac_enforce_pipe) 26451aa37f53SRobert Watson return (0); 26461aa37f53SRobert Watson 264795fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 264895fab37eSRobert Watson 264995fab37eSRobert Watson return (error); 265095fab37eSRobert Watson } 265195fab37eSRobert Watson 265295fab37eSRobert Watson int 2653c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 265495fab37eSRobert Watson { 265595fab37eSRobert Watson int error; 265695fab37eSRobert Watson 26571aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26581aa37f53SRobert Watson 26591aa37f53SRobert Watson if (!mac_enforce_pipe) 26601aa37f53SRobert Watson return (0); 26611aa37f53SRobert Watson 2662c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2663c024c3eeSRobert Watson 2664c024c3eeSRobert Watson return (error); 2665c024c3eeSRobert Watson } 2666c024c3eeSRobert Watson 2667c024c3eeSRobert Watson int 2668c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2669c024c3eeSRobert Watson { 2670c024c3eeSRobert Watson int error; 2671c024c3eeSRobert Watson 26721aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26731aa37f53SRobert Watson 26741aa37f53SRobert Watson if (!mac_enforce_pipe) 26751aa37f53SRobert Watson return (0); 26761aa37f53SRobert Watson 2677c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 267895fab37eSRobert Watson 267995fab37eSRobert Watson return (error); 268095fab37eSRobert Watson } 268195fab37eSRobert Watson 268295fab37eSRobert Watson static int 268395fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 268495fab37eSRobert Watson struct label *newlabel) 268595fab37eSRobert Watson { 268695fab37eSRobert Watson int error; 268795fab37eSRobert Watson 26881aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 26891aa37f53SRobert Watson 26901aa37f53SRobert Watson if (!mac_enforce_pipe) 26911aa37f53SRobert Watson return (0); 26921aa37f53SRobert Watson 269395fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 269495fab37eSRobert Watson 269595fab37eSRobert Watson return (error); 269695fab37eSRobert Watson } 269795fab37eSRobert Watson 269895fab37eSRobert Watson int 2699c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2700c024c3eeSRobert Watson { 2701c024c3eeSRobert Watson int error; 2702c024c3eeSRobert Watson 27031aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 27041aa37f53SRobert Watson 27051aa37f53SRobert Watson if (!mac_enforce_pipe) 27061aa37f53SRobert Watson return (0); 27071aa37f53SRobert Watson 2708c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2709c024c3eeSRobert Watson 2710c024c3eeSRobert Watson return (error); 2711c024c3eeSRobert Watson } 2712c024c3eeSRobert Watson 2713c024c3eeSRobert Watson int 2714c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2715c024c3eeSRobert Watson { 2716c024c3eeSRobert Watson int error; 2717c024c3eeSRobert Watson 27181aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 27191aa37f53SRobert Watson 27201aa37f53SRobert Watson if (!mac_enforce_pipe) 27211aa37f53SRobert Watson return (0); 27221aa37f53SRobert Watson 2723c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2724c024c3eeSRobert Watson 2725c024c3eeSRobert Watson return (error); 2726c024c3eeSRobert Watson } 2727c024c3eeSRobert Watson 2728c024c3eeSRobert Watson int 272995fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 273095fab37eSRobert Watson { 273195fab37eSRobert Watson int error; 273295fab37eSRobert Watson 2733b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2734b12baf55SRobert Watson 273595fab37eSRobert Watson if (!mac_enforce_process) 273695fab37eSRobert Watson return (0); 273795fab37eSRobert Watson 273895fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 273995fab37eSRobert Watson 274095fab37eSRobert Watson return (error); 274195fab37eSRobert Watson } 274295fab37eSRobert Watson 274395fab37eSRobert Watson int 274495fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 274595fab37eSRobert Watson { 274695fab37eSRobert Watson int error; 274795fab37eSRobert Watson 2748b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2749b12baf55SRobert Watson 275095fab37eSRobert Watson if (!mac_enforce_process) 275195fab37eSRobert Watson return (0); 275295fab37eSRobert Watson 275395fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 275495fab37eSRobert Watson 275595fab37eSRobert Watson return (error); 275695fab37eSRobert Watson } 275795fab37eSRobert Watson 275895fab37eSRobert Watson int 275995fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 276095fab37eSRobert Watson { 276195fab37eSRobert Watson int error; 276295fab37eSRobert Watson 2763b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2764b12baf55SRobert Watson 276595fab37eSRobert Watson if (!mac_enforce_process) 276695fab37eSRobert Watson return (0); 276795fab37eSRobert Watson 276895fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 276995fab37eSRobert Watson 277095fab37eSRobert Watson return (error); 277195fab37eSRobert Watson } 277295fab37eSRobert Watson 277395fab37eSRobert Watson int 277495fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 277595fab37eSRobert Watson struct sockaddr *sockaddr) 277695fab37eSRobert Watson { 277795fab37eSRobert Watson int error; 277895fab37eSRobert Watson 277995fab37eSRobert Watson if (!mac_enforce_socket) 278095fab37eSRobert Watson return (0); 278195fab37eSRobert Watson 278295fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 278395fab37eSRobert Watson sockaddr); 278495fab37eSRobert Watson 278595fab37eSRobert Watson return (error); 278695fab37eSRobert Watson } 278795fab37eSRobert Watson 278895fab37eSRobert Watson int 278995fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 279095fab37eSRobert Watson struct sockaddr *sockaddr) 279195fab37eSRobert Watson { 279295fab37eSRobert Watson int error; 279395fab37eSRobert Watson 279495fab37eSRobert Watson if (!mac_enforce_socket) 279595fab37eSRobert Watson return (0); 279695fab37eSRobert Watson 279795fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 279895fab37eSRobert Watson sockaddr); 279995fab37eSRobert Watson 280095fab37eSRobert Watson return (error); 280195fab37eSRobert Watson } 280295fab37eSRobert Watson 280395fab37eSRobert Watson int 2804d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2805d61198e4SRobert Watson { 280610eeb10cSRobert Watson struct label *label; 2807d61198e4SRobert Watson int error; 2808d61198e4SRobert Watson 2809d61198e4SRobert Watson if (!mac_enforce_socket) 2810d61198e4SRobert Watson return (0); 2811d61198e4SRobert Watson 281210eeb10cSRobert Watson label = mbuf_to_label(mbuf); 281310eeb10cSRobert Watson 2814d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 281510eeb10cSRobert Watson label); 2816d61198e4SRobert Watson 2817d61198e4SRobert Watson return (error); 2818d61198e4SRobert Watson } 2819d61198e4SRobert Watson 2820d61198e4SRobert Watson int 282195fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 282295fab37eSRobert Watson { 282395fab37eSRobert Watson int error; 282495fab37eSRobert Watson 282595fab37eSRobert Watson if (!mac_enforce_socket) 282695fab37eSRobert Watson return (0); 282795fab37eSRobert Watson 282895fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 282995fab37eSRobert Watson return (error); 283095fab37eSRobert Watson } 283195fab37eSRobert Watson 2832b371c939SRobert Watson int 2833b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 2834b371c939SRobert Watson { 2835b371c939SRobert Watson int error; 2836b371c939SRobert Watson 2837b371c939SRobert Watson if (!mac_enforce_socket) 2838b371c939SRobert Watson return (0); 2839b371c939SRobert Watson 2840b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2841b371c939SRobert Watson 2842b371c939SRobert Watson return (error); 2843b371c939SRobert Watson } 2844b371c939SRobert Watson 284595fab37eSRobert Watson static int 284695fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 284795fab37eSRobert Watson struct label *newlabel) 284895fab37eSRobert Watson { 284995fab37eSRobert Watson int error; 285095fab37eSRobert Watson 285195fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 285295fab37eSRobert Watson newlabel); 285395fab37eSRobert Watson 285495fab37eSRobert Watson return (error); 285595fab37eSRobert Watson } 285695fab37eSRobert Watson 285795fab37eSRobert Watson int 2858b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 2859b371c939SRobert Watson { 2860b371c939SRobert Watson int error; 2861b371c939SRobert Watson 2862b371c939SRobert Watson if (!mac_enforce_socket) 2863b371c939SRobert Watson return (0); 2864b371c939SRobert Watson 2865b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2866b371c939SRobert Watson 2867b371c939SRobert Watson return (error); 2868b371c939SRobert Watson } 2869b371c939SRobert Watson 2870b371c939SRobert Watson int 287195fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 287295fab37eSRobert Watson { 287395fab37eSRobert Watson int error; 287495fab37eSRobert Watson 287595fab37eSRobert Watson if (!mac_enforce_socket) 287695fab37eSRobert Watson return (0); 287795fab37eSRobert Watson 287895fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 287995fab37eSRobert Watson 288095fab37eSRobert Watson return (error); 288195fab37eSRobert Watson } 288295fab37eSRobert Watson 288395fab37eSRobert Watson int 288492835789SRobert Watson mac_check_sysarch_ioperm(struct ucred *cred) 288592835789SRobert Watson { 288692835789SRobert Watson int error; 288792835789SRobert Watson 288892835789SRobert Watson if (!mac_enforce_system) 288992835789SRobert Watson return (0); 289092835789SRobert Watson 289192835789SRobert Watson MAC_CHECK(check_sysarch_ioperm, cred); 289292835789SRobert Watson return (error); 289392835789SRobert Watson } 289492835789SRobert Watson 289592835789SRobert Watson int 2896e5e820fdSRobert Watson mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2897e5e820fdSRobert Watson { 2898e5e820fdSRobert Watson int error; 2899e5e820fdSRobert Watson 2900e5e820fdSRobert Watson if (vp != NULL) { 2901e5e820fdSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2902e5e820fdSRobert Watson } 2903e5e820fdSRobert Watson 2904e5e820fdSRobert Watson if (!mac_enforce_system) 2905e5e820fdSRobert Watson return (0); 2906e5e820fdSRobert Watson 2907e5e820fdSRobert Watson MAC_CHECK(check_system_acct, cred, vp, 2908e5e820fdSRobert Watson vp != NULL ? &vp->v_label : NULL); 2909e5e820fdSRobert Watson 2910e5e820fdSRobert Watson return (error); 2911e5e820fdSRobert Watson } 2912e5e820fdSRobert Watson 2913e5e820fdSRobert Watson int 2914e5e820fdSRobert Watson mac_check_system_nfsd(struct ucred *cred) 2915e5e820fdSRobert Watson { 2916e5e820fdSRobert Watson int error; 2917e5e820fdSRobert Watson 2918e5e820fdSRobert Watson if (!mac_enforce_system) 2919e5e820fdSRobert Watson return (0); 2920e5e820fdSRobert Watson 2921e5e820fdSRobert Watson MAC_CHECK(check_system_nfsd, cred); 2922e5e820fdSRobert Watson 2923e5e820fdSRobert Watson return (error); 2924e5e820fdSRobert Watson } 2925e5e820fdSRobert Watson 2926e5e820fdSRobert Watson int 2927a2ecb9b7SRobert Watson mac_check_system_reboot(struct ucred *cred, int howto) 2928a2ecb9b7SRobert Watson { 2929a2ecb9b7SRobert Watson int error; 2930a2ecb9b7SRobert Watson 29319e913ebdSRobert Watson if (!mac_enforce_system) 2932a2ecb9b7SRobert Watson return (0); 2933a2ecb9b7SRobert Watson 2934a2ecb9b7SRobert Watson MAC_CHECK(check_system_reboot, cred, howto); 29359e913ebdSRobert Watson 2936a2ecb9b7SRobert Watson return (error); 2937a2ecb9b7SRobert Watson } 2938a2ecb9b7SRobert Watson 2939a2ecb9b7SRobert Watson int 29404b8d5f2dSRobert Watson mac_check_system_settime(struct ucred *cred) 29414b8d5f2dSRobert Watson { 29424b8d5f2dSRobert Watson int error; 29434b8d5f2dSRobert Watson 29444b8d5f2dSRobert Watson if (!mac_enforce_system) 29454b8d5f2dSRobert Watson return (0); 29464b8d5f2dSRobert Watson 29474b8d5f2dSRobert Watson MAC_CHECK(check_system_settime, cred); 29484b8d5f2dSRobert Watson 29494b8d5f2dSRobert Watson return (error); 29504b8d5f2dSRobert Watson } 29514b8d5f2dSRobert Watson 29524b8d5f2dSRobert Watson int 295303ce2c0cSRobert Watson mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 295403ce2c0cSRobert Watson { 295503ce2c0cSRobert Watson int error; 295603ce2c0cSRobert Watson 295703ce2c0cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 295803ce2c0cSRobert Watson 29599e913ebdSRobert Watson if (!mac_enforce_system) 296003ce2c0cSRobert Watson return (0); 296103ce2c0cSRobert Watson 296203ce2c0cSRobert Watson MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 296303ce2c0cSRobert Watson return (error); 296403ce2c0cSRobert Watson } 296503ce2c0cSRobert Watson 296603ce2c0cSRobert Watson int 29671b2c2ab2SRobert Watson mac_check_system_swapoff(struct ucred *cred, struct vnode *vp) 29681b2c2ab2SRobert Watson { 29691b2c2ab2SRobert Watson int error; 29701b2c2ab2SRobert Watson 29711b2c2ab2SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff"); 29721b2c2ab2SRobert Watson 29731b2c2ab2SRobert Watson if (!mac_enforce_system) 29741b2c2ab2SRobert Watson return (0); 29751b2c2ab2SRobert Watson 29761b2c2ab2SRobert Watson MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label); 29771b2c2ab2SRobert Watson return (error); 29781b2c2ab2SRobert Watson } 29791b2c2ab2SRobert Watson 29801b2c2ab2SRobert Watson int 2981d3fc69eeSRobert Watson mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2982d3fc69eeSRobert Watson void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2983d3fc69eeSRobert Watson { 2984d3fc69eeSRobert Watson int error; 2985d3fc69eeSRobert Watson 2986d3fc69eeSRobert Watson /* 2987d3fc69eeSRobert Watson * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2988d3fc69eeSRobert Watson * but since it's not exported from kern_sysctl.c, we can't. 2989d3fc69eeSRobert Watson */ 29909e913ebdSRobert Watson if (!mac_enforce_system) 2991d3fc69eeSRobert Watson return (0); 2992d3fc69eeSRobert Watson 2993d3fc69eeSRobert Watson MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2994d3fc69eeSRobert Watson inkernel, new, newlen); 2995d3fc69eeSRobert Watson 2996d3fc69eeSRobert Watson return (error); 2997d3fc69eeSRobert Watson } 2998d3fc69eeSRobert Watson 2999d3fc69eeSRobert Watson int 300095fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 300195fab37eSRobert Watson struct ifnet *ifnet) 300295fab37eSRobert Watson { 3003f7b951a8SRobert Watson char *elements, *buffer; 3004f7b951a8SRobert Watson struct mac mac; 300595fab37eSRobert Watson int error; 300695fab37eSRobert Watson 3007f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 300895fab37eSRobert Watson if (error) 300995fab37eSRobert Watson return (error); 301095fab37eSRobert Watson 3011f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3012f7b951a8SRobert Watson if (error) 3013f7b951a8SRobert Watson return (error); 3014f7b951a8SRobert Watson 3015a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3016f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3017f7b951a8SRobert Watson if (error) { 3018f7b951a8SRobert Watson free(elements, M_MACTEMP); 3019f7b951a8SRobert Watson return (error); 3020f7b951a8SRobert Watson } 3021f7b951a8SRobert Watson 3022a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3023f7b951a8SRobert Watson error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 3024a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3025f7b951a8SRobert Watson if (error == 0) 3026f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3027f7b951a8SRobert Watson 3028f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3029f7b951a8SRobert Watson free(elements, M_MACTEMP); 3030f7b951a8SRobert Watson 3031f7b951a8SRobert Watson return (error); 303295fab37eSRobert Watson } 303395fab37eSRobert Watson 303495fab37eSRobert Watson int 303595fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 303695fab37eSRobert Watson struct ifnet *ifnet) 303795fab37eSRobert Watson { 303895fab37eSRobert Watson struct label intlabel; 3039f7b951a8SRobert Watson struct mac mac; 3040f7b951a8SRobert Watson char *buffer; 304195fab37eSRobert Watson int error; 304295fab37eSRobert Watson 3043f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 304495fab37eSRobert Watson if (error) 304595fab37eSRobert Watson return (error); 304695fab37eSRobert Watson 3047f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 304895fab37eSRobert Watson if (error) 304995fab37eSRobert Watson return (error); 305095fab37eSRobert Watson 3051a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3052f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3053f7b951a8SRobert Watson if (error) { 3054f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3055f7b951a8SRobert Watson return (error); 3056f7b951a8SRobert Watson } 3057f7b951a8SRobert Watson 3058f7b951a8SRobert Watson mac_init_ifnet_label(&intlabel); 3059f7b951a8SRobert Watson error = mac_internalize_ifnet_label(&intlabel, buffer); 3060f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3061f7b951a8SRobert Watson if (error) { 3062f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3063f7b951a8SRobert Watson return (error); 3064f7b951a8SRobert Watson } 3065f7b951a8SRobert Watson 306695fab37eSRobert Watson /* 306795fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 306895fab37eSRobert Watson * policies impose this check themselves if required by the 306995fab37eSRobert Watson * policy. Eventually, this should go away. 307095fab37eSRobert Watson */ 307195fab37eSRobert Watson error = suser_cred(cred, 0); 3072f7b951a8SRobert Watson if (error) { 3073f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3074f7b951a8SRobert Watson return (error); 3075f7b951a8SRobert Watson } 307695fab37eSRobert Watson 307795fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 307895fab37eSRobert Watson &intlabel); 3079f7b951a8SRobert Watson if (error) { 3080f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3081f7b951a8SRobert Watson return (error); 3082f7b951a8SRobert Watson } 308395fab37eSRobert Watson 308495fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 308595fab37eSRobert Watson 3086f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 3087f7b951a8SRobert Watson return (0); 308895fab37eSRobert Watson } 308995fab37eSRobert Watson 309095fab37eSRobert Watson void 3091990b4b2dSRobert Watson mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de) 309295fab37eSRobert Watson { 309395fab37eSRobert Watson 3094990b4b2dSRobert Watson MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label); 309595fab37eSRobert Watson } 309695fab37eSRobert Watson 309774e62b1bSRobert Watson void 3098990b4b2dSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct mount *mp, 3099990b4b2dSRobert Watson struct devfs_dirent *dd, struct devfs_dirent *de) 310074e62b1bSRobert Watson { 310174e62b1bSRobert Watson 3102990b4b2dSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de, 310374e62b1bSRobert Watson &de->de_label); 310474e62b1bSRobert Watson } 310574e62b1bSRobert Watson 310695fab37eSRobert Watson void 3107990b4b2dSRobert Watson mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, 310895fab37eSRobert Watson struct devfs_dirent *de) 310995fab37eSRobert Watson { 311095fab37eSRobert Watson 3111990b4b2dSRobert Watson MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de, 311295fab37eSRobert Watson &de->de_label); 311395fab37eSRobert Watson } 311495fab37eSRobert Watson 311595fab37eSRobert Watson int 311695fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 3117f7b951a8SRobert Watson struct mac *mac) 311895fab37eSRobert Watson { 311995fab37eSRobert Watson struct label intlabel; 3120f7b951a8SRobert Watson char *buffer; 312195fab37eSRobert Watson int error; 312295fab37eSRobert Watson 3123f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 312495fab37eSRobert Watson if (error) 312595fab37eSRobert Watson return (error); 312695fab37eSRobert Watson 3127a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3128f7b951a8SRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 3129f7b951a8SRobert Watson if (error) { 3130f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3131f7b951a8SRobert Watson return (error); 3132f7b951a8SRobert Watson } 3133f7b951a8SRobert Watson 3134a163d034SWarner Losh mac_init_socket_label(&intlabel, M_WAITOK); 3135f7b951a8SRobert Watson error = mac_internalize_socket_label(&intlabel, buffer); 3136f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3137f7b951a8SRobert Watson if (error) { 3138f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 3139f7b951a8SRobert Watson return (error); 3140f7b951a8SRobert Watson } 3141f7b951a8SRobert Watson 314295fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 314395fab37eSRobert Watson if (error) { 3144f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 314595fab37eSRobert Watson return (error); 314695fab37eSRobert Watson } 314795fab37eSRobert Watson 314895fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 314995fab37eSRobert Watson 3150f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 315195fab37eSRobert Watson return (0); 315295fab37eSRobert Watson } 315395fab37eSRobert Watson 315495fab37eSRobert Watson int 315595fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 315695fab37eSRobert Watson { 315795fab37eSRobert Watson int error; 315895fab37eSRobert Watson 31591aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 31601aa37f53SRobert Watson 316195fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 316295fab37eSRobert Watson if (error) 316395fab37eSRobert Watson return (error); 316495fab37eSRobert Watson 316595fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 316695fab37eSRobert Watson 316795fab37eSRobert Watson return (0); 316895fab37eSRobert Watson } 316995fab37eSRobert Watson 317095fab37eSRobert Watson int 317195fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 3172f7b951a8SRobert Watson struct mac *mac) 317395fab37eSRobert Watson { 3174f7b951a8SRobert Watson char *buffer, *elements; 3175f7b951a8SRobert Watson int error; 317695fab37eSRobert Watson 3177f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3178f7b951a8SRobert Watson if (error) 3179f7b951a8SRobert Watson return (error); 3180f7b951a8SRobert Watson 3181a163d034SWarner Losh elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3182f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3183f7b951a8SRobert Watson if (error) { 3184f7b951a8SRobert Watson free(elements, M_MACTEMP); 3185f7b951a8SRobert Watson return (error); 3186f7b951a8SRobert Watson } 3187f7b951a8SRobert Watson 3188a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3189f7b951a8SRobert Watson error = mac_externalize_socket_label(&so->so_label, elements, 3190a163d034SWarner Losh buffer, mac->m_buflen, M_WAITOK); 3191f7b951a8SRobert Watson if (error == 0) 3192f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3193f7b951a8SRobert Watson 3194f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3195f7b951a8SRobert Watson free(elements, M_MACTEMP); 3196f7b951a8SRobert Watson 3197f7b951a8SRobert Watson return (error); 319895fab37eSRobert Watson } 319995fab37eSRobert Watson 320095fab37eSRobert Watson int 320195fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 3202f7b951a8SRobert Watson struct mac *mac) 320395fab37eSRobert Watson { 3204f7b951a8SRobert Watson char *elements, *buffer; 3205f7b951a8SRobert Watson int error; 320695fab37eSRobert Watson 3207f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 3208f7b951a8SRobert Watson if (error) 3209f7b951a8SRobert Watson return (error); 3210f7b951a8SRobert Watson 3211a163d034SWarner Losh elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 3212f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 3213f7b951a8SRobert Watson if (error) { 3214f7b951a8SRobert Watson free(elements, M_MACTEMP); 3215f7b951a8SRobert Watson return (error); 3216f7b951a8SRobert Watson } 3217f7b951a8SRobert Watson 3218a163d034SWarner Losh buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3219f7b951a8SRobert Watson error = mac_externalize_socket_peer_label(&so->so_peerlabel, 3220a163d034SWarner Losh elements, buffer, mac->m_buflen, M_WAITOK); 3221f7b951a8SRobert Watson if (error == 0) 3222f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 3223f7b951a8SRobert Watson 3224f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3225f7b951a8SRobert Watson free(elements, M_MACTEMP); 3226f7b951a8SRobert Watson 3227f7b951a8SRobert Watson return (error); 322895fab37eSRobert Watson } 322995fab37eSRobert Watson 323095fab37eSRobert Watson /* 323195fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 323295fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 323395fab37eSRobert Watson * extended attributes. 323495fab37eSRobert Watson */ 323595fab37eSRobert Watson int 323695fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 323795fab37eSRobert Watson { 323895fab37eSRobert Watson struct vnode *vp = ap->a_vp; 323995fab37eSRobert Watson struct label *intlabel = ap->a_label; 324095fab37eSRobert Watson int error; 324195fab37eSRobert Watson 324295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 324395fab37eSRobert Watson 3244763bbd2fSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 3245763bbd2fSRobert Watson return (EOPNOTSUPP); 324695fab37eSRobert Watson 3247763bbd2fSRobert Watson error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 324895fab37eSRobert Watson if (error) 324995fab37eSRobert Watson return (error); 325095fab37eSRobert Watson 325195fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 325295fab37eSRobert Watson 325395fab37eSRobert Watson return (0); 325495fab37eSRobert Watson } 325595fab37eSRobert Watson 325695fab37eSRobert Watson static int 325795fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 325895fab37eSRobert Watson { 325995fab37eSRobert Watson int error; 326095fab37eSRobert Watson 326195fab37eSRobert Watson if (vp->v_mount == NULL) { 326295fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 326306be2aaaSNate Lawson if (vp->v_type != VNON) 326406be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 326595fab37eSRobert Watson return (EBADF); 326695fab37eSRobert Watson } 326795fab37eSRobert Watson 326895fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 326995fab37eSRobert Watson return (EOPNOTSUPP); 327095fab37eSRobert Watson 327195fab37eSRobert Watson /* 327295fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 327395fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 327495fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 327595fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 327695fab37eSRobert Watson */ 327795fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 327895fab37eSRobert Watson if (error) 327995fab37eSRobert Watson return (error); 328095fab37eSRobert Watson 328195fab37eSRobert Watson /* 328295fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 328395fab37eSRobert Watson * decisions about who is and is not able to modify labels 328495fab37eSRobert Watson * and protections on files. This might not be right. We can't 328595fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 328695fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 328795fab37eSRobert Watson */ 328895fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 328995fab37eSRobert Watson if (error) 329095fab37eSRobert Watson return (error); 329195fab37eSRobert Watson 329295fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 329395fab37eSRobert Watson if (error) 329495fab37eSRobert Watson return (error); 329595fab37eSRobert Watson 329695fab37eSRobert Watson return (0); 329795fab37eSRobert Watson } 329895fab37eSRobert Watson 3299f7b951a8SRobert Watson int 3300f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3301f7b951a8SRobert Watson { 3302f7b951a8SRobert Watson char *elements, *buffer; 3303f7b951a8SRobert Watson struct mac mac; 3304f7b951a8SRobert Watson struct proc *tproc; 3305f7b951a8SRobert Watson struct ucred *tcred; 3306f7b951a8SRobert Watson int error; 3307f7b951a8SRobert Watson 3308d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 3309f7b951a8SRobert Watson if (error) 3310f7b951a8SRobert Watson return (error); 3311f7b951a8SRobert Watson 3312f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3313f7b951a8SRobert Watson if (error) 3314f7b951a8SRobert Watson return (error); 3315f7b951a8SRobert Watson 3316f7b951a8SRobert Watson tproc = pfind(uap->pid); 3317f7b951a8SRobert Watson if (tproc == NULL) 3318f7b951a8SRobert Watson return (ESRCH); 3319f7b951a8SRobert Watson 3320f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 3321f7b951a8SRobert Watson error = p_cansee(td, tproc); 3322f7b951a8SRobert Watson if (error == 0) 3323f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 3324f7b951a8SRobert Watson PROC_UNLOCK(tproc); 3325f7b951a8SRobert Watson if (error) 3326f7b951a8SRobert Watson return (error); 3327f7b951a8SRobert Watson 3328a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3329f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3330f7b951a8SRobert Watson if (error) { 3331f7b951a8SRobert Watson free(elements, M_MACTEMP); 3332f7b951a8SRobert Watson crfree(tcred); 3333f7b951a8SRobert Watson return (error); 3334f7b951a8SRobert Watson } 3335f7b951a8SRobert Watson 3336a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3337f7b951a8SRobert Watson error = mac_externalize_cred_label(&tcred->cr_label, elements, 3338a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3339f7b951a8SRobert Watson if (error == 0) 3340f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3341f7b951a8SRobert Watson 3342f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3343f7b951a8SRobert Watson free(elements, M_MACTEMP); 3344f7b951a8SRobert Watson crfree(tcred); 3345f7b951a8SRobert Watson return (error); 3346f7b951a8SRobert Watson } 3347f7b951a8SRobert Watson 334895fab37eSRobert Watson /* 334995fab37eSRobert Watson * MPSAFE 335095fab37eSRobert Watson */ 335195fab37eSRobert Watson int 335295fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 335395fab37eSRobert Watson { 3354f7b951a8SRobert Watson char *elements, *buffer; 3355f7b951a8SRobert Watson struct mac mac; 335695fab37eSRobert Watson int error; 335795fab37eSRobert Watson 3358f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3359f7b951a8SRobert Watson if (error) 3360f7b951a8SRobert Watson return (error); 336195fab37eSRobert Watson 3362f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3363f7b951a8SRobert Watson if (error) 3364f7b951a8SRobert Watson return (error); 3365f7b951a8SRobert Watson 3366a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3367f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3368f7b951a8SRobert Watson if (error) { 3369f7b951a8SRobert Watson free(elements, M_MACTEMP); 3370f7b951a8SRobert Watson return (error); 3371f7b951a8SRobert Watson } 3372f7b951a8SRobert Watson 3373a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3374f7b951a8SRobert Watson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3375a163d034SWarner Losh elements, buffer, mac.m_buflen, M_WAITOK); 3376f7b951a8SRobert Watson if (error == 0) 3377f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3378f7b951a8SRobert Watson 3379f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3380f7b951a8SRobert Watson free(elements, M_MACTEMP); 338195fab37eSRobert Watson return (error); 338295fab37eSRobert Watson } 338395fab37eSRobert Watson 338495fab37eSRobert Watson /* 338595fab37eSRobert Watson * MPSAFE 338695fab37eSRobert Watson */ 338795fab37eSRobert Watson int 338895fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 338995fab37eSRobert Watson { 339095fab37eSRobert Watson struct ucred *newcred, *oldcred; 339195fab37eSRobert Watson struct label intlabel; 3392f7b951a8SRobert Watson struct proc *p; 3393f7b951a8SRobert Watson struct mac mac; 3394f7b951a8SRobert Watson char *buffer; 339595fab37eSRobert Watson int error; 339695fab37eSRobert Watson 3397f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 339895fab37eSRobert Watson if (error) 339995fab37eSRobert Watson return (error); 340095fab37eSRobert Watson 3401f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 340295fab37eSRobert Watson if (error) 340395fab37eSRobert Watson return (error); 340495fab37eSRobert Watson 3405a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3406f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3407f7b951a8SRobert Watson if (error) { 3408f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3409f7b951a8SRobert Watson return (error); 3410f7b951a8SRobert Watson } 3411f7b951a8SRobert Watson 3412f7b951a8SRobert Watson mac_init_cred_label(&intlabel); 3413f7b951a8SRobert Watson error = mac_internalize_cred_label(&intlabel, buffer); 3414f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3415f7b951a8SRobert Watson if (error) { 3416f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3417f7b951a8SRobert Watson return (error); 3418f7b951a8SRobert Watson } 3419f7b951a8SRobert Watson 342095fab37eSRobert Watson newcred = crget(); 342195fab37eSRobert Watson 342295fab37eSRobert Watson p = td->td_proc; 342395fab37eSRobert Watson PROC_LOCK(p); 342495fab37eSRobert Watson oldcred = p->p_ucred; 342595fab37eSRobert Watson 342695fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 342795fab37eSRobert Watson if (error) { 342895fab37eSRobert Watson PROC_UNLOCK(p); 342995fab37eSRobert Watson crfree(newcred); 3430f7b951a8SRobert Watson goto out; 343195fab37eSRobert Watson } 343295fab37eSRobert Watson 343395fab37eSRobert Watson setsugid(p); 343495fab37eSRobert Watson crcopy(newcred, oldcred); 343595fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 343695fab37eSRobert Watson p->p_ucred = newcred; 3437e5cb5e37SRobert Watson 3438e5cb5e37SRobert Watson /* 3439e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3440e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3441e5cb5e37SRobert Watson */ 3442e5cb5e37SRobert Watson crhold(newcred); 344395fab37eSRobert Watson PROC_UNLOCK(p); 3444e5cb5e37SRobert Watson 3445f7b951a8SRobert Watson if (mac_enforce_vm) { 344616140035SRobert Watson mtx_lock(&Giant); 3447e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 344816140035SRobert Watson mtx_unlock(&Giant); 3449f7b951a8SRobert Watson } 3450e5cb5e37SRobert Watson 3451e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 345295fab37eSRobert Watson crfree(oldcred); 3453f7b951a8SRobert Watson 3454f7b951a8SRobert Watson out: 3455f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3456f7b951a8SRobert Watson return (error); 345795fab37eSRobert Watson } 345895fab37eSRobert Watson 345995fab37eSRobert Watson /* 346095fab37eSRobert Watson * MPSAFE 346195fab37eSRobert Watson */ 346295fab37eSRobert Watson int 346395fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 346495fab37eSRobert Watson { 3465f7b951a8SRobert Watson char *elements, *buffer; 3466f7b951a8SRobert Watson struct label intlabel; 346795fab37eSRobert Watson struct file *fp; 3468f7b951a8SRobert Watson struct mac mac; 346995fab37eSRobert Watson struct vnode *vp; 347095fab37eSRobert Watson struct pipe *pipe; 3471f7b951a8SRobert Watson short label_type; 347295fab37eSRobert Watson int error; 347395fab37eSRobert Watson 3474f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3475f7b951a8SRobert Watson if (error) 3476f7b951a8SRobert Watson return (error); 347795fab37eSRobert Watson 3478f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3479f7b951a8SRobert Watson if (error) 3480f7b951a8SRobert Watson return (error); 3481f7b951a8SRobert Watson 3482a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3483f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3484f7b951a8SRobert Watson if (error) { 3485f7b951a8SRobert Watson free(elements, M_MACTEMP); 3486f7b951a8SRobert Watson return (error); 3487f7b951a8SRobert Watson } 3488f7b951a8SRobert Watson 3489a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3490f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3491d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 349295fab37eSRobert Watson if (error) 349395fab37eSRobert Watson goto out; 349495fab37eSRobert Watson 3495f7b951a8SRobert Watson label_type = fp->f_type; 349695fab37eSRobert Watson switch (fp->f_type) { 349795fab37eSRobert Watson case DTYPE_FIFO: 349895fab37eSRobert Watson case DTYPE_VNODE: 349948e3128bSMatthew Dillon vp = fp->f_data; 350095fab37eSRobert Watson 3501f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3502f7b951a8SRobert Watson 350395fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3504f7b951a8SRobert Watson mac_copy_vnode_label(&vp->v_label, &intlabel); 350595fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 3506f7b951a8SRobert Watson 350795fab37eSRobert Watson break; 350895fab37eSRobert Watson case DTYPE_PIPE: 350948e3128bSMatthew Dillon pipe = fp->f_data; 3510f7b951a8SRobert Watson 3511f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3512f7b951a8SRobert Watson 3513f7b951a8SRobert Watson PIPE_LOCK(pipe); 3514f7b951a8SRobert Watson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3515f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 351695fab37eSRobert Watson break; 351795fab37eSRobert Watson default: 351895fab37eSRobert Watson error = EINVAL; 3519f7b951a8SRobert Watson fdrop(fp, td); 3520f7b951a8SRobert Watson goto out; 3521f7b951a8SRobert Watson } 3522f7b951a8SRobert Watson fdrop(fp, td); 3523f7b951a8SRobert Watson 3524f7b951a8SRobert Watson switch (label_type) { 3525f7b951a8SRobert Watson case DTYPE_FIFO: 3526f7b951a8SRobert Watson case DTYPE_VNODE: 3527f7b951a8SRobert Watson if (error == 0) 3528f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, 3529a163d034SWarner Losh elements, buffer, mac.m_buflen, M_WAITOK); 3530f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3531f7b951a8SRobert Watson break; 3532f7b951a8SRobert Watson case DTYPE_PIPE: 3533f7b951a8SRobert Watson error = mac_externalize_pipe_label(&intlabel, elements, 3534a163d034SWarner Losh buffer, mac.m_buflen, M_WAITOK); 3535f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 3536f7b951a8SRobert Watson break; 3537f7b951a8SRobert Watson default: 3538f7b951a8SRobert Watson panic("__mac_get_fd: corrupted label_type"); 353995fab37eSRobert Watson } 354095fab37eSRobert Watson 354195fab37eSRobert Watson if (error == 0) 3542f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 354395fab37eSRobert Watson 354495fab37eSRobert Watson out: 3545f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3546f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3547f7b951a8SRobert Watson free(elements, M_MACTEMP); 3548f7b951a8SRobert Watson 354995fab37eSRobert Watson return (error); 355095fab37eSRobert Watson } 355195fab37eSRobert Watson 355295fab37eSRobert Watson /* 355395fab37eSRobert Watson * MPSAFE 355495fab37eSRobert Watson */ 355595fab37eSRobert Watson int 355695fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 355795fab37eSRobert Watson { 3558f7b951a8SRobert Watson char *elements, *buffer; 355995fab37eSRobert Watson struct nameidata nd; 3560f7b951a8SRobert Watson struct label intlabel; 3561f7b951a8SRobert Watson struct mac mac; 356295fab37eSRobert Watson int error; 356395fab37eSRobert Watson 3564f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3565f7b951a8SRobert Watson if (error) 3566f7b951a8SRobert Watson return (error); 3567f7b951a8SRobert Watson 3568f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3569f7b951a8SRobert Watson if (error) 3570f7b951a8SRobert Watson return (error); 3571f7b951a8SRobert Watson 3572a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3573f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3574f7b951a8SRobert Watson if (error) { 3575f7b951a8SRobert Watson free(elements, M_MACTEMP); 3576f7b951a8SRobert Watson return (error); 3577f7b951a8SRobert Watson } 3578f7b951a8SRobert Watson 3579a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3580f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3581f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3582f7b951a8SRobert Watson td); 358395fab37eSRobert Watson error = namei(&nd); 358495fab37eSRobert Watson if (error) 358595fab37eSRobert Watson goto out; 358695fab37eSRobert Watson 3587f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3588f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3589763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3590a163d034SWarner Losh mac.m_buflen, M_WAITOK); 3591f7b951a8SRobert Watson 359295fab37eSRobert Watson NDFREE(&nd, 0); 3593f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3594f7b951a8SRobert Watson 3595f7b951a8SRobert Watson if (error == 0) 3596f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3597f7b951a8SRobert Watson 3598f7b951a8SRobert Watson out: 3599f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3600f7b951a8SRobert Watson 3601f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3602f7b951a8SRobert Watson free(elements, M_MACTEMP); 3603f7b951a8SRobert Watson 3604f7b951a8SRobert Watson return (error); 3605f7b951a8SRobert Watson } 3606f7b951a8SRobert Watson 3607f7b951a8SRobert Watson /* 3608f7b951a8SRobert Watson * MPSAFE 3609f7b951a8SRobert Watson */ 3610f7b951a8SRobert Watson int 3611f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3612f7b951a8SRobert Watson { 3613f7b951a8SRobert Watson char *elements, *buffer; 3614f7b951a8SRobert Watson struct nameidata nd; 3615f7b951a8SRobert Watson struct label intlabel; 3616f7b951a8SRobert Watson struct mac mac; 3617f7b951a8SRobert Watson int error; 3618f7b951a8SRobert Watson 3619f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3620f7b951a8SRobert Watson if (error) 3621f7b951a8SRobert Watson return (error); 3622f7b951a8SRobert Watson 3623f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3624f7b951a8SRobert Watson if (error) 3625f7b951a8SRobert Watson return (error); 3626f7b951a8SRobert Watson 3627a163d034SWarner Losh elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3628f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3629f7b951a8SRobert Watson if (error) { 3630f7b951a8SRobert Watson free(elements, M_MACTEMP); 3631f7b951a8SRobert Watson return (error); 3632f7b951a8SRobert Watson } 3633f7b951a8SRobert Watson 3634a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3635f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3636f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3637f7b951a8SRobert Watson td); 3638f7b951a8SRobert Watson error = namei(&nd); 363995fab37eSRobert Watson if (error) 364095fab37eSRobert Watson goto out; 364195fab37eSRobert Watson 3642f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3643f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3644763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3645a163d034SWarner Losh mac.m_buflen, M_WAITOK); 3646f7b951a8SRobert Watson NDFREE(&nd, 0); 3647f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3648f7b951a8SRobert Watson 3649f7b951a8SRobert Watson if (error == 0) 3650f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 365195fab37eSRobert Watson 365295fab37eSRobert Watson out: 3653f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3654f7b951a8SRobert Watson 3655f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3656f7b951a8SRobert Watson free(elements, M_MACTEMP); 3657f7b951a8SRobert Watson 365895fab37eSRobert Watson return (error); 365995fab37eSRobert Watson } 366095fab37eSRobert Watson 366195fab37eSRobert Watson /* 366295fab37eSRobert Watson * MPSAFE 366395fab37eSRobert Watson */ 366495fab37eSRobert Watson int 366595fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 366695fab37eSRobert Watson { 366795fab37eSRobert Watson struct label intlabel; 3668f7b951a8SRobert Watson struct pipe *pipe; 3669f7b951a8SRobert Watson struct file *fp; 367095fab37eSRobert Watson struct mount *mp; 367195fab37eSRobert Watson struct vnode *vp; 3672f7b951a8SRobert Watson struct mac mac; 3673f7b951a8SRobert Watson char *buffer; 367495fab37eSRobert Watson int error; 367595fab37eSRobert Watson 3676f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3677f7b951a8SRobert Watson if (error) 3678f7b951a8SRobert Watson return (error); 3679f7b951a8SRobert Watson 3680f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3681f7b951a8SRobert Watson if (error) 3682f7b951a8SRobert Watson return (error); 3683f7b951a8SRobert Watson 3684a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3685f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3686f7b951a8SRobert Watson if (error) { 3687f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3688f7b951a8SRobert Watson return (error); 3689f7b951a8SRobert Watson } 3690f7b951a8SRobert Watson 3691f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3692f7b951a8SRobert Watson 3693d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 369495fab37eSRobert Watson if (error) 3695f7b951a8SRobert Watson goto out; 369695fab37eSRobert Watson 369795fab37eSRobert Watson switch (fp->f_type) { 369895fab37eSRobert Watson case DTYPE_FIFO: 369995fab37eSRobert Watson case DTYPE_VNODE: 3700f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3701f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3702f7b951a8SRobert Watson if (error) { 3703f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3704f7b951a8SRobert Watson break; 3705f7b951a8SRobert Watson } 3706f7b951a8SRobert Watson 370748e3128bSMatthew Dillon vp = fp->f_data; 370895fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3709f7b951a8SRobert Watson if (error != 0) { 3710f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 371195fab37eSRobert Watson break; 3712f7b951a8SRobert Watson } 371395fab37eSRobert Watson 371495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 371595fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 371695fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 371795fab37eSRobert Watson vn_finished_write(mp); 3718f7b951a8SRobert Watson 3719f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 372095fab37eSRobert Watson break; 3721f7b951a8SRobert Watson 372295fab37eSRobert Watson case DTYPE_PIPE: 3723f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3724f7b951a8SRobert Watson error = mac_internalize_pipe_label(&intlabel, buffer); 3725f7b951a8SRobert Watson if (error == 0) { 372648e3128bSMatthew Dillon pipe = fp->f_data; 37271aa37f53SRobert Watson PIPE_LOCK(pipe); 3728f7b951a8SRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, 3729f7b951a8SRobert Watson &intlabel); 37301aa37f53SRobert Watson PIPE_UNLOCK(pipe); 3731f7b951a8SRobert Watson } 3732f7b951a8SRobert Watson 3733f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 373495fab37eSRobert Watson break; 3735f7b951a8SRobert Watson 373695fab37eSRobert Watson default: 373795fab37eSRobert Watson error = EINVAL; 373895fab37eSRobert Watson } 373995fab37eSRobert Watson 374095fab37eSRobert Watson fdrop(fp, td); 3741f7b951a8SRobert Watson out: 3742f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3743f7b951a8SRobert Watson 3744f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3745f7b951a8SRobert Watson 374695fab37eSRobert Watson return (error); 374795fab37eSRobert Watson } 374895fab37eSRobert Watson 374995fab37eSRobert Watson /* 375095fab37eSRobert Watson * MPSAFE 375195fab37eSRobert Watson */ 375295fab37eSRobert Watson int 375395fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 375495fab37eSRobert Watson { 375595fab37eSRobert Watson struct label intlabel; 3756f7b951a8SRobert Watson struct nameidata nd; 375795fab37eSRobert Watson struct mount *mp; 3758f7b951a8SRobert Watson struct mac mac; 3759f7b951a8SRobert Watson char *buffer; 376095fab37eSRobert Watson int error; 376195fab37eSRobert Watson 3762f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 376395fab37eSRobert Watson if (error) 3764f7b951a8SRobert Watson return (error); 376595fab37eSRobert Watson 3766f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 376795fab37eSRobert Watson if (error) 3768f7b951a8SRobert Watson return (error); 376995fab37eSRobert Watson 3770a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3771f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3772f7b951a8SRobert Watson if (error) { 3773f7b951a8SRobert Watson free(buffer, M_MACTEMP); 377495fab37eSRobert Watson return (error); 377595fab37eSRobert Watson } 377695fab37eSRobert Watson 3777f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3778f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3779f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3780f7b951a8SRobert Watson if (error) { 3781f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3782f7b951a8SRobert Watson return (error); 3783f7b951a8SRobert Watson } 3784f7b951a8SRobert Watson 3785f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3786f7b951a8SRobert Watson 3787f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3788f7b951a8SRobert Watson td); 3789f7b951a8SRobert Watson error = namei(&nd); 3790f7b951a8SRobert Watson if (error == 0) { 3791f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3792f7b951a8SRobert Watson if (error == 0) 3793f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3794f7b951a8SRobert Watson td->td_ucred); 3795f7b951a8SRobert Watson vn_finished_write(mp); 3796f7b951a8SRobert Watson } 3797f7b951a8SRobert Watson 3798f7b951a8SRobert Watson NDFREE(&nd, 0); 3799f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3800f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3801f7b951a8SRobert Watson 3802f7b951a8SRobert Watson return (error); 3803f7b951a8SRobert Watson } 3804f7b951a8SRobert Watson 3805f7b951a8SRobert Watson /* 3806f7b951a8SRobert Watson * MPSAFE 3807f7b951a8SRobert Watson */ 3808f7b951a8SRobert Watson int 3809f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3810f7b951a8SRobert Watson { 3811f7b951a8SRobert Watson struct label intlabel; 3812f7b951a8SRobert Watson struct nameidata nd; 3813f7b951a8SRobert Watson struct mount *mp; 3814f7b951a8SRobert Watson struct mac mac; 3815f7b951a8SRobert Watson char *buffer; 3816f7b951a8SRobert Watson int error; 3817f7b951a8SRobert Watson 3818f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3819f7b951a8SRobert Watson if (error) 3820f7b951a8SRobert Watson return (error); 3821f7b951a8SRobert Watson 3822f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3823f7b951a8SRobert Watson if (error) 3824f7b951a8SRobert Watson return (error); 3825f7b951a8SRobert Watson 3826a163d034SWarner Losh buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3827f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3828f7b951a8SRobert Watson if (error) { 3829f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3830f7b951a8SRobert Watson return (error); 3831f7b951a8SRobert Watson } 3832f7b951a8SRobert Watson 3833f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3834f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3835f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3836f7b951a8SRobert Watson if (error) { 3837f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3838f7b951a8SRobert Watson return (error); 3839f7b951a8SRobert Watson } 3840f7b951a8SRobert Watson 3841f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3842f7b951a8SRobert Watson 3843f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3844f7b951a8SRobert Watson td); 3845f7b951a8SRobert Watson error = namei(&nd); 3846f7b951a8SRobert Watson if (error == 0) { 3847f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3848f7b951a8SRobert Watson if (error == 0) 3849f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3850f7b951a8SRobert Watson td->td_ucred); 3851f7b951a8SRobert Watson vn_finished_write(mp); 3852f7b951a8SRobert Watson } 3853f7b951a8SRobert Watson 3854f7b951a8SRobert Watson NDFREE(&nd, 0); 3855f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3856f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3857f7b951a8SRobert Watson 3858f7b951a8SRobert Watson return (error); 3859f7b951a8SRobert Watson } 3860f7b951a8SRobert Watson 3861f7b951a8SRobert Watson /* 3862f7b951a8SRobert Watson * MPSAFE 3863f7b951a8SRobert Watson */ 386427f2eac7SRobert Watson int 386527f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 386627f2eac7SRobert Watson { 386727f2eac7SRobert Watson struct mac_policy_conf *mpc; 386827f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 386941a17fe3SRobert Watson int entrycount, error; 387027f2eac7SRobert Watson 3871d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 387227f2eac7SRobert Watson if (error) 387327f2eac7SRobert Watson return (error); 387427f2eac7SRobert Watson 387527f2eac7SRobert Watson error = ENOSYS; 387627f2eac7SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 387727f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 387827f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 387927f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 3880d1e405c5SAlfred Perlstein uap->call, uap->arg); 388127f2eac7SRobert Watson goto out; 388227f2eac7SRobert Watson } 388327f2eac7SRobert Watson } 388427f2eac7SRobert Watson 388541a17fe3SRobert Watson if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 388641a17fe3SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 388741a17fe3SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 388841a17fe3SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 388941a17fe3SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 389041a17fe3SRobert Watson uap->call, uap->arg); 389141a17fe3SRobert Watson break; 389241a17fe3SRobert Watson } 389341a17fe3SRobert Watson } 389441a17fe3SRobert Watson mac_policy_list_unbusy(); 389541a17fe3SRobert Watson } 389627f2eac7SRobert Watson out: 389727f2eac7SRobert Watson return (error); 389827f2eac7SRobert Watson } 389927f2eac7SRobert Watson 390095fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 390195fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 390295fab37eSRobert Watson 390395fab37eSRobert Watson #else /* !MAC */ 39047bc82500SRobert Watson 39057bc82500SRobert Watson int 3906f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3907f7b951a8SRobert Watson { 3908f7b951a8SRobert Watson 3909f7b951a8SRobert Watson return (ENOSYS); 3910f7b951a8SRobert Watson } 3911f7b951a8SRobert Watson 3912f7b951a8SRobert Watson int 39137bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 39147bc82500SRobert Watson { 39157bc82500SRobert Watson 39167bc82500SRobert Watson return (ENOSYS); 39177bc82500SRobert Watson } 39187bc82500SRobert Watson 39197bc82500SRobert Watson int 39207bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 39217bc82500SRobert Watson { 39227bc82500SRobert Watson 39237bc82500SRobert Watson return (ENOSYS); 39247bc82500SRobert Watson } 39257bc82500SRobert Watson 39267bc82500SRobert Watson int 39277bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 39287bc82500SRobert Watson { 39297bc82500SRobert Watson 39307bc82500SRobert Watson return (ENOSYS); 39317bc82500SRobert Watson } 39327bc82500SRobert Watson 39337bc82500SRobert Watson int 39347bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 39357bc82500SRobert Watson { 39367bc82500SRobert Watson 39377bc82500SRobert Watson return (ENOSYS); 39387bc82500SRobert Watson } 39397bc82500SRobert Watson 39407bc82500SRobert Watson int 3941f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3942f7b951a8SRobert Watson { 3943f7b951a8SRobert Watson 3944f7b951a8SRobert Watson return (ENOSYS); 3945f7b951a8SRobert Watson } 3946f7b951a8SRobert Watson 3947f7b951a8SRobert Watson int 39487bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 39497bc82500SRobert Watson { 39507bc82500SRobert Watson 39517bc82500SRobert Watson return (ENOSYS); 39527bc82500SRobert Watson } 39537bc82500SRobert Watson 39547bc82500SRobert Watson int 39557bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 39567bc82500SRobert Watson { 39577bc82500SRobert Watson 39587bc82500SRobert Watson return (ENOSYS); 39597bc82500SRobert Watson } 396095fab37eSRobert Watson 396127f2eac7SRobert Watson int 3962f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3963f7b951a8SRobert Watson { 3964f7b951a8SRobert Watson 3965f7b951a8SRobert Watson return (ENOSYS); 3966f7b951a8SRobert Watson } 3967f7b951a8SRobert Watson 3968f7b951a8SRobert Watson int 396927f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 397027f2eac7SRobert Watson { 397127f2eac7SRobert Watson 397227f2eac7SRobert Watson return (ENOSYS); 397327f2eac7SRobert Watson } 397427f2eac7SRobert Watson 3975f7b951a8SRobert Watson #endif 3976