17bc82500SRobert Watson /*- 27bc82500SRobert Watson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 37bc82500SRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 47bc82500SRobert Watson * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 57bc82500SRobert Watson * All rights reserved. 67bc82500SRobert Watson * 77bc82500SRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 87bc82500SRobert Watson * TrustedBSD Project. 97bc82500SRobert Watson * 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 10195fab37eSRobert Watson #if MAC_MAX_POLICIES > 32 10295fab37eSRobert Watson #error "MAC_MAX_POLICIES too large" 10395fab37eSRobert Watson #endif 104a13c67daSRobert Watson 10595fab37eSRobert Watson static unsigned int mac_max_policies = MAC_MAX_POLICIES; 10695fab37eSRobert Watson static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 10795fab37eSRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 10895fab37eSRobert Watson &mac_max_policies, 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 12395fab37eSRobert Watson static int mac_enforce_fs = 1; 12495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 12595fab37eSRobert Watson &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 12695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 12795fab37eSRobert Watson 128a3df768bSRobert Watson static int mac_enforce_kld = 1; 129a3df768bSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW, 130a3df768bSRobert Watson &mac_enforce_kld, 0, "Enforce MAC policy on kld operations"); 131a3df768bSRobert Watson TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld); 132a3df768bSRobert Watson 13395fab37eSRobert Watson static int mac_enforce_network = 1; 13495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 13595fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 13695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 13795fab37eSRobert Watson 138b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 139b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 140b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 141c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 142b88c98f6SRobert Watson 14395fab37eSRobert Watson static int mac_enforce_process = 1; 14495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 14595fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 14695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 14795fab37eSRobert Watson 14895fab37eSRobert Watson static int mac_enforce_socket = 1; 14995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 15095fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 15195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 15295fab37eSRobert Watson 1539e913ebdSRobert Watson static int mac_enforce_system = 1; 1549e913ebdSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 1559e913ebdSRobert Watson &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 1569e913ebdSRobert Watson TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 157d3fc69eeSRobert Watson 158ca7850c3SRobert Watson static int mac_enforce_vm = 1; 159ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 160ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 161c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 162ca7850c3SRobert Watson 163c0f39905SRobert Watson static int mac_mmap_revocation = 1; 164c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 165c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 166c0f39905SRobert Watson "relabel"); 16799fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 16895fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 16995fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 17095fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 17195fab37eSRobert Watson 172f050add5SRobert Watson #ifdef MAC_DEBUG 1736be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1746be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1756be0c25eSRobert Watson 1766be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1776be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1786be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1796be0c25eSRobert Watson "when label is corrupted."); 1806be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1816be0c25eSRobert Watson &mac_debug_label_fallback); 1826be0c25eSRobert Watson 183b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 184b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 185b2f0927aSRobert Watson 18695fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 18795fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 1882555374cSRobert Watson nmacipqs, nmacpipes, nmacprocs; 189b2f0927aSRobert Watson 190b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 19195fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 192b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 19395fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 194b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 19595fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 196b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 19795fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 198b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 19995fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 200b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 20195fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 202b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 20395fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 2042555374cSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD, 2052555374cSRobert Watson &nmacprocs, 0, "number of procs in use"); 206b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 20795fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 208b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 20995fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 210b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 21195fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 212b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 21395fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 214f050add5SRobert Watson #endif 21595fab37eSRobert Watson 21695fab37eSRobert Watson static int error_select(int error1, int error2); 21795fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 21895fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 21995fab37eSRobert Watson 220e183f80eSRobert Watson static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 221e183f80eSRobert Watson struct vnode *vp, int *prot); 22295fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 22395fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 22495fab37eSRobert Watson 22583985c26SRobert Watson static void mac_destroy_socket_label(struct label *label); 22683985c26SRobert Watson 227763bbd2fSRobert Watson static int mac_setlabel_vnode_extattr(struct ucred *cred, 228763bbd2fSRobert Watson struct vnode *vp, struct label *intlabel); 229763bbd2fSRobert Watson 23095fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 231f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 23295fab37eSRobert Watson 23395fab37eSRobert Watson /* 234a96acd1aSRobert Watson * mac_policy_list stores the list of active policies. A busy count is 235a96acd1aSRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count 236a96acd1aSRobert Watson * is protected by mac_policy_list_lock; the list may be modified only 237a96acd1aSRobert Watson * while the busy count is 0, requiring that the lock be held to 238a96acd1aSRobert Watson * prevent new references to the list from being acquired. For almost 239a96acd1aSRobert Watson * all operations, incrementing the busy count is sufficient to 240a96acd1aSRobert Watson * guarantee consistency, as the list cannot be modified while the 241a96acd1aSRobert Watson * busy count is elevated. For a few special operations involving a 242a96acd1aSRobert Watson * change to the list of active policies, the lock itself must be held. 243a96acd1aSRobert Watson * A condition variable, mac_policy_list_not_busy, is used to signal 244a96acd1aSRobert Watson * potential exclusive consumers that they should try to acquire the 245a96acd1aSRobert Watson * lock if a first attempt at exclusive access fails. 24695fab37eSRobert Watson */ 24795fab37eSRobert Watson static struct mtx mac_policy_list_lock; 248a96acd1aSRobert Watson static struct cv mac_policy_list_not_busy; 24995fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 25095fab37eSRobert Watson static int mac_policy_list_busy; 251a96acd1aSRobert Watson 252a96acd1aSRobert Watson #define MAC_POLICY_LIST_LOCKINIT() do { \ 253a96acd1aSRobert Watson mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL, \ 254a96acd1aSRobert Watson MTX_DEF); \ 255a96acd1aSRobert Watson cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy"); \ 256a96acd1aSRobert Watson } while (0) 257a96acd1aSRobert Watson 258a96acd1aSRobert Watson #define MAC_POLICY_LIST_LOCK() do { \ 259a96acd1aSRobert Watson mtx_lock(&mac_policy_list_lock); \ 260a96acd1aSRobert Watson } while (0) 261a96acd1aSRobert Watson 262a96acd1aSRobert Watson #define MAC_POLICY_LIST_UNLOCK() do { \ 263a96acd1aSRobert Watson mtx_unlock(&mac_policy_list_lock); \ 264a96acd1aSRobert Watson } while (0) 265a96acd1aSRobert Watson 266a96acd1aSRobert Watson /* 267a96acd1aSRobert Watson * We manually invoke WITNESS_SLEEP() to allow Witness to generate 268a96acd1aSRobert Watson * warnings even if we don't end up ever triggering the wait at 269a96acd1aSRobert Watson * run-time. The consumer of the exclusive interface must not hold 270a96acd1aSRobert Watson * any locks (other than potentially Giant) since we may sleep for 271a96acd1aSRobert Watson * long (potentially indefinite) periods of time waiting for the 272a96acd1aSRobert Watson * framework to become quiescent so that a policy list change may 273a96acd1aSRobert Watson * be made. 274a96acd1aSRobert Watson */ 275a96acd1aSRobert Watson #define MAC_POLICY_LIST_EXCLUSIVE() do { \ 276a96acd1aSRobert Watson WITNESS_SLEEP(1, NULL); \ 277a96acd1aSRobert Watson mtx_lock(&mac_policy_list_lock); \ 278a96acd1aSRobert Watson while (mac_policy_list_busy != 0) \ 279a96acd1aSRobert Watson cv_wait(&mac_policy_list_not_busy, \ 280a96acd1aSRobert Watson &mac_policy_list_lock); \ 281a96acd1aSRobert Watson } while (0) 28295fab37eSRobert Watson 28395fab37eSRobert Watson #define MAC_POLICY_LIST_BUSY() do { \ 28495fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 28595fab37eSRobert Watson mac_policy_list_busy++; \ 28695fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 28795fab37eSRobert Watson } while (0) 28895fab37eSRobert Watson 28995fab37eSRobert Watson #define MAC_POLICY_LIST_UNBUSY() do { \ 29095fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 29195fab37eSRobert Watson mac_policy_list_busy--; \ 292a96acd1aSRobert Watson KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK")); \ 293a96acd1aSRobert Watson if (mac_policy_list_busy == 0) \ 294a96acd1aSRobert Watson cv_signal(&mac_policy_list_not_busy); \ 29595fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 29695fab37eSRobert Watson } while (0) 29795fab37eSRobert Watson 29895fab37eSRobert Watson /* 29995fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 30095fab37eSRobert Watson * module list and checking with each as to how it feels about the 30195fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 30295fab37eSRobert Watson * of the caller. 30395fab37eSRobert Watson */ 30495fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 30595fab37eSRobert Watson struct mac_policy_conf *mpc; \ 30695fab37eSRobert Watson \ 30795fab37eSRobert Watson error = 0; \ 30895fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 30995fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 31095fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 31195fab37eSRobert Watson error = error_select( \ 31295fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 31395fab37eSRobert Watson error); \ 31495fab37eSRobert Watson } \ 31595fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 31695fab37eSRobert Watson } while (0) 31795fab37eSRobert Watson 31895fab37eSRobert Watson /* 31995fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 32095fab37eSRobert Watson * the module list, invoking each instance of the operation, and 32195fab37eSRobert Watson * combining the results using the passed C operator. Note that it 32295fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 32395fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 32495fab37eSRobert Watson * a meaningful result. 32595fab37eSRobert Watson */ 32695fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 32795fab37eSRobert Watson struct mac_policy_conf *mpc; \ 32895fab37eSRobert Watson \ 32995fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 33095fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 33195fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 33295fab37eSRobert Watson result = result composition \ 33395fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 33495fab37eSRobert Watson } \ 33595fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 33695fab37eSRobert Watson } while (0) 33795fab37eSRobert Watson 338f7b951a8SRobert Watson #define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 339f7b951a8SRobert Watson outbuflen) do { \ 340f7b951a8SRobert Watson char *curptr, *curptr_start, *element_name, *element_temp; \ 341f7b951a8SRobert Watson size_t left, left_start, len; \ 342f7b951a8SRobert Watson int claimed, first, first_start, ignorenotfound; \ 343f7b951a8SRobert Watson \ 344f7b951a8SRobert Watson error = 0; \ 345f7b951a8SRobert Watson element_temp = elementlist; \ 346f7b951a8SRobert Watson curptr = outbuf; \ 347f7b951a8SRobert Watson curptr[0] = '\0'; \ 348f7b951a8SRobert Watson left = outbuflen; \ 349f7b951a8SRobert Watson first = 1; \ 350f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 351f7b951a8SRobert Watson curptr_start = curptr; \ 352f7b951a8SRobert Watson left_start = left; \ 353f7b951a8SRobert Watson first_start = first; \ 354f7b951a8SRobert Watson if (element_name[0] == '?') { \ 355f7b951a8SRobert Watson element_name++; \ 356f7b951a8SRobert Watson ignorenotfound = 1; \ 357f7b951a8SRobert Watson } else \ 358f7b951a8SRobert Watson ignorenotfound = 0; \ 359f7b951a8SRobert Watson claimed = 0; \ 360f7b951a8SRobert Watson if (first) { \ 361f7b951a8SRobert Watson len = snprintf(curptr, left, "%s/", \ 362f7b951a8SRobert Watson element_name); \ 363f7b951a8SRobert Watson first = 0; \ 364f7b951a8SRobert Watson } else \ 365f7b951a8SRobert Watson len = snprintf(curptr, left, ",%s/", \ 366f7b951a8SRobert Watson element_name); \ 367f7b951a8SRobert Watson if (len >= left) { \ 368f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 369f7b951a8SRobert Watson break; \ 370f7b951a8SRobert Watson } \ 371f7b951a8SRobert Watson curptr += len; \ 372f7b951a8SRobert Watson left -= len; \ 373f7b951a8SRobert Watson \ 374f7b951a8SRobert Watson MAC_CHECK(externalize_ ## type, label, element_name, \ 375f7b951a8SRobert Watson curptr, left, &len, &claimed); \ 376f7b951a8SRobert Watson if (error) \ 377f7b951a8SRobert Watson break; \ 378f7b951a8SRobert Watson if (claimed == 1) { \ 379f7b951a8SRobert Watson if (len >= outbuflen) { \ 380f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 381f7b951a8SRobert Watson break; \ 382f7b951a8SRobert Watson } \ 383f7b951a8SRobert Watson curptr += len; \ 384f7b951a8SRobert Watson left -= len; \ 385f7b951a8SRobert Watson } else if (claimed == 0 && ignorenotfound) { \ 386f7b951a8SRobert Watson /* \ 387f7b951a8SRobert Watson * Revert addition of the label element \ 388f7b951a8SRobert Watson * name. \ 389f7b951a8SRobert Watson */ \ 390f7b951a8SRobert Watson curptr = curptr_start; \ 391f7b951a8SRobert Watson *curptr = '\0'; \ 392f7b951a8SRobert Watson left = left_start; \ 393f7b951a8SRobert Watson first = first_start; \ 394f7b951a8SRobert Watson } else { \ 395f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: ENOLABEL */ \ 396f7b951a8SRobert Watson break; \ 397f7b951a8SRobert Watson } \ 398f7b951a8SRobert Watson } \ 399f7b951a8SRobert Watson } while (0) 400f7b951a8SRobert Watson 401f7b951a8SRobert Watson #define MAC_INTERNALIZE(type, label, instring) do { \ 402f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 403f7b951a8SRobert Watson int claimed; \ 404f7b951a8SRobert Watson \ 405f7b951a8SRobert Watson error = 0; \ 406f7b951a8SRobert Watson element = instring; \ 407f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 408f7b951a8SRobert Watson element_data = element_name; \ 409f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 410f7b951a8SRobert Watson if (element_data == NULL) { \ 411f7b951a8SRobert Watson error = EINVAL; \ 412f7b951a8SRobert Watson break; \ 413f7b951a8SRobert Watson } \ 414f7b951a8SRobert Watson claimed = 0; \ 415f7b951a8SRobert Watson MAC_CHECK(internalize_ ## type, label, element_name, \ 416f7b951a8SRobert Watson element_data, &claimed); \ 417f7b951a8SRobert Watson if (error) \ 418f7b951a8SRobert Watson break; \ 419f7b951a8SRobert Watson if (claimed != 1) { \ 420f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 421f7b951a8SRobert Watson error = EINVAL; \ 422f7b951a8SRobert Watson break; \ 423f7b951a8SRobert Watson } \ 424f7b951a8SRobert Watson } \ 425f7b951a8SRobert Watson } while (0) 426f7b951a8SRobert Watson 42795fab37eSRobert Watson /* 42895fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 42995fab37eSRobert Watson * module list and invoking that operation for each policy. 43095fab37eSRobert Watson */ 43195fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 43295fab37eSRobert Watson struct mac_policy_conf *mpc; \ 43395fab37eSRobert Watson \ 43495fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 43595fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 43695fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 43795fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 43895fab37eSRobert Watson } \ 43995fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 44095fab37eSRobert Watson } while (0) 44195fab37eSRobert Watson 44295fab37eSRobert Watson /* 44395fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 44495fab37eSRobert Watson */ 44595fab37eSRobert Watson static void 44695fab37eSRobert Watson mac_init(void) 44795fab37eSRobert Watson { 44895fab37eSRobert Watson 44995fab37eSRobert Watson LIST_INIT(&mac_policy_list); 45095fab37eSRobert Watson MAC_POLICY_LIST_LOCKINIT(); 45195fab37eSRobert Watson } 45295fab37eSRobert Watson 45395fab37eSRobert Watson /* 45495fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 45595fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 45695fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 45795fab37eSRobert Watson */ 45895fab37eSRobert Watson static void 45995fab37eSRobert Watson mac_late_init(void) 46095fab37eSRobert Watson { 46195fab37eSRobert Watson 46295fab37eSRobert Watson mac_late = 1; 46395fab37eSRobert Watson } 46495fab37eSRobert Watson 46595fab37eSRobert Watson /* 46695fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 46795fab37eSRobert Watson */ 46895fab37eSRobert Watson int 46995fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 47095fab37eSRobert Watson { 47195fab37eSRobert Watson struct mac_policy_conf *mpc; 47295fab37eSRobert Watson int error; 47395fab37eSRobert Watson 47495fab37eSRobert Watson error = 0; 47595fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 47695fab37eSRobert Watson 47795fab37eSRobert Watson switch (type) { 47895fab37eSRobert Watson case MOD_LOAD: 47995fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 48095fab37eSRobert Watson mac_late) { 48195fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 48295fab37eSRobert Watson "after booting\n", mpc->mpc_name); 48395fab37eSRobert Watson error = EBUSY; 48495fab37eSRobert Watson break; 48595fab37eSRobert Watson } 48695fab37eSRobert Watson error = mac_policy_register(mpc); 48795fab37eSRobert Watson break; 48895fab37eSRobert Watson case MOD_UNLOAD: 48995fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 49095fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 49195fab37eSRobert Watson != 0) 49295fab37eSRobert Watson error = mac_policy_unregister(mpc); 49395fab37eSRobert Watson else 49495fab37eSRobert Watson error = 0; 49595fab37eSRobert Watson break; 49695fab37eSRobert Watson default: 49795fab37eSRobert Watson break; 49895fab37eSRobert Watson } 49995fab37eSRobert Watson 50095fab37eSRobert Watson return (error); 50195fab37eSRobert Watson } 50295fab37eSRobert Watson 50395fab37eSRobert Watson static int 50495fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 50595fab37eSRobert Watson { 50695fab37eSRobert Watson struct mac_policy_conf *tmpc; 50795fab37eSRobert Watson int slot; 50895fab37eSRobert Watson 509a96acd1aSRobert Watson MAC_POLICY_LIST_EXCLUSIVE(); 51095fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 51195fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 51295fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 51395fab37eSRobert Watson return (EEXIST); 51495fab37eSRobert Watson } 51595fab37eSRobert Watson } 51695fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 51795fab37eSRobert Watson slot = ffs(mac_policy_offsets_free); 51895fab37eSRobert Watson if (slot == 0) { 51995fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 52095fab37eSRobert Watson return (ENOMEM); 52195fab37eSRobert Watson } 52295fab37eSRobert Watson slot--; 52395fab37eSRobert Watson mac_policy_offsets_free &= ~(1 << slot); 52495fab37eSRobert Watson *mpc->mpc_field_off = slot; 52595fab37eSRobert Watson } 52695fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 52795fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 52895fab37eSRobert Watson 52995fab37eSRobert Watson /* Per-policy initialization. */ 53095fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 53195fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 53295fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 53395fab37eSRobert Watson 53495fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 53595fab37eSRobert Watson mpc->mpc_name); 53695fab37eSRobert Watson 53795fab37eSRobert Watson return (0); 53895fab37eSRobert Watson } 53995fab37eSRobert Watson 54095fab37eSRobert Watson static int 54195fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 54295fab37eSRobert Watson { 54395fab37eSRobert Watson 544ea599aa0SRobert Watson /* 545ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 546ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 547ea599aa0SRobert Watson * silently succeed. 548ea599aa0SRobert Watson */ 549a96acd1aSRobert Watson MAC_POLICY_LIST_EXCLUSIVE(); 550ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 551ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 552ea599aa0SRobert Watson return (0); 553ea599aa0SRobert Watson } 55495fab37eSRobert Watson #if 0 55595fab37eSRobert Watson /* 55695fab37eSRobert Watson * Don't allow unloading modules with private data. 55795fab37eSRobert Watson */ 558ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 559ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 56095fab37eSRobert Watson return (EBUSY); 561ea599aa0SRobert Watson } 56295fab37eSRobert Watson #endif 563ea599aa0SRobert Watson /* 564ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 565ea599aa0SRobert Watson * by its own definition. 566ea599aa0SRobert Watson */ 567ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 568ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 56995fab37eSRobert Watson return (EBUSY); 570ea599aa0SRobert Watson } 57195fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 57295fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 57395fab37eSRobert Watson 57495fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 5759aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 57695fab37eSRobert Watson 577a96acd1aSRobert Watson MAC_POLICY_LIST_UNLOCK(); 578a96acd1aSRobert Watson 57995fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 58095fab37eSRobert Watson mpc->mpc_name); 58195fab37eSRobert Watson 58295fab37eSRobert Watson return (0); 58395fab37eSRobert Watson } 58495fab37eSRobert Watson 58595fab37eSRobert Watson /* 58695fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 58795fab37eSRobert Watson * value with the higher precedence. 58895fab37eSRobert Watson */ 58995fab37eSRobert Watson static int 59095fab37eSRobert Watson error_select(int error1, int error2) 59195fab37eSRobert Watson { 59295fab37eSRobert Watson 59395fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 59495fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 59595fab37eSRobert Watson return (EDEADLK); 59695fab37eSRobert Watson 59795fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 59895fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 59995fab37eSRobert Watson return (EINVAL); 60095fab37eSRobert Watson 60195fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 60295fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 60395fab37eSRobert Watson return (ESRCH); 60495fab37eSRobert Watson 60595fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 60695fab37eSRobert Watson return (ENOENT); 60795fab37eSRobert Watson 60895fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 60995fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 61095fab37eSRobert Watson return (EACCES); 61195fab37eSRobert Watson 61295fab37eSRobert Watson /* Precedence goes to privilege. */ 61395fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 61495fab37eSRobert Watson return (EPERM); 61595fab37eSRobert Watson 61695fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 61795fab37eSRobert Watson if (error1 != 0) 61895fab37eSRobert Watson return (error1); 61995fab37eSRobert Watson return (error2); 62095fab37eSRobert Watson } 62195fab37eSRobert Watson 62208bcdc58SRobert Watson static void 62308bcdc58SRobert Watson mac_init_label(struct label *label) 62408bcdc58SRobert Watson { 62508bcdc58SRobert Watson 62608bcdc58SRobert Watson bzero(label, sizeof(*label)); 62708bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 62808bcdc58SRobert Watson } 62908bcdc58SRobert Watson 63008bcdc58SRobert Watson static void 63108bcdc58SRobert Watson mac_destroy_label(struct label *label) 63208bcdc58SRobert Watson { 63308bcdc58SRobert Watson 63408bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 63508bcdc58SRobert Watson ("destroying uninitialized label")); 63608bcdc58SRobert Watson 63708bcdc58SRobert Watson bzero(label, sizeof(*label)); 63808bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 63908bcdc58SRobert Watson } 64008bcdc58SRobert Watson 64108bcdc58SRobert Watson void 64287807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 64308bcdc58SRobert Watson { 64408bcdc58SRobert Watson 64587807196SRobert Watson mac_init_label(&bpf_d->bd_label); 64687807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 64708bcdc58SRobert Watson #ifdef MAC_DEBUG 64887807196SRobert Watson atomic_add_int(&nmacbpfdescs, 1); 64908bcdc58SRobert Watson #endif 65008bcdc58SRobert Watson } 65108bcdc58SRobert Watson 652f7b951a8SRobert Watson static void 653f7b951a8SRobert Watson mac_init_cred_label(struct label *label) 65408bcdc58SRobert Watson { 65508bcdc58SRobert Watson 656f7b951a8SRobert Watson mac_init_label(label); 657f7b951a8SRobert Watson MAC_PERFORM(init_cred_label, label); 65808bcdc58SRobert Watson #ifdef MAC_DEBUG 65908bcdc58SRobert Watson atomic_add_int(&nmaccreds, 1); 66008bcdc58SRobert Watson #endif 66108bcdc58SRobert Watson } 66208bcdc58SRobert Watson 66308bcdc58SRobert Watson void 664f7b951a8SRobert Watson mac_init_cred(struct ucred *cred) 665f7b951a8SRobert Watson { 666f7b951a8SRobert Watson 667f7b951a8SRobert Watson mac_init_cred_label(&cred->cr_label); 668f7b951a8SRobert Watson } 669f7b951a8SRobert Watson 670f7b951a8SRobert Watson void 67187807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 67208bcdc58SRobert Watson { 67308bcdc58SRobert Watson 67487807196SRobert Watson mac_init_label(&de->de_label); 67587807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 67608bcdc58SRobert Watson #ifdef MAC_DEBUG 67787807196SRobert Watson atomic_add_int(&nmacdevfsdirents, 1); 67808bcdc58SRobert Watson #endif 67908bcdc58SRobert Watson } 68008bcdc58SRobert Watson 681f7b951a8SRobert Watson static void 682f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label) 683f7b951a8SRobert Watson { 684f7b951a8SRobert Watson 685f7b951a8SRobert Watson mac_init_label(label); 686f7b951a8SRobert Watson MAC_PERFORM(init_ifnet_label, label); 687f7b951a8SRobert Watson #ifdef MAC_DEBUG 688f7b951a8SRobert Watson atomic_add_int(&nmacifnets, 1); 689f7b951a8SRobert Watson #endif 690f7b951a8SRobert Watson } 691f7b951a8SRobert Watson 69208bcdc58SRobert Watson void 69308bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 69408bcdc58SRobert Watson { 69508bcdc58SRobert Watson 696f7b951a8SRobert Watson mac_init_ifnet_label(&ifp->if_label); 69708bcdc58SRobert Watson } 69808bcdc58SRobert Watson 69908bcdc58SRobert Watson void 70008bcdc58SRobert Watson mac_init_ipq(struct ipq *ipq) 70108bcdc58SRobert Watson { 70208bcdc58SRobert Watson 70308bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 70408bcdc58SRobert Watson MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 70508bcdc58SRobert Watson #ifdef MAC_DEBUG 70608bcdc58SRobert Watson atomic_add_int(&nmacipqs, 1); 70708bcdc58SRobert Watson #endif 70808bcdc58SRobert Watson } 70908bcdc58SRobert Watson 71087807196SRobert Watson int 71187807196SRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 71208bcdc58SRobert Watson { 71356c15412SRobert Watson int error; 71456c15412SRobert Watson 71587807196SRobert Watson KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 71608bcdc58SRobert Watson 71787807196SRobert Watson mac_init_label(&m->m_pkthdr.label); 71887807196SRobert Watson 71956c15412SRobert Watson MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 72056c15412SRobert Watson if (error) { 72156c15412SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 72256c15412SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 72356c15412SRobert Watson } 72456c15412SRobert Watson 72508bcdc58SRobert Watson #ifdef MAC_DEBUG 72656c15412SRobert Watson if (error == 0) 72787807196SRobert Watson atomic_add_int(&nmacmbufs, 1); 72808bcdc58SRobert Watson #endif 72956c15412SRobert Watson return (error); 73008bcdc58SRobert Watson } 73108bcdc58SRobert Watson 73208bcdc58SRobert Watson void 73387807196SRobert Watson mac_init_mount(struct mount *mp) 73408bcdc58SRobert Watson { 73508bcdc58SRobert Watson 73687807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 73787807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 73887807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 73987807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 74008bcdc58SRobert Watson #ifdef MAC_DEBUG 74187807196SRobert Watson atomic_add_int(&nmacmounts, 1); 74208bcdc58SRobert Watson #endif 74308bcdc58SRobert Watson } 74408bcdc58SRobert Watson 745f7b951a8SRobert Watson static void 746f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 747f7b951a8SRobert Watson { 748f7b951a8SRobert Watson 749f7b951a8SRobert Watson mac_init_label(label); 750f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 751f7b951a8SRobert Watson #ifdef MAC_DEBUG 752f7b951a8SRobert Watson atomic_add_int(&nmacpipes, 1); 753f7b951a8SRobert Watson #endif 754f7b951a8SRobert Watson } 755f7b951a8SRobert Watson 75608bcdc58SRobert Watson void 75708bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 75808bcdc58SRobert Watson { 75908bcdc58SRobert Watson struct label *label; 76008bcdc58SRobert Watson 76108bcdc58SRobert Watson label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 76208bcdc58SRobert Watson pipe->pipe_label = label; 76308bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 764f7b951a8SRobert Watson mac_init_pipe_label(label); 76508bcdc58SRobert Watson } 76608bcdc58SRobert Watson 7672555374cSRobert Watson void 7682555374cSRobert Watson mac_init_proc(struct proc *p) 7692555374cSRobert Watson { 7702555374cSRobert Watson 7712555374cSRobert Watson mac_init_label(&p->p_label); 7722555374cSRobert Watson MAC_PERFORM(init_proc_label, &p->p_label); 7732555374cSRobert Watson #ifdef MAC_DEBUG 7742555374cSRobert Watson atomic_add_int(&nmacprocs, 1); 7752555374cSRobert Watson #endif 7762555374cSRobert Watson } 7772555374cSRobert Watson 77883985c26SRobert Watson static int 77983985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 78008bcdc58SRobert Watson { 78183985c26SRobert Watson int error; 78208bcdc58SRobert Watson 78383985c26SRobert Watson mac_init_label(label); 78483985c26SRobert Watson 78583985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 78683985c26SRobert Watson if (error) { 78783985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 78883985c26SRobert Watson mac_destroy_label(label); 78983985c26SRobert Watson } 79083985c26SRobert Watson 79108bcdc58SRobert Watson #ifdef MAC_DEBUG 79283985c26SRobert Watson if (error == 0) 79387807196SRobert Watson atomic_add_int(&nmacsockets, 1); 79487807196SRobert Watson #endif 79583985c26SRobert Watson 79683985c26SRobert Watson return (error); 79783985c26SRobert Watson } 79883985c26SRobert Watson 79983985c26SRobert Watson static int 80083985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 80183985c26SRobert Watson { 80283985c26SRobert Watson int error; 80383985c26SRobert Watson 80483985c26SRobert Watson mac_init_label(label); 80583985c26SRobert Watson 80683985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 80783985c26SRobert Watson if (error) { 80883985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 80983985c26SRobert Watson mac_destroy_label(label); 81083985c26SRobert Watson } 81183985c26SRobert Watson 81283985c26SRobert Watson return (error); 81383985c26SRobert Watson } 81483985c26SRobert Watson 81583985c26SRobert Watson int 81683985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 81783985c26SRobert Watson { 81883985c26SRobert Watson int error; 81983985c26SRobert Watson 82083985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 82183985c26SRobert Watson if (error) 82283985c26SRobert Watson return (error); 82383985c26SRobert Watson 82483985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 82583985c26SRobert Watson if (error) 82683985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 82783985c26SRobert Watson 82883985c26SRobert Watson return (error); 82987807196SRobert Watson } 83087807196SRobert Watson 831763bbd2fSRobert Watson void 832f7b951a8SRobert Watson mac_init_vnode_label(struct label *label) 83387807196SRobert Watson { 83487807196SRobert Watson 83587807196SRobert Watson mac_init_label(label); 836f7b951a8SRobert Watson MAC_PERFORM(init_vnode_label, label); 83787807196SRobert Watson #ifdef MAC_DEBUG 838f7b951a8SRobert Watson atomic_add_int(&nmacvnodes, 1); 83908bcdc58SRobert Watson #endif 84008bcdc58SRobert Watson } 84108bcdc58SRobert Watson 84208bcdc58SRobert Watson void 84387807196SRobert Watson mac_init_vnode(struct vnode *vp) 84408bcdc58SRobert Watson { 84508bcdc58SRobert Watson 846f7b951a8SRobert Watson mac_init_vnode_label(&vp->v_label); 84708bcdc58SRobert Watson } 84808bcdc58SRobert Watson 84908bcdc58SRobert Watson void 85008bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 85108bcdc58SRobert Watson { 85208bcdc58SRobert Watson 85308bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 85408bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 85508bcdc58SRobert Watson #ifdef MAC_DEBUG 85608bcdc58SRobert Watson atomic_subtract_int(&nmacbpfdescs, 1); 85708bcdc58SRobert Watson #endif 85808bcdc58SRobert Watson } 85908bcdc58SRobert Watson 860f7b951a8SRobert Watson static void 861f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label) 86208bcdc58SRobert Watson { 86308bcdc58SRobert Watson 864f7b951a8SRobert Watson MAC_PERFORM(destroy_cred_label, label); 865f7b951a8SRobert Watson mac_destroy_label(label); 86608bcdc58SRobert Watson #ifdef MAC_DEBUG 86787807196SRobert Watson atomic_subtract_int(&nmaccreds, 1); 86887807196SRobert Watson #endif 86987807196SRobert Watson } 87087807196SRobert Watson 87187807196SRobert Watson void 872f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred) 873f7b951a8SRobert Watson { 874f7b951a8SRobert Watson 875f7b951a8SRobert Watson mac_destroy_cred_label(&cred->cr_label); 876f7b951a8SRobert Watson } 877f7b951a8SRobert Watson 878f7b951a8SRobert Watson void 87987807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 88087807196SRobert Watson { 88187807196SRobert Watson 88287807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 88387807196SRobert Watson mac_destroy_label(&de->de_label); 88487807196SRobert Watson #ifdef MAC_DEBUG 88587807196SRobert Watson atomic_subtract_int(&nmacdevfsdirents, 1); 88687807196SRobert Watson #endif 88787807196SRobert Watson } 88887807196SRobert Watson 889f7b951a8SRobert Watson static void 890f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label) 891f7b951a8SRobert Watson { 892f7b951a8SRobert Watson 893f7b951a8SRobert Watson MAC_PERFORM(destroy_ifnet_label, label); 894f7b951a8SRobert Watson mac_destroy_label(label); 895f7b951a8SRobert Watson #ifdef MAC_DEBUG 896f7b951a8SRobert Watson atomic_subtract_int(&nmacifnets, 1); 897f7b951a8SRobert Watson #endif 898f7b951a8SRobert Watson } 899f7b951a8SRobert Watson 90087807196SRobert Watson void 90187807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 90287807196SRobert Watson { 90387807196SRobert Watson 904f7b951a8SRobert Watson mac_destroy_ifnet_label(&ifp->if_label); 90587807196SRobert Watson } 90687807196SRobert Watson 90787807196SRobert Watson void 90887807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 90987807196SRobert Watson { 91087807196SRobert Watson 91187807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 91287807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 91387807196SRobert Watson #ifdef MAC_DEBUG 91487807196SRobert Watson atomic_subtract_int(&nmacipqs, 1); 91587807196SRobert Watson #endif 91687807196SRobert Watson } 91787807196SRobert Watson 91887807196SRobert Watson void 91987807196SRobert Watson mac_destroy_mbuf(struct mbuf *m) 92087807196SRobert Watson { 92187807196SRobert Watson 92287807196SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 92387807196SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 92487807196SRobert Watson #ifdef MAC_DEBUG 92587807196SRobert Watson atomic_subtract_int(&nmacmbufs, 1); 92608bcdc58SRobert Watson #endif 92708bcdc58SRobert Watson } 92808bcdc58SRobert Watson 92908bcdc58SRobert Watson void 93008bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 93108bcdc58SRobert Watson { 93208bcdc58SRobert Watson 93308bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 93408bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 93508bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 93608bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 93708bcdc58SRobert Watson #ifdef MAC_DEBUG 93808bcdc58SRobert Watson atomic_subtract_int(&nmacmounts, 1); 93908bcdc58SRobert Watson #endif 94008bcdc58SRobert Watson } 94108bcdc58SRobert Watson 942f7b951a8SRobert Watson static void 943f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 944f7b951a8SRobert Watson { 945f7b951a8SRobert Watson 946f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 947f7b951a8SRobert Watson mac_destroy_label(label); 948f7b951a8SRobert Watson #ifdef MAC_DEBUG 949f7b951a8SRobert Watson atomic_subtract_int(&nmacpipes, 1); 950f7b951a8SRobert Watson #endif 951f7b951a8SRobert Watson } 952f7b951a8SRobert Watson 95387807196SRobert Watson void 95487807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 95508bcdc58SRobert Watson { 95608bcdc58SRobert Watson 957f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 95887807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 95987807196SRobert Watson } 96087807196SRobert Watson 9612555374cSRobert Watson void 9622555374cSRobert Watson mac_destroy_proc(struct proc *p) 9632555374cSRobert Watson { 9642555374cSRobert Watson 9652555374cSRobert Watson MAC_PERFORM(destroy_proc_label, &p->p_label); 9662555374cSRobert Watson mac_destroy_label(&p->p_label); 9672555374cSRobert Watson #ifdef MAC_DEBUG 9682555374cSRobert Watson atomic_subtract_int(&nmacprocs, 1); 9692555374cSRobert Watson #endif 9702555374cSRobert Watson } 9712555374cSRobert Watson 97283985c26SRobert Watson static void 97383985c26SRobert Watson mac_destroy_socket_label(struct label *label) 97483985c26SRobert Watson { 97583985c26SRobert Watson 97683985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 97783985c26SRobert Watson mac_destroy_label(label); 97883985c26SRobert Watson #ifdef MAC_DEBUG 97983985c26SRobert Watson atomic_subtract_int(&nmacsockets, 1); 98083985c26SRobert Watson #endif 98183985c26SRobert Watson } 98283985c26SRobert Watson 98383985c26SRobert Watson static void 98483985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 98583985c26SRobert Watson { 98683985c26SRobert Watson 98783985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 98883985c26SRobert Watson mac_destroy_label(label); 98983985c26SRobert Watson } 99083985c26SRobert Watson 99187807196SRobert Watson void 99287807196SRobert Watson mac_destroy_socket(struct socket *socket) 99387807196SRobert Watson { 99487807196SRobert Watson 99583985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 99683985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 99708bcdc58SRobert Watson } 99808bcdc58SRobert Watson 999763bbd2fSRobert Watson void 1000f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label) 100108bcdc58SRobert Watson { 100208bcdc58SRobert Watson 1003f7b951a8SRobert Watson MAC_PERFORM(destroy_vnode_label, label); 100408bcdc58SRobert Watson mac_destroy_label(label); 100508bcdc58SRobert Watson #ifdef MAC_DEBUG 1006f7b951a8SRobert Watson atomic_subtract_int(&nmacvnodes, 1); 100708bcdc58SRobert Watson #endif 100808bcdc58SRobert Watson } 100908bcdc58SRobert Watson 101008bcdc58SRobert Watson void 101108bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 101208bcdc58SRobert Watson { 101308bcdc58SRobert Watson 1014f7b951a8SRobert Watson mac_destroy_vnode_label(&vp->v_label); 1015f7b951a8SRobert Watson } 1016f7b951a8SRobert Watson 1017f7b951a8SRobert Watson static void 1018f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 1019f7b951a8SRobert Watson { 1020f7b951a8SRobert Watson 1021f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 1022f7b951a8SRobert Watson } 1023f7b951a8SRobert Watson 1024763bbd2fSRobert Watson void 1025f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest) 1026f7b951a8SRobert Watson { 1027f7b951a8SRobert Watson 1028f7b951a8SRobert Watson MAC_PERFORM(copy_vnode_label, src, dest); 102908bcdc58SRobert Watson } 103008bcdc58SRobert Watson 103169bbb5b1SRobert Watson static int 1032f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 1033f7b951a8SRobert Watson { 1034f7b951a8SRobert Watson 1035f7b951a8SRobert Watson if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1036f7b951a8SRobert Watson return (EINVAL); 1037f7b951a8SRobert Watson 1038f7b951a8SRobert Watson return (0); 1039f7b951a8SRobert Watson } 1040f7b951a8SRobert Watson 1041f7b951a8SRobert Watson static int 1042f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements, 1043f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 104469bbb5b1SRobert Watson { 104569bbb5b1SRobert Watson int error; 104669bbb5b1SRobert Watson 1047f7b951a8SRobert Watson MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 104869bbb5b1SRobert Watson 104969bbb5b1SRobert Watson return (error); 105069bbb5b1SRobert Watson } 105169bbb5b1SRobert Watson 105269bbb5b1SRobert Watson static int 1053f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements, 1054f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 105569bbb5b1SRobert Watson { 105669bbb5b1SRobert Watson int error; 105769bbb5b1SRobert Watson 1058f7b951a8SRobert Watson MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1059f7b951a8SRobert Watson 1060f7b951a8SRobert Watson return (error); 1061f7b951a8SRobert Watson } 1062f7b951a8SRobert Watson 1063f7b951a8SRobert Watson static int 1064f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 1065f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1066f7b951a8SRobert Watson { 1067f7b951a8SRobert Watson int error; 1068f7b951a8SRobert Watson 1069f7b951a8SRobert Watson MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1070f7b951a8SRobert Watson 1071f7b951a8SRobert Watson return (error); 1072f7b951a8SRobert Watson } 1073f7b951a8SRobert Watson 1074f7b951a8SRobert Watson static int 1075f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 1076f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1077f7b951a8SRobert Watson { 1078f7b951a8SRobert Watson int error; 1079f7b951a8SRobert Watson 1080f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1081f7b951a8SRobert Watson 1082f7b951a8SRobert Watson return (error); 1083f7b951a8SRobert Watson } 1084f7b951a8SRobert Watson 1085f7b951a8SRobert Watson static int 1086f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 1087f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1088f7b951a8SRobert Watson { 1089f7b951a8SRobert Watson int error; 1090f7b951a8SRobert Watson 1091f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1092f7b951a8SRobert Watson 1093f7b951a8SRobert Watson return (error); 1094f7b951a8SRobert Watson } 1095f7b951a8SRobert Watson 1096f7b951a8SRobert Watson static int 1097f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements, 1098f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1099f7b951a8SRobert Watson { 1100f7b951a8SRobert Watson int error; 1101f7b951a8SRobert Watson 1102f7b951a8SRobert Watson MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1103f7b951a8SRobert Watson 1104f7b951a8SRobert Watson return (error); 1105f7b951a8SRobert Watson } 1106f7b951a8SRobert Watson 1107f7b951a8SRobert Watson static int 1108f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string) 1109f7b951a8SRobert Watson { 1110f7b951a8SRobert Watson int error; 1111f7b951a8SRobert Watson 1112f7b951a8SRobert Watson MAC_INTERNALIZE(cred_label, label, string); 1113f7b951a8SRobert Watson 1114f7b951a8SRobert Watson return (error); 1115f7b951a8SRobert Watson } 1116f7b951a8SRobert Watson 1117f7b951a8SRobert Watson static int 1118f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string) 1119f7b951a8SRobert Watson { 1120f7b951a8SRobert Watson int error; 1121f7b951a8SRobert Watson 1122f7b951a8SRobert Watson MAC_INTERNALIZE(ifnet_label, label, string); 1123f7b951a8SRobert Watson 1124f7b951a8SRobert Watson return (error); 1125f7b951a8SRobert Watson } 1126f7b951a8SRobert Watson 1127f7b951a8SRobert Watson static int 1128f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 1129f7b951a8SRobert Watson { 1130f7b951a8SRobert Watson int error; 1131f7b951a8SRobert Watson 1132f7b951a8SRobert Watson MAC_INTERNALIZE(pipe_label, label, string); 1133f7b951a8SRobert Watson 1134f7b951a8SRobert Watson return (error); 1135f7b951a8SRobert Watson } 1136f7b951a8SRobert Watson 1137f7b951a8SRobert Watson static int 1138f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string) 1139f7b951a8SRobert Watson { 1140f7b951a8SRobert Watson int error; 1141f7b951a8SRobert Watson 1142f7b951a8SRobert Watson MAC_INTERNALIZE(socket_label, label, string); 1143f7b951a8SRobert Watson 1144f7b951a8SRobert Watson return (error); 1145f7b951a8SRobert Watson } 1146f7b951a8SRobert Watson 1147f7b951a8SRobert Watson static int 1148f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string) 1149f7b951a8SRobert Watson { 1150f7b951a8SRobert Watson int error; 1151f7b951a8SRobert Watson 1152f7b951a8SRobert Watson MAC_INTERNALIZE(vnode_label, label, string); 115369bbb5b1SRobert Watson 115469bbb5b1SRobert Watson return (error); 115569bbb5b1SRobert Watson } 115669bbb5b1SRobert Watson 115769bbb5b1SRobert Watson /* 115869bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 115969bbb5b1SRobert Watson * kernel processes and threads are spawned. 116069bbb5b1SRobert Watson */ 116169bbb5b1SRobert Watson void 116269bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 116369bbb5b1SRobert Watson { 116469bbb5b1SRobert Watson 116569bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 116669bbb5b1SRobert Watson } 116769bbb5b1SRobert Watson 116869bbb5b1SRobert Watson /* 116969bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 117069bbb5b1SRobert Watson * userland processes and threads are spawned. 117169bbb5b1SRobert Watson */ 117269bbb5b1SRobert Watson void 117369bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 117469bbb5b1SRobert Watson { 117569bbb5b1SRobert Watson 117669bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 117769bbb5b1SRobert Watson } 117869bbb5b1SRobert Watson 117969bbb5b1SRobert Watson void 118069bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 118169bbb5b1SRobert Watson { 118269bbb5b1SRobert Watson 118369bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 118469bbb5b1SRobert Watson } 118569bbb5b1SRobert Watson 118669bbb5b1SRobert Watson /* 118769bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 118869bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 118969bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 119069bbb5b1SRobert Watson */ 119169bbb5b1SRobert Watson void 119269bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 119369bbb5b1SRobert Watson { 119469bbb5b1SRobert Watson 119569bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 119669bbb5b1SRobert Watson } 119769bbb5b1SRobert Watson 119895fab37eSRobert Watson void 1199990b4b2dSRobert Watson mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de, 1200990b4b2dSRobert Watson struct vnode *vp) 120195fab37eSRobert Watson { 120295fab37eSRobert Watson 1203990b4b2dSRobert Watson MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp, 1204990b4b2dSRobert Watson &vp->v_label); 120595fab37eSRobert Watson } 120695fab37eSRobert Watson 120795fab37eSRobert Watson void 1208763bbd2fSRobert Watson mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1209763bbd2fSRobert Watson struct vnode *vp) 121095fab37eSRobert Watson { 121195fab37eSRobert Watson 1212763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1213763bbd2fSRobert Watson &de->de_label, vp, &vp->v_label); 121495fab37eSRobert Watson } 121595fab37eSRobert Watson 1216763bbd2fSRobert Watson int 1217763bbd2fSRobert Watson mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 121895fab37eSRobert Watson { 121995fab37eSRobert Watson int error; 122095fab37eSRobert Watson 1221763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1222763bbd2fSRobert Watson 1223763bbd2fSRobert Watson MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1224763bbd2fSRobert Watson &vp->v_label); 122595fab37eSRobert Watson 122695fab37eSRobert Watson return (error); 122795fab37eSRobert Watson } 122895fab37eSRobert Watson 122995fab37eSRobert Watson void 1230763bbd2fSRobert Watson mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 123195fab37eSRobert Watson { 123295fab37eSRobert Watson 1233763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1234763bbd2fSRobert Watson &vp->v_label); 123595fab37eSRobert Watson } 123695fab37eSRobert Watson 123795fab37eSRobert Watson int 1238763bbd2fSRobert Watson mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1239763bbd2fSRobert Watson struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 124095fab37eSRobert Watson { 1241763bbd2fSRobert Watson int error; 124295fab37eSRobert Watson 1243763bbd2fSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1244763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 124595fab37eSRobert Watson 1246763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1247763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1248763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1249763bbd2fSRobert Watson if (ea_warn_once == 0) { 1250763bbd2fSRobert Watson printf("Warning: transactions not supported " 1251763bbd2fSRobert Watson "in EA write.\n"); 1252763bbd2fSRobert Watson ea_warn_once = 1; 1253763bbd2fSRobert Watson } 1254763bbd2fSRobert Watson } else if (error) 125595fab37eSRobert Watson return (error); 125695fab37eSRobert Watson 1257763bbd2fSRobert Watson MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1258763bbd2fSRobert Watson dvp, &dvp->v_label, vp, &vp->v_label, cnp); 125995fab37eSRobert Watson 1260763bbd2fSRobert Watson if (error) { 1261763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 126295fab37eSRobert Watson return (error); 126395fab37eSRobert Watson } 126495fab37eSRobert Watson 1265763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 126695fab37eSRobert Watson 1267763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1268763bbd2fSRobert Watson error = 0; /* XXX */ 126995fab37eSRobert Watson 127095fab37eSRobert Watson return (error); 127195fab37eSRobert Watson } 127295fab37eSRobert Watson 127395fab37eSRobert Watson static int 1274763bbd2fSRobert Watson mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1275763bbd2fSRobert Watson struct label *intlabel) 127695fab37eSRobert Watson { 127795fab37eSRobert Watson int error; 127895fab37eSRobert Watson 1279763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 128095fab37eSRobert Watson 1281763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1282763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1283763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1284763bbd2fSRobert Watson if (ea_warn_once == 0) { 1285763bbd2fSRobert Watson printf("Warning: transactions not supported " 1286763bbd2fSRobert Watson "in EA write.\n"); 1287763bbd2fSRobert Watson ea_warn_once = 1; 128895fab37eSRobert Watson } 1289763bbd2fSRobert Watson } else if (error) 129095fab37eSRobert Watson return (error); 129195fab37eSRobert Watson 1292763bbd2fSRobert Watson MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 129395fab37eSRobert Watson 1294763bbd2fSRobert Watson if (error) { 1295763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 129695fab37eSRobert Watson return (error); 129795fab37eSRobert Watson } 129895fab37eSRobert Watson 1299763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1300763bbd2fSRobert Watson 1301763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1302763bbd2fSRobert Watson error = 0; /* XXX */ 1303763bbd2fSRobert Watson 1304763bbd2fSRobert Watson return (error); 130595fab37eSRobert Watson } 130695fab37eSRobert Watson 1307670cb89bSRobert Watson int 1308670cb89bSRobert Watson mac_execve_enter(struct image_params *imgp, struct mac *mac_p, 1309670cb89bSRobert Watson struct label *execlabelstorage) 1310670cb89bSRobert Watson { 1311670cb89bSRobert Watson struct mac mac; 1312670cb89bSRobert Watson char *buffer; 1313670cb89bSRobert Watson int error; 1314670cb89bSRobert Watson 1315670cb89bSRobert Watson if (mac_p == NULL) 1316670cb89bSRobert Watson return (0); 1317670cb89bSRobert Watson 1318670cb89bSRobert Watson error = copyin(mac_p, &mac, sizeof(mac)); 1319670cb89bSRobert Watson if (error) 1320670cb89bSRobert Watson return (error); 1321670cb89bSRobert Watson 1322670cb89bSRobert Watson error = mac_check_structmac_consistent(&mac); 1323670cb89bSRobert Watson if (error) 1324670cb89bSRobert Watson return (error); 1325670cb89bSRobert Watson 1326670cb89bSRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1327670cb89bSRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1328670cb89bSRobert Watson if (error) { 1329670cb89bSRobert Watson free(buffer, M_MACTEMP); 1330670cb89bSRobert Watson return (error); 1331670cb89bSRobert Watson } 1332670cb89bSRobert Watson 1333670cb89bSRobert Watson mac_init_cred_label(execlabelstorage); 1334670cb89bSRobert Watson error = mac_internalize_cred_label(execlabelstorage, buffer); 1335670cb89bSRobert Watson free(buffer, M_MACTEMP); 1336670cb89bSRobert Watson if (error) { 1337670cb89bSRobert Watson mac_destroy_cred_label(execlabelstorage); 1338670cb89bSRobert Watson return (error); 1339670cb89bSRobert Watson } 1340670cb89bSRobert Watson imgp->execlabel = execlabelstorage; 1341670cb89bSRobert Watson return (0); 1342670cb89bSRobert Watson } 1343670cb89bSRobert Watson 134495fab37eSRobert Watson void 1345670cb89bSRobert Watson mac_execve_exit(struct image_params *imgp) 1346670cb89bSRobert Watson { 1347670cb89bSRobert Watson if (imgp->execlabel != NULL) 1348670cb89bSRobert Watson mac_destroy_cred_label(imgp->execlabel); 1349670cb89bSRobert Watson } 1350670cb89bSRobert Watson 1351670cb89bSRobert Watson void 1352670cb89bSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 1353670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 135495fab37eSRobert Watson { 135595fab37eSRobert Watson 135695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 135795fab37eSRobert Watson 13584443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 13594443e9ffSRobert Watson return; 13604443e9ffSRobert Watson 1361670cb89bSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 13629fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 136395fab37eSRobert Watson } 136495fab37eSRobert Watson 136595fab37eSRobert Watson int 1366670cb89bSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp, 1367670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 136895fab37eSRobert Watson { 1369763bbd2fSRobert Watson int result; 137095fab37eSRobert Watson 13714443e9ffSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 13724443e9ffSRobert Watson 13734443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 13744443e9ffSRobert Watson return (0); 13754443e9ffSRobert Watson 137695fab37eSRobert Watson result = 0; 1377670cb89bSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 13789fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 137995fab37eSRobert Watson 138095fab37eSRobert Watson return (result); 138195fab37eSRobert Watson } 138295fab37eSRobert Watson 138395fab37eSRobert Watson int 1384b914de36SRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 138595fab37eSRobert Watson { 138695fab37eSRobert Watson int error; 138795fab37eSRobert Watson 138895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 138995fab37eSRobert Watson 139095fab37eSRobert Watson if (!mac_enforce_fs) 139195fab37eSRobert Watson return (0); 139295fab37eSRobert Watson 1393b914de36SRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 139495fab37eSRobert Watson return (error); 139595fab37eSRobert Watson } 139695fab37eSRobert Watson 139795fab37eSRobert Watson int 139895fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 139995fab37eSRobert Watson { 140095fab37eSRobert Watson int error; 140195fab37eSRobert Watson 140295fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 140395fab37eSRobert Watson 140495fab37eSRobert Watson if (!mac_enforce_fs) 140595fab37eSRobert Watson return (0); 140695fab37eSRobert Watson 140795fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 140895fab37eSRobert Watson return (error); 140995fab37eSRobert Watson } 141095fab37eSRobert Watson 141195fab37eSRobert Watson int 141295fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 141395fab37eSRobert Watson { 141495fab37eSRobert Watson int error; 141595fab37eSRobert Watson 141695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 141795fab37eSRobert Watson 141895fab37eSRobert Watson if (!mac_enforce_fs) 141995fab37eSRobert Watson return (0); 142095fab37eSRobert Watson 142195fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 142295fab37eSRobert Watson return (error); 142395fab37eSRobert Watson } 142495fab37eSRobert Watson 142595fab37eSRobert Watson int 142695fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 142795fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 142895fab37eSRobert Watson { 142995fab37eSRobert Watson int error; 143095fab37eSRobert Watson 143195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 143295fab37eSRobert Watson 143395fab37eSRobert Watson if (!mac_enforce_fs) 143495fab37eSRobert Watson return (0); 143595fab37eSRobert Watson 143695fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 143795fab37eSRobert Watson return (error); 143895fab37eSRobert Watson } 143995fab37eSRobert Watson 144095fab37eSRobert Watson int 144195fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 144295fab37eSRobert Watson struct componentname *cnp) 144395fab37eSRobert Watson { 144495fab37eSRobert Watson int error; 144595fab37eSRobert Watson 144695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 144795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 144895fab37eSRobert Watson 144995fab37eSRobert Watson if (!mac_enforce_fs) 145095fab37eSRobert Watson return (0); 145195fab37eSRobert Watson 145295fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 145395fab37eSRobert Watson &vp->v_label, cnp); 145495fab37eSRobert Watson return (error); 145595fab37eSRobert Watson } 145695fab37eSRobert Watson 145795fab37eSRobert Watson int 145895fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 145995fab37eSRobert Watson acl_type_t type) 146095fab37eSRobert Watson { 146195fab37eSRobert Watson int error; 146295fab37eSRobert Watson 146395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 146495fab37eSRobert Watson 146595fab37eSRobert Watson if (!mac_enforce_fs) 146695fab37eSRobert Watson return (0); 146795fab37eSRobert Watson 146895fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 146995fab37eSRobert Watson return (error); 147095fab37eSRobert Watson } 147195fab37eSRobert Watson 147295fab37eSRobert Watson int 1473670cb89bSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1474670cb89bSRobert Watson struct image_params *imgp) 147595fab37eSRobert Watson { 147695fab37eSRobert Watson int error; 147795fab37eSRobert Watson 1478851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1479851704bbSRobert Watson 148095fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 148195fab37eSRobert Watson return (0); 148295fab37eSRobert Watson 14839fa3506eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 14849fa3506eSRobert Watson imgp->execlabel); 148595fab37eSRobert Watson 148695fab37eSRobert Watson return (error); 148795fab37eSRobert Watson } 148895fab37eSRobert Watson 148995fab37eSRobert Watson int 149095fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 149195fab37eSRobert Watson { 149295fab37eSRobert Watson int error; 149395fab37eSRobert Watson 149495fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 149595fab37eSRobert Watson 149695fab37eSRobert Watson if (!mac_enforce_fs) 149795fab37eSRobert Watson return (0); 149895fab37eSRobert Watson 149995fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 150095fab37eSRobert Watson return (error); 150195fab37eSRobert Watson } 150295fab37eSRobert Watson 150395fab37eSRobert Watson int 150495fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 150595fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 150695fab37eSRobert Watson { 150795fab37eSRobert Watson int error; 150895fab37eSRobert Watson 150995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 151095fab37eSRobert Watson 151195fab37eSRobert Watson if (!mac_enforce_fs) 151295fab37eSRobert Watson return (0); 151395fab37eSRobert Watson 151495fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 151595fab37eSRobert Watson attrnamespace, name, uio); 151695fab37eSRobert Watson return (error); 151795fab37eSRobert Watson } 151895fab37eSRobert Watson 151995fab37eSRobert Watson int 15200a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 15210a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 15220a694196SRobert Watson { 15230a694196SRobert Watson int error; 15240a694196SRobert Watson 15250a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 15260a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 15270a694196SRobert Watson 15280a694196SRobert Watson if (!mac_enforce_fs) 15290a694196SRobert Watson return (0); 15300a694196SRobert Watson 15310a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 15320a694196SRobert Watson &vp->v_label, cnp); 15330a694196SRobert Watson return (error); 15340a694196SRobert Watson } 15350a694196SRobert Watson 15360a694196SRobert Watson int 153795fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 153895fab37eSRobert Watson struct componentname *cnp) 153995fab37eSRobert Watson { 154095fab37eSRobert Watson int error; 154195fab37eSRobert Watson 154295fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 154395fab37eSRobert Watson 154495fab37eSRobert Watson if (!mac_enforce_fs) 154595fab37eSRobert Watson return (0); 154695fab37eSRobert Watson 154795fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 154895fab37eSRobert Watson return (error); 154995fab37eSRobert Watson } 155095fab37eSRobert Watson 1551e183f80eSRobert Watson int 1552e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 155395fab37eSRobert Watson { 1554e183f80eSRobert Watson int error; 155595fab37eSRobert Watson 1556e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1557ca7850c3SRobert Watson 1558e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1559e183f80eSRobert Watson return (0); 1560e183f80eSRobert Watson 1561e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1562e183f80eSRobert Watson return (error); 1563e183f80eSRobert Watson } 1564e183f80eSRobert Watson 1565e183f80eSRobert Watson void 1566e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1567e183f80eSRobert Watson { 1568e183f80eSRobert Watson int result = *prot; 1569e183f80eSRobert Watson 1570e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1571e183f80eSRobert Watson 1572e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1573e183f80eSRobert Watson return; 1574e183f80eSRobert Watson 1575e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1576e183f80eSRobert Watson &result); 1577e183f80eSRobert Watson 1578e183f80eSRobert Watson *prot = result; 1579e183f80eSRobert Watson } 1580e183f80eSRobert Watson 1581e183f80eSRobert Watson int 1582e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1583e183f80eSRobert Watson { 1584e183f80eSRobert Watson int error; 1585e183f80eSRobert Watson 1586e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1587e183f80eSRobert Watson 1588e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1589e183f80eSRobert Watson return (0); 1590e183f80eSRobert Watson 1591e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1592e183f80eSRobert Watson return (error); 159395fab37eSRobert Watson } 159495fab37eSRobert Watson 159595fab37eSRobert Watson int 1596b914de36SRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 159795fab37eSRobert Watson { 159895fab37eSRobert Watson int error; 159995fab37eSRobert Watson 160095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 160195fab37eSRobert Watson 160295fab37eSRobert Watson if (!mac_enforce_fs) 160395fab37eSRobert Watson return (0); 160495fab37eSRobert Watson 160595fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 160695fab37eSRobert Watson return (error); 160795fab37eSRobert Watson } 160895fab37eSRobert Watson 160995fab37eSRobert Watson int 1610177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1611177142e4SRobert Watson struct vnode *vp) 16127f724f8bSRobert Watson { 16137f724f8bSRobert Watson int error; 16147f724f8bSRobert Watson 16157f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 16167f724f8bSRobert Watson 16177f724f8bSRobert Watson if (!mac_enforce_fs) 16187f724f8bSRobert Watson return (0); 16197f724f8bSRobert Watson 1620177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1621177142e4SRobert Watson &vp->v_label); 16227f724f8bSRobert Watson 16237f724f8bSRobert Watson return (error); 16247f724f8bSRobert Watson } 16257f724f8bSRobert Watson 16267f724f8bSRobert Watson int 1627177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1628177142e4SRobert Watson struct vnode *vp) 16297f724f8bSRobert Watson { 16307f724f8bSRobert Watson int error; 16317f724f8bSRobert Watson 16327f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 16337f724f8bSRobert Watson 16347f724f8bSRobert Watson if (!mac_enforce_fs) 16357f724f8bSRobert Watson return (0); 16367f724f8bSRobert Watson 1637177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1638177142e4SRobert Watson &vp->v_label); 16397f724f8bSRobert Watson 16407f724f8bSRobert Watson return (error); 16417f724f8bSRobert Watson } 16427f724f8bSRobert Watson 16437f724f8bSRobert Watson int 164495fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 164595fab37eSRobert Watson { 164695fab37eSRobert Watson int error; 164795fab37eSRobert Watson 164895fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 164995fab37eSRobert Watson 165095fab37eSRobert Watson if (!mac_enforce_fs) 165195fab37eSRobert Watson return (0); 165295fab37eSRobert Watson 165395fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 165495fab37eSRobert Watson return (error); 165595fab37eSRobert Watson } 165695fab37eSRobert Watson 165795fab37eSRobert Watson int 165895fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 165995fab37eSRobert Watson { 166095fab37eSRobert Watson int error; 166195fab37eSRobert Watson 166295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 166395fab37eSRobert Watson 166495fab37eSRobert Watson if (!mac_enforce_fs) 166595fab37eSRobert Watson return (0); 166695fab37eSRobert Watson 166795fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 166895fab37eSRobert Watson return (error); 166995fab37eSRobert Watson } 167095fab37eSRobert Watson 167195fab37eSRobert Watson static int 167295fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 167395fab37eSRobert Watson struct label *newlabel) 167495fab37eSRobert Watson { 167595fab37eSRobert Watson int error; 167695fab37eSRobert Watson 167795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 167895fab37eSRobert Watson 167995fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 168095fab37eSRobert Watson 168195fab37eSRobert Watson return (error); 168295fab37eSRobert Watson } 168395fab37eSRobert Watson 168495fab37eSRobert Watson int 168595fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 168695fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 168795fab37eSRobert Watson { 168895fab37eSRobert Watson int error; 168995fab37eSRobert Watson 169095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 169195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 169295fab37eSRobert Watson 169395fab37eSRobert Watson if (!mac_enforce_fs) 169495fab37eSRobert Watson return (0); 169595fab37eSRobert Watson 169695fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 169795fab37eSRobert Watson &vp->v_label, cnp); 169895fab37eSRobert Watson return (error); 169995fab37eSRobert Watson } 170095fab37eSRobert Watson 170195fab37eSRobert Watson int 170295fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 170395fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 170495fab37eSRobert Watson { 170595fab37eSRobert Watson int error; 170695fab37eSRobert Watson 170795fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 170895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 170995fab37eSRobert Watson 171095fab37eSRobert Watson if (!mac_enforce_fs) 171195fab37eSRobert Watson return (0); 171295fab37eSRobert Watson 171395fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 171495fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 171595fab37eSRobert Watson return (error); 171695fab37eSRobert Watson } 171795fab37eSRobert Watson 171895fab37eSRobert Watson int 171995fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 172095fab37eSRobert Watson { 172195fab37eSRobert Watson int error; 172295fab37eSRobert Watson 172395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 172495fab37eSRobert Watson 172595fab37eSRobert Watson if (!mac_enforce_fs) 172695fab37eSRobert Watson return (0); 172795fab37eSRobert Watson 172895fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 172995fab37eSRobert Watson return (error); 173095fab37eSRobert Watson } 173195fab37eSRobert Watson 173295fab37eSRobert Watson int 173395fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 173495fab37eSRobert Watson struct acl *acl) 173595fab37eSRobert Watson { 173695fab37eSRobert Watson int error; 173795fab37eSRobert Watson 173895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 173995fab37eSRobert Watson 174095fab37eSRobert Watson if (!mac_enforce_fs) 174195fab37eSRobert Watson return (0); 174295fab37eSRobert Watson 174395fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 174495fab37eSRobert Watson return (error); 174595fab37eSRobert Watson } 174695fab37eSRobert Watson 174795fab37eSRobert Watson int 174895fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 174995fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 175095fab37eSRobert Watson { 175195fab37eSRobert Watson int error; 175295fab37eSRobert Watson 175395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 175495fab37eSRobert Watson 175595fab37eSRobert Watson if (!mac_enforce_fs) 175695fab37eSRobert Watson return (0); 175795fab37eSRobert Watson 175895fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 175995fab37eSRobert Watson attrnamespace, name, uio); 176095fab37eSRobert Watson return (error); 176195fab37eSRobert Watson } 176295fab37eSRobert Watson 176395fab37eSRobert Watson int 176495fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 176595fab37eSRobert Watson { 176695fab37eSRobert Watson int error; 176795fab37eSRobert Watson 176895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 176995fab37eSRobert Watson 177095fab37eSRobert Watson if (!mac_enforce_fs) 177195fab37eSRobert Watson return (0); 177295fab37eSRobert Watson 177395fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 177495fab37eSRobert Watson return (error); 177595fab37eSRobert Watson } 177695fab37eSRobert Watson 177795fab37eSRobert Watson int 177895fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 177995fab37eSRobert Watson { 178095fab37eSRobert Watson int error; 178195fab37eSRobert Watson 178295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 178395fab37eSRobert Watson 178495fab37eSRobert Watson if (!mac_enforce_fs) 178595fab37eSRobert Watson return (0); 178695fab37eSRobert Watson 178795fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 178895fab37eSRobert Watson return (error); 178995fab37eSRobert Watson } 179095fab37eSRobert Watson 179195fab37eSRobert Watson int 179295fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 179395fab37eSRobert Watson gid_t gid) 179495fab37eSRobert Watson { 179595fab37eSRobert Watson int error; 179695fab37eSRobert Watson 179795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 179895fab37eSRobert Watson 179995fab37eSRobert Watson if (!mac_enforce_fs) 180095fab37eSRobert Watson return (0); 180195fab37eSRobert Watson 180295fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 180395fab37eSRobert Watson return (error); 180495fab37eSRobert Watson } 180595fab37eSRobert Watson 180695fab37eSRobert Watson int 180795fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 180895fab37eSRobert Watson struct timespec atime, struct timespec mtime) 180995fab37eSRobert Watson { 181095fab37eSRobert Watson int error; 181195fab37eSRobert Watson 181295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 181395fab37eSRobert Watson 181495fab37eSRobert Watson if (!mac_enforce_fs) 181595fab37eSRobert Watson return (0); 181695fab37eSRobert Watson 181795fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 181895fab37eSRobert Watson mtime); 181995fab37eSRobert Watson return (error); 182095fab37eSRobert Watson } 182195fab37eSRobert Watson 182295fab37eSRobert Watson int 1823177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 1824177142e4SRobert Watson struct vnode *vp) 182595fab37eSRobert Watson { 182695fab37eSRobert Watson int error; 182795fab37eSRobert Watson 182895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 182995fab37eSRobert Watson 183095fab37eSRobert Watson if (!mac_enforce_fs) 183195fab37eSRobert Watson return (0); 183295fab37eSRobert Watson 1833177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 1834177142e4SRobert Watson &vp->v_label); 183595fab37eSRobert Watson return (error); 183695fab37eSRobert Watson } 183795fab37eSRobert Watson 18387f724f8bSRobert Watson int 1839177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 1840177142e4SRobert Watson struct vnode *vp) 18417f724f8bSRobert Watson { 18427f724f8bSRobert Watson int error; 18437f724f8bSRobert Watson 18447f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 18457f724f8bSRobert Watson 18467f724f8bSRobert Watson if (!mac_enforce_fs) 18477f724f8bSRobert Watson return (0); 18487f724f8bSRobert Watson 1849177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 1850177142e4SRobert Watson &vp->v_label); 18517f724f8bSRobert Watson 18527f724f8bSRobert Watson return (error); 18537f724f8bSRobert Watson } 18547f724f8bSRobert Watson 185595fab37eSRobert Watson /* 185695fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 185795fab37eSRobert Watson * permission allowed for each object type we know about in its 185895fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 185995fab37eSRobert Watson * know) when necessary. The process lock is not held here. 186095fab37eSRobert Watson */ 18614d10c0ceSRobert Watson void 186295fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 186395fab37eSRobert Watson { 186495fab37eSRobert Watson 186595fab37eSRobert Watson /* XXX freeze all other threads */ 186695fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 186795fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 186895fab37eSRobert Watson /* XXX allow other threads to continue */ 186995fab37eSRobert Watson } 187095fab37eSRobert Watson 187195fab37eSRobert Watson static __inline const char * 187295fab37eSRobert Watson prot2str(vm_prot_t prot) 187395fab37eSRobert Watson { 187495fab37eSRobert Watson 187595fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 187695fab37eSRobert Watson case VM_PROT_READ: 187795fab37eSRobert Watson return ("r--"); 187895fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 187995fab37eSRobert Watson return ("rw-"); 188095fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 188195fab37eSRobert Watson return ("r-x"); 188295fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 188395fab37eSRobert Watson return ("rwx"); 188495fab37eSRobert Watson case VM_PROT_WRITE: 188595fab37eSRobert Watson return ("-w-"); 188695fab37eSRobert Watson case VM_PROT_EXECUTE: 188795fab37eSRobert Watson return ("--x"); 188895fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 188995fab37eSRobert Watson return ("-wx"); 189095fab37eSRobert Watson default: 189195fab37eSRobert Watson return ("---"); 189295fab37eSRobert Watson } 189395fab37eSRobert Watson } 189495fab37eSRobert Watson 189595fab37eSRobert Watson static void 189695fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 189795fab37eSRobert Watson struct vm_map *map) 189895fab37eSRobert Watson { 189995fab37eSRobert Watson struct vm_map_entry *vme; 1900e183f80eSRobert Watson int result; 1901e183f80eSRobert Watson vm_prot_t revokeperms; 190295fab37eSRobert Watson vm_object_t object; 190395fab37eSRobert Watson vm_ooffset_t offset; 190495fab37eSRobert Watson struct vnode *vp; 190595fab37eSRobert Watson 1906c0f39905SRobert Watson if (!mac_mmap_revocation) 1907c0f39905SRobert Watson return; 1908c0f39905SRobert Watson 190995fab37eSRobert Watson vm_map_lock_read(map); 191095fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 191195fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 191295fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 191395fab37eSRobert Watson vme->object.sub_map); 191495fab37eSRobert Watson continue; 191595fab37eSRobert Watson } 191695fab37eSRobert Watson /* 191795fab37eSRobert Watson * Skip over entries that obviously are not shared. 191895fab37eSRobert Watson */ 191995fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 192095fab37eSRobert Watson !vme->max_protection) 192195fab37eSRobert Watson continue; 192295fab37eSRobert Watson /* 192395fab37eSRobert Watson * Drill down to the deepest backing object. 192495fab37eSRobert Watson */ 192595fab37eSRobert Watson offset = vme->offset; 192695fab37eSRobert Watson object = vme->object.vm_object; 192795fab37eSRobert Watson if (object == NULL) 192895fab37eSRobert Watson continue; 192995fab37eSRobert Watson while (object->backing_object != NULL) { 193095fab37eSRobert Watson object = object->backing_object; 193195fab37eSRobert Watson offset += object->backing_object_offset; 193295fab37eSRobert Watson } 193395fab37eSRobert Watson /* 193495fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 193595fab37eSRobert Watson * by the MAC system, so only things with backing by a 193695fab37eSRobert Watson * normal object (read: vnodes) are checked. 193795fab37eSRobert Watson */ 193895fab37eSRobert Watson if (object->type != OBJT_VNODE) 193995fab37eSRobert Watson continue; 194095fab37eSRobert Watson vp = (struct vnode *)object->handle; 194195fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1942e183f80eSRobert Watson result = vme->max_protection; 1943e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 194495fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 194595fab37eSRobert Watson /* 194695fab37eSRobert Watson * Find out what maximum protection we may be allowing 194795fab37eSRobert Watson * now but a policy needs to get removed. 194895fab37eSRobert Watson */ 194995fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 195095fab37eSRobert Watson if (!revokeperms) 195195fab37eSRobert Watson continue; 1952b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 1953b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 1954b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 1955b656366bSBruce Evans (long)(vme->end - vme->start), 195695fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 195795fab37eSRobert Watson vm_map_lock_upgrade(map); 195895fab37eSRobert Watson /* 195995fab37eSRobert Watson * This is the really simple case: if a map has more 196095fab37eSRobert Watson * max_protection than is allowed, but it's not being 196195fab37eSRobert Watson * actually used (that is, the current protection is 196295fab37eSRobert Watson * still allowed), we can just wipe it out and do 196395fab37eSRobert Watson * nothing more. 196495fab37eSRobert Watson */ 196595fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 196695fab37eSRobert Watson vme->max_protection -= revokeperms; 196795fab37eSRobert Watson } else { 196895fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 196995fab37eSRobert Watson /* 197095fab37eSRobert Watson * In the more complicated case, flush out all 197195fab37eSRobert Watson * pending changes to the object then turn it 197295fab37eSRobert Watson * copy-on-write. 197395fab37eSRobert Watson */ 197495fab37eSRobert Watson vm_object_reference(object); 197595fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 197695fab37eSRobert Watson vm_object_page_clean(object, 197795fab37eSRobert Watson OFF_TO_IDX(offset), 197895fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 197995fab37eSRobert Watson PAGE_MASK), 198095fab37eSRobert Watson OBJPC_SYNC); 198195fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 198295fab37eSRobert Watson vm_object_deallocate(object); 198395fab37eSRobert Watson /* 198495fab37eSRobert Watson * Why bother if there's no read permissions 198595fab37eSRobert Watson * anymore? For the rest, we need to leave 198695fab37eSRobert Watson * the write permissions on for COW, or 198795fab37eSRobert Watson * remove them entirely if configured to. 198895fab37eSRobert Watson */ 198995fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 199095fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 199195fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 199295fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 199395fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 199495fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 199595fab37eSRobert Watson } 199695fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 199795fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 199895fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 199995fab37eSRobert Watson } 200095fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 200195fab37eSRobert Watson vme->max_protection = 0; 200295fab37eSRobert Watson vme->protection = 0; 200395fab37eSRobert Watson } 200495fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 200595fab37eSRobert Watson vme->protection & ~revokeperms); 200695fab37eSRobert Watson vm_map_simplify_entry(map, vme); 200795fab37eSRobert Watson } 200895fab37eSRobert Watson vm_map_lock_downgrade(map); 200995fab37eSRobert Watson } 201095fab37eSRobert Watson vm_map_unlock_read(map); 201195fab37eSRobert Watson } 201295fab37eSRobert Watson 201395fab37eSRobert Watson /* 201495fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 201595fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 201695fab37eSRobert Watson * buffer cache. 201795fab37eSRobert Watson */ 201895fab37eSRobert Watson static void 201995fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 202095fab37eSRobert Watson { 202195fab37eSRobert Watson 202295fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 202395fab37eSRobert Watson } 202495fab37eSRobert Watson 202595fab37eSRobert Watson void 202695fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 202795fab37eSRobert Watson { 202895fab37eSRobert Watson 202995fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 203095fab37eSRobert Watson } 203195fab37eSRobert Watson 203295fab37eSRobert Watson void 203395fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 203495fab37eSRobert Watson { 203595fab37eSRobert Watson 203695fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 203795fab37eSRobert Watson } 203895fab37eSRobert Watson 203995fab37eSRobert Watson void 204095fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 204195fab37eSRobert Watson { 204295fab37eSRobert Watson 204395fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 204495fab37eSRobert Watson } 204595fab37eSRobert Watson 204695fab37eSRobert Watson void 204795fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 204895fab37eSRobert Watson { 204995fab37eSRobert Watson 205095fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 205195fab37eSRobert Watson } 205295fab37eSRobert Watson 205395fab37eSRobert Watson void 205495fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 205595fab37eSRobert Watson { 205695fab37eSRobert Watson 205795fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 205895fab37eSRobert Watson } 205995fab37eSRobert Watson 206095fab37eSRobert Watson void 206195fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 206295fab37eSRobert Watson struct socket *newsocket) 206395fab37eSRobert Watson { 206495fab37eSRobert Watson 206595fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 206695fab37eSRobert Watson newsocket, &newsocket->so_label); 206795fab37eSRobert Watson } 206895fab37eSRobert Watson 206995fab37eSRobert Watson static void 207095fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 207195fab37eSRobert Watson struct label *newlabel) 207295fab37eSRobert Watson { 207395fab37eSRobert Watson 207495fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 207595fab37eSRobert Watson } 207695fab37eSRobert Watson 207795fab37eSRobert Watson static void 207895fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 207995fab37eSRobert Watson { 208095fab37eSRobert Watson 208195fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 208295fab37eSRobert Watson } 208395fab37eSRobert Watson 208495fab37eSRobert Watson void 208595fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 208695fab37eSRobert Watson { 208795fab37eSRobert Watson 208895fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 208995fab37eSRobert Watson socket, &socket->so_peerlabel); 209095fab37eSRobert Watson } 209195fab37eSRobert Watson 209295fab37eSRobert Watson void 209395fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 209495fab37eSRobert Watson struct socket *newsocket) 209595fab37eSRobert Watson { 209695fab37eSRobert Watson 209795fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 209895fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 209995fab37eSRobert Watson } 210095fab37eSRobert Watson 210195fab37eSRobert Watson void 210295fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 210395fab37eSRobert Watson { 210495fab37eSRobert Watson 210595fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 210695fab37eSRobert Watson datagram, &datagram->m_pkthdr.label); 210795fab37eSRobert Watson } 210895fab37eSRobert Watson 210995fab37eSRobert Watson void 211095fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 211195fab37eSRobert Watson { 211295fab37eSRobert Watson 211395fab37eSRobert Watson MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 211495fab37eSRobert Watson fragment, &fragment->m_pkthdr.label); 211595fab37eSRobert Watson } 211695fab37eSRobert Watson 211795fab37eSRobert Watson void 211895fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 211995fab37eSRobert Watson { 212095fab37eSRobert Watson 212195fab37eSRobert Watson MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 212295fab37eSRobert Watson &ipq->ipq_label); 212395fab37eSRobert Watson } 212495fab37eSRobert Watson 212595fab37eSRobert Watson void 212695fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 212795fab37eSRobert Watson { 212895fab37eSRobert Watson 212995fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 213095fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 213195fab37eSRobert Watson } 213295fab37eSRobert Watson 213395fab37eSRobert Watson void 213495fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 213595fab37eSRobert Watson { 213695fab37eSRobert Watson 213795fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 213895fab37eSRobert Watson &mbuf->m_pkthdr.label); 213995fab37eSRobert Watson } 214095fab37eSRobert Watson 214195fab37eSRobert Watson void 214295fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 214395fab37eSRobert Watson { 214495fab37eSRobert Watson 214595fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 214695fab37eSRobert Watson &mbuf->m_pkthdr.label); 214795fab37eSRobert Watson } 214895fab37eSRobert Watson 214995fab37eSRobert Watson void 215095fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 215195fab37eSRobert Watson { 215295fab37eSRobert Watson 215395fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 215495fab37eSRobert Watson &mbuf->m_pkthdr.label); 215595fab37eSRobert Watson } 215695fab37eSRobert Watson 215795fab37eSRobert Watson void 215895fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 215995fab37eSRobert Watson struct mbuf *newmbuf) 216095fab37eSRobert Watson { 216195fab37eSRobert Watson 216295fab37eSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 216395fab37eSRobert Watson &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 216495fab37eSRobert Watson &newmbuf->m_pkthdr.label); 216595fab37eSRobert Watson } 216695fab37eSRobert Watson 216795fab37eSRobert Watson void 216895fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 216995fab37eSRobert Watson { 217095fab37eSRobert Watson 217195fab37eSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 217295fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 217395fab37eSRobert Watson } 217495fab37eSRobert Watson 217595fab37eSRobert Watson int 217695fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 217795fab37eSRobert Watson { 217895fab37eSRobert Watson int result; 217995fab37eSRobert Watson 218095fab37eSRobert Watson result = 1; 218195fab37eSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 218295fab37eSRobert Watson ipq, &ipq->ipq_label); 218395fab37eSRobert Watson 218495fab37eSRobert Watson return (result); 218595fab37eSRobert Watson } 218695fab37eSRobert Watson 218795fab37eSRobert Watson void 218895fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 218995fab37eSRobert Watson { 219095fab37eSRobert Watson 219195fab37eSRobert Watson MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 219295fab37eSRobert Watson &ipq->ipq_label); 219395fab37eSRobert Watson } 219495fab37eSRobert Watson 219595fab37eSRobert Watson void 219695fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 219795fab37eSRobert Watson { 219895fab37eSRobert Watson 219995fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 220095fab37eSRobert Watson &mbuf->m_pkthdr.label); 220195fab37eSRobert Watson } 220295fab37eSRobert Watson 220395fab37eSRobert Watson void 220495fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 220595fab37eSRobert Watson { 220695fab37eSRobert Watson 220795fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 220895fab37eSRobert Watson &mp->mnt_fslabel); 220995fab37eSRobert Watson } 221095fab37eSRobert Watson 221195fab37eSRobert Watson void 221295fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 221395fab37eSRobert Watson { 221495fab37eSRobert Watson 221595fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 221695fab37eSRobert Watson &mp->mnt_fslabel); 221795fab37eSRobert Watson } 221895fab37eSRobert Watson 221995fab37eSRobert Watson int 222095fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 222195fab37eSRobert Watson { 222295fab37eSRobert Watson int error; 222395fab37eSRobert Watson 222495fab37eSRobert Watson if (!mac_enforce_network) 222595fab37eSRobert Watson return (0); 222695fab37eSRobert Watson 222795fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 222895fab37eSRobert Watson &ifnet->if_label); 222995fab37eSRobert Watson 223095fab37eSRobert Watson return (error); 223195fab37eSRobert Watson } 223295fab37eSRobert Watson 223395fab37eSRobert Watson static int 223495fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 223595fab37eSRobert Watson { 223695fab37eSRobert Watson int error; 223795fab37eSRobert Watson 223895fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 223995fab37eSRobert Watson 224095fab37eSRobert Watson return (error); 224195fab37eSRobert Watson } 224295fab37eSRobert Watson 224395fab37eSRobert Watson int 224495fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 224595fab37eSRobert Watson { 224695fab37eSRobert Watson int error; 224795fab37eSRobert Watson 224895fab37eSRobert Watson if (!mac_enforce_process) 224995fab37eSRobert Watson return (0); 225095fab37eSRobert Watson 225195fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 225295fab37eSRobert Watson 225395fab37eSRobert Watson return (error); 225495fab37eSRobert Watson } 225595fab37eSRobert Watson 225695fab37eSRobert Watson int 225795fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 225895fab37eSRobert Watson { 225995fab37eSRobert Watson int error; 226095fab37eSRobert Watson 226195fab37eSRobert Watson if (!mac_enforce_network) 226295fab37eSRobert Watson return (0); 226395fab37eSRobert Watson 226495fab37eSRobert Watson KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 226595fab37eSRobert Watson if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 226629e1b85fSBrooks Davis if_printf(ifnet, "not initialized\n"); 226795fab37eSRobert Watson 226895fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 226995fab37eSRobert Watson &mbuf->m_pkthdr.label); 227095fab37eSRobert Watson 227195fab37eSRobert Watson return (error); 227295fab37eSRobert Watson } 227395fab37eSRobert Watson 227495fab37eSRobert Watson int 2275e686e5aeSRobert Watson mac_check_kenv_dump(struct ucred *cred) 2276e686e5aeSRobert Watson { 2277e686e5aeSRobert Watson int error; 2278e686e5aeSRobert Watson 2279e686e5aeSRobert Watson if (!mac_enforce_system) 2280e686e5aeSRobert Watson return (0); 2281e686e5aeSRobert Watson 2282e686e5aeSRobert Watson MAC_CHECK(check_kenv_dump, cred); 2283e686e5aeSRobert Watson 2284e686e5aeSRobert Watson return (error); 2285e686e5aeSRobert Watson } 2286e686e5aeSRobert Watson 2287e686e5aeSRobert Watson int 2288e686e5aeSRobert Watson mac_check_kenv_get(struct ucred *cred, char *name) 2289e686e5aeSRobert Watson { 2290e686e5aeSRobert Watson int error; 2291e686e5aeSRobert Watson 2292e686e5aeSRobert Watson if (!mac_enforce_system) 2293e686e5aeSRobert Watson return (0); 2294e686e5aeSRobert Watson 2295e686e5aeSRobert Watson MAC_CHECK(check_kenv_get, cred, name); 2296e686e5aeSRobert Watson 2297e686e5aeSRobert Watson return (error); 2298e686e5aeSRobert Watson } 2299e686e5aeSRobert Watson 2300e686e5aeSRobert Watson int 2301e686e5aeSRobert Watson mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2302e686e5aeSRobert Watson { 2303e686e5aeSRobert Watson int error; 2304e686e5aeSRobert Watson 2305e686e5aeSRobert Watson if (!mac_enforce_system) 2306e686e5aeSRobert Watson return (0); 2307e686e5aeSRobert Watson 2308e686e5aeSRobert Watson MAC_CHECK(check_kenv_set, cred, name, value); 2309e686e5aeSRobert Watson 2310e686e5aeSRobert Watson return (error); 2311e686e5aeSRobert Watson } 2312e686e5aeSRobert Watson 2313e686e5aeSRobert Watson int 2314e686e5aeSRobert Watson mac_check_kenv_unset(struct ucred *cred, char *name) 2315e686e5aeSRobert Watson { 2316e686e5aeSRobert Watson int error; 2317e686e5aeSRobert Watson 2318e686e5aeSRobert Watson if (!mac_enforce_system) 2319e686e5aeSRobert Watson return (0); 2320e686e5aeSRobert Watson 2321e686e5aeSRobert Watson MAC_CHECK(check_kenv_unset, cred, name); 2322e686e5aeSRobert Watson 2323e686e5aeSRobert Watson return (error); 2324e686e5aeSRobert Watson } 2325e686e5aeSRobert Watson 2326e686e5aeSRobert Watson int 2327a3df768bSRobert Watson mac_check_kld_load(struct ucred *cred, struct vnode *vp) 2328a3df768bSRobert Watson { 2329a3df768bSRobert Watson int error; 2330a3df768bSRobert Watson 2331a3df768bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_kld_load"); 2332a3df768bSRobert Watson 2333a3df768bSRobert Watson if (!mac_enforce_kld) 2334a3df768bSRobert Watson return (0); 2335a3df768bSRobert Watson 2336a3df768bSRobert Watson MAC_CHECK(check_kld_load, cred, vp, &vp->v_label); 2337a3df768bSRobert Watson 2338a3df768bSRobert Watson return (error); 2339a3df768bSRobert Watson } 2340a3df768bSRobert Watson 2341a3df768bSRobert Watson int 2342a3df768bSRobert Watson mac_check_kld_stat(struct ucred *cred) 2343a3df768bSRobert Watson { 2344a3df768bSRobert Watson int error; 2345a3df768bSRobert Watson 2346a3df768bSRobert Watson if (!mac_enforce_kld) 2347a3df768bSRobert Watson return (0); 2348a3df768bSRobert Watson 2349a3df768bSRobert Watson MAC_CHECK(check_kld_stat, cred); 2350a3df768bSRobert Watson 2351a3df768bSRobert Watson return (error); 2352a3df768bSRobert Watson } 2353a3df768bSRobert Watson 2354a3df768bSRobert Watson int 2355a3df768bSRobert Watson mac_check_kld_unload(struct ucred *cred) 2356a3df768bSRobert Watson { 2357a3df768bSRobert Watson int error; 2358a3df768bSRobert Watson 2359a3df768bSRobert Watson if (!mac_enforce_kld) 2360a3df768bSRobert Watson return (0); 2361a3df768bSRobert Watson 2362a3df768bSRobert Watson MAC_CHECK(check_kld_unload, cred); 2363a3df768bSRobert Watson 2364a3df768bSRobert Watson return (error); 2365a3df768bSRobert Watson } 2366a3df768bSRobert Watson 2367a3df768bSRobert Watson int 236895fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 236995fab37eSRobert Watson { 237095fab37eSRobert Watson int error; 237195fab37eSRobert Watson 237295fab37eSRobert Watson if (!mac_enforce_fs) 237395fab37eSRobert Watson return (0); 237495fab37eSRobert Watson 237595fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 237695fab37eSRobert Watson 237795fab37eSRobert Watson return (error); 237895fab37eSRobert Watson } 237995fab37eSRobert Watson 238095fab37eSRobert Watson int 238195fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 238295fab37eSRobert Watson void *data) 238395fab37eSRobert Watson { 238495fab37eSRobert Watson int error; 238595fab37eSRobert Watson 23861aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 23871aa37f53SRobert Watson 23881aa37f53SRobert Watson if (!mac_enforce_pipe) 23891aa37f53SRobert Watson return (0); 23901aa37f53SRobert Watson 239195fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 239295fab37eSRobert Watson 239395fab37eSRobert Watson return (error); 239495fab37eSRobert Watson } 239595fab37eSRobert Watson 239695fab37eSRobert Watson int 2397c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 239895fab37eSRobert Watson { 239995fab37eSRobert Watson int error; 240095fab37eSRobert Watson 24011aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 24021aa37f53SRobert Watson 24031aa37f53SRobert Watson if (!mac_enforce_pipe) 24041aa37f53SRobert Watson return (0); 24051aa37f53SRobert Watson 2406c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2407c024c3eeSRobert Watson 2408c024c3eeSRobert Watson return (error); 2409c024c3eeSRobert Watson } 2410c024c3eeSRobert Watson 2411c024c3eeSRobert Watson int 2412c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2413c024c3eeSRobert Watson { 2414c024c3eeSRobert Watson int error; 2415c024c3eeSRobert Watson 24161aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 24171aa37f53SRobert Watson 24181aa37f53SRobert Watson if (!mac_enforce_pipe) 24191aa37f53SRobert Watson return (0); 24201aa37f53SRobert Watson 2421c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 242295fab37eSRobert Watson 242395fab37eSRobert Watson return (error); 242495fab37eSRobert Watson } 242595fab37eSRobert Watson 242695fab37eSRobert Watson static int 242795fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 242895fab37eSRobert Watson struct label *newlabel) 242995fab37eSRobert Watson { 243095fab37eSRobert Watson int error; 243195fab37eSRobert Watson 24321aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 24331aa37f53SRobert Watson 24341aa37f53SRobert Watson if (!mac_enforce_pipe) 24351aa37f53SRobert Watson return (0); 24361aa37f53SRobert Watson 243795fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 243895fab37eSRobert Watson 243995fab37eSRobert Watson return (error); 244095fab37eSRobert Watson } 244195fab37eSRobert Watson 244295fab37eSRobert Watson int 2443c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2444c024c3eeSRobert Watson { 2445c024c3eeSRobert Watson int error; 2446c024c3eeSRobert Watson 24471aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 24481aa37f53SRobert Watson 24491aa37f53SRobert Watson if (!mac_enforce_pipe) 24501aa37f53SRobert Watson return (0); 24511aa37f53SRobert Watson 2452c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2453c024c3eeSRobert Watson 2454c024c3eeSRobert Watson return (error); 2455c024c3eeSRobert Watson } 2456c024c3eeSRobert Watson 2457c024c3eeSRobert Watson int 2458c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2459c024c3eeSRobert Watson { 2460c024c3eeSRobert Watson int error; 2461c024c3eeSRobert Watson 24621aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 24631aa37f53SRobert Watson 24641aa37f53SRobert Watson if (!mac_enforce_pipe) 24651aa37f53SRobert Watson return (0); 24661aa37f53SRobert Watson 2467c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2468c024c3eeSRobert Watson 2469c024c3eeSRobert Watson return (error); 2470c024c3eeSRobert Watson } 2471c024c3eeSRobert Watson 2472c024c3eeSRobert Watson int 247395fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 247495fab37eSRobert Watson { 247595fab37eSRobert Watson int error; 247695fab37eSRobert Watson 2477b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2478b12baf55SRobert Watson 247995fab37eSRobert Watson if (!mac_enforce_process) 248095fab37eSRobert Watson return (0); 248195fab37eSRobert Watson 248295fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 248395fab37eSRobert Watson 248495fab37eSRobert Watson return (error); 248595fab37eSRobert Watson } 248695fab37eSRobert Watson 248795fab37eSRobert Watson int 248895fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 248995fab37eSRobert Watson { 249095fab37eSRobert Watson int error; 249195fab37eSRobert Watson 2492b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2493b12baf55SRobert Watson 249495fab37eSRobert Watson if (!mac_enforce_process) 249595fab37eSRobert Watson return (0); 249695fab37eSRobert Watson 249795fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 249895fab37eSRobert Watson 249995fab37eSRobert Watson return (error); 250095fab37eSRobert Watson } 250195fab37eSRobert Watson 250295fab37eSRobert Watson int 250395fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 250495fab37eSRobert Watson { 250595fab37eSRobert Watson int error; 250695fab37eSRobert Watson 2507b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2508b12baf55SRobert Watson 250995fab37eSRobert Watson if (!mac_enforce_process) 251095fab37eSRobert Watson return (0); 251195fab37eSRobert Watson 251295fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 251395fab37eSRobert Watson 251495fab37eSRobert Watson return (error); 251595fab37eSRobert Watson } 251695fab37eSRobert Watson 251795fab37eSRobert Watson int 251895fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 251995fab37eSRobert Watson struct sockaddr *sockaddr) 252095fab37eSRobert Watson { 252195fab37eSRobert Watson int error; 252295fab37eSRobert Watson 252395fab37eSRobert Watson if (!mac_enforce_socket) 252495fab37eSRobert Watson return (0); 252595fab37eSRobert Watson 252695fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 252795fab37eSRobert Watson sockaddr); 252895fab37eSRobert Watson 252995fab37eSRobert Watson return (error); 253095fab37eSRobert Watson } 253195fab37eSRobert Watson 253295fab37eSRobert Watson int 253395fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 253495fab37eSRobert Watson struct sockaddr *sockaddr) 253595fab37eSRobert Watson { 253695fab37eSRobert Watson int error; 253795fab37eSRobert Watson 253895fab37eSRobert Watson if (!mac_enforce_socket) 253995fab37eSRobert Watson return (0); 254095fab37eSRobert Watson 254195fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 254295fab37eSRobert Watson sockaddr); 254395fab37eSRobert Watson 254495fab37eSRobert Watson return (error); 254595fab37eSRobert Watson } 254695fab37eSRobert Watson 254795fab37eSRobert Watson int 2548d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2549d61198e4SRobert Watson { 2550d61198e4SRobert Watson int error; 2551d61198e4SRobert Watson 2552d61198e4SRobert Watson if (!mac_enforce_socket) 2553d61198e4SRobert Watson return (0); 2554d61198e4SRobert Watson 2555d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2556d61198e4SRobert Watson &mbuf->m_pkthdr.label); 2557d61198e4SRobert Watson 2558d61198e4SRobert Watson return (error); 2559d61198e4SRobert Watson } 2560d61198e4SRobert Watson 2561d61198e4SRobert Watson int 256295fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 256395fab37eSRobert Watson { 256495fab37eSRobert Watson int error; 256595fab37eSRobert Watson 256695fab37eSRobert Watson if (!mac_enforce_socket) 256795fab37eSRobert Watson return (0); 256895fab37eSRobert Watson 256995fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 257095fab37eSRobert Watson return (error); 257195fab37eSRobert Watson } 257295fab37eSRobert Watson 2573b371c939SRobert Watson int 2574b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 2575b371c939SRobert Watson { 2576b371c939SRobert Watson int error; 2577b371c939SRobert Watson 2578b371c939SRobert Watson if (!mac_enforce_socket) 2579b371c939SRobert Watson return (0); 2580b371c939SRobert Watson 2581b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2582b371c939SRobert Watson 2583b371c939SRobert Watson return (error); 2584b371c939SRobert Watson } 2585b371c939SRobert Watson 258695fab37eSRobert Watson static int 258795fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 258895fab37eSRobert Watson struct label *newlabel) 258995fab37eSRobert Watson { 259095fab37eSRobert Watson int error; 259195fab37eSRobert Watson 259295fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 259395fab37eSRobert Watson newlabel); 259495fab37eSRobert Watson 259595fab37eSRobert Watson return (error); 259695fab37eSRobert Watson } 259795fab37eSRobert Watson 259895fab37eSRobert Watson int 2599b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 2600b371c939SRobert Watson { 2601b371c939SRobert Watson int error; 2602b371c939SRobert Watson 2603b371c939SRobert Watson if (!mac_enforce_socket) 2604b371c939SRobert Watson return (0); 2605b371c939SRobert Watson 2606b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2607b371c939SRobert Watson 2608b371c939SRobert Watson return (error); 2609b371c939SRobert Watson } 2610b371c939SRobert Watson 2611b371c939SRobert Watson int 261295fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 261395fab37eSRobert Watson { 261495fab37eSRobert Watson int error; 261595fab37eSRobert Watson 261695fab37eSRobert Watson if (!mac_enforce_socket) 261795fab37eSRobert Watson return (0); 261895fab37eSRobert Watson 261995fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 262095fab37eSRobert Watson 262195fab37eSRobert Watson return (error); 262295fab37eSRobert Watson } 262395fab37eSRobert Watson 262495fab37eSRobert Watson int 2625e5e820fdSRobert Watson mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2626e5e820fdSRobert Watson { 2627e5e820fdSRobert Watson int error; 2628e5e820fdSRobert Watson 2629e5e820fdSRobert Watson if (vp != NULL) { 2630e5e820fdSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2631e5e820fdSRobert Watson } 2632e5e820fdSRobert Watson 2633e5e820fdSRobert Watson if (!mac_enforce_system) 2634e5e820fdSRobert Watson return (0); 2635e5e820fdSRobert Watson 2636e5e820fdSRobert Watson MAC_CHECK(check_system_acct, cred, vp, 2637e5e820fdSRobert Watson vp != NULL ? &vp->v_label : NULL); 2638e5e820fdSRobert Watson 2639e5e820fdSRobert Watson return (error); 2640e5e820fdSRobert Watson } 2641e5e820fdSRobert Watson 2642e5e820fdSRobert Watson int 2643e5e820fdSRobert Watson mac_check_system_nfsd(struct ucred *cred) 2644e5e820fdSRobert Watson { 2645e5e820fdSRobert Watson int error; 2646e5e820fdSRobert Watson 2647e5e820fdSRobert Watson if (!mac_enforce_system) 2648e5e820fdSRobert Watson return (0); 2649e5e820fdSRobert Watson 2650e5e820fdSRobert Watson MAC_CHECK(check_system_nfsd, cred); 2651e5e820fdSRobert Watson 2652e5e820fdSRobert Watson return (error); 2653e5e820fdSRobert Watson } 2654e5e820fdSRobert Watson 2655e5e820fdSRobert Watson int 2656a2ecb9b7SRobert Watson mac_check_system_reboot(struct ucred *cred, int howto) 2657a2ecb9b7SRobert Watson { 2658a2ecb9b7SRobert Watson int error; 2659a2ecb9b7SRobert Watson 26609e913ebdSRobert Watson if (!mac_enforce_system) 2661a2ecb9b7SRobert Watson return (0); 2662a2ecb9b7SRobert Watson 2663a2ecb9b7SRobert Watson MAC_CHECK(check_system_reboot, cred, howto); 26649e913ebdSRobert Watson 2665a2ecb9b7SRobert Watson return (error); 2666a2ecb9b7SRobert Watson } 2667a2ecb9b7SRobert Watson 2668a2ecb9b7SRobert Watson int 26694b8d5f2dSRobert Watson mac_check_system_settime(struct ucred *cred) 26704b8d5f2dSRobert Watson { 26714b8d5f2dSRobert Watson int error; 26724b8d5f2dSRobert Watson 26734b8d5f2dSRobert Watson if (!mac_enforce_system) 26744b8d5f2dSRobert Watson return (0); 26754b8d5f2dSRobert Watson 26764b8d5f2dSRobert Watson MAC_CHECK(check_system_settime, cred); 26774b8d5f2dSRobert Watson 26784b8d5f2dSRobert Watson return (error); 26794b8d5f2dSRobert Watson } 26804b8d5f2dSRobert Watson 26814b8d5f2dSRobert Watson int 268203ce2c0cSRobert Watson mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 268303ce2c0cSRobert Watson { 268403ce2c0cSRobert Watson int error; 268503ce2c0cSRobert Watson 268603ce2c0cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 268703ce2c0cSRobert Watson 26889e913ebdSRobert Watson if (!mac_enforce_system) 268903ce2c0cSRobert Watson return (0); 269003ce2c0cSRobert Watson 269103ce2c0cSRobert Watson MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 269203ce2c0cSRobert Watson return (error); 269303ce2c0cSRobert Watson } 269403ce2c0cSRobert Watson 269503ce2c0cSRobert Watson int 2696d3fc69eeSRobert Watson mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2697d3fc69eeSRobert Watson void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2698d3fc69eeSRobert Watson { 2699d3fc69eeSRobert Watson int error; 2700d3fc69eeSRobert Watson 2701d3fc69eeSRobert Watson /* 2702d3fc69eeSRobert Watson * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2703d3fc69eeSRobert Watson * but since it's not exported from kern_sysctl.c, we can't. 2704d3fc69eeSRobert Watson */ 27059e913ebdSRobert Watson if (!mac_enforce_system) 2706d3fc69eeSRobert Watson return (0); 2707d3fc69eeSRobert Watson 2708d3fc69eeSRobert Watson MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2709d3fc69eeSRobert Watson inkernel, new, newlen); 2710d3fc69eeSRobert Watson 2711d3fc69eeSRobert Watson return (error); 2712d3fc69eeSRobert Watson } 2713d3fc69eeSRobert Watson 2714d3fc69eeSRobert Watson int 271595fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 271695fab37eSRobert Watson struct ifnet *ifnet) 271795fab37eSRobert Watson { 2718f7b951a8SRobert Watson char *elements, *buffer; 2719f7b951a8SRobert Watson struct mac mac; 272095fab37eSRobert Watson int error; 272195fab37eSRobert Watson 2722f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 272395fab37eSRobert Watson if (error) 272495fab37eSRobert Watson return (error); 272595fab37eSRobert Watson 2726f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 2727f7b951a8SRobert Watson if (error) 2728f7b951a8SRobert Watson return (error); 2729f7b951a8SRobert Watson 2730f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2731f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2732f7b951a8SRobert Watson if (error) { 2733f7b951a8SRobert Watson free(elements, M_MACTEMP); 2734f7b951a8SRobert Watson return (error); 2735f7b951a8SRobert Watson } 2736f7b951a8SRobert Watson 2737f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2738f7b951a8SRobert Watson error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 2739f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 2740f7b951a8SRobert Watson if (error == 0) 2741f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2742f7b951a8SRobert Watson 2743f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2744f7b951a8SRobert Watson free(elements, M_MACTEMP); 2745f7b951a8SRobert Watson 2746f7b951a8SRobert Watson return (error); 274795fab37eSRobert Watson } 274895fab37eSRobert Watson 274995fab37eSRobert Watson int 275095fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 275195fab37eSRobert Watson struct ifnet *ifnet) 275295fab37eSRobert Watson { 275395fab37eSRobert Watson struct label intlabel; 2754f7b951a8SRobert Watson struct mac mac; 2755f7b951a8SRobert Watson char *buffer; 275695fab37eSRobert Watson int error; 275795fab37eSRobert Watson 2758f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 275995fab37eSRobert Watson if (error) 276095fab37eSRobert Watson return (error); 276195fab37eSRobert Watson 2762f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 276395fab37eSRobert Watson if (error) 276495fab37eSRobert Watson return (error); 276595fab37eSRobert Watson 2766f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2767f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 2768f7b951a8SRobert Watson if (error) { 2769f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2770f7b951a8SRobert Watson return (error); 2771f7b951a8SRobert Watson } 2772f7b951a8SRobert Watson 2773f7b951a8SRobert Watson mac_init_ifnet_label(&intlabel); 2774f7b951a8SRobert Watson error = mac_internalize_ifnet_label(&intlabel, buffer); 2775f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2776f7b951a8SRobert Watson if (error) { 2777f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2778f7b951a8SRobert Watson return (error); 2779f7b951a8SRobert Watson } 2780f7b951a8SRobert Watson 278195fab37eSRobert Watson /* 278295fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 278395fab37eSRobert Watson * policies impose this check themselves if required by the 278495fab37eSRobert Watson * policy. Eventually, this should go away. 278595fab37eSRobert Watson */ 278695fab37eSRobert Watson error = suser_cred(cred, 0); 2787f7b951a8SRobert Watson if (error) { 2788f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2789f7b951a8SRobert Watson return (error); 2790f7b951a8SRobert Watson } 279195fab37eSRobert Watson 279295fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 279395fab37eSRobert Watson &intlabel); 2794f7b951a8SRobert Watson if (error) { 2795f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2796f7b951a8SRobert Watson return (error); 2797f7b951a8SRobert Watson } 279895fab37eSRobert Watson 279995fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 280095fab37eSRobert Watson 2801f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2802f7b951a8SRobert Watson return (0); 280395fab37eSRobert Watson } 280495fab37eSRobert Watson 280595fab37eSRobert Watson void 2806990b4b2dSRobert Watson mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de) 280795fab37eSRobert Watson { 280895fab37eSRobert Watson 2809990b4b2dSRobert Watson MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label); 281095fab37eSRobert Watson } 281195fab37eSRobert Watson 281274e62b1bSRobert Watson void 2813990b4b2dSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct mount *mp, 2814990b4b2dSRobert Watson struct devfs_dirent *dd, struct devfs_dirent *de) 281574e62b1bSRobert Watson { 281674e62b1bSRobert Watson 2817990b4b2dSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de, 281874e62b1bSRobert Watson &de->de_label); 281974e62b1bSRobert Watson } 282074e62b1bSRobert Watson 282195fab37eSRobert Watson void 2822990b4b2dSRobert Watson mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen, 282395fab37eSRobert Watson struct devfs_dirent *de) 282495fab37eSRobert Watson { 282595fab37eSRobert Watson 2826990b4b2dSRobert Watson MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de, 282795fab37eSRobert Watson &de->de_label); 282895fab37eSRobert Watson } 282995fab37eSRobert Watson 283095fab37eSRobert Watson int 283195fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2832f7b951a8SRobert Watson struct mac *mac) 283395fab37eSRobert Watson { 283495fab37eSRobert Watson struct label intlabel; 2835f7b951a8SRobert Watson char *buffer; 283695fab37eSRobert Watson int error; 283795fab37eSRobert Watson 2838f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 283995fab37eSRobert Watson if (error) 284095fab37eSRobert Watson return (error); 284195fab37eSRobert Watson 2842f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2843f7b951a8SRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 2844f7b951a8SRobert Watson if (error) { 2845f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2846f7b951a8SRobert Watson return (error); 2847f7b951a8SRobert Watson } 2848f7b951a8SRobert Watson 2849f7b951a8SRobert Watson mac_init_socket_label(&intlabel, M_WAITOK); 2850f7b951a8SRobert Watson error = mac_internalize_socket_label(&intlabel, buffer); 2851f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2852f7b951a8SRobert Watson if (error) { 2853f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 2854f7b951a8SRobert Watson return (error); 2855f7b951a8SRobert Watson } 2856f7b951a8SRobert Watson 285795fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 285895fab37eSRobert Watson if (error) { 2859f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 286095fab37eSRobert Watson return (error); 286195fab37eSRobert Watson } 286295fab37eSRobert Watson 286395fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 286495fab37eSRobert Watson 2865f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 286695fab37eSRobert Watson return (0); 286795fab37eSRobert Watson } 286895fab37eSRobert Watson 286995fab37eSRobert Watson int 287095fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 287195fab37eSRobert Watson { 287295fab37eSRobert Watson int error; 287395fab37eSRobert Watson 28741aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28751aa37f53SRobert Watson 287695fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 287795fab37eSRobert Watson if (error) 287895fab37eSRobert Watson return (error); 287995fab37eSRobert Watson 288095fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 288195fab37eSRobert Watson 288295fab37eSRobert Watson return (0); 288395fab37eSRobert Watson } 288495fab37eSRobert Watson 288595fab37eSRobert Watson int 288695fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2887f7b951a8SRobert Watson struct mac *mac) 288895fab37eSRobert Watson { 2889f7b951a8SRobert Watson char *buffer, *elements; 2890f7b951a8SRobert Watson int error; 289195fab37eSRobert Watson 2892f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 2893f7b951a8SRobert Watson if (error) 2894f7b951a8SRobert Watson return (error); 2895f7b951a8SRobert Watson 2896f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2897f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2898f7b951a8SRobert Watson if (error) { 2899f7b951a8SRobert Watson free(elements, M_MACTEMP); 2900f7b951a8SRobert Watson return (error); 2901f7b951a8SRobert Watson } 2902f7b951a8SRobert Watson 2903f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2904f7b951a8SRobert Watson error = mac_externalize_socket_label(&so->so_label, elements, 2905f7b951a8SRobert Watson buffer, mac->m_buflen, M_WAITOK); 2906f7b951a8SRobert Watson if (error == 0) 2907f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2908f7b951a8SRobert Watson 2909f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2910f7b951a8SRobert Watson free(elements, M_MACTEMP); 2911f7b951a8SRobert Watson 2912f7b951a8SRobert Watson return (error); 291395fab37eSRobert Watson } 291495fab37eSRobert Watson 291595fab37eSRobert Watson int 291695fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2917f7b951a8SRobert Watson struct mac *mac) 291895fab37eSRobert Watson { 2919f7b951a8SRobert Watson char *elements, *buffer; 2920f7b951a8SRobert Watson int error; 292195fab37eSRobert Watson 2922f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 2923f7b951a8SRobert Watson if (error) 2924f7b951a8SRobert Watson return (error); 2925f7b951a8SRobert Watson 2926f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2927f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2928f7b951a8SRobert Watson if (error) { 2929f7b951a8SRobert Watson free(elements, M_MACTEMP); 2930f7b951a8SRobert Watson return (error); 2931f7b951a8SRobert Watson } 2932f7b951a8SRobert Watson 2933f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2934f7b951a8SRobert Watson error = mac_externalize_socket_peer_label(&so->so_peerlabel, 2935f7b951a8SRobert Watson elements, buffer, mac->m_buflen, M_WAITOK); 2936f7b951a8SRobert Watson if (error == 0) 2937f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2938f7b951a8SRobert Watson 2939f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2940f7b951a8SRobert Watson free(elements, M_MACTEMP); 2941f7b951a8SRobert Watson 2942f7b951a8SRobert Watson return (error); 294395fab37eSRobert Watson } 294495fab37eSRobert Watson 294595fab37eSRobert Watson /* 294695fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 294795fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 294895fab37eSRobert Watson * extended attributes. 294995fab37eSRobert Watson */ 295095fab37eSRobert Watson int 295195fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 295295fab37eSRobert Watson { 295395fab37eSRobert Watson struct vnode *vp = ap->a_vp; 295495fab37eSRobert Watson struct label *intlabel = ap->a_label; 295595fab37eSRobert Watson int error; 295695fab37eSRobert Watson 295795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 295895fab37eSRobert Watson 2959763bbd2fSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2960763bbd2fSRobert Watson return (EOPNOTSUPP); 296195fab37eSRobert Watson 2962763bbd2fSRobert Watson error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 296395fab37eSRobert Watson if (error) 296495fab37eSRobert Watson return (error); 296595fab37eSRobert Watson 296695fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 296795fab37eSRobert Watson 296895fab37eSRobert Watson return (0); 296995fab37eSRobert Watson } 297095fab37eSRobert Watson 297195fab37eSRobert Watson static int 297295fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 297395fab37eSRobert Watson { 297495fab37eSRobert Watson int error; 297595fab37eSRobert Watson 297695fab37eSRobert Watson if (vp->v_mount == NULL) { 297795fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 297806be2aaaSNate Lawson if (vp->v_type != VNON) 297906be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 298095fab37eSRobert Watson return (EBADF); 298195fab37eSRobert Watson } 298295fab37eSRobert Watson 298395fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 298495fab37eSRobert Watson return (EOPNOTSUPP); 298595fab37eSRobert Watson 298695fab37eSRobert Watson /* 298795fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 298895fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 298995fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 299095fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 299195fab37eSRobert Watson */ 299295fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 299395fab37eSRobert Watson if (error) 299495fab37eSRobert Watson return (error); 299595fab37eSRobert Watson 299695fab37eSRobert Watson /* 299795fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 299895fab37eSRobert Watson * decisions about who is and is not able to modify labels 299995fab37eSRobert Watson * and protections on files. This might not be right. We can't 300095fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 300195fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 300295fab37eSRobert Watson */ 300395fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 300495fab37eSRobert Watson if (error) 300595fab37eSRobert Watson return (error); 300695fab37eSRobert Watson 300795fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 300895fab37eSRobert Watson if (error) 300995fab37eSRobert Watson return (error); 301095fab37eSRobert Watson 301195fab37eSRobert Watson return (0); 301295fab37eSRobert Watson } 301395fab37eSRobert Watson 3014f7b951a8SRobert Watson int 3015f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3016f7b951a8SRobert Watson { 3017f7b951a8SRobert Watson char *elements, *buffer; 3018f7b951a8SRobert Watson struct mac mac; 3019f7b951a8SRobert Watson struct proc *tproc; 3020f7b951a8SRobert Watson struct ucred *tcred; 3021f7b951a8SRobert Watson int error; 3022f7b951a8SRobert Watson 3023d1e405c5SAlfred Perlstein error = copyin(uap->mac_p, &mac, sizeof(mac)); 3024f7b951a8SRobert Watson if (error) 3025f7b951a8SRobert Watson return (error); 3026f7b951a8SRobert Watson 3027f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3028f7b951a8SRobert Watson if (error) 3029f7b951a8SRobert Watson return (error); 3030f7b951a8SRobert Watson 3031f7b951a8SRobert Watson tproc = pfind(uap->pid); 3032f7b951a8SRobert Watson if (tproc == NULL) 3033f7b951a8SRobert Watson return (ESRCH); 3034f7b951a8SRobert Watson 3035f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 3036f7b951a8SRobert Watson error = p_cansee(td, tproc); 3037f7b951a8SRobert Watson if (error == 0) 3038f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 3039f7b951a8SRobert Watson PROC_UNLOCK(tproc); 3040f7b951a8SRobert Watson if (error) 3041f7b951a8SRobert Watson return (error); 3042f7b951a8SRobert Watson 3043f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3044f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3045f7b951a8SRobert Watson if (error) { 3046f7b951a8SRobert Watson free(elements, M_MACTEMP); 3047f7b951a8SRobert Watson crfree(tcred); 3048f7b951a8SRobert Watson return (error); 3049f7b951a8SRobert Watson } 3050f7b951a8SRobert Watson 3051f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3052f7b951a8SRobert Watson error = mac_externalize_cred_label(&tcred->cr_label, elements, 3053f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3054f7b951a8SRobert Watson if (error == 0) 3055f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3056f7b951a8SRobert Watson 3057f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3058f7b951a8SRobert Watson free(elements, M_MACTEMP); 3059f7b951a8SRobert Watson crfree(tcred); 3060f7b951a8SRobert Watson return (error); 3061f7b951a8SRobert Watson } 3062f7b951a8SRobert Watson 306395fab37eSRobert Watson /* 306495fab37eSRobert Watson * MPSAFE 306595fab37eSRobert Watson */ 306695fab37eSRobert Watson int 306795fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 306895fab37eSRobert Watson { 3069f7b951a8SRobert Watson char *elements, *buffer; 3070f7b951a8SRobert Watson struct mac mac; 307195fab37eSRobert Watson int error; 307295fab37eSRobert Watson 3073f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3074f7b951a8SRobert Watson if (error) 3075f7b951a8SRobert Watson return (error); 307695fab37eSRobert Watson 3077f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3078f7b951a8SRobert Watson if (error) 3079f7b951a8SRobert Watson return (error); 3080f7b951a8SRobert Watson 3081f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3082f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3083f7b951a8SRobert Watson if (error) { 3084f7b951a8SRobert Watson free(elements, M_MACTEMP); 3085f7b951a8SRobert Watson return (error); 3086f7b951a8SRobert Watson } 3087f7b951a8SRobert Watson 3088f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3089f7b951a8SRobert Watson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3090f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3091f7b951a8SRobert Watson if (error == 0) 3092f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3093f7b951a8SRobert Watson 3094f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3095f7b951a8SRobert Watson free(elements, M_MACTEMP); 309695fab37eSRobert Watson return (error); 309795fab37eSRobert Watson } 309895fab37eSRobert Watson 309995fab37eSRobert Watson /* 310095fab37eSRobert Watson * MPSAFE 310195fab37eSRobert Watson */ 310295fab37eSRobert Watson int 310395fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 310495fab37eSRobert Watson { 310595fab37eSRobert Watson struct ucred *newcred, *oldcred; 310695fab37eSRobert Watson struct label intlabel; 3107f7b951a8SRobert Watson struct proc *p; 3108f7b951a8SRobert Watson struct mac mac; 3109f7b951a8SRobert Watson char *buffer; 311095fab37eSRobert Watson int error; 311195fab37eSRobert Watson 3112f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 311395fab37eSRobert Watson if (error) 311495fab37eSRobert Watson return (error); 311595fab37eSRobert Watson 3116f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 311795fab37eSRobert Watson if (error) 311895fab37eSRobert Watson return (error); 311995fab37eSRobert Watson 3120f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3121f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3122f7b951a8SRobert Watson if (error) { 3123f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3124f7b951a8SRobert Watson return (error); 3125f7b951a8SRobert Watson } 3126f7b951a8SRobert Watson 3127f7b951a8SRobert Watson mac_init_cred_label(&intlabel); 3128f7b951a8SRobert Watson error = mac_internalize_cred_label(&intlabel, buffer); 3129f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3130f7b951a8SRobert Watson if (error) { 3131f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3132f7b951a8SRobert Watson return (error); 3133f7b951a8SRobert Watson } 3134f7b951a8SRobert Watson 313595fab37eSRobert Watson newcred = crget(); 313695fab37eSRobert Watson 313795fab37eSRobert Watson p = td->td_proc; 313895fab37eSRobert Watson PROC_LOCK(p); 313995fab37eSRobert Watson oldcred = p->p_ucred; 314095fab37eSRobert Watson 314195fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 314295fab37eSRobert Watson if (error) { 314395fab37eSRobert Watson PROC_UNLOCK(p); 314495fab37eSRobert Watson crfree(newcred); 3145f7b951a8SRobert Watson goto out; 314695fab37eSRobert Watson } 314795fab37eSRobert Watson 314895fab37eSRobert Watson setsugid(p); 314995fab37eSRobert Watson crcopy(newcred, oldcred); 315095fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 315195fab37eSRobert Watson p->p_ucred = newcred; 3152e5cb5e37SRobert Watson 3153e5cb5e37SRobert Watson /* 3154e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3155e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3156e5cb5e37SRobert Watson */ 3157e5cb5e37SRobert Watson crhold(newcred); 315895fab37eSRobert Watson PROC_UNLOCK(p); 3159e5cb5e37SRobert Watson 3160f7b951a8SRobert Watson if (mac_enforce_vm) { 316116140035SRobert Watson mtx_lock(&Giant); 3162e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 316316140035SRobert Watson mtx_unlock(&Giant); 3164f7b951a8SRobert Watson } 3165e5cb5e37SRobert Watson 3166e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 316795fab37eSRobert Watson crfree(oldcred); 3168f7b951a8SRobert Watson 3169f7b951a8SRobert Watson out: 3170f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3171f7b951a8SRobert Watson return (error); 317295fab37eSRobert Watson } 317395fab37eSRobert Watson 317495fab37eSRobert Watson /* 317595fab37eSRobert Watson * MPSAFE 317695fab37eSRobert Watson */ 317795fab37eSRobert Watson int 317895fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 317995fab37eSRobert Watson { 3180f7b951a8SRobert Watson char *elements, *buffer; 3181f7b951a8SRobert Watson struct label intlabel; 318295fab37eSRobert Watson struct file *fp; 3183f7b951a8SRobert Watson struct mac mac; 318495fab37eSRobert Watson struct vnode *vp; 318595fab37eSRobert Watson struct pipe *pipe; 3186f7b951a8SRobert Watson short label_type; 318795fab37eSRobert Watson int error; 318895fab37eSRobert Watson 3189f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3190f7b951a8SRobert Watson if (error) 3191f7b951a8SRobert Watson return (error); 319295fab37eSRobert Watson 3193f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3194f7b951a8SRobert Watson if (error) 3195f7b951a8SRobert Watson return (error); 3196f7b951a8SRobert Watson 3197f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3198f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3199f7b951a8SRobert Watson if (error) { 3200f7b951a8SRobert Watson free(elements, M_MACTEMP); 3201f7b951a8SRobert Watson return (error); 3202f7b951a8SRobert Watson } 3203f7b951a8SRobert Watson 3204f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3205f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3206d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 320795fab37eSRobert Watson if (error) 320895fab37eSRobert Watson goto out; 320995fab37eSRobert Watson 3210f7b951a8SRobert Watson label_type = fp->f_type; 321195fab37eSRobert Watson switch (fp->f_type) { 321295fab37eSRobert Watson case DTYPE_FIFO: 321395fab37eSRobert Watson case DTYPE_VNODE: 321448e3128bSMatthew Dillon vp = fp->f_data; 321595fab37eSRobert Watson 3216f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3217f7b951a8SRobert Watson 321895fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3219f7b951a8SRobert Watson mac_copy_vnode_label(&vp->v_label, &intlabel); 322095fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 3221f7b951a8SRobert Watson 322295fab37eSRobert Watson break; 322395fab37eSRobert Watson case DTYPE_PIPE: 322448e3128bSMatthew Dillon pipe = fp->f_data; 3225f7b951a8SRobert Watson 3226f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3227f7b951a8SRobert Watson 3228f7b951a8SRobert Watson PIPE_LOCK(pipe); 3229f7b951a8SRobert Watson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3230f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 323195fab37eSRobert Watson break; 323295fab37eSRobert Watson default: 323395fab37eSRobert Watson error = EINVAL; 3234f7b951a8SRobert Watson fdrop(fp, td); 3235f7b951a8SRobert Watson goto out; 3236f7b951a8SRobert Watson } 3237f7b951a8SRobert Watson fdrop(fp, td); 3238f7b951a8SRobert Watson 3239f7b951a8SRobert Watson switch (label_type) { 3240f7b951a8SRobert Watson case DTYPE_FIFO: 3241f7b951a8SRobert Watson case DTYPE_VNODE: 3242f7b951a8SRobert Watson if (error == 0) 3243f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, 3244f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3245f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3246f7b951a8SRobert Watson break; 3247f7b951a8SRobert Watson case DTYPE_PIPE: 3248f7b951a8SRobert Watson error = mac_externalize_pipe_label(&intlabel, elements, 3249f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3250f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 3251f7b951a8SRobert Watson break; 3252f7b951a8SRobert Watson default: 3253f7b951a8SRobert Watson panic("__mac_get_fd: corrupted label_type"); 325495fab37eSRobert Watson } 325595fab37eSRobert Watson 325695fab37eSRobert Watson if (error == 0) 3257f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 325895fab37eSRobert Watson 325995fab37eSRobert Watson out: 3260f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3261f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3262f7b951a8SRobert Watson free(elements, M_MACTEMP); 3263f7b951a8SRobert Watson 326495fab37eSRobert Watson return (error); 326595fab37eSRobert Watson } 326695fab37eSRobert Watson 326795fab37eSRobert Watson /* 326895fab37eSRobert Watson * MPSAFE 326995fab37eSRobert Watson */ 327095fab37eSRobert Watson int 327195fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 327295fab37eSRobert Watson { 3273f7b951a8SRobert Watson char *elements, *buffer; 327495fab37eSRobert Watson struct nameidata nd; 3275f7b951a8SRobert Watson struct label intlabel; 3276f7b951a8SRobert Watson struct mac mac; 327795fab37eSRobert Watson int error; 327895fab37eSRobert Watson 3279f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3280f7b951a8SRobert Watson if (error) 3281f7b951a8SRobert Watson return (error); 3282f7b951a8SRobert Watson 3283f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3284f7b951a8SRobert Watson if (error) 3285f7b951a8SRobert Watson return (error); 3286f7b951a8SRobert Watson 3287f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3288f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3289f7b951a8SRobert Watson if (error) { 3290f7b951a8SRobert Watson free(elements, M_MACTEMP); 3291f7b951a8SRobert Watson return (error); 3292f7b951a8SRobert Watson } 3293f7b951a8SRobert Watson 3294f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3295f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3296f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3297f7b951a8SRobert Watson td); 329895fab37eSRobert Watson error = namei(&nd); 329995fab37eSRobert Watson if (error) 330095fab37eSRobert Watson goto out; 330195fab37eSRobert Watson 3302f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3303f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3304763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3305763bbd2fSRobert Watson mac.m_buflen, M_WAITOK); 3306f7b951a8SRobert Watson 330795fab37eSRobert Watson NDFREE(&nd, 0); 3308f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3309f7b951a8SRobert Watson 3310f7b951a8SRobert Watson if (error == 0) 3311f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3312f7b951a8SRobert Watson 3313f7b951a8SRobert Watson out: 3314f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3315f7b951a8SRobert Watson 3316f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3317f7b951a8SRobert Watson free(elements, M_MACTEMP); 3318f7b951a8SRobert Watson 3319f7b951a8SRobert Watson return (error); 3320f7b951a8SRobert Watson } 3321f7b951a8SRobert Watson 3322f7b951a8SRobert Watson /* 3323f7b951a8SRobert Watson * MPSAFE 3324f7b951a8SRobert Watson */ 3325f7b951a8SRobert Watson int 3326f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3327f7b951a8SRobert Watson { 3328f7b951a8SRobert Watson char *elements, *buffer; 3329f7b951a8SRobert Watson struct nameidata nd; 3330f7b951a8SRobert Watson struct label intlabel; 3331f7b951a8SRobert Watson struct mac mac; 3332f7b951a8SRobert Watson int error; 3333f7b951a8SRobert Watson 3334f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3335f7b951a8SRobert Watson if (error) 3336f7b951a8SRobert Watson return (error); 3337f7b951a8SRobert Watson 3338f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3339f7b951a8SRobert Watson if (error) 3340f7b951a8SRobert Watson return (error); 3341f7b951a8SRobert Watson 3342f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3343f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3344f7b951a8SRobert Watson if (error) { 3345f7b951a8SRobert Watson free(elements, M_MACTEMP); 3346f7b951a8SRobert Watson return (error); 3347f7b951a8SRobert Watson } 3348f7b951a8SRobert Watson 3349f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3350f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3351f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3352f7b951a8SRobert Watson td); 3353f7b951a8SRobert Watson error = namei(&nd); 335495fab37eSRobert Watson if (error) 335595fab37eSRobert Watson goto out; 335695fab37eSRobert Watson 3357f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3358f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3359763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3360763bbd2fSRobert Watson mac.m_buflen, M_WAITOK); 3361f7b951a8SRobert Watson NDFREE(&nd, 0); 3362f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3363f7b951a8SRobert Watson 3364f7b951a8SRobert Watson if (error == 0) 3365f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 336695fab37eSRobert Watson 336795fab37eSRobert Watson out: 3368f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3369f7b951a8SRobert Watson 3370f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3371f7b951a8SRobert Watson free(elements, M_MACTEMP); 3372f7b951a8SRobert Watson 337395fab37eSRobert Watson return (error); 337495fab37eSRobert Watson } 337595fab37eSRobert Watson 337695fab37eSRobert Watson /* 337795fab37eSRobert Watson * MPSAFE 337895fab37eSRobert Watson */ 337995fab37eSRobert Watson int 338095fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 338195fab37eSRobert Watson { 338295fab37eSRobert Watson struct label intlabel; 3383f7b951a8SRobert Watson struct pipe *pipe; 3384f7b951a8SRobert Watson struct file *fp; 338595fab37eSRobert Watson struct mount *mp; 338695fab37eSRobert Watson struct vnode *vp; 3387f7b951a8SRobert Watson struct mac mac; 3388f7b951a8SRobert Watson char *buffer; 338995fab37eSRobert Watson int error; 339095fab37eSRobert Watson 3391f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3392f7b951a8SRobert Watson if (error) 3393f7b951a8SRobert Watson return (error); 3394f7b951a8SRobert Watson 3395f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3396f7b951a8SRobert Watson if (error) 3397f7b951a8SRobert Watson return (error); 3398f7b951a8SRobert Watson 3399f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3400f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3401f7b951a8SRobert Watson if (error) { 3402f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3403f7b951a8SRobert Watson return (error); 3404f7b951a8SRobert Watson } 3405f7b951a8SRobert Watson 3406f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3407f7b951a8SRobert Watson 3408d1e405c5SAlfred Perlstein error = fget(td, uap->fd, &fp); 340995fab37eSRobert Watson if (error) 3410f7b951a8SRobert Watson goto out; 341195fab37eSRobert Watson 341295fab37eSRobert Watson switch (fp->f_type) { 341395fab37eSRobert Watson case DTYPE_FIFO: 341495fab37eSRobert Watson case DTYPE_VNODE: 3415f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3416f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3417f7b951a8SRobert Watson if (error) { 3418f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3419f7b951a8SRobert Watson break; 3420f7b951a8SRobert Watson } 3421f7b951a8SRobert Watson 342248e3128bSMatthew Dillon vp = fp->f_data; 342395fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3424f7b951a8SRobert Watson if (error != 0) { 3425f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 342695fab37eSRobert Watson break; 3427f7b951a8SRobert Watson } 342895fab37eSRobert Watson 342995fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 343095fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 343195fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 343295fab37eSRobert Watson vn_finished_write(mp); 3433f7b951a8SRobert Watson 3434f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 343595fab37eSRobert Watson break; 3436f7b951a8SRobert Watson 343795fab37eSRobert Watson case DTYPE_PIPE: 3438f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3439f7b951a8SRobert Watson error = mac_internalize_pipe_label(&intlabel, buffer); 3440f7b951a8SRobert Watson if (error == 0) { 344148e3128bSMatthew Dillon pipe = fp->f_data; 34421aa37f53SRobert Watson PIPE_LOCK(pipe); 3443f7b951a8SRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, 3444f7b951a8SRobert Watson &intlabel); 34451aa37f53SRobert Watson PIPE_UNLOCK(pipe); 3446f7b951a8SRobert Watson } 3447f7b951a8SRobert Watson 3448f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 344995fab37eSRobert Watson break; 3450f7b951a8SRobert Watson 345195fab37eSRobert Watson default: 345295fab37eSRobert Watson error = EINVAL; 345395fab37eSRobert Watson } 345495fab37eSRobert Watson 345595fab37eSRobert Watson fdrop(fp, td); 3456f7b951a8SRobert Watson out: 3457f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3458f7b951a8SRobert Watson 3459f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3460f7b951a8SRobert Watson 346195fab37eSRobert Watson return (error); 346295fab37eSRobert Watson } 346395fab37eSRobert Watson 346495fab37eSRobert Watson /* 346595fab37eSRobert Watson * MPSAFE 346695fab37eSRobert Watson */ 346795fab37eSRobert Watson int 346895fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 346995fab37eSRobert Watson { 347095fab37eSRobert Watson struct label intlabel; 3471f7b951a8SRobert Watson struct nameidata nd; 347295fab37eSRobert Watson struct mount *mp; 3473f7b951a8SRobert Watson struct mac mac; 3474f7b951a8SRobert Watson char *buffer; 347595fab37eSRobert Watson int error; 347695fab37eSRobert Watson 3477f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 347895fab37eSRobert Watson if (error) 3479f7b951a8SRobert Watson return (error); 348095fab37eSRobert Watson 3481f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 348295fab37eSRobert Watson if (error) 3483f7b951a8SRobert Watson return (error); 348495fab37eSRobert Watson 3485f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3486f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3487f7b951a8SRobert Watson if (error) { 3488f7b951a8SRobert Watson free(buffer, M_MACTEMP); 348995fab37eSRobert Watson return (error); 349095fab37eSRobert Watson } 349195fab37eSRobert Watson 3492f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3493f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3494f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3495f7b951a8SRobert Watson if (error) { 3496f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3497f7b951a8SRobert Watson return (error); 3498f7b951a8SRobert Watson } 3499f7b951a8SRobert Watson 3500f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3501f7b951a8SRobert Watson 3502f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3503f7b951a8SRobert Watson td); 3504f7b951a8SRobert Watson error = namei(&nd); 3505f7b951a8SRobert Watson if (error == 0) { 3506f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3507f7b951a8SRobert Watson if (error == 0) 3508f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3509f7b951a8SRobert Watson td->td_ucred); 3510f7b951a8SRobert Watson vn_finished_write(mp); 3511f7b951a8SRobert Watson } 3512f7b951a8SRobert Watson 3513f7b951a8SRobert Watson NDFREE(&nd, 0); 3514f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3515f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3516f7b951a8SRobert Watson 3517f7b951a8SRobert Watson return (error); 3518f7b951a8SRobert Watson } 3519f7b951a8SRobert Watson 3520f7b951a8SRobert Watson /* 3521f7b951a8SRobert Watson * MPSAFE 3522f7b951a8SRobert Watson */ 3523f7b951a8SRobert Watson int 3524f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3525f7b951a8SRobert Watson { 3526f7b951a8SRobert Watson struct label intlabel; 3527f7b951a8SRobert Watson struct nameidata nd; 3528f7b951a8SRobert Watson struct mount *mp; 3529f7b951a8SRobert Watson struct mac mac; 3530f7b951a8SRobert Watson char *buffer; 3531f7b951a8SRobert Watson int error; 3532f7b951a8SRobert Watson 3533f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3534f7b951a8SRobert Watson if (error) 3535f7b951a8SRobert Watson return (error); 3536f7b951a8SRobert Watson 3537f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3538f7b951a8SRobert Watson if (error) 3539f7b951a8SRobert Watson return (error); 3540f7b951a8SRobert Watson 3541f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3542f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3543f7b951a8SRobert Watson if (error) { 3544f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3545f7b951a8SRobert Watson return (error); 3546f7b951a8SRobert Watson } 3547f7b951a8SRobert Watson 3548f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3549f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3550f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3551f7b951a8SRobert Watson if (error) { 3552f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3553f7b951a8SRobert Watson return (error); 3554f7b951a8SRobert Watson } 3555f7b951a8SRobert Watson 3556f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3557f7b951a8SRobert Watson 3558f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3559f7b951a8SRobert Watson td); 3560f7b951a8SRobert Watson error = namei(&nd); 3561f7b951a8SRobert Watson if (error == 0) { 3562f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3563f7b951a8SRobert Watson if (error == 0) 3564f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3565f7b951a8SRobert Watson td->td_ucred); 3566f7b951a8SRobert Watson vn_finished_write(mp); 3567f7b951a8SRobert Watson } 3568f7b951a8SRobert Watson 3569f7b951a8SRobert Watson NDFREE(&nd, 0); 3570f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3571f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3572f7b951a8SRobert Watson 3573f7b951a8SRobert Watson return (error); 3574f7b951a8SRobert Watson } 3575f7b951a8SRobert Watson 3576f7b951a8SRobert Watson /* 3577f7b951a8SRobert Watson * MPSAFE 3578f7b951a8SRobert Watson */ 357927f2eac7SRobert Watson int 358027f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 358127f2eac7SRobert Watson { 358227f2eac7SRobert Watson struct mac_policy_conf *mpc; 358327f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 358427f2eac7SRobert Watson int error; 358527f2eac7SRobert Watson 3586d1e405c5SAlfred Perlstein error = copyinstr(uap->policy, target, sizeof(target), NULL); 358727f2eac7SRobert Watson if (error) 358827f2eac7SRobert Watson return (error); 358927f2eac7SRobert Watson 359027f2eac7SRobert Watson error = ENOSYS; 359127f2eac7SRobert Watson MAC_POLICY_LIST_BUSY(); 359227f2eac7SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 359327f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 359427f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 359527f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 3596d1e405c5SAlfred Perlstein uap->call, uap->arg); 359727f2eac7SRobert Watson goto out; 359827f2eac7SRobert Watson } 359927f2eac7SRobert Watson } 360027f2eac7SRobert Watson 360127f2eac7SRobert Watson out: 360227f2eac7SRobert Watson MAC_POLICY_LIST_UNBUSY(); 360327f2eac7SRobert Watson return (error); 360427f2eac7SRobert Watson } 360527f2eac7SRobert Watson 360695fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 360795fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 360895fab37eSRobert Watson 360995fab37eSRobert Watson #else /* !MAC */ 36107bc82500SRobert Watson 36117bc82500SRobert Watson int 3612f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3613f7b951a8SRobert Watson { 3614f7b951a8SRobert Watson 3615f7b951a8SRobert Watson return (ENOSYS); 3616f7b951a8SRobert Watson } 3617f7b951a8SRobert Watson 3618f7b951a8SRobert Watson int 36197bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 36207bc82500SRobert Watson { 36217bc82500SRobert Watson 36227bc82500SRobert Watson return (ENOSYS); 36237bc82500SRobert Watson } 36247bc82500SRobert Watson 36257bc82500SRobert Watson int 36267bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 36277bc82500SRobert Watson { 36287bc82500SRobert Watson 36297bc82500SRobert Watson return (ENOSYS); 36307bc82500SRobert Watson } 36317bc82500SRobert Watson 36327bc82500SRobert Watson int 36337bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 36347bc82500SRobert Watson { 36357bc82500SRobert Watson 36367bc82500SRobert Watson return (ENOSYS); 36377bc82500SRobert Watson } 36387bc82500SRobert Watson 36397bc82500SRobert Watson int 36407bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 36417bc82500SRobert Watson { 36427bc82500SRobert Watson 36437bc82500SRobert Watson return (ENOSYS); 36447bc82500SRobert Watson } 36457bc82500SRobert Watson 36467bc82500SRobert Watson int 3647f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3648f7b951a8SRobert Watson { 3649f7b951a8SRobert Watson 3650f7b951a8SRobert Watson return (ENOSYS); 3651f7b951a8SRobert Watson } 3652f7b951a8SRobert Watson 3653f7b951a8SRobert Watson int 36547bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 36557bc82500SRobert Watson { 36567bc82500SRobert Watson 36577bc82500SRobert Watson return (ENOSYS); 36587bc82500SRobert Watson } 36597bc82500SRobert Watson 36607bc82500SRobert Watson int 36617bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 36627bc82500SRobert Watson { 36637bc82500SRobert Watson 36647bc82500SRobert Watson return (ENOSYS); 36657bc82500SRobert Watson } 366695fab37eSRobert Watson 366727f2eac7SRobert Watson int 3668f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3669f7b951a8SRobert Watson { 3670f7b951a8SRobert Watson 3671f7b951a8SRobert Watson return (ENOSYS); 3672f7b951a8SRobert Watson } 3673f7b951a8SRobert Watson 3674f7b951a8SRobert Watson int 367527f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 367627f2eac7SRobert Watson { 367727f2eac7SRobert Watson 367827f2eac7SRobert Watson return (ENOSYS); 367927f2eac7SRobert Watson } 368027f2eac7SRobert Watson 3681f7b951a8SRobert Watson #endif 3682