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 12895fab37eSRobert Watson static int mac_enforce_network = 1; 12995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 13095fab37eSRobert Watson &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 13195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 13295fab37eSRobert Watson 133b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 134b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 135b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 136c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 137b88c98f6SRobert Watson 13895fab37eSRobert Watson static int mac_enforce_process = 1; 13995fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 14095fab37eSRobert Watson &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 14195fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 14295fab37eSRobert Watson 14395fab37eSRobert Watson static int mac_enforce_socket = 1; 14495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 14595fab37eSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 14695fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 14795fab37eSRobert Watson 1489e913ebdSRobert Watson static int mac_enforce_system = 1; 1499e913ebdSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, 1509e913ebdSRobert Watson &mac_enforce_system, 0, "Enforce MAC policy on system operations"); 1519e913ebdSRobert Watson TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); 152d3fc69eeSRobert Watson 153ca7850c3SRobert Watson static int mac_enforce_vm = 1; 154ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, 155ca7850c3SRobert Watson &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); 156c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); 157ca7850c3SRobert Watson 158c0f39905SRobert Watson static int mac_mmap_revocation = 1; 159c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, 160c0f39905SRobert Watson &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " 161c0f39905SRobert Watson "relabel"); 16299fa64f8SRobert Watson static int mac_mmap_revocation_via_cow = 0; 16395fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 16495fab37eSRobert Watson &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 16595fab37eSRobert Watson "copy-on-write semantics, or by removing all write access"); 16695fab37eSRobert Watson 167f050add5SRobert Watson #ifdef MAC_DEBUG 1686be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 1696be0c25eSRobert Watson "TrustedBSD MAC debug info"); 1706be0c25eSRobert Watson 1716be0c25eSRobert Watson static int mac_debug_label_fallback = 0; 1726be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 1736be0c25eSRobert Watson &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 1746be0c25eSRobert Watson "when label is corrupted."); 1756be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback", 1766be0c25eSRobert Watson &mac_debug_label_fallback); 1776be0c25eSRobert Watson 178b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 179b2f0927aSRobert Watson "TrustedBSD MAC object counters"); 180b2f0927aSRobert Watson 18195fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 18295fab37eSRobert Watson nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 18395fab37eSRobert Watson nmacipqs, nmacpipes; 184b2f0927aSRobert Watson 185b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD, 18695fab37eSRobert Watson &nmacmbufs, 0, "number of mbufs in use"); 187b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD, 18895fab37eSRobert Watson &nmaccreds, 0, "number of ucreds in use"); 189b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD, 19095fab37eSRobert Watson &nmacifnets, 0, "number of ifnets in use"); 191b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD, 19295fab37eSRobert Watson &nmacipqs, 0, "number of ipqs in use"); 193b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD, 19495fab37eSRobert Watson &nmacbpfdescs, 0, "number of bpfdescs in use"); 195b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 19695fab37eSRobert Watson &nmacsockets, 0, "number of sockets in use"); 197b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 19895fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 199b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD, 20095fab37eSRobert Watson &nmacmounts, 0, "number of mounts in use"); 201b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 20295fab37eSRobert Watson &nmactemp, 0, "number of temporary labels in use"); 203b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD, 20495fab37eSRobert Watson &nmacvnodes, 0, "number of vnodes in use"); 205b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, 20695fab37eSRobert Watson &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 207f050add5SRobert Watson #endif 20895fab37eSRobert Watson 20995fab37eSRobert Watson static int error_select(int error1, int error2); 21095fab37eSRobert Watson static int mac_policy_register(struct mac_policy_conf *mpc); 21195fab37eSRobert Watson static int mac_policy_unregister(struct mac_policy_conf *mpc); 21295fab37eSRobert Watson 213e183f80eSRobert Watson static void mac_check_vnode_mmap_downgrade(struct ucred *cred, 214e183f80eSRobert Watson struct vnode *vp, int *prot); 21595fab37eSRobert Watson static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 21695fab37eSRobert Watson struct ucred *cred, struct vm_map *map); 21795fab37eSRobert Watson 21883985c26SRobert Watson static void mac_destroy_socket_label(struct label *label); 21983985c26SRobert Watson 220763bbd2fSRobert Watson static int mac_setlabel_vnode_extattr(struct ucred *cred, 221763bbd2fSRobert Watson struct vnode *vp, struct label *intlabel); 222763bbd2fSRobert Watson 22395fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 224f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 22595fab37eSRobert Watson 22695fab37eSRobert Watson /* 227a96acd1aSRobert Watson * mac_policy_list stores the list of active policies. A busy count is 228a96acd1aSRobert Watson * maintained for the list, stored in mac_policy_busy. The busy count 229a96acd1aSRobert Watson * is protected by mac_policy_list_lock; the list may be modified only 230a96acd1aSRobert Watson * while the busy count is 0, requiring that the lock be held to 231a96acd1aSRobert Watson * prevent new references to the list from being acquired. For almost 232a96acd1aSRobert Watson * all operations, incrementing the busy count is sufficient to 233a96acd1aSRobert Watson * guarantee consistency, as the list cannot be modified while the 234a96acd1aSRobert Watson * busy count is elevated. For a few special operations involving a 235a96acd1aSRobert Watson * change to the list of active policies, the lock itself must be held. 236a96acd1aSRobert Watson * A condition variable, mac_policy_list_not_busy, is used to signal 237a96acd1aSRobert Watson * potential exclusive consumers that they should try to acquire the 238a96acd1aSRobert Watson * lock if a first attempt at exclusive access fails. 23995fab37eSRobert Watson */ 24095fab37eSRobert Watson static struct mtx mac_policy_list_lock; 241a96acd1aSRobert Watson static struct cv mac_policy_list_not_busy; 24295fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list; 24395fab37eSRobert Watson static int mac_policy_list_busy; 244a96acd1aSRobert Watson 245a96acd1aSRobert Watson #define MAC_POLICY_LIST_LOCKINIT() do { \ 246a96acd1aSRobert Watson mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL, \ 247a96acd1aSRobert Watson MTX_DEF); \ 248a96acd1aSRobert Watson cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy"); \ 249a96acd1aSRobert Watson } while (0) 250a96acd1aSRobert Watson 251a96acd1aSRobert Watson #define MAC_POLICY_LIST_LOCK() do { \ 252a96acd1aSRobert Watson mtx_lock(&mac_policy_list_lock); \ 253a96acd1aSRobert Watson } while (0) 254a96acd1aSRobert Watson 255a96acd1aSRobert Watson #define MAC_POLICY_LIST_UNLOCK() do { \ 256a96acd1aSRobert Watson mtx_unlock(&mac_policy_list_lock); \ 257a96acd1aSRobert Watson } while (0) 258a96acd1aSRobert Watson 259a96acd1aSRobert Watson /* 260a96acd1aSRobert Watson * We manually invoke WITNESS_SLEEP() to allow Witness to generate 261a96acd1aSRobert Watson * warnings even if we don't end up ever triggering the wait at 262a96acd1aSRobert Watson * run-time. The consumer of the exclusive interface must not hold 263a96acd1aSRobert Watson * any locks (other than potentially Giant) since we may sleep for 264a96acd1aSRobert Watson * long (potentially indefinite) periods of time waiting for the 265a96acd1aSRobert Watson * framework to become quiescent so that a policy list change may 266a96acd1aSRobert Watson * be made. 267a96acd1aSRobert Watson */ 268a96acd1aSRobert Watson #define MAC_POLICY_LIST_EXCLUSIVE() do { \ 269a96acd1aSRobert Watson WITNESS_SLEEP(1, NULL); \ 270a96acd1aSRobert Watson mtx_lock(&mac_policy_list_lock); \ 271a96acd1aSRobert Watson while (mac_policy_list_busy != 0) \ 272a96acd1aSRobert Watson cv_wait(&mac_policy_list_not_busy, \ 273a96acd1aSRobert Watson &mac_policy_list_lock); \ 274a96acd1aSRobert Watson } while (0) 27595fab37eSRobert Watson 27695fab37eSRobert Watson #define MAC_POLICY_LIST_BUSY() do { \ 27795fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 27895fab37eSRobert Watson mac_policy_list_busy++; \ 27995fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 28095fab37eSRobert Watson } while (0) 28195fab37eSRobert Watson 28295fab37eSRobert Watson #define MAC_POLICY_LIST_UNBUSY() do { \ 28395fab37eSRobert Watson MAC_POLICY_LIST_LOCK(); \ 28495fab37eSRobert Watson mac_policy_list_busy--; \ 285a96acd1aSRobert Watson KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK")); \ 286a96acd1aSRobert Watson if (mac_policy_list_busy == 0) \ 287a96acd1aSRobert Watson cv_signal(&mac_policy_list_not_busy); \ 28895fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); \ 28995fab37eSRobert Watson } while (0) 29095fab37eSRobert Watson 29195fab37eSRobert Watson /* 29295fab37eSRobert Watson * MAC_CHECK performs the designated check by walking the policy 29395fab37eSRobert Watson * module list and checking with each as to how it feels about the 29495fab37eSRobert Watson * request. Note that it returns its value via 'error' in the scope 29595fab37eSRobert Watson * of the caller. 29695fab37eSRobert Watson */ 29795fab37eSRobert Watson #define MAC_CHECK(check, args...) do { \ 29895fab37eSRobert Watson struct mac_policy_conf *mpc; \ 29995fab37eSRobert Watson \ 30095fab37eSRobert Watson error = 0; \ 30195fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 30295fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 30395fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## check != NULL) \ 30495fab37eSRobert Watson error = error_select( \ 30595fab37eSRobert Watson mpc->mpc_ops->mpo_ ## check (args), \ 30695fab37eSRobert Watson error); \ 30795fab37eSRobert Watson } \ 30895fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 30995fab37eSRobert Watson } while (0) 31095fab37eSRobert Watson 31195fab37eSRobert Watson /* 31295fab37eSRobert Watson * MAC_BOOLEAN performs the designated boolean composition by walking 31395fab37eSRobert Watson * the module list, invoking each instance of the operation, and 31495fab37eSRobert Watson * combining the results using the passed C operator. Note that it 31595fab37eSRobert Watson * returns its value via 'result' in the scope of the caller, which 31695fab37eSRobert Watson * should be initialized by the caller in a meaningful way to get 31795fab37eSRobert Watson * a meaningful result. 31895fab37eSRobert Watson */ 31995fab37eSRobert Watson #define MAC_BOOLEAN(operation, composition, args...) do { \ 32095fab37eSRobert Watson struct mac_policy_conf *mpc; \ 32195fab37eSRobert Watson \ 32295fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 32395fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 32495fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 32595fab37eSRobert Watson result = result composition \ 32695fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 32795fab37eSRobert Watson } \ 32895fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 32995fab37eSRobert Watson } while (0) 33095fab37eSRobert Watson 331f7b951a8SRobert Watson #define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \ 332f7b951a8SRobert Watson outbuflen) do { \ 333f7b951a8SRobert Watson char *curptr, *curptr_start, *element_name, *element_temp; \ 334f7b951a8SRobert Watson size_t left, left_start, len; \ 335f7b951a8SRobert Watson int claimed, first, first_start, ignorenotfound; \ 336f7b951a8SRobert Watson \ 337f7b951a8SRobert Watson error = 0; \ 338f7b951a8SRobert Watson element_temp = elementlist; \ 339f7b951a8SRobert Watson curptr = outbuf; \ 340f7b951a8SRobert Watson curptr[0] = '\0'; \ 341f7b951a8SRobert Watson left = outbuflen; \ 342f7b951a8SRobert Watson first = 1; \ 343f7b951a8SRobert Watson while ((element_name = strsep(&element_temp, ",")) != NULL) { \ 344f7b951a8SRobert Watson curptr_start = curptr; \ 345f7b951a8SRobert Watson left_start = left; \ 346f7b951a8SRobert Watson first_start = first; \ 347f7b951a8SRobert Watson if (element_name[0] == '?') { \ 348f7b951a8SRobert Watson element_name++; \ 349f7b951a8SRobert Watson ignorenotfound = 1; \ 350f7b951a8SRobert Watson } else \ 351f7b951a8SRobert Watson ignorenotfound = 0; \ 352f7b951a8SRobert Watson claimed = 0; \ 353f7b951a8SRobert Watson if (first) { \ 354f7b951a8SRobert Watson len = snprintf(curptr, left, "%s/", \ 355f7b951a8SRobert Watson element_name); \ 356f7b951a8SRobert Watson first = 0; \ 357f7b951a8SRobert Watson } else \ 358f7b951a8SRobert Watson len = snprintf(curptr, left, ",%s/", \ 359f7b951a8SRobert Watson element_name); \ 360f7b951a8SRobert Watson if (len >= left) { \ 361f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 362f7b951a8SRobert Watson break; \ 363f7b951a8SRobert Watson } \ 364f7b951a8SRobert Watson curptr += len; \ 365f7b951a8SRobert Watson left -= len; \ 366f7b951a8SRobert Watson \ 367f7b951a8SRobert Watson MAC_CHECK(externalize_ ## type, label, element_name, \ 368f7b951a8SRobert Watson curptr, left, &len, &claimed); \ 369f7b951a8SRobert Watson if (error) \ 370f7b951a8SRobert Watson break; \ 371f7b951a8SRobert Watson if (claimed == 1) { \ 372f7b951a8SRobert Watson if (len >= outbuflen) { \ 373f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: E2BIG */ \ 374f7b951a8SRobert Watson break; \ 375f7b951a8SRobert Watson } \ 376f7b951a8SRobert Watson curptr += len; \ 377f7b951a8SRobert Watson left -= len; \ 378f7b951a8SRobert Watson } else if (claimed == 0 && ignorenotfound) { \ 379f7b951a8SRobert Watson /* \ 380f7b951a8SRobert Watson * Revert addition of the label element \ 381f7b951a8SRobert Watson * name. \ 382f7b951a8SRobert Watson */ \ 383f7b951a8SRobert Watson curptr = curptr_start; \ 384f7b951a8SRobert Watson *curptr = '\0'; \ 385f7b951a8SRobert Watson left = left_start; \ 386f7b951a8SRobert Watson first = first_start; \ 387f7b951a8SRobert Watson } else { \ 388f7b951a8SRobert Watson error = EINVAL; /* XXXMAC: ENOLABEL */ \ 389f7b951a8SRobert Watson break; \ 390f7b951a8SRobert Watson } \ 391f7b951a8SRobert Watson } \ 392f7b951a8SRobert Watson } while (0) 393f7b951a8SRobert Watson 394f7b951a8SRobert Watson #define MAC_INTERNALIZE(type, label, instring) do { \ 395f7b951a8SRobert Watson char *element, *element_name, *element_data; \ 396f7b951a8SRobert Watson int claimed; \ 397f7b951a8SRobert Watson \ 398f7b951a8SRobert Watson error = 0; \ 399f7b951a8SRobert Watson element = instring; \ 400f7b951a8SRobert Watson while ((element_name = strsep(&element, ",")) != NULL) { \ 401f7b951a8SRobert Watson element_data = element_name; \ 402f7b951a8SRobert Watson element_name = strsep(&element_data, "/"); \ 403f7b951a8SRobert Watson if (element_data == NULL) { \ 404f7b951a8SRobert Watson error = EINVAL; \ 405f7b951a8SRobert Watson break; \ 406f7b951a8SRobert Watson } \ 407f7b951a8SRobert Watson claimed = 0; \ 408f7b951a8SRobert Watson MAC_CHECK(internalize_ ## type, label, element_name, \ 409f7b951a8SRobert Watson element_data, &claimed); \ 410f7b951a8SRobert Watson if (error) \ 411f7b951a8SRobert Watson break; \ 412f7b951a8SRobert Watson if (claimed != 1) { \ 413f7b951a8SRobert Watson /* XXXMAC: Another error here? */ \ 414f7b951a8SRobert Watson error = EINVAL; \ 415f7b951a8SRobert Watson break; \ 416f7b951a8SRobert Watson } \ 417f7b951a8SRobert Watson } \ 418f7b951a8SRobert Watson } while (0) 419f7b951a8SRobert Watson 42095fab37eSRobert Watson /* 42195fab37eSRobert Watson * MAC_PERFORM performs the designated operation by walking the policy 42295fab37eSRobert Watson * module list and invoking that operation for each policy. 42395fab37eSRobert Watson */ 42495fab37eSRobert Watson #define MAC_PERFORM(operation, args...) do { \ 42595fab37eSRobert Watson struct mac_policy_conf *mpc; \ 42695fab37eSRobert Watson \ 42795fab37eSRobert Watson MAC_POLICY_LIST_BUSY(); \ 42895fab37eSRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 42995fab37eSRobert Watson if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 43095fab37eSRobert Watson mpc->mpc_ops->mpo_ ## operation (args); \ 43195fab37eSRobert Watson } \ 43295fab37eSRobert Watson MAC_POLICY_LIST_UNBUSY(); \ 43395fab37eSRobert Watson } while (0) 43495fab37eSRobert Watson 43595fab37eSRobert Watson /* 43695fab37eSRobert Watson * Initialize the MAC subsystem, including appropriate SMP locks. 43795fab37eSRobert Watson */ 43895fab37eSRobert Watson static void 43995fab37eSRobert Watson mac_init(void) 44095fab37eSRobert Watson { 44195fab37eSRobert Watson 44295fab37eSRobert Watson LIST_INIT(&mac_policy_list); 44395fab37eSRobert Watson MAC_POLICY_LIST_LOCKINIT(); 44495fab37eSRobert Watson } 44595fab37eSRobert Watson 44695fab37eSRobert Watson /* 44795fab37eSRobert Watson * For the purposes of modules that want to know if they were loaded 44895fab37eSRobert Watson * "early", set the mac_late flag once we've processed modules either 44995fab37eSRobert Watson * linked into the kernel, or loaded before the kernel startup. 45095fab37eSRobert Watson */ 45195fab37eSRobert Watson static void 45295fab37eSRobert Watson mac_late_init(void) 45395fab37eSRobert Watson { 45495fab37eSRobert Watson 45595fab37eSRobert Watson mac_late = 1; 45695fab37eSRobert Watson } 45795fab37eSRobert Watson 45895fab37eSRobert Watson /* 45995fab37eSRobert Watson * Allow MAC policy modules to register during boot, etc. 46095fab37eSRobert Watson */ 46195fab37eSRobert Watson int 46295fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data) 46395fab37eSRobert Watson { 46495fab37eSRobert Watson struct mac_policy_conf *mpc; 46595fab37eSRobert Watson int error; 46695fab37eSRobert Watson 46795fab37eSRobert Watson error = 0; 46895fab37eSRobert Watson mpc = (struct mac_policy_conf *) data; 46995fab37eSRobert Watson 47095fab37eSRobert Watson switch (type) { 47195fab37eSRobert Watson case MOD_LOAD: 47295fab37eSRobert Watson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 47395fab37eSRobert Watson mac_late) { 47495fab37eSRobert Watson printf("mac_policy_modevent: can't load %s policy " 47595fab37eSRobert Watson "after booting\n", mpc->mpc_name); 47695fab37eSRobert Watson error = EBUSY; 47795fab37eSRobert Watson break; 47895fab37eSRobert Watson } 47995fab37eSRobert Watson error = mac_policy_register(mpc); 48095fab37eSRobert Watson break; 48195fab37eSRobert Watson case MOD_UNLOAD: 48295fab37eSRobert Watson /* Don't unregister the module if it was never registered. */ 48395fab37eSRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 48495fab37eSRobert Watson != 0) 48595fab37eSRobert Watson error = mac_policy_unregister(mpc); 48695fab37eSRobert Watson else 48795fab37eSRobert Watson error = 0; 48895fab37eSRobert Watson break; 48995fab37eSRobert Watson default: 49095fab37eSRobert Watson break; 49195fab37eSRobert Watson } 49295fab37eSRobert Watson 49395fab37eSRobert Watson return (error); 49495fab37eSRobert Watson } 49595fab37eSRobert Watson 49695fab37eSRobert Watson static int 49795fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc) 49895fab37eSRobert Watson { 49995fab37eSRobert Watson struct mac_policy_conf *tmpc; 50095fab37eSRobert Watson int slot; 50195fab37eSRobert Watson 502a96acd1aSRobert Watson MAC_POLICY_LIST_EXCLUSIVE(); 50395fab37eSRobert Watson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 50495fab37eSRobert Watson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 50595fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 50695fab37eSRobert Watson return (EEXIST); 50795fab37eSRobert Watson } 50895fab37eSRobert Watson } 50995fab37eSRobert Watson if (mpc->mpc_field_off != NULL) { 51095fab37eSRobert Watson slot = ffs(mac_policy_offsets_free); 51195fab37eSRobert Watson if (slot == 0) { 51295fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 51395fab37eSRobert Watson return (ENOMEM); 51495fab37eSRobert Watson } 51595fab37eSRobert Watson slot--; 51695fab37eSRobert Watson mac_policy_offsets_free &= ~(1 << slot); 51795fab37eSRobert Watson *mpc->mpc_field_off = slot; 51895fab37eSRobert Watson } 51995fab37eSRobert Watson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 52095fab37eSRobert Watson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 52195fab37eSRobert Watson 52295fab37eSRobert Watson /* Per-policy initialization. */ 52395fab37eSRobert Watson if (mpc->mpc_ops->mpo_init != NULL) 52495fab37eSRobert Watson (*(mpc->mpc_ops->mpo_init))(mpc); 52595fab37eSRobert Watson MAC_POLICY_LIST_UNLOCK(); 52695fab37eSRobert Watson 52795fab37eSRobert Watson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 52895fab37eSRobert Watson mpc->mpc_name); 52995fab37eSRobert Watson 53095fab37eSRobert Watson return (0); 53195fab37eSRobert Watson } 53295fab37eSRobert Watson 53395fab37eSRobert Watson static int 53495fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc) 53595fab37eSRobert Watson { 53695fab37eSRobert Watson 537ea599aa0SRobert Watson /* 538ea599aa0SRobert Watson * If we fail the load, we may get a request to unload. Check 539ea599aa0SRobert Watson * to see if we did the run-time registration, and if not, 540ea599aa0SRobert Watson * silently succeed. 541ea599aa0SRobert Watson */ 542a96acd1aSRobert Watson MAC_POLICY_LIST_EXCLUSIVE(); 543ea599aa0SRobert Watson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 544ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 545ea599aa0SRobert Watson return (0); 546ea599aa0SRobert Watson } 54795fab37eSRobert Watson #if 0 54895fab37eSRobert Watson /* 54995fab37eSRobert Watson * Don't allow unloading modules with private data. 55095fab37eSRobert Watson */ 551ea599aa0SRobert Watson if (mpc->mpc_field_off != NULL) { 552ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 55395fab37eSRobert Watson return (EBUSY); 554ea599aa0SRobert Watson } 55595fab37eSRobert Watson #endif 556ea599aa0SRobert Watson /* 557ea599aa0SRobert Watson * Only allow the unload to proceed if the module is unloadable 558ea599aa0SRobert Watson * by its own definition. 559ea599aa0SRobert Watson */ 560ea599aa0SRobert Watson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 561ea599aa0SRobert Watson MAC_POLICY_LIST_UNLOCK(); 56295fab37eSRobert Watson return (EBUSY); 563ea599aa0SRobert Watson } 56495fab37eSRobert Watson if (mpc->mpc_ops->mpo_destroy != NULL) 56595fab37eSRobert Watson (*(mpc->mpc_ops->mpo_destroy))(mpc); 56695fab37eSRobert Watson 56795fab37eSRobert Watson LIST_REMOVE(mpc, mpc_list); 5689aeffb2bSRobert Watson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 56995fab37eSRobert Watson 570a96acd1aSRobert Watson MAC_POLICY_LIST_UNLOCK(); 571a96acd1aSRobert Watson 57295fab37eSRobert Watson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 57395fab37eSRobert Watson mpc->mpc_name); 57495fab37eSRobert Watson 57595fab37eSRobert Watson return (0); 57695fab37eSRobert Watson } 57795fab37eSRobert Watson 57895fab37eSRobert Watson /* 57995fab37eSRobert Watson * Define an error value precedence, and given two arguments, selects the 58095fab37eSRobert Watson * value with the higher precedence. 58195fab37eSRobert Watson */ 58295fab37eSRobert Watson static int 58395fab37eSRobert Watson error_select(int error1, int error2) 58495fab37eSRobert Watson { 58595fab37eSRobert Watson 58695fab37eSRobert Watson /* Certain decision-making errors take top priority. */ 58795fab37eSRobert Watson if (error1 == EDEADLK || error2 == EDEADLK) 58895fab37eSRobert Watson return (EDEADLK); 58995fab37eSRobert Watson 59095fab37eSRobert Watson /* Invalid arguments should be reported where possible. */ 59195fab37eSRobert Watson if (error1 == EINVAL || error2 == EINVAL) 59295fab37eSRobert Watson return (EINVAL); 59395fab37eSRobert Watson 59495fab37eSRobert Watson /* Precedence goes to "visibility", with both process and file. */ 59595fab37eSRobert Watson if (error1 == ESRCH || error2 == ESRCH) 59695fab37eSRobert Watson return (ESRCH); 59795fab37eSRobert Watson 59895fab37eSRobert Watson if (error1 == ENOENT || error2 == ENOENT) 59995fab37eSRobert Watson return (ENOENT); 60095fab37eSRobert Watson 60195fab37eSRobert Watson /* Precedence goes to DAC/MAC protections. */ 60295fab37eSRobert Watson if (error1 == EACCES || error2 == EACCES) 60395fab37eSRobert Watson return (EACCES); 60495fab37eSRobert Watson 60595fab37eSRobert Watson /* Precedence goes to privilege. */ 60695fab37eSRobert Watson if (error1 == EPERM || error2 == EPERM) 60795fab37eSRobert Watson return (EPERM); 60895fab37eSRobert Watson 60995fab37eSRobert Watson /* Precedence goes to error over success; otherwise, arbitrary. */ 61095fab37eSRobert Watson if (error1 != 0) 61195fab37eSRobert Watson return (error1); 61295fab37eSRobert Watson return (error2); 61395fab37eSRobert Watson } 61495fab37eSRobert Watson 61508bcdc58SRobert Watson static void 61608bcdc58SRobert Watson mac_init_label(struct label *label) 61708bcdc58SRobert Watson { 61808bcdc58SRobert Watson 61908bcdc58SRobert Watson bzero(label, sizeof(*label)); 62008bcdc58SRobert Watson label->l_flags = MAC_FLAG_INITIALIZED; 62108bcdc58SRobert Watson } 62208bcdc58SRobert Watson 62308bcdc58SRobert Watson static void 62408bcdc58SRobert Watson mac_destroy_label(struct label *label) 62508bcdc58SRobert Watson { 62608bcdc58SRobert Watson 62708bcdc58SRobert Watson KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 62808bcdc58SRobert Watson ("destroying uninitialized label")); 62908bcdc58SRobert Watson 63008bcdc58SRobert Watson bzero(label, sizeof(*label)); 63108bcdc58SRobert Watson /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 63208bcdc58SRobert Watson } 63308bcdc58SRobert Watson 63408bcdc58SRobert Watson void 63587807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d) 63608bcdc58SRobert Watson { 63708bcdc58SRobert Watson 63887807196SRobert Watson mac_init_label(&bpf_d->bd_label); 63987807196SRobert Watson MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label); 64008bcdc58SRobert Watson #ifdef MAC_DEBUG 64187807196SRobert Watson atomic_add_int(&nmacbpfdescs, 1); 64208bcdc58SRobert Watson #endif 64308bcdc58SRobert Watson } 64408bcdc58SRobert Watson 645f7b951a8SRobert Watson static void 646f7b951a8SRobert Watson mac_init_cred_label(struct label *label) 64708bcdc58SRobert Watson { 64808bcdc58SRobert Watson 649f7b951a8SRobert Watson mac_init_label(label); 650f7b951a8SRobert Watson MAC_PERFORM(init_cred_label, label); 65108bcdc58SRobert Watson #ifdef MAC_DEBUG 65208bcdc58SRobert Watson atomic_add_int(&nmaccreds, 1); 65308bcdc58SRobert Watson #endif 65408bcdc58SRobert Watson } 65508bcdc58SRobert Watson 65608bcdc58SRobert Watson void 657f7b951a8SRobert Watson mac_init_cred(struct ucred *cred) 658f7b951a8SRobert Watson { 659f7b951a8SRobert Watson 660f7b951a8SRobert Watson mac_init_cred_label(&cred->cr_label); 661f7b951a8SRobert Watson } 662f7b951a8SRobert Watson 663f7b951a8SRobert Watson void 66487807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de) 66508bcdc58SRobert Watson { 66608bcdc58SRobert Watson 66787807196SRobert Watson mac_init_label(&de->de_label); 66887807196SRobert Watson MAC_PERFORM(init_devfsdirent_label, &de->de_label); 66908bcdc58SRobert Watson #ifdef MAC_DEBUG 67087807196SRobert Watson atomic_add_int(&nmacdevfsdirents, 1); 67108bcdc58SRobert Watson #endif 67208bcdc58SRobert Watson } 67308bcdc58SRobert Watson 674f7b951a8SRobert Watson static void 675f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label) 676f7b951a8SRobert Watson { 677f7b951a8SRobert Watson 678f7b951a8SRobert Watson mac_init_label(label); 679f7b951a8SRobert Watson MAC_PERFORM(init_ifnet_label, label); 680f7b951a8SRobert Watson #ifdef MAC_DEBUG 681f7b951a8SRobert Watson atomic_add_int(&nmacifnets, 1); 682f7b951a8SRobert Watson #endif 683f7b951a8SRobert Watson } 684f7b951a8SRobert Watson 68508bcdc58SRobert Watson void 68608bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp) 68708bcdc58SRobert Watson { 68808bcdc58SRobert Watson 689f7b951a8SRobert Watson mac_init_ifnet_label(&ifp->if_label); 69008bcdc58SRobert Watson } 69108bcdc58SRobert Watson 69208bcdc58SRobert Watson void 69308bcdc58SRobert Watson mac_init_ipq(struct ipq *ipq) 69408bcdc58SRobert Watson { 69508bcdc58SRobert Watson 69608bcdc58SRobert Watson mac_init_label(&ipq->ipq_label); 69708bcdc58SRobert Watson MAC_PERFORM(init_ipq_label, &ipq->ipq_label); 69808bcdc58SRobert Watson #ifdef MAC_DEBUG 69908bcdc58SRobert Watson atomic_add_int(&nmacipqs, 1); 70008bcdc58SRobert Watson #endif 70108bcdc58SRobert Watson } 70208bcdc58SRobert Watson 70387807196SRobert Watson int 70487807196SRobert Watson mac_init_mbuf(struct mbuf *m, int flag) 70508bcdc58SRobert Watson { 70656c15412SRobert Watson int error; 70756c15412SRobert Watson 70887807196SRobert Watson KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 70908bcdc58SRobert Watson 71087807196SRobert Watson mac_init_label(&m->m_pkthdr.label); 71187807196SRobert Watson 71256c15412SRobert Watson MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag); 71356c15412SRobert Watson if (error) { 71456c15412SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 71556c15412SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 71656c15412SRobert Watson } 71756c15412SRobert Watson 71808bcdc58SRobert Watson #ifdef MAC_DEBUG 71956c15412SRobert Watson if (error == 0) 72087807196SRobert Watson atomic_add_int(&nmacmbufs, 1); 72108bcdc58SRobert Watson #endif 72256c15412SRobert Watson return (error); 72308bcdc58SRobert Watson } 72408bcdc58SRobert Watson 72508bcdc58SRobert Watson void 72687807196SRobert Watson mac_init_mount(struct mount *mp) 72708bcdc58SRobert Watson { 72808bcdc58SRobert Watson 72987807196SRobert Watson mac_init_label(&mp->mnt_mntlabel); 73087807196SRobert Watson mac_init_label(&mp->mnt_fslabel); 73187807196SRobert Watson MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel); 73287807196SRobert Watson MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel); 73308bcdc58SRobert Watson #ifdef MAC_DEBUG 73487807196SRobert Watson atomic_add_int(&nmacmounts, 1); 73508bcdc58SRobert Watson #endif 73608bcdc58SRobert Watson } 73708bcdc58SRobert Watson 738f7b951a8SRobert Watson static void 739f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 740f7b951a8SRobert Watson { 741f7b951a8SRobert Watson 742f7b951a8SRobert Watson mac_init_label(label); 743f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 744f7b951a8SRobert Watson #ifdef MAC_DEBUG 745f7b951a8SRobert Watson atomic_add_int(&nmacpipes, 1); 746f7b951a8SRobert Watson #endif 747f7b951a8SRobert Watson } 748f7b951a8SRobert Watson 74908bcdc58SRobert Watson void 75008bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 75108bcdc58SRobert Watson { 75208bcdc58SRobert Watson struct label *label; 75308bcdc58SRobert Watson 75408bcdc58SRobert Watson label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 75508bcdc58SRobert Watson pipe->pipe_label = label; 75608bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 757f7b951a8SRobert Watson mac_init_pipe_label(label); 75808bcdc58SRobert Watson } 75908bcdc58SRobert Watson 76083985c26SRobert Watson static int 76183985c26SRobert Watson mac_init_socket_label(struct label *label, int flag) 76208bcdc58SRobert Watson { 76383985c26SRobert Watson int error; 76408bcdc58SRobert Watson 76583985c26SRobert Watson mac_init_label(label); 76683985c26SRobert Watson 76783985c26SRobert Watson MAC_CHECK(init_socket_label, label, flag); 76883985c26SRobert Watson if (error) { 76983985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 77083985c26SRobert Watson mac_destroy_label(label); 77183985c26SRobert Watson } 77283985c26SRobert Watson 77308bcdc58SRobert Watson #ifdef MAC_DEBUG 77483985c26SRobert Watson if (error == 0) 77587807196SRobert Watson atomic_add_int(&nmacsockets, 1); 77687807196SRobert Watson #endif 77783985c26SRobert Watson 77883985c26SRobert Watson return (error); 77983985c26SRobert Watson } 78083985c26SRobert Watson 78183985c26SRobert Watson static int 78283985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag) 78383985c26SRobert Watson { 78483985c26SRobert Watson int error; 78583985c26SRobert Watson 78683985c26SRobert Watson mac_init_label(label); 78783985c26SRobert Watson 78883985c26SRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 78983985c26SRobert Watson if (error) { 79083985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 79183985c26SRobert Watson mac_destroy_label(label); 79283985c26SRobert Watson } 79383985c26SRobert Watson 79483985c26SRobert Watson return (error); 79583985c26SRobert Watson } 79683985c26SRobert Watson 79783985c26SRobert Watson int 79883985c26SRobert Watson mac_init_socket(struct socket *socket, int flag) 79983985c26SRobert Watson { 80083985c26SRobert Watson int error; 80183985c26SRobert Watson 80283985c26SRobert Watson error = mac_init_socket_label(&socket->so_label, flag); 80383985c26SRobert Watson if (error) 80483985c26SRobert Watson return (error); 80583985c26SRobert Watson 80683985c26SRobert Watson error = mac_init_socket_peer_label(&socket->so_peerlabel, flag); 80783985c26SRobert Watson if (error) 80883985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 80983985c26SRobert Watson 81083985c26SRobert Watson return (error); 81187807196SRobert Watson } 81287807196SRobert Watson 813763bbd2fSRobert Watson void 814f7b951a8SRobert Watson mac_init_vnode_label(struct label *label) 81587807196SRobert Watson { 81687807196SRobert Watson 81787807196SRobert Watson mac_init_label(label); 818f7b951a8SRobert Watson MAC_PERFORM(init_vnode_label, label); 81987807196SRobert Watson #ifdef MAC_DEBUG 820f7b951a8SRobert Watson atomic_add_int(&nmacvnodes, 1); 82108bcdc58SRobert Watson #endif 82208bcdc58SRobert Watson } 82308bcdc58SRobert Watson 82408bcdc58SRobert Watson void 82587807196SRobert Watson mac_init_vnode(struct vnode *vp) 82608bcdc58SRobert Watson { 82708bcdc58SRobert Watson 828f7b951a8SRobert Watson mac_init_vnode_label(&vp->v_label); 82908bcdc58SRobert Watson } 83008bcdc58SRobert Watson 83108bcdc58SRobert Watson void 83208bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d) 83308bcdc58SRobert Watson { 83408bcdc58SRobert Watson 83508bcdc58SRobert Watson MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label); 83608bcdc58SRobert Watson mac_destroy_label(&bpf_d->bd_label); 83708bcdc58SRobert Watson #ifdef MAC_DEBUG 83808bcdc58SRobert Watson atomic_subtract_int(&nmacbpfdescs, 1); 83908bcdc58SRobert Watson #endif 84008bcdc58SRobert Watson } 84108bcdc58SRobert Watson 842f7b951a8SRobert Watson static void 843f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label) 84408bcdc58SRobert Watson { 84508bcdc58SRobert Watson 846f7b951a8SRobert Watson MAC_PERFORM(destroy_cred_label, label); 847f7b951a8SRobert Watson mac_destroy_label(label); 84808bcdc58SRobert Watson #ifdef MAC_DEBUG 84987807196SRobert Watson atomic_subtract_int(&nmaccreds, 1); 85087807196SRobert Watson #endif 85187807196SRobert Watson } 85287807196SRobert Watson 85387807196SRobert Watson void 854f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred) 855f7b951a8SRobert Watson { 856f7b951a8SRobert Watson 857f7b951a8SRobert Watson mac_destroy_cred_label(&cred->cr_label); 858f7b951a8SRobert Watson } 859f7b951a8SRobert Watson 860f7b951a8SRobert Watson void 86187807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de) 86287807196SRobert Watson { 86387807196SRobert Watson 86487807196SRobert Watson MAC_PERFORM(destroy_devfsdirent_label, &de->de_label); 86587807196SRobert Watson mac_destroy_label(&de->de_label); 86687807196SRobert Watson #ifdef MAC_DEBUG 86787807196SRobert Watson atomic_subtract_int(&nmacdevfsdirents, 1); 86887807196SRobert Watson #endif 86987807196SRobert Watson } 87087807196SRobert Watson 871f7b951a8SRobert Watson static void 872f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label) 873f7b951a8SRobert Watson { 874f7b951a8SRobert Watson 875f7b951a8SRobert Watson MAC_PERFORM(destroy_ifnet_label, label); 876f7b951a8SRobert Watson mac_destroy_label(label); 877f7b951a8SRobert Watson #ifdef MAC_DEBUG 878f7b951a8SRobert Watson atomic_subtract_int(&nmacifnets, 1); 879f7b951a8SRobert Watson #endif 880f7b951a8SRobert Watson } 881f7b951a8SRobert Watson 88287807196SRobert Watson void 88387807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp) 88487807196SRobert Watson { 88587807196SRobert Watson 886f7b951a8SRobert Watson mac_destroy_ifnet_label(&ifp->if_label); 88787807196SRobert Watson } 88887807196SRobert Watson 88987807196SRobert Watson void 89087807196SRobert Watson mac_destroy_ipq(struct ipq *ipq) 89187807196SRobert Watson { 89287807196SRobert Watson 89387807196SRobert Watson MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label); 89487807196SRobert Watson mac_destroy_label(&ipq->ipq_label); 89587807196SRobert Watson #ifdef MAC_DEBUG 89687807196SRobert Watson atomic_subtract_int(&nmacipqs, 1); 89787807196SRobert Watson #endif 89887807196SRobert Watson } 89987807196SRobert Watson 90087807196SRobert Watson void 90187807196SRobert Watson mac_destroy_mbuf(struct mbuf *m) 90287807196SRobert Watson { 90387807196SRobert Watson 90487807196SRobert Watson MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label); 90587807196SRobert Watson mac_destroy_label(&m->m_pkthdr.label); 90687807196SRobert Watson #ifdef MAC_DEBUG 90787807196SRobert Watson atomic_subtract_int(&nmacmbufs, 1); 90808bcdc58SRobert Watson #endif 90908bcdc58SRobert Watson } 91008bcdc58SRobert Watson 91108bcdc58SRobert Watson void 91208bcdc58SRobert Watson mac_destroy_mount(struct mount *mp) 91308bcdc58SRobert Watson { 91408bcdc58SRobert Watson 91508bcdc58SRobert Watson MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel); 91608bcdc58SRobert Watson MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel); 91708bcdc58SRobert Watson mac_destroy_label(&mp->mnt_fslabel); 91808bcdc58SRobert Watson mac_destroy_label(&mp->mnt_mntlabel); 91908bcdc58SRobert Watson #ifdef MAC_DEBUG 92008bcdc58SRobert Watson atomic_subtract_int(&nmacmounts, 1); 92108bcdc58SRobert Watson #endif 92208bcdc58SRobert Watson } 92308bcdc58SRobert Watson 924f7b951a8SRobert Watson static void 925f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 926f7b951a8SRobert Watson { 927f7b951a8SRobert Watson 928f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 929f7b951a8SRobert Watson mac_destroy_label(label); 930f7b951a8SRobert Watson #ifdef MAC_DEBUG 931f7b951a8SRobert Watson atomic_subtract_int(&nmacpipes, 1); 932f7b951a8SRobert Watson #endif 933f7b951a8SRobert Watson } 934f7b951a8SRobert Watson 93587807196SRobert Watson void 93687807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 93708bcdc58SRobert Watson { 93808bcdc58SRobert Watson 939f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 94087807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 94187807196SRobert Watson } 94287807196SRobert Watson 94383985c26SRobert Watson static void 94483985c26SRobert Watson mac_destroy_socket_label(struct label *label) 94583985c26SRobert Watson { 94683985c26SRobert Watson 94783985c26SRobert Watson MAC_PERFORM(destroy_socket_label, label); 94883985c26SRobert Watson mac_destroy_label(label); 94983985c26SRobert Watson #ifdef MAC_DEBUG 95083985c26SRobert Watson atomic_subtract_int(&nmacsockets, 1); 95183985c26SRobert Watson #endif 95283985c26SRobert Watson } 95383985c26SRobert Watson 95483985c26SRobert Watson static void 95583985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label) 95683985c26SRobert Watson { 95783985c26SRobert Watson 95883985c26SRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 95983985c26SRobert Watson mac_destroy_label(label); 96083985c26SRobert Watson } 96183985c26SRobert Watson 96287807196SRobert Watson void 96387807196SRobert Watson mac_destroy_socket(struct socket *socket) 96487807196SRobert Watson { 96587807196SRobert Watson 96683985c26SRobert Watson mac_destroy_socket_label(&socket->so_label); 96783985c26SRobert Watson mac_destroy_socket_peer_label(&socket->so_peerlabel); 96808bcdc58SRobert Watson } 96908bcdc58SRobert Watson 970763bbd2fSRobert Watson void 971f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label) 97208bcdc58SRobert Watson { 97308bcdc58SRobert Watson 974f7b951a8SRobert Watson MAC_PERFORM(destroy_vnode_label, label); 97508bcdc58SRobert Watson mac_destroy_label(label); 97608bcdc58SRobert Watson #ifdef MAC_DEBUG 977f7b951a8SRobert Watson atomic_subtract_int(&nmacvnodes, 1); 97808bcdc58SRobert Watson #endif 97908bcdc58SRobert Watson } 98008bcdc58SRobert Watson 98108bcdc58SRobert Watson void 98208bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp) 98308bcdc58SRobert Watson { 98408bcdc58SRobert Watson 985f7b951a8SRobert Watson mac_destroy_vnode_label(&vp->v_label); 986f7b951a8SRobert Watson } 987f7b951a8SRobert Watson 988f7b951a8SRobert Watson static void 989f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 990f7b951a8SRobert Watson { 991f7b951a8SRobert Watson 992f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 993f7b951a8SRobert Watson } 994f7b951a8SRobert Watson 995763bbd2fSRobert Watson void 996f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest) 997f7b951a8SRobert Watson { 998f7b951a8SRobert Watson 999f7b951a8SRobert Watson MAC_PERFORM(copy_vnode_label, src, dest); 100008bcdc58SRobert Watson } 100108bcdc58SRobert Watson 100269bbb5b1SRobert Watson static int 1003f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac) 1004f7b951a8SRobert Watson { 1005f7b951a8SRobert Watson 1006f7b951a8SRobert Watson if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 1007f7b951a8SRobert Watson return (EINVAL); 1008f7b951a8SRobert Watson 1009f7b951a8SRobert Watson return (0); 1010f7b951a8SRobert Watson } 1011f7b951a8SRobert Watson 1012f7b951a8SRobert Watson static int 1013f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements, 1014f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 101569bbb5b1SRobert Watson { 101669bbb5b1SRobert Watson int error; 101769bbb5b1SRobert Watson 1018f7b951a8SRobert Watson MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen); 101969bbb5b1SRobert Watson 102069bbb5b1SRobert Watson return (error); 102169bbb5b1SRobert Watson } 102269bbb5b1SRobert Watson 102369bbb5b1SRobert Watson static int 1024f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements, 1025f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 102669bbb5b1SRobert Watson { 102769bbb5b1SRobert Watson int error; 102869bbb5b1SRobert Watson 1029f7b951a8SRobert Watson MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen); 1030f7b951a8SRobert Watson 1031f7b951a8SRobert Watson return (error); 1032f7b951a8SRobert Watson } 1033f7b951a8SRobert Watson 1034f7b951a8SRobert Watson static int 1035f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 1036f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1037f7b951a8SRobert Watson { 1038f7b951a8SRobert Watson int error; 1039f7b951a8SRobert Watson 1040f7b951a8SRobert Watson MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen); 1041f7b951a8SRobert Watson 1042f7b951a8SRobert Watson return (error); 1043f7b951a8SRobert Watson } 1044f7b951a8SRobert Watson 1045f7b951a8SRobert Watson static int 1046f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 1047f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1048f7b951a8SRobert Watson { 1049f7b951a8SRobert Watson int error; 1050f7b951a8SRobert Watson 1051f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen); 1052f7b951a8SRobert Watson 1053f7b951a8SRobert Watson return (error); 1054f7b951a8SRobert Watson } 1055f7b951a8SRobert Watson 1056f7b951a8SRobert Watson static int 1057f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 1058f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1059f7b951a8SRobert Watson { 1060f7b951a8SRobert Watson int error; 1061f7b951a8SRobert Watson 1062f7b951a8SRobert Watson MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen); 1063f7b951a8SRobert Watson 1064f7b951a8SRobert Watson return (error); 1065f7b951a8SRobert Watson } 1066f7b951a8SRobert Watson 1067f7b951a8SRobert Watson static int 1068f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements, 1069f7b951a8SRobert Watson char *outbuf, size_t outbuflen, int flags) 1070f7b951a8SRobert Watson { 1071f7b951a8SRobert Watson int error; 1072f7b951a8SRobert Watson 1073f7b951a8SRobert Watson MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen); 1074f7b951a8SRobert Watson 1075f7b951a8SRobert Watson return (error); 1076f7b951a8SRobert Watson } 1077f7b951a8SRobert Watson 1078f7b951a8SRobert Watson static int 1079f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string) 1080f7b951a8SRobert Watson { 1081f7b951a8SRobert Watson int error; 1082f7b951a8SRobert Watson 1083f7b951a8SRobert Watson MAC_INTERNALIZE(cred_label, label, string); 1084f7b951a8SRobert Watson 1085f7b951a8SRobert Watson return (error); 1086f7b951a8SRobert Watson } 1087f7b951a8SRobert Watson 1088f7b951a8SRobert Watson static int 1089f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string) 1090f7b951a8SRobert Watson { 1091f7b951a8SRobert Watson int error; 1092f7b951a8SRobert Watson 1093f7b951a8SRobert Watson MAC_INTERNALIZE(ifnet_label, label, string); 1094f7b951a8SRobert Watson 1095f7b951a8SRobert Watson return (error); 1096f7b951a8SRobert Watson } 1097f7b951a8SRobert Watson 1098f7b951a8SRobert Watson static int 1099f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 1100f7b951a8SRobert Watson { 1101f7b951a8SRobert Watson int error; 1102f7b951a8SRobert Watson 1103f7b951a8SRobert Watson MAC_INTERNALIZE(pipe_label, label, string); 1104f7b951a8SRobert Watson 1105f7b951a8SRobert Watson return (error); 1106f7b951a8SRobert Watson } 1107f7b951a8SRobert Watson 1108f7b951a8SRobert Watson static int 1109f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string) 1110f7b951a8SRobert Watson { 1111f7b951a8SRobert Watson int error; 1112f7b951a8SRobert Watson 1113f7b951a8SRobert Watson MAC_INTERNALIZE(socket_label, label, string); 1114f7b951a8SRobert Watson 1115f7b951a8SRobert Watson return (error); 1116f7b951a8SRobert Watson } 1117f7b951a8SRobert Watson 1118f7b951a8SRobert Watson static int 1119f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string) 1120f7b951a8SRobert Watson { 1121f7b951a8SRobert Watson int error; 1122f7b951a8SRobert Watson 1123f7b951a8SRobert Watson MAC_INTERNALIZE(vnode_label, label, string); 112469bbb5b1SRobert Watson 112569bbb5b1SRobert Watson return (error); 112669bbb5b1SRobert Watson } 112769bbb5b1SRobert Watson 112869bbb5b1SRobert Watson /* 112969bbb5b1SRobert Watson * Initialize MAC label for the first kernel process, from which other 113069bbb5b1SRobert Watson * kernel processes and threads are spawned. 113169bbb5b1SRobert Watson */ 113269bbb5b1SRobert Watson void 113369bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred) 113469bbb5b1SRobert Watson { 113569bbb5b1SRobert Watson 113669bbb5b1SRobert Watson MAC_PERFORM(create_proc0, cred); 113769bbb5b1SRobert Watson } 113869bbb5b1SRobert Watson 113969bbb5b1SRobert Watson /* 114069bbb5b1SRobert Watson * Initialize MAC label for the first userland process, from which other 114169bbb5b1SRobert Watson * userland processes and threads are spawned. 114269bbb5b1SRobert Watson */ 114369bbb5b1SRobert Watson void 114469bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred) 114569bbb5b1SRobert Watson { 114669bbb5b1SRobert Watson 114769bbb5b1SRobert Watson MAC_PERFORM(create_proc1, cred); 114869bbb5b1SRobert Watson } 114969bbb5b1SRobert Watson 115069bbb5b1SRobert Watson void 115169bbb5b1SRobert Watson mac_thread_userret(struct thread *td) 115269bbb5b1SRobert Watson { 115369bbb5b1SRobert Watson 115469bbb5b1SRobert Watson MAC_PERFORM(thread_userret, td); 115569bbb5b1SRobert Watson } 115669bbb5b1SRobert Watson 115769bbb5b1SRobert Watson /* 115869bbb5b1SRobert Watson * When a new process is created, its label must be initialized. Generally, 115969bbb5b1SRobert Watson * this involves inheritence from the parent process, modulo possible 116069bbb5b1SRobert Watson * deltas. This function allows that processing to take place. 116169bbb5b1SRobert Watson */ 116269bbb5b1SRobert Watson void 116369bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 116469bbb5b1SRobert Watson { 116569bbb5b1SRobert Watson 116669bbb5b1SRobert Watson MAC_PERFORM(create_cred, parent_cred, child_cred); 116769bbb5b1SRobert Watson } 116869bbb5b1SRobert Watson 116995fab37eSRobert Watson void 117095fab37eSRobert Watson mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 117195fab37eSRobert Watson { 117295fab37eSRobert Watson 117395fab37eSRobert Watson MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 117495fab37eSRobert Watson } 117595fab37eSRobert Watson 117695fab37eSRobert Watson void 1177763bbd2fSRobert Watson mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, 1178763bbd2fSRobert Watson struct vnode *vp) 117995fab37eSRobert Watson { 118095fab37eSRobert Watson 1181763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, 1182763bbd2fSRobert Watson &de->de_label, vp, &vp->v_label); 118395fab37eSRobert Watson } 118495fab37eSRobert Watson 1185763bbd2fSRobert Watson int 1186763bbd2fSRobert Watson mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) 118795fab37eSRobert Watson { 118895fab37eSRobert Watson int error; 118995fab37eSRobert Watson 1190763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); 1191763bbd2fSRobert Watson 1192763bbd2fSRobert Watson MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, 1193763bbd2fSRobert Watson &vp->v_label); 119495fab37eSRobert Watson 119595fab37eSRobert Watson return (error); 119695fab37eSRobert Watson } 119795fab37eSRobert Watson 119895fab37eSRobert Watson void 1199763bbd2fSRobert Watson mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) 120095fab37eSRobert Watson { 120195fab37eSRobert Watson 1202763bbd2fSRobert Watson MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, 1203763bbd2fSRobert Watson &vp->v_label); 120495fab37eSRobert Watson } 120595fab37eSRobert Watson 120695fab37eSRobert Watson int 1207763bbd2fSRobert Watson mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, 1208763bbd2fSRobert Watson struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 120995fab37eSRobert Watson { 1210763bbd2fSRobert Watson int error; 121195fab37eSRobert Watson 1212763bbd2fSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); 1213763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); 121495fab37eSRobert Watson 1215763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1216763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1217763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1218763bbd2fSRobert Watson if (ea_warn_once == 0) { 1219763bbd2fSRobert Watson printf("Warning: transactions not supported " 1220763bbd2fSRobert Watson "in EA write.\n"); 1221763bbd2fSRobert Watson ea_warn_once = 1; 1222763bbd2fSRobert Watson } 1223763bbd2fSRobert Watson } else if (error) 122495fab37eSRobert Watson return (error); 122595fab37eSRobert Watson 1226763bbd2fSRobert Watson MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, 1227763bbd2fSRobert Watson dvp, &dvp->v_label, vp, &vp->v_label, cnp); 122895fab37eSRobert Watson 1229763bbd2fSRobert Watson if (error) { 1230763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 123195fab37eSRobert Watson return (error); 123295fab37eSRobert Watson } 123395fab37eSRobert Watson 1234763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 123595fab37eSRobert Watson 1236763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1237763bbd2fSRobert Watson error = 0; /* XXX */ 123895fab37eSRobert Watson 123995fab37eSRobert Watson return (error); 124095fab37eSRobert Watson } 124195fab37eSRobert Watson 124295fab37eSRobert Watson static int 1243763bbd2fSRobert Watson mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, 1244763bbd2fSRobert Watson struct label *intlabel) 124595fab37eSRobert Watson { 124695fab37eSRobert Watson int error; 124795fab37eSRobert Watson 1248763bbd2fSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); 124995fab37eSRobert Watson 1250763bbd2fSRobert Watson error = VOP_OPENEXTATTR(vp, cred, curthread); 1251763bbd2fSRobert Watson if (error == EOPNOTSUPP) { 1252763bbd2fSRobert Watson /* XXX: Optionally abort if transactions not supported. */ 1253763bbd2fSRobert Watson if (ea_warn_once == 0) { 1254763bbd2fSRobert Watson printf("Warning: transactions not supported " 1255763bbd2fSRobert Watson "in EA write.\n"); 1256763bbd2fSRobert Watson ea_warn_once = 1; 125795fab37eSRobert Watson } 1258763bbd2fSRobert Watson } else if (error) 125995fab37eSRobert Watson return (error); 126095fab37eSRobert Watson 1261763bbd2fSRobert Watson MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); 126295fab37eSRobert Watson 1263763bbd2fSRobert Watson if (error) { 1264763bbd2fSRobert Watson VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); 126595fab37eSRobert Watson return (error); 126695fab37eSRobert Watson } 126795fab37eSRobert Watson 1268763bbd2fSRobert Watson error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); 1269763bbd2fSRobert Watson 1270763bbd2fSRobert Watson if (error == EOPNOTSUPP) 1271763bbd2fSRobert Watson error = 0; /* XXX */ 1272763bbd2fSRobert Watson 1273763bbd2fSRobert Watson return (error); 127495fab37eSRobert Watson } 127595fab37eSRobert Watson 1276670cb89bSRobert Watson int 1277670cb89bSRobert Watson mac_execve_enter(struct image_params *imgp, struct mac *mac_p, 1278670cb89bSRobert Watson struct label *execlabelstorage) 1279670cb89bSRobert Watson { 1280670cb89bSRobert Watson struct mac mac; 1281670cb89bSRobert Watson char *buffer; 1282670cb89bSRobert Watson int error; 1283670cb89bSRobert Watson 1284670cb89bSRobert Watson if (mac_p == NULL) 1285670cb89bSRobert Watson return (0); 1286670cb89bSRobert Watson 1287670cb89bSRobert Watson error = copyin(mac_p, &mac, sizeof(mac)); 1288670cb89bSRobert Watson if (error) 1289670cb89bSRobert Watson return (error); 1290670cb89bSRobert Watson 1291670cb89bSRobert Watson error = mac_check_structmac_consistent(&mac); 1292670cb89bSRobert Watson if (error) 1293670cb89bSRobert Watson return (error); 1294670cb89bSRobert Watson 1295670cb89bSRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1296670cb89bSRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1297670cb89bSRobert Watson if (error) { 1298670cb89bSRobert Watson free(buffer, M_MACTEMP); 1299670cb89bSRobert Watson return (error); 1300670cb89bSRobert Watson } 1301670cb89bSRobert Watson 1302670cb89bSRobert Watson mac_init_cred_label(execlabelstorage); 1303670cb89bSRobert Watson error = mac_internalize_cred_label(execlabelstorage, buffer); 1304670cb89bSRobert Watson free(buffer, M_MACTEMP); 1305670cb89bSRobert Watson if (error) { 1306670cb89bSRobert Watson mac_destroy_cred_label(execlabelstorage); 1307670cb89bSRobert Watson return (error); 1308670cb89bSRobert Watson } 1309670cb89bSRobert Watson imgp->execlabel = execlabelstorage; 1310670cb89bSRobert Watson return (0); 1311670cb89bSRobert Watson } 1312670cb89bSRobert Watson 131395fab37eSRobert Watson void 1314670cb89bSRobert Watson mac_execve_exit(struct image_params *imgp) 1315670cb89bSRobert Watson { 1316670cb89bSRobert Watson if (imgp->execlabel != NULL) 1317670cb89bSRobert Watson mac_destroy_cred_label(imgp->execlabel); 1318670cb89bSRobert Watson } 1319670cb89bSRobert Watson 1320670cb89bSRobert Watson void 1321670cb89bSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, 1322670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 132395fab37eSRobert Watson { 132495fab37eSRobert Watson 132595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 132695fab37eSRobert Watson 13274443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 13284443e9ffSRobert Watson return; 13294443e9ffSRobert Watson 1330670cb89bSRobert Watson MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label, 13319fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 133295fab37eSRobert Watson } 133395fab37eSRobert Watson 133495fab37eSRobert Watson int 1335670cb89bSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp, 1336670cb89bSRobert Watson struct label *interpvnodelabel, struct image_params *imgp) 133795fab37eSRobert Watson { 1338763bbd2fSRobert Watson int result; 133995fab37eSRobert Watson 13404443e9ffSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition"); 13414443e9ffSRobert Watson 13424443e9ffSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 13434443e9ffSRobert Watson return (0); 13444443e9ffSRobert Watson 134595fab37eSRobert Watson result = 0; 1346670cb89bSRobert Watson MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label, 13479fa3506eSRobert Watson interpvnodelabel, imgp, imgp->execlabel); 134895fab37eSRobert Watson 134995fab37eSRobert Watson return (result); 135095fab37eSRobert Watson } 135195fab37eSRobert Watson 135295fab37eSRobert Watson int 1353b914de36SRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode) 135495fab37eSRobert Watson { 135595fab37eSRobert Watson int error; 135695fab37eSRobert Watson 135795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 135895fab37eSRobert Watson 135995fab37eSRobert Watson if (!mac_enforce_fs) 136095fab37eSRobert Watson return (0); 136195fab37eSRobert Watson 1362b914de36SRobert Watson MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode); 136395fab37eSRobert Watson return (error); 136495fab37eSRobert Watson } 136595fab37eSRobert Watson 136695fab37eSRobert Watson int 136795fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 136895fab37eSRobert Watson { 136995fab37eSRobert Watson int error; 137095fab37eSRobert Watson 137195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 137295fab37eSRobert Watson 137395fab37eSRobert Watson if (!mac_enforce_fs) 137495fab37eSRobert Watson return (0); 137595fab37eSRobert Watson 137695fab37eSRobert Watson MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 137795fab37eSRobert Watson return (error); 137895fab37eSRobert Watson } 137995fab37eSRobert Watson 138095fab37eSRobert Watson int 138195fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 138295fab37eSRobert Watson { 138395fab37eSRobert Watson int error; 138495fab37eSRobert Watson 138595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 138695fab37eSRobert Watson 138795fab37eSRobert Watson if (!mac_enforce_fs) 138895fab37eSRobert Watson return (0); 138995fab37eSRobert Watson 139095fab37eSRobert Watson MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 139195fab37eSRobert Watson return (error); 139295fab37eSRobert Watson } 139395fab37eSRobert Watson 139495fab37eSRobert Watson int 139595fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 139695fab37eSRobert Watson struct componentname *cnp, struct vattr *vap) 139795fab37eSRobert Watson { 139895fab37eSRobert Watson int error; 139995fab37eSRobert Watson 140095fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 140195fab37eSRobert Watson 140295fab37eSRobert Watson if (!mac_enforce_fs) 140395fab37eSRobert Watson return (0); 140495fab37eSRobert Watson 140595fab37eSRobert Watson MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 140695fab37eSRobert Watson return (error); 140795fab37eSRobert Watson } 140895fab37eSRobert Watson 140995fab37eSRobert Watson int 141095fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 141195fab37eSRobert Watson struct componentname *cnp) 141295fab37eSRobert Watson { 141395fab37eSRobert Watson int error; 141495fab37eSRobert Watson 141595fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 141695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 141795fab37eSRobert Watson 141895fab37eSRobert Watson if (!mac_enforce_fs) 141995fab37eSRobert Watson return (0); 142095fab37eSRobert Watson 142195fab37eSRobert Watson MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 142295fab37eSRobert Watson &vp->v_label, cnp); 142395fab37eSRobert Watson return (error); 142495fab37eSRobert Watson } 142595fab37eSRobert Watson 142695fab37eSRobert Watson int 142795fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 142895fab37eSRobert Watson acl_type_t type) 142995fab37eSRobert Watson { 143095fab37eSRobert Watson int error; 143195fab37eSRobert Watson 143295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 143395fab37eSRobert Watson 143495fab37eSRobert Watson if (!mac_enforce_fs) 143595fab37eSRobert Watson return (0); 143695fab37eSRobert Watson 143795fab37eSRobert Watson MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 143895fab37eSRobert Watson return (error); 143995fab37eSRobert Watson } 144095fab37eSRobert Watson 144195fab37eSRobert Watson int 1442670cb89bSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1443670cb89bSRobert Watson struct image_params *imgp) 144495fab37eSRobert Watson { 144595fab37eSRobert Watson int error; 144695fab37eSRobert Watson 1447851704bbSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1448851704bbSRobert Watson 144995fab37eSRobert Watson if (!mac_enforce_process && !mac_enforce_fs) 145095fab37eSRobert Watson return (0); 145195fab37eSRobert Watson 14529fa3506eSRobert Watson MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp, 14539fa3506eSRobert Watson imgp->execlabel); 145495fab37eSRobert Watson 145595fab37eSRobert Watson return (error); 145695fab37eSRobert Watson } 145795fab37eSRobert Watson 145895fab37eSRobert Watson int 145995fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 146095fab37eSRobert Watson { 146195fab37eSRobert Watson int error; 146295fab37eSRobert Watson 146395fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 146495fab37eSRobert Watson 146595fab37eSRobert Watson if (!mac_enforce_fs) 146695fab37eSRobert Watson return (0); 146795fab37eSRobert Watson 146895fab37eSRobert Watson MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 146995fab37eSRobert Watson return (error); 147095fab37eSRobert Watson } 147195fab37eSRobert Watson 147295fab37eSRobert Watson int 147395fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 147495fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 147595fab37eSRobert Watson { 147695fab37eSRobert Watson int error; 147795fab37eSRobert Watson 147895fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 147995fab37eSRobert Watson 148095fab37eSRobert Watson if (!mac_enforce_fs) 148195fab37eSRobert Watson return (0); 148295fab37eSRobert Watson 148395fab37eSRobert Watson MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 148495fab37eSRobert Watson attrnamespace, name, uio); 148595fab37eSRobert Watson return (error); 148695fab37eSRobert Watson } 148795fab37eSRobert Watson 148895fab37eSRobert Watson int 14890a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, 14900a694196SRobert Watson struct vnode *vp, struct componentname *cnp) 14910a694196SRobert Watson { 14920a694196SRobert Watson int error; 14930a694196SRobert Watson 14940a694196SRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link"); 14950a694196SRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link"); 14960a694196SRobert Watson 14970a694196SRobert Watson if (!mac_enforce_fs) 14980a694196SRobert Watson return (0); 14990a694196SRobert Watson 15000a694196SRobert Watson MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, 15010a694196SRobert Watson &vp->v_label, cnp); 15020a694196SRobert Watson return (error); 15030a694196SRobert Watson } 15040a694196SRobert Watson 15050a694196SRobert Watson int 150695fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 150795fab37eSRobert Watson struct componentname *cnp) 150895fab37eSRobert Watson { 150995fab37eSRobert Watson int error; 151095fab37eSRobert Watson 151195fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 151295fab37eSRobert Watson 151395fab37eSRobert Watson if (!mac_enforce_fs) 151495fab37eSRobert Watson return (0); 151595fab37eSRobert Watson 151695fab37eSRobert Watson MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 151795fab37eSRobert Watson return (error); 151895fab37eSRobert Watson } 151995fab37eSRobert Watson 1520e183f80eSRobert Watson int 1521e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) 152295fab37eSRobert Watson { 1523e183f80eSRobert Watson int error; 152495fab37eSRobert Watson 1525e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap"); 1526ca7850c3SRobert Watson 1527e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1528e183f80eSRobert Watson return (0); 1529e183f80eSRobert Watson 1530e183f80eSRobert Watson MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); 1531e183f80eSRobert Watson return (error); 1532e183f80eSRobert Watson } 1533e183f80eSRobert Watson 1534e183f80eSRobert Watson void 1535e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) 1536e183f80eSRobert Watson { 1537e183f80eSRobert Watson int result = *prot; 1538e183f80eSRobert Watson 1539e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade"); 1540e183f80eSRobert Watson 1541e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1542e183f80eSRobert Watson return; 1543e183f80eSRobert Watson 1544e183f80eSRobert Watson MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label, 1545e183f80eSRobert Watson &result); 1546e183f80eSRobert Watson 1547e183f80eSRobert Watson *prot = result; 1548e183f80eSRobert Watson } 1549e183f80eSRobert Watson 1550e183f80eSRobert Watson int 1551e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) 1552e183f80eSRobert Watson { 1553e183f80eSRobert Watson int error; 1554e183f80eSRobert Watson 1555e183f80eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect"); 1556e183f80eSRobert Watson 1557e183f80eSRobert Watson if (!mac_enforce_fs || !mac_enforce_vm) 1558e183f80eSRobert Watson return (0); 1559e183f80eSRobert Watson 1560e183f80eSRobert Watson MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); 1561e183f80eSRobert Watson return (error); 156295fab37eSRobert Watson } 156395fab37eSRobert Watson 156495fab37eSRobert Watson int 1565b914de36SRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode) 156695fab37eSRobert Watson { 156795fab37eSRobert Watson int error; 156895fab37eSRobert Watson 156995fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 157095fab37eSRobert Watson 157195fab37eSRobert Watson if (!mac_enforce_fs) 157295fab37eSRobert Watson return (0); 157395fab37eSRobert Watson 157495fab37eSRobert Watson MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 157595fab37eSRobert Watson return (error); 157695fab37eSRobert Watson } 157795fab37eSRobert Watson 157895fab37eSRobert Watson int 1579177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 1580177142e4SRobert Watson struct vnode *vp) 15817f724f8bSRobert Watson { 15827f724f8bSRobert Watson int error; 15837f724f8bSRobert Watson 15847f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 15857f724f8bSRobert Watson 15867f724f8bSRobert Watson if (!mac_enforce_fs) 15877f724f8bSRobert Watson return (0); 15887f724f8bSRobert Watson 1589177142e4SRobert Watson MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, 1590177142e4SRobert Watson &vp->v_label); 15917f724f8bSRobert Watson 15927f724f8bSRobert Watson return (error); 15937f724f8bSRobert Watson } 15947f724f8bSRobert Watson 15957f724f8bSRobert Watson int 1596177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 1597177142e4SRobert Watson struct vnode *vp) 15987f724f8bSRobert Watson { 15997f724f8bSRobert Watson int error; 16007f724f8bSRobert Watson 16017f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 16027f724f8bSRobert Watson 16037f724f8bSRobert Watson if (!mac_enforce_fs) 16047f724f8bSRobert Watson return (0); 16057f724f8bSRobert Watson 1606177142e4SRobert Watson MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, 1607177142e4SRobert Watson &vp->v_label); 16087f724f8bSRobert Watson 16097f724f8bSRobert Watson return (error); 16107f724f8bSRobert Watson } 16117f724f8bSRobert Watson 16127f724f8bSRobert Watson int 161395fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 161495fab37eSRobert Watson { 161595fab37eSRobert Watson int error; 161695fab37eSRobert Watson 161795fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 161895fab37eSRobert Watson 161995fab37eSRobert Watson if (!mac_enforce_fs) 162095fab37eSRobert Watson return (0); 162195fab37eSRobert Watson 162295fab37eSRobert Watson MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 162395fab37eSRobert Watson return (error); 162495fab37eSRobert Watson } 162595fab37eSRobert Watson 162695fab37eSRobert Watson int 162795fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 162895fab37eSRobert Watson { 162995fab37eSRobert Watson int error; 163095fab37eSRobert Watson 163195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 163295fab37eSRobert Watson 163395fab37eSRobert Watson if (!mac_enforce_fs) 163495fab37eSRobert Watson return (0); 163595fab37eSRobert Watson 163695fab37eSRobert Watson MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 163795fab37eSRobert Watson return (error); 163895fab37eSRobert Watson } 163995fab37eSRobert Watson 164095fab37eSRobert Watson static int 164195fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 164295fab37eSRobert Watson struct label *newlabel) 164395fab37eSRobert Watson { 164495fab37eSRobert Watson int error; 164595fab37eSRobert Watson 164695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 164795fab37eSRobert Watson 164895fab37eSRobert Watson MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 164995fab37eSRobert Watson 165095fab37eSRobert Watson return (error); 165195fab37eSRobert Watson } 165295fab37eSRobert Watson 165395fab37eSRobert Watson int 165495fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 165595fab37eSRobert Watson struct vnode *vp, struct componentname *cnp) 165695fab37eSRobert Watson { 165795fab37eSRobert Watson int error; 165895fab37eSRobert Watson 165995fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 166095fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 166195fab37eSRobert Watson 166295fab37eSRobert Watson if (!mac_enforce_fs) 166395fab37eSRobert Watson return (0); 166495fab37eSRobert Watson 166595fab37eSRobert Watson MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 166695fab37eSRobert Watson &vp->v_label, cnp); 166795fab37eSRobert Watson return (error); 166895fab37eSRobert Watson } 166995fab37eSRobert Watson 167095fab37eSRobert Watson int 167195fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 167295fab37eSRobert Watson struct vnode *vp, int samedir, struct componentname *cnp) 167395fab37eSRobert Watson { 167495fab37eSRobert Watson int error; 167595fab37eSRobert Watson 167695fab37eSRobert Watson ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 167795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 167895fab37eSRobert Watson 167995fab37eSRobert Watson if (!mac_enforce_fs) 168095fab37eSRobert Watson return (0); 168195fab37eSRobert Watson 168295fab37eSRobert Watson MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 168395fab37eSRobert Watson vp != NULL ? &vp->v_label : NULL, samedir, cnp); 168495fab37eSRobert Watson return (error); 168595fab37eSRobert Watson } 168695fab37eSRobert Watson 168795fab37eSRobert Watson int 168895fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 168995fab37eSRobert Watson { 169095fab37eSRobert Watson int error; 169195fab37eSRobert Watson 169295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 169395fab37eSRobert Watson 169495fab37eSRobert Watson if (!mac_enforce_fs) 169595fab37eSRobert Watson return (0); 169695fab37eSRobert Watson 169795fab37eSRobert Watson MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 169895fab37eSRobert Watson return (error); 169995fab37eSRobert Watson } 170095fab37eSRobert Watson 170195fab37eSRobert Watson int 170295fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 170395fab37eSRobert Watson struct acl *acl) 170495fab37eSRobert Watson { 170595fab37eSRobert Watson int error; 170695fab37eSRobert Watson 170795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 170895fab37eSRobert Watson 170995fab37eSRobert Watson if (!mac_enforce_fs) 171095fab37eSRobert Watson return (0); 171195fab37eSRobert Watson 171295fab37eSRobert Watson MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 171395fab37eSRobert Watson return (error); 171495fab37eSRobert Watson } 171595fab37eSRobert Watson 171695fab37eSRobert Watson int 171795fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 171895fab37eSRobert Watson int attrnamespace, const char *name, struct uio *uio) 171995fab37eSRobert Watson { 172095fab37eSRobert Watson int error; 172195fab37eSRobert Watson 172295fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 172395fab37eSRobert Watson 172495fab37eSRobert Watson if (!mac_enforce_fs) 172595fab37eSRobert Watson return (0); 172695fab37eSRobert Watson 172795fab37eSRobert Watson MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 172895fab37eSRobert Watson attrnamespace, name, uio); 172995fab37eSRobert Watson return (error); 173095fab37eSRobert Watson } 173195fab37eSRobert Watson 173295fab37eSRobert Watson int 173395fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 173495fab37eSRobert Watson { 173595fab37eSRobert Watson int error; 173695fab37eSRobert Watson 173795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 173895fab37eSRobert Watson 173995fab37eSRobert Watson if (!mac_enforce_fs) 174095fab37eSRobert Watson return (0); 174195fab37eSRobert Watson 174295fab37eSRobert Watson MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 174395fab37eSRobert Watson return (error); 174495fab37eSRobert Watson } 174595fab37eSRobert Watson 174695fab37eSRobert Watson int 174795fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 174895fab37eSRobert Watson { 174995fab37eSRobert Watson int error; 175095fab37eSRobert Watson 175195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 175295fab37eSRobert Watson 175395fab37eSRobert Watson if (!mac_enforce_fs) 175495fab37eSRobert Watson return (0); 175595fab37eSRobert Watson 175695fab37eSRobert Watson MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 175795fab37eSRobert Watson return (error); 175895fab37eSRobert Watson } 175995fab37eSRobert Watson 176095fab37eSRobert Watson int 176195fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 176295fab37eSRobert Watson gid_t gid) 176395fab37eSRobert Watson { 176495fab37eSRobert Watson int error; 176595fab37eSRobert Watson 176695fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 176795fab37eSRobert Watson 176895fab37eSRobert Watson if (!mac_enforce_fs) 176995fab37eSRobert Watson return (0); 177095fab37eSRobert Watson 177195fab37eSRobert Watson MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 177295fab37eSRobert Watson return (error); 177395fab37eSRobert Watson } 177495fab37eSRobert Watson 177595fab37eSRobert Watson int 177695fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 177795fab37eSRobert Watson struct timespec atime, struct timespec mtime) 177895fab37eSRobert Watson { 177995fab37eSRobert Watson int error; 178095fab37eSRobert Watson 178195fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 178295fab37eSRobert Watson 178395fab37eSRobert Watson if (!mac_enforce_fs) 178495fab37eSRobert Watson return (0); 178595fab37eSRobert Watson 178695fab37eSRobert Watson MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 178795fab37eSRobert Watson mtime); 178895fab37eSRobert Watson return (error); 178995fab37eSRobert Watson } 179095fab37eSRobert Watson 179195fab37eSRobert Watson int 1792177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 1793177142e4SRobert Watson struct vnode *vp) 179495fab37eSRobert Watson { 179595fab37eSRobert Watson int error; 179695fab37eSRobert Watson 179795fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 179895fab37eSRobert Watson 179995fab37eSRobert Watson if (!mac_enforce_fs) 180095fab37eSRobert Watson return (0); 180195fab37eSRobert Watson 1802177142e4SRobert Watson MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, 1803177142e4SRobert Watson &vp->v_label); 180495fab37eSRobert Watson return (error); 180595fab37eSRobert Watson } 180695fab37eSRobert Watson 18077f724f8bSRobert Watson int 1808177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 1809177142e4SRobert Watson struct vnode *vp) 18107f724f8bSRobert Watson { 18117f724f8bSRobert Watson int error; 18127f724f8bSRobert Watson 18137f724f8bSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 18147f724f8bSRobert Watson 18157f724f8bSRobert Watson if (!mac_enforce_fs) 18167f724f8bSRobert Watson return (0); 18177f724f8bSRobert Watson 1818177142e4SRobert Watson MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, 1819177142e4SRobert Watson &vp->v_label); 18207f724f8bSRobert Watson 18217f724f8bSRobert Watson return (error); 18227f724f8bSRobert Watson } 18237f724f8bSRobert Watson 182495fab37eSRobert Watson /* 182595fab37eSRobert Watson * When relabeling a process, call out to the policies for the maximum 182695fab37eSRobert Watson * permission allowed for each object type we know about in its 182795fab37eSRobert Watson * memory space, and revoke access (in the least surprising ways we 182895fab37eSRobert Watson * know) when necessary. The process lock is not held here. 182995fab37eSRobert Watson */ 183095fab37eSRobert Watson static void 183195fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 183295fab37eSRobert Watson { 183395fab37eSRobert Watson 183495fab37eSRobert Watson /* XXX freeze all other threads */ 183595fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 183695fab37eSRobert Watson &td->td_proc->p_vmspace->vm_map); 183795fab37eSRobert Watson /* XXX allow other threads to continue */ 183895fab37eSRobert Watson } 183995fab37eSRobert Watson 184095fab37eSRobert Watson static __inline const char * 184195fab37eSRobert Watson prot2str(vm_prot_t prot) 184295fab37eSRobert Watson { 184395fab37eSRobert Watson 184495fab37eSRobert Watson switch (prot & VM_PROT_ALL) { 184595fab37eSRobert Watson case VM_PROT_READ: 184695fab37eSRobert Watson return ("r--"); 184795fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE: 184895fab37eSRobert Watson return ("rw-"); 184995fab37eSRobert Watson case VM_PROT_READ | VM_PROT_EXECUTE: 185095fab37eSRobert Watson return ("r-x"); 185195fab37eSRobert Watson case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 185295fab37eSRobert Watson return ("rwx"); 185395fab37eSRobert Watson case VM_PROT_WRITE: 185495fab37eSRobert Watson return ("-w-"); 185595fab37eSRobert Watson case VM_PROT_EXECUTE: 185695fab37eSRobert Watson return ("--x"); 185795fab37eSRobert Watson case VM_PROT_WRITE | VM_PROT_EXECUTE: 185895fab37eSRobert Watson return ("-wx"); 185995fab37eSRobert Watson default: 186095fab37eSRobert Watson return ("---"); 186195fab37eSRobert Watson } 186295fab37eSRobert Watson } 186395fab37eSRobert Watson 186495fab37eSRobert Watson static void 186595fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 186695fab37eSRobert Watson struct vm_map *map) 186795fab37eSRobert Watson { 186895fab37eSRobert Watson struct vm_map_entry *vme; 1869e183f80eSRobert Watson int result; 1870e183f80eSRobert Watson vm_prot_t revokeperms; 187195fab37eSRobert Watson vm_object_t object; 187295fab37eSRobert Watson vm_ooffset_t offset; 187395fab37eSRobert Watson struct vnode *vp; 187495fab37eSRobert Watson 1875c0f39905SRobert Watson if (!mac_mmap_revocation) 1876c0f39905SRobert Watson return; 1877c0f39905SRobert Watson 187895fab37eSRobert Watson vm_map_lock_read(map); 187995fab37eSRobert Watson for (vme = map->header.next; vme != &map->header; vme = vme->next) { 188095fab37eSRobert Watson if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 188195fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(td, cred, 188295fab37eSRobert Watson vme->object.sub_map); 188395fab37eSRobert Watson continue; 188495fab37eSRobert Watson } 188595fab37eSRobert Watson /* 188695fab37eSRobert Watson * Skip over entries that obviously are not shared. 188795fab37eSRobert Watson */ 188895fab37eSRobert Watson if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 188995fab37eSRobert Watson !vme->max_protection) 189095fab37eSRobert Watson continue; 189195fab37eSRobert Watson /* 189295fab37eSRobert Watson * Drill down to the deepest backing object. 189395fab37eSRobert Watson */ 189495fab37eSRobert Watson offset = vme->offset; 189595fab37eSRobert Watson object = vme->object.vm_object; 189695fab37eSRobert Watson if (object == NULL) 189795fab37eSRobert Watson continue; 189895fab37eSRobert Watson while (object->backing_object != NULL) { 189995fab37eSRobert Watson object = object->backing_object; 190095fab37eSRobert Watson offset += object->backing_object_offset; 190195fab37eSRobert Watson } 190295fab37eSRobert Watson /* 190395fab37eSRobert Watson * At the moment, vm_maps and objects aren't considered 190495fab37eSRobert Watson * by the MAC system, so only things with backing by a 190595fab37eSRobert Watson * normal object (read: vnodes) are checked. 190695fab37eSRobert Watson */ 190795fab37eSRobert Watson if (object->type != OBJT_VNODE) 190895fab37eSRobert Watson continue; 190995fab37eSRobert Watson vp = (struct vnode *)object->handle; 191095fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1911e183f80eSRobert Watson result = vme->max_protection; 1912e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(cred, vp, &result); 191395fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 191495fab37eSRobert Watson /* 191595fab37eSRobert Watson * Find out what maximum protection we may be allowing 191695fab37eSRobert Watson * now but a policy needs to get removed. 191795fab37eSRobert Watson */ 191895fab37eSRobert Watson revokeperms = vme->max_protection & ~result; 191995fab37eSRobert Watson if (!revokeperms) 192095fab37eSRobert Watson continue; 1921b656366bSBruce Evans printf("pid %ld: revoking %s perms from %#lx:%ld " 1922b656366bSBruce Evans "(max %s/cur %s)\n", (long)td->td_proc->p_pid, 1923b656366bSBruce Evans prot2str(revokeperms), (u_long)vme->start, 1924b656366bSBruce Evans (long)(vme->end - vme->start), 192595fab37eSRobert Watson prot2str(vme->max_protection), prot2str(vme->protection)); 192695fab37eSRobert Watson vm_map_lock_upgrade(map); 192795fab37eSRobert Watson /* 192895fab37eSRobert Watson * This is the really simple case: if a map has more 192995fab37eSRobert Watson * max_protection than is allowed, but it's not being 193095fab37eSRobert Watson * actually used (that is, the current protection is 193195fab37eSRobert Watson * still allowed), we can just wipe it out and do 193295fab37eSRobert Watson * nothing more. 193395fab37eSRobert Watson */ 193495fab37eSRobert Watson if ((vme->protection & revokeperms) == 0) { 193595fab37eSRobert Watson vme->max_protection -= revokeperms; 193695fab37eSRobert Watson } else { 193795fab37eSRobert Watson if (revokeperms & VM_PROT_WRITE) { 193895fab37eSRobert Watson /* 193995fab37eSRobert Watson * In the more complicated case, flush out all 194095fab37eSRobert Watson * pending changes to the object then turn it 194195fab37eSRobert Watson * copy-on-write. 194295fab37eSRobert Watson */ 194395fab37eSRobert Watson vm_object_reference(object); 194495fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 194595fab37eSRobert Watson vm_object_page_clean(object, 194695fab37eSRobert Watson OFF_TO_IDX(offset), 194795fab37eSRobert Watson OFF_TO_IDX(offset + vme->end - vme->start + 194895fab37eSRobert Watson PAGE_MASK), 194995fab37eSRobert Watson OBJPC_SYNC); 195095fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 195195fab37eSRobert Watson vm_object_deallocate(object); 195295fab37eSRobert Watson /* 195395fab37eSRobert Watson * Why bother if there's no read permissions 195495fab37eSRobert Watson * anymore? For the rest, we need to leave 195595fab37eSRobert Watson * the write permissions on for COW, or 195695fab37eSRobert Watson * remove them entirely if configured to. 195795fab37eSRobert Watson */ 195895fab37eSRobert Watson if (!mac_mmap_revocation_via_cow) { 195995fab37eSRobert Watson vme->max_protection &= ~VM_PROT_WRITE; 196095fab37eSRobert Watson vme->protection &= ~VM_PROT_WRITE; 196195fab37eSRobert Watson } if ((revokeperms & VM_PROT_READ) == 0) 196295fab37eSRobert Watson vme->eflags |= MAP_ENTRY_COW | 196395fab37eSRobert Watson MAP_ENTRY_NEEDS_COPY; 196495fab37eSRobert Watson } 196595fab37eSRobert Watson if (revokeperms & VM_PROT_EXECUTE) { 196695fab37eSRobert Watson vme->max_protection &= ~VM_PROT_EXECUTE; 196795fab37eSRobert Watson vme->protection &= ~VM_PROT_EXECUTE; 196895fab37eSRobert Watson } 196995fab37eSRobert Watson if (revokeperms & VM_PROT_READ) { 197095fab37eSRobert Watson vme->max_protection = 0; 197195fab37eSRobert Watson vme->protection = 0; 197295fab37eSRobert Watson } 197395fab37eSRobert Watson pmap_protect(map->pmap, vme->start, vme->end, 197495fab37eSRobert Watson vme->protection & ~revokeperms); 197595fab37eSRobert Watson vm_map_simplify_entry(map, vme); 197695fab37eSRobert Watson } 197795fab37eSRobert Watson vm_map_lock_downgrade(map); 197895fab37eSRobert Watson } 197995fab37eSRobert Watson vm_map_unlock_read(map); 198095fab37eSRobert Watson } 198195fab37eSRobert Watson 198295fab37eSRobert Watson /* 198395fab37eSRobert Watson * When the subject's label changes, it may require revocation of privilege 198495fab37eSRobert Watson * to mapped objects. This can't be done on-the-fly later with a unified 198595fab37eSRobert Watson * buffer cache. 198695fab37eSRobert Watson */ 198795fab37eSRobert Watson static void 198895fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel) 198995fab37eSRobert Watson { 199095fab37eSRobert Watson 199195fab37eSRobert Watson MAC_PERFORM(relabel_cred, cred, newlabel); 199295fab37eSRobert Watson } 199395fab37eSRobert Watson 199495fab37eSRobert Watson void 199595fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 199695fab37eSRobert Watson { 199795fab37eSRobert Watson 199895fab37eSRobert Watson MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 199995fab37eSRobert Watson } 200095fab37eSRobert Watson 200195fab37eSRobert Watson void 200295fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet) 200395fab37eSRobert Watson { 200495fab37eSRobert Watson 200595fab37eSRobert Watson MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 200695fab37eSRobert Watson } 200795fab37eSRobert Watson 200895fab37eSRobert Watson void 200995fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 201095fab37eSRobert Watson { 201195fab37eSRobert Watson 201295fab37eSRobert Watson MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 201395fab37eSRobert Watson } 201495fab37eSRobert Watson 201595fab37eSRobert Watson void 201695fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 201795fab37eSRobert Watson { 201895fab37eSRobert Watson 201995fab37eSRobert Watson MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 202095fab37eSRobert Watson } 202195fab37eSRobert Watson 202295fab37eSRobert Watson void 202395fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 202495fab37eSRobert Watson { 202595fab37eSRobert Watson 202695fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 202795fab37eSRobert Watson } 202895fab37eSRobert Watson 202995fab37eSRobert Watson void 203095fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 203195fab37eSRobert Watson struct socket *newsocket) 203295fab37eSRobert Watson { 203395fab37eSRobert Watson 203495fab37eSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 203595fab37eSRobert Watson newsocket, &newsocket->so_label); 203695fab37eSRobert Watson } 203795fab37eSRobert Watson 203895fab37eSRobert Watson static void 203995fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 204095fab37eSRobert Watson struct label *newlabel) 204195fab37eSRobert Watson { 204295fab37eSRobert Watson 204395fab37eSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 204495fab37eSRobert Watson } 204595fab37eSRobert Watson 204695fab37eSRobert Watson static void 204795fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 204895fab37eSRobert Watson { 204995fab37eSRobert Watson 205095fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 205195fab37eSRobert Watson } 205295fab37eSRobert Watson 205395fab37eSRobert Watson void 205495fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 205595fab37eSRobert Watson { 205695fab37eSRobert Watson 205795fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 205895fab37eSRobert Watson socket, &socket->so_peerlabel); 205995fab37eSRobert Watson } 206095fab37eSRobert Watson 206195fab37eSRobert Watson void 206295fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 206395fab37eSRobert Watson struct socket *newsocket) 206495fab37eSRobert Watson { 206595fab37eSRobert Watson 206695fab37eSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 206795fab37eSRobert Watson &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 206895fab37eSRobert Watson } 206995fab37eSRobert Watson 207095fab37eSRobert Watson void 207195fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 207295fab37eSRobert Watson { 207395fab37eSRobert Watson 207495fab37eSRobert Watson MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 207595fab37eSRobert Watson datagram, &datagram->m_pkthdr.label); 207695fab37eSRobert Watson } 207795fab37eSRobert Watson 207895fab37eSRobert Watson void 207995fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 208095fab37eSRobert Watson { 208195fab37eSRobert Watson 208295fab37eSRobert Watson MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 208395fab37eSRobert Watson fragment, &fragment->m_pkthdr.label); 208495fab37eSRobert Watson } 208595fab37eSRobert Watson 208695fab37eSRobert Watson void 208795fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 208895fab37eSRobert Watson { 208995fab37eSRobert Watson 209095fab37eSRobert Watson MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 209195fab37eSRobert Watson &ipq->ipq_label); 209295fab37eSRobert Watson } 209395fab37eSRobert Watson 209495fab37eSRobert Watson void 209595fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 209695fab37eSRobert Watson { 209795fab37eSRobert Watson 209895fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 209995fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 210095fab37eSRobert Watson } 210195fab37eSRobert Watson 210295fab37eSRobert Watson void 210395fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 210495fab37eSRobert Watson { 210595fab37eSRobert Watson 210695fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 210795fab37eSRobert Watson &mbuf->m_pkthdr.label); 210895fab37eSRobert Watson } 210995fab37eSRobert Watson 211095fab37eSRobert Watson void 211195fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 211295fab37eSRobert Watson { 211395fab37eSRobert Watson 211495fab37eSRobert Watson MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 211595fab37eSRobert Watson &mbuf->m_pkthdr.label); 211695fab37eSRobert Watson } 211795fab37eSRobert Watson 211895fab37eSRobert Watson void 211995fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 212095fab37eSRobert Watson { 212195fab37eSRobert Watson 212295fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 212395fab37eSRobert Watson &mbuf->m_pkthdr.label); 212495fab37eSRobert Watson } 212595fab37eSRobert Watson 212695fab37eSRobert Watson void 212795fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 212895fab37eSRobert Watson struct mbuf *newmbuf) 212995fab37eSRobert Watson { 213095fab37eSRobert Watson 213195fab37eSRobert Watson MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 213295fab37eSRobert Watson &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 213395fab37eSRobert Watson &newmbuf->m_pkthdr.label); 213495fab37eSRobert Watson } 213595fab37eSRobert Watson 213695fab37eSRobert Watson void 213795fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 213895fab37eSRobert Watson { 213995fab37eSRobert Watson 214095fab37eSRobert Watson MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 214195fab37eSRobert Watson newmbuf, &newmbuf->m_pkthdr.label); 214295fab37eSRobert Watson } 214395fab37eSRobert Watson 214495fab37eSRobert Watson int 214595fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 214695fab37eSRobert Watson { 214795fab37eSRobert Watson int result; 214895fab37eSRobert Watson 214995fab37eSRobert Watson result = 1; 215095fab37eSRobert Watson MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 215195fab37eSRobert Watson ipq, &ipq->ipq_label); 215295fab37eSRobert Watson 215395fab37eSRobert Watson return (result); 215495fab37eSRobert Watson } 215595fab37eSRobert Watson 215695fab37eSRobert Watson void 215795fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 215895fab37eSRobert Watson { 215995fab37eSRobert Watson 216095fab37eSRobert Watson MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 216195fab37eSRobert Watson &ipq->ipq_label); 216295fab37eSRobert Watson } 216395fab37eSRobert Watson 216495fab37eSRobert Watson void 216595fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 216695fab37eSRobert Watson { 216795fab37eSRobert Watson 216895fab37eSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 216995fab37eSRobert Watson &mbuf->m_pkthdr.label); 217095fab37eSRobert Watson } 217195fab37eSRobert Watson 217295fab37eSRobert Watson void 217395fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp) 217495fab37eSRobert Watson { 217595fab37eSRobert Watson 217695fab37eSRobert Watson MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 217795fab37eSRobert Watson &mp->mnt_fslabel); 217895fab37eSRobert Watson } 217995fab37eSRobert Watson 218095fab37eSRobert Watson void 218195fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp) 218295fab37eSRobert Watson { 218395fab37eSRobert Watson 218495fab37eSRobert Watson MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 218595fab37eSRobert Watson &mp->mnt_fslabel); 218695fab37eSRobert Watson } 218795fab37eSRobert Watson 218895fab37eSRobert Watson int 218995fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 219095fab37eSRobert Watson { 219195fab37eSRobert Watson int error; 219295fab37eSRobert Watson 219395fab37eSRobert Watson if (!mac_enforce_network) 219495fab37eSRobert Watson return (0); 219595fab37eSRobert Watson 219695fab37eSRobert Watson MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 219795fab37eSRobert Watson &ifnet->if_label); 219895fab37eSRobert Watson 219995fab37eSRobert Watson return (error); 220095fab37eSRobert Watson } 220195fab37eSRobert Watson 220295fab37eSRobert Watson static int 220395fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 220495fab37eSRobert Watson { 220595fab37eSRobert Watson int error; 220695fab37eSRobert Watson 220795fab37eSRobert Watson MAC_CHECK(check_cred_relabel, cred, newlabel); 220895fab37eSRobert Watson 220995fab37eSRobert Watson return (error); 221095fab37eSRobert Watson } 221195fab37eSRobert Watson 221295fab37eSRobert Watson int 221395fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 221495fab37eSRobert Watson { 221595fab37eSRobert Watson int error; 221695fab37eSRobert Watson 221795fab37eSRobert Watson if (!mac_enforce_process) 221895fab37eSRobert Watson return (0); 221995fab37eSRobert Watson 222095fab37eSRobert Watson MAC_CHECK(check_cred_visible, u1, u2); 222195fab37eSRobert Watson 222295fab37eSRobert Watson return (error); 222395fab37eSRobert Watson } 222495fab37eSRobert Watson 222595fab37eSRobert Watson int 222695fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 222795fab37eSRobert Watson { 222895fab37eSRobert Watson int error; 222995fab37eSRobert Watson 223095fab37eSRobert Watson if (!mac_enforce_network) 223195fab37eSRobert Watson return (0); 223295fab37eSRobert Watson 223395fab37eSRobert Watson KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 223495fab37eSRobert Watson if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 223529e1b85fSBrooks Davis if_printf(ifnet, "not initialized\n"); 223695fab37eSRobert Watson 223795fab37eSRobert Watson MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 223895fab37eSRobert Watson &mbuf->m_pkthdr.label); 223995fab37eSRobert Watson 224095fab37eSRobert Watson return (error); 224195fab37eSRobert Watson } 224295fab37eSRobert Watson 224395fab37eSRobert Watson int 2244e686e5aeSRobert Watson mac_check_kenv_dump(struct ucred *cred) 2245e686e5aeSRobert Watson { 2246e686e5aeSRobert Watson int error; 2247e686e5aeSRobert Watson 2248e686e5aeSRobert Watson if (!mac_enforce_system) 2249e686e5aeSRobert Watson return (0); 2250e686e5aeSRobert Watson 2251e686e5aeSRobert Watson MAC_CHECK(check_kenv_dump, cred); 2252e686e5aeSRobert Watson 2253e686e5aeSRobert Watson return (error); 2254e686e5aeSRobert Watson } 2255e686e5aeSRobert Watson 2256e686e5aeSRobert Watson int 2257e686e5aeSRobert Watson mac_check_kenv_get(struct ucred *cred, char *name) 2258e686e5aeSRobert Watson { 2259e686e5aeSRobert Watson int error; 2260e686e5aeSRobert Watson 2261e686e5aeSRobert Watson if (!mac_enforce_system) 2262e686e5aeSRobert Watson return (0); 2263e686e5aeSRobert Watson 2264e686e5aeSRobert Watson MAC_CHECK(check_kenv_get, cred, name); 2265e686e5aeSRobert Watson 2266e686e5aeSRobert Watson return (error); 2267e686e5aeSRobert Watson } 2268e686e5aeSRobert Watson 2269e686e5aeSRobert Watson int 2270e686e5aeSRobert Watson mac_check_kenv_set(struct ucred *cred, char *name, char *value) 2271e686e5aeSRobert Watson { 2272e686e5aeSRobert Watson int error; 2273e686e5aeSRobert Watson 2274e686e5aeSRobert Watson if (!mac_enforce_system) 2275e686e5aeSRobert Watson return (0); 2276e686e5aeSRobert Watson 2277e686e5aeSRobert Watson MAC_CHECK(check_kenv_set, cred, name, value); 2278e686e5aeSRobert Watson 2279e686e5aeSRobert Watson return (error); 2280e686e5aeSRobert Watson } 2281e686e5aeSRobert Watson 2282e686e5aeSRobert Watson int 2283e686e5aeSRobert Watson mac_check_kenv_unset(struct ucred *cred, char *name) 2284e686e5aeSRobert Watson { 2285e686e5aeSRobert Watson int error; 2286e686e5aeSRobert Watson 2287e686e5aeSRobert Watson if (!mac_enforce_system) 2288e686e5aeSRobert Watson return (0); 2289e686e5aeSRobert Watson 2290e686e5aeSRobert Watson MAC_CHECK(check_kenv_unset, cred, name); 2291e686e5aeSRobert Watson 2292e686e5aeSRobert Watson return (error); 2293e686e5aeSRobert Watson } 2294e686e5aeSRobert Watson 2295e686e5aeSRobert Watson int 229695fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount) 229795fab37eSRobert Watson { 229895fab37eSRobert Watson int error; 229995fab37eSRobert Watson 230095fab37eSRobert Watson if (!mac_enforce_fs) 230195fab37eSRobert Watson return (0); 230295fab37eSRobert Watson 230395fab37eSRobert Watson MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 230495fab37eSRobert Watson 230595fab37eSRobert Watson return (error); 230695fab37eSRobert Watson } 230795fab37eSRobert Watson 230895fab37eSRobert Watson int 230995fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 231095fab37eSRobert Watson void *data) 231195fab37eSRobert Watson { 231295fab37eSRobert Watson int error; 231395fab37eSRobert Watson 23141aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 23151aa37f53SRobert Watson 23161aa37f53SRobert Watson if (!mac_enforce_pipe) 23171aa37f53SRobert Watson return (0); 23181aa37f53SRobert Watson 231995fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 232095fab37eSRobert Watson 232195fab37eSRobert Watson return (error); 232295fab37eSRobert Watson } 232395fab37eSRobert Watson 232495fab37eSRobert Watson int 2325c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 232695fab37eSRobert Watson { 232795fab37eSRobert Watson int error; 232895fab37eSRobert Watson 23291aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 23301aa37f53SRobert Watson 23311aa37f53SRobert Watson if (!mac_enforce_pipe) 23321aa37f53SRobert Watson return (0); 23331aa37f53SRobert Watson 2334c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2335c024c3eeSRobert Watson 2336c024c3eeSRobert Watson return (error); 2337c024c3eeSRobert Watson } 2338c024c3eeSRobert Watson 2339c024c3eeSRobert Watson int 2340c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2341c024c3eeSRobert Watson { 2342c024c3eeSRobert Watson int error; 2343c024c3eeSRobert Watson 23441aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 23451aa37f53SRobert Watson 23461aa37f53SRobert Watson if (!mac_enforce_pipe) 23471aa37f53SRobert Watson return (0); 23481aa37f53SRobert Watson 2349c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 235095fab37eSRobert Watson 235195fab37eSRobert Watson return (error); 235295fab37eSRobert Watson } 235395fab37eSRobert Watson 235495fab37eSRobert Watson static int 235595fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 235695fab37eSRobert Watson struct label *newlabel) 235795fab37eSRobert Watson { 235895fab37eSRobert Watson int error; 235995fab37eSRobert Watson 23601aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 23611aa37f53SRobert Watson 23621aa37f53SRobert Watson if (!mac_enforce_pipe) 23631aa37f53SRobert Watson return (0); 23641aa37f53SRobert Watson 236595fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 236695fab37eSRobert Watson 236795fab37eSRobert Watson return (error); 236895fab37eSRobert Watson } 236995fab37eSRobert Watson 237095fab37eSRobert Watson int 2371c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2372c024c3eeSRobert Watson { 2373c024c3eeSRobert Watson int error; 2374c024c3eeSRobert Watson 23751aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 23761aa37f53SRobert Watson 23771aa37f53SRobert Watson if (!mac_enforce_pipe) 23781aa37f53SRobert Watson return (0); 23791aa37f53SRobert Watson 2380c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2381c024c3eeSRobert Watson 2382c024c3eeSRobert Watson return (error); 2383c024c3eeSRobert Watson } 2384c024c3eeSRobert Watson 2385c024c3eeSRobert Watson int 2386c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2387c024c3eeSRobert Watson { 2388c024c3eeSRobert Watson int error; 2389c024c3eeSRobert Watson 23901aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 23911aa37f53SRobert Watson 23921aa37f53SRobert Watson if (!mac_enforce_pipe) 23931aa37f53SRobert Watson return (0); 23941aa37f53SRobert Watson 2395c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2396c024c3eeSRobert Watson 2397c024c3eeSRobert Watson return (error); 2398c024c3eeSRobert Watson } 2399c024c3eeSRobert Watson 2400c024c3eeSRobert Watson int 240195fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc) 240295fab37eSRobert Watson { 240395fab37eSRobert Watson int error; 240495fab37eSRobert Watson 2405b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2406b12baf55SRobert Watson 240795fab37eSRobert Watson if (!mac_enforce_process) 240895fab37eSRobert Watson return (0); 240995fab37eSRobert Watson 241095fab37eSRobert Watson MAC_CHECK(check_proc_debug, cred, proc); 241195fab37eSRobert Watson 241295fab37eSRobert Watson return (error); 241395fab37eSRobert Watson } 241495fab37eSRobert Watson 241595fab37eSRobert Watson int 241695fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc) 241795fab37eSRobert Watson { 241895fab37eSRobert Watson int error; 241995fab37eSRobert Watson 2420b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2421b12baf55SRobert Watson 242295fab37eSRobert Watson if (!mac_enforce_process) 242395fab37eSRobert Watson return (0); 242495fab37eSRobert Watson 242595fab37eSRobert Watson MAC_CHECK(check_proc_sched, cred, proc); 242695fab37eSRobert Watson 242795fab37eSRobert Watson return (error); 242895fab37eSRobert Watson } 242995fab37eSRobert Watson 243095fab37eSRobert Watson int 243195fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 243295fab37eSRobert Watson { 243395fab37eSRobert Watson int error; 243495fab37eSRobert Watson 2435b12baf55SRobert Watson PROC_LOCK_ASSERT(proc, MA_OWNED); 2436b12baf55SRobert Watson 243795fab37eSRobert Watson if (!mac_enforce_process) 243895fab37eSRobert Watson return (0); 243995fab37eSRobert Watson 244095fab37eSRobert Watson MAC_CHECK(check_proc_signal, cred, proc, signum); 244195fab37eSRobert Watson 244295fab37eSRobert Watson return (error); 244395fab37eSRobert Watson } 244495fab37eSRobert Watson 244595fab37eSRobert Watson int 244695fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 244795fab37eSRobert Watson struct sockaddr *sockaddr) 244895fab37eSRobert Watson { 244995fab37eSRobert Watson int error; 245095fab37eSRobert Watson 245195fab37eSRobert Watson if (!mac_enforce_socket) 245295fab37eSRobert Watson return (0); 245395fab37eSRobert Watson 245495fab37eSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 245595fab37eSRobert Watson sockaddr); 245695fab37eSRobert Watson 245795fab37eSRobert Watson return (error); 245895fab37eSRobert Watson } 245995fab37eSRobert Watson 246095fab37eSRobert Watson int 246195fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 246295fab37eSRobert Watson struct sockaddr *sockaddr) 246395fab37eSRobert Watson { 246495fab37eSRobert Watson int error; 246595fab37eSRobert Watson 246695fab37eSRobert Watson if (!mac_enforce_socket) 246795fab37eSRobert Watson return (0); 246895fab37eSRobert Watson 246995fab37eSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 247095fab37eSRobert Watson sockaddr); 247195fab37eSRobert Watson 247295fab37eSRobert Watson return (error); 247395fab37eSRobert Watson } 247495fab37eSRobert Watson 247595fab37eSRobert Watson int 2476d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2477d61198e4SRobert Watson { 2478d61198e4SRobert Watson int error; 2479d61198e4SRobert Watson 2480d61198e4SRobert Watson if (!mac_enforce_socket) 2481d61198e4SRobert Watson return (0); 2482d61198e4SRobert Watson 2483d61198e4SRobert Watson MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2484d61198e4SRobert Watson &mbuf->m_pkthdr.label); 2485d61198e4SRobert Watson 2486d61198e4SRobert Watson return (error); 2487d61198e4SRobert Watson } 2488d61198e4SRobert Watson 2489d61198e4SRobert Watson int 249095fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 249195fab37eSRobert Watson { 249295fab37eSRobert Watson int error; 249395fab37eSRobert Watson 249495fab37eSRobert Watson if (!mac_enforce_socket) 249595fab37eSRobert Watson return (0); 249695fab37eSRobert Watson 249795fab37eSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 249895fab37eSRobert Watson return (error); 249995fab37eSRobert Watson } 250095fab37eSRobert Watson 2501b371c939SRobert Watson int 2502b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 2503b371c939SRobert Watson { 2504b371c939SRobert Watson int error; 2505b371c939SRobert Watson 2506b371c939SRobert Watson if (!mac_enforce_socket) 2507b371c939SRobert Watson return (0); 2508b371c939SRobert Watson 2509b371c939SRobert Watson MAC_CHECK(check_socket_receive, cred, so, &so->so_label); 2510b371c939SRobert Watson 2511b371c939SRobert Watson return (error); 2512b371c939SRobert Watson } 2513b371c939SRobert Watson 251495fab37eSRobert Watson static int 251595fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 251695fab37eSRobert Watson struct label *newlabel) 251795fab37eSRobert Watson { 251895fab37eSRobert Watson int error; 251995fab37eSRobert Watson 252095fab37eSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 252195fab37eSRobert Watson newlabel); 252295fab37eSRobert Watson 252395fab37eSRobert Watson return (error); 252495fab37eSRobert Watson } 252595fab37eSRobert Watson 252695fab37eSRobert Watson int 2527b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 2528b371c939SRobert Watson { 2529b371c939SRobert Watson int error; 2530b371c939SRobert Watson 2531b371c939SRobert Watson if (!mac_enforce_socket) 2532b371c939SRobert Watson return (0); 2533b371c939SRobert Watson 2534b371c939SRobert Watson MAC_CHECK(check_socket_send, cred, so, &so->so_label); 2535b371c939SRobert Watson 2536b371c939SRobert Watson return (error); 2537b371c939SRobert Watson } 2538b371c939SRobert Watson 2539b371c939SRobert Watson int 254095fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 254195fab37eSRobert Watson { 254295fab37eSRobert Watson int error; 254395fab37eSRobert Watson 254495fab37eSRobert Watson if (!mac_enforce_socket) 254595fab37eSRobert Watson return (0); 254695fab37eSRobert Watson 254795fab37eSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 254895fab37eSRobert Watson 254995fab37eSRobert Watson return (error); 255095fab37eSRobert Watson } 255195fab37eSRobert Watson 255295fab37eSRobert Watson int 2553e5e820fdSRobert Watson mac_check_system_acct(struct ucred *cred, struct vnode *vp) 2554e5e820fdSRobert Watson { 2555e5e820fdSRobert Watson int error; 2556e5e820fdSRobert Watson 2557e5e820fdSRobert Watson if (vp != NULL) { 2558e5e820fdSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_acct"); 2559e5e820fdSRobert Watson } 2560e5e820fdSRobert Watson 2561e5e820fdSRobert Watson if (!mac_enforce_system) 2562e5e820fdSRobert Watson return (0); 2563e5e820fdSRobert Watson 2564e5e820fdSRobert Watson MAC_CHECK(check_system_acct, cred, vp, 2565e5e820fdSRobert Watson vp != NULL ? &vp->v_label : NULL); 2566e5e820fdSRobert Watson 2567e5e820fdSRobert Watson return (error); 2568e5e820fdSRobert Watson } 2569e5e820fdSRobert Watson 2570e5e820fdSRobert Watson int 2571e5e820fdSRobert Watson mac_check_system_nfsd(struct ucred *cred) 2572e5e820fdSRobert Watson { 2573e5e820fdSRobert Watson int error; 2574e5e820fdSRobert Watson 2575e5e820fdSRobert Watson if (!mac_enforce_system) 2576e5e820fdSRobert Watson return (0); 2577e5e820fdSRobert Watson 2578e5e820fdSRobert Watson MAC_CHECK(check_system_nfsd, cred); 2579e5e820fdSRobert Watson 2580e5e820fdSRobert Watson return (error); 2581e5e820fdSRobert Watson } 2582e5e820fdSRobert Watson 2583e5e820fdSRobert Watson int 2584a2ecb9b7SRobert Watson mac_check_system_reboot(struct ucred *cred, int howto) 2585a2ecb9b7SRobert Watson { 2586a2ecb9b7SRobert Watson int error; 2587a2ecb9b7SRobert Watson 25889e913ebdSRobert Watson if (!mac_enforce_system) 2589a2ecb9b7SRobert Watson return (0); 2590a2ecb9b7SRobert Watson 2591a2ecb9b7SRobert Watson MAC_CHECK(check_system_reboot, cred, howto); 25929e913ebdSRobert Watson 2593a2ecb9b7SRobert Watson return (error); 2594a2ecb9b7SRobert Watson } 2595a2ecb9b7SRobert Watson 2596a2ecb9b7SRobert Watson int 25974b8d5f2dSRobert Watson mac_check_system_settime(struct ucred *cred) 25984b8d5f2dSRobert Watson { 25994b8d5f2dSRobert Watson int error; 26004b8d5f2dSRobert Watson 26014b8d5f2dSRobert Watson if (!mac_enforce_system) 26024b8d5f2dSRobert Watson return (0); 26034b8d5f2dSRobert Watson 26044b8d5f2dSRobert Watson MAC_CHECK(check_system_settime, cred); 26054b8d5f2dSRobert Watson 26064b8d5f2dSRobert Watson return (error); 26074b8d5f2dSRobert Watson } 26084b8d5f2dSRobert Watson 26094b8d5f2dSRobert Watson int 261003ce2c0cSRobert Watson mac_check_system_swapon(struct ucred *cred, struct vnode *vp) 261103ce2c0cSRobert Watson { 261203ce2c0cSRobert Watson int error; 261303ce2c0cSRobert Watson 261403ce2c0cSRobert Watson ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon"); 261503ce2c0cSRobert Watson 26169e913ebdSRobert Watson if (!mac_enforce_system) 261703ce2c0cSRobert Watson return (0); 261803ce2c0cSRobert Watson 261903ce2c0cSRobert Watson MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label); 262003ce2c0cSRobert Watson return (error); 262103ce2c0cSRobert Watson } 262203ce2c0cSRobert Watson 262303ce2c0cSRobert Watson int 2624d3fc69eeSRobert Watson mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen, 2625d3fc69eeSRobert Watson void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen) 2626d3fc69eeSRobert Watson { 2627d3fc69eeSRobert Watson int error; 2628d3fc69eeSRobert Watson 2629d3fc69eeSRobert Watson /* 2630d3fc69eeSRobert Watson * XXXMAC: We're very much like to assert the SYSCTL_LOCK here, 2631d3fc69eeSRobert Watson * but since it's not exported from kern_sysctl.c, we can't. 2632d3fc69eeSRobert Watson */ 26339e913ebdSRobert Watson if (!mac_enforce_system) 2634d3fc69eeSRobert Watson return (0); 2635d3fc69eeSRobert Watson 2636d3fc69eeSRobert Watson MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp, 2637d3fc69eeSRobert Watson inkernel, new, newlen); 2638d3fc69eeSRobert Watson 2639d3fc69eeSRobert Watson return (error); 2640d3fc69eeSRobert Watson } 2641d3fc69eeSRobert Watson 2642d3fc69eeSRobert Watson int 264395fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 264495fab37eSRobert Watson struct ifnet *ifnet) 264595fab37eSRobert Watson { 2646f7b951a8SRobert Watson char *elements, *buffer; 2647f7b951a8SRobert Watson struct mac mac; 264895fab37eSRobert Watson int error; 264995fab37eSRobert Watson 2650f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 265195fab37eSRobert Watson if (error) 265295fab37eSRobert Watson return (error); 265395fab37eSRobert Watson 2654f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 2655f7b951a8SRobert Watson if (error) 2656f7b951a8SRobert Watson return (error); 2657f7b951a8SRobert Watson 2658f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2659f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2660f7b951a8SRobert Watson if (error) { 2661f7b951a8SRobert Watson free(elements, M_MACTEMP); 2662f7b951a8SRobert Watson return (error); 2663f7b951a8SRobert Watson } 2664f7b951a8SRobert Watson 2665f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2666f7b951a8SRobert Watson error = mac_externalize_ifnet_label(&ifnet->if_label, elements, 2667f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 2668f7b951a8SRobert Watson if (error == 0) 2669f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2670f7b951a8SRobert Watson 2671f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2672f7b951a8SRobert Watson free(elements, M_MACTEMP); 2673f7b951a8SRobert Watson 2674f7b951a8SRobert Watson return (error); 267595fab37eSRobert Watson } 267695fab37eSRobert Watson 267795fab37eSRobert Watson int 267895fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 267995fab37eSRobert Watson struct ifnet *ifnet) 268095fab37eSRobert Watson { 268195fab37eSRobert Watson struct label intlabel; 2682f7b951a8SRobert Watson struct mac mac; 2683f7b951a8SRobert Watson char *buffer; 268495fab37eSRobert Watson int error; 268595fab37eSRobert Watson 2686f7b951a8SRobert Watson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 268795fab37eSRobert Watson if (error) 268895fab37eSRobert Watson return (error); 268995fab37eSRobert Watson 2690f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 269195fab37eSRobert Watson if (error) 269295fab37eSRobert Watson return (error); 269395fab37eSRobert Watson 2694f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2695f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 2696f7b951a8SRobert Watson if (error) { 2697f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2698f7b951a8SRobert Watson return (error); 2699f7b951a8SRobert Watson } 2700f7b951a8SRobert Watson 2701f7b951a8SRobert Watson mac_init_ifnet_label(&intlabel); 2702f7b951a8SRobert Watson error = mac_internalize_ifnet_label(&intlabel, buffer); 2703f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2704f7b951a8SRobert Watson if (error) { 2705f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2706f7b951a8SRobert Watson return (error); 2707f7b951a8SRobert Watson } 2708f7b951a8SRobert Watson 270995fab37eSRobert Watson /* 271095fab37eSRobert Watson * XXX: Note that this is a redundant privilege check, since 271195fab37eSRobert Watson * policies impose this check themselves if required by the 271295fab37eSRobert Watson * policy. Eventually, this should go away. 271395fab37eSRobert Watson */ 271495fab37eSRobert Watson error = suser_cred(cred, 0); 2715f7b951a8SRobert Watson if (error) { 2716f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2717f7b951a8SRobert Watson return (error); 2718f7b951a8SRobert Watson } 271995fab37eSRobert Watson 272095fab37eSRobert Watson MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 272195fab37eSRobert Watson &intlabel); 2722f7b951a8SRobert Watson if (error) { 2723f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2724f7b951a8SRobert Watson return (error); 2725f7b951a8SRobert Watson } 272695fab37eSRobert Watson 272795fab37eSRobert Watson MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 272895fab37eSRobert Watson 2729f7b951a8SRobert Watson mac_destroy_ifnet_label(&intlabel); 2730f7b951a8SRobert Watson return (0); 273195fab37eSRobert Watson } 273295fab37eSRobert Watson 273395fab37eSRobert Watson void 273495fab37eSRobert Watson mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 273595fab37eSRobert Watson { 273695fab37eSRobert Watson 273795fab37eSRobert Watson MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 273895fab37eSRobert Watson } 273995fab37eSRobert Watson 274074e62b1bSRobert Watson void 274174e62b1bSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 274274e62b1bSRobert Watson struct devfs_dirent *de) 274374e62b1bSRobert Watson { 274474e62b1bSRobert Watson 274574e62b1bSRobert Watson MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de, 274674e62b1bSRobert Watson &de->de_label); 274774e62b1bSRobert Watson } 274874e62b1bSRobert Watson 274995fab37eSRobert Watson void 275095fab37eSRobert Watson mac_create_devfs_directory(char *dirname, int dirnamelen, 275195fab37eSRobert Watson struct devfs_dirent *de) 275295fab37eSRobert Watson { 275395fab37eSRobert Watson 275495fab37eSRobert Watson MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 275595fab37eSRobert Watson &de->de_label); 275695fab37eSRobert Watson } 275795fab37eSRobert Watson 275895fab37eSRobert Watson int 275995fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2760f7b951a8SRobert Watson struct mac *mac) 276195fab37eSRobert Watson { 276295fab37eSRobert Watson struct label intlabel; 2763f7b951a8SRobert Watson char *buffer; 276495fab37eSRobert Watson int error; 276595fab37eSRobert Watson 2766f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 276795fab37eSRobert Watson if (error) 276895fab37eSRobert Watson return (error); 276995fab37eSRobert Watson 2770f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2771f7b951a8SRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 2772f7b951a8SRobert Watson if (error) { 2773f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2774f7b951a8SRobert Watson return (error); 2775f7b951a8SRobert Watson } 2776f7b951a8SRobert Watson 2777f7b951a8SRobert Watson mac_init_socket_label(&intlabel, M_WAITOK); 2778f7b951a8SRobert Watson error = mac_internalize_socket_label(&intlabel, buffer); 2779f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2780f7b951a8SRobert Watson if (error) { 2781f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 2782f7b951a8SRobert Watson return (error); 2783f7b951a8SRobert Watson } 2784f7b951a8SRobert Watson 278595fab37eSRobert Watson mac_check_socket_relabel(cred, so, &intlabel); 278695fab37eSRobert Watson if (error) { 2787f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 278895fab37eSRobert Watson return (error); 278995fab37eSRobert Watson } 279095fab37eSRobert Watson 279195fab37eSRobert Watson mac_relabel_socket(cred, so, &intlabel); 279295fab37eSRobert Watson 2793f7b951a8SRobert Watson mac_destroy_socket_label(&intlabel); 279495fab37eSRobert Watson return (0); 279595fab37eSRobert Watson } 279695fab37eSRobert Watson 279795fab37eSRobert Watson int 279895fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 279995fab37eSRobert Watson { 280095fab37eSRobert Watson int error; 280195fab37eSRobert Watson 28021aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 28031aa37f53SRobert Watson 280495fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 280595fab37eSRobert Watson if (error) 280695fab37eSRobert Watson return (error); 280795fab37eSRobert Watson 280895fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 280995fab37eSRobert Watson 281095fab37eSRobert Watson return (0); 281195fab37eSRobert Watson } 281295fab37eSRobert Watson 281395fab37eSRobert Watson int 281495fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2815f7b951a8SRobert Watson struct mac *mac) 281695fab37eSRobert Watson { 2817f7b951a8SRobert Watson char *buffer, *elements; 2818f7b951a8SRobert Watson int error; 281995fab37eSRobert Watson 2820f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 2821f7b951a8SRobert Watson if (error) 2822f7b951a8SRobert Watson return (error); 2823f7b951a8SRobert Watson 2824f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2825f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2826f7b951a8SRobert Watson if (error) { 2827f7b951a8SRobert Watson free(elements, M_MACTEMP); 2828f7b951a8SRobert Watson return (error); 2829f7b951a8SRobert Watson } 2830f7b951a8SRobert Watson 2831f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2832f7b951a8SRobert Watson error = mac_externalize_socket_label(&so->so_label, elements, 2833f7b951a8SRobert Watson buffer, mac->m_buflen, M_WAITOK); 2834f7b951a8SRobert Watson if (error == 0) 2835f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2836f7b951a8SRobert Watson 2837f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2838f7b951a8SRobert Watson free(elements, M_MACTEMP); 2839f7b951a8SRobert Watson 2840f7b951a8SRobert Watson return (error); 284195fab37eSRobert Watson } 284295fab37eSRobert Watson 284395fab37eSRobert Watson int 284495fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2845f7b951a8SRobert Watson struct mac *mac) 284695fab37eSRobert Watson { 2847f7b951a8SRobert Watson char *elements, *buffer; 2848f7b951a8SRobert Watson int error; 284995fab37eSRobert Watson 2850f7b951a8SRobert Watson error = mac_check_structmac_consistent(mac); 2851f7b951a8SRobert Watson if (error) 2852f7b951a8SRobert Watson return (error); 2853f7b951a8SRobert Watson 2854f7b951a8SRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 2855f7b951a8SRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 2856f7b951a8SRobert Watson if (error) { 2857f7b951a8SRobert Watson free(elements, M_MACTEMP); 2858f7b951a8SRobert Watson return (error); 2859f7b951a8SRobert Watson } 2860f7b951a8SRobert Watson 2861f7b951a8SRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2862f7b951a8SRobert Watson error = mac_externalize_socket_peer_label(&so->so_peerlabel, 2863f7b951a8SRobert Watson elements, buffer, mac->m_buflen, M_WAITOK); 2864f7b951a8SRobert Watson if (error == 0) 2865f7b951a8SRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 2866f7b951a8SRobert Watson 2867f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2868f7b951a8SRobert Watson free(elements, M_MACTEMP); 2869f7b951a8SRobert Watson 2870f7b951a8SRobert Watson return (error); 287195fab37eSRobert Watson } 287295fab37eSRobert Watson 287395fab37eSRobert Watson /* 287495fab37eSRobert Watson * Implementation of VOP_SETLABEL() that relies on extended attributes 287595fab37eSRobert Watson * to store label data. Can be referenced by filesystems supporting 287695fab37eSRobert Watson * extended attributes. 287795fab37eSRobert Watson */ 287895fab37eSRobert Watson int 287995fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 288095fab37eSRobert Watson { 288195fab37eSRobert Watson struct vnode *vp = ap->a_vp; 288295fab37eSRobert Watson struct label *intlabel = ap->a_label; 288395fab37eSRobert Watson int error; 288495fab37eSRobert Watson 288595fab37eSRobert Watson ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 288695fab37eSRobert Watson 2887763bbd2fSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2888763bbd2fSRobert Watson return (EOPNOTSUPP); 288995fab37eSRobert Watson 2890763bbd2fSRobert Watson error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); 289195fab37eSRobert Watson if (error) 289295fab37eSRobert Watson return (error); 289395fab37eSRobert Watson 289495fab37eSRobert Watson mac_relabel_vnode(ap->a_cred, vp, intlabel); 289595fab37eSRobert Watson 289695fab37eSRobert Watson return (0); 289795fab37eSRobert Watson } 289895fab37eSRobert Watson 289995fab37eSRobert Watson static int 290095fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 290195fab37eSRobert Watson { 290295fab37eSRobert Watson int error; 290395fab37eSRobert Watson 290495fab37eSRobert Watson if (vp->v_mount == NULL) { 290595fab37eSRobert Watson /* printf("vn_setlabel: null v_mount\n"); */ 290606be2aaaSNate Lawson if (vp->v_type != VNON) 290706be2aaaSNate Lawson printf("vn_setlabel: null v_mount with non-VNON\n"); 290895fab37eSRobert Watson return (EBADF); 290995fab37eSRobert Watson } 291095fab37eSRobert Watson 291195fab37eSRobert Watson if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 291295fab37eSRobert Watson return (EOPNOTSUPP); 291395fab37eSRobert Watson 291495fab37eSRobert Watson /* 291595fab37eSRobert Watson * Multi-phase commit. First check the policies to confirm the 291695fab37eSRobert Watson * change is OK. Then commit via the filesystem. Finally, 291795fab37eSRobert Watson * update the actual vnode label. Question: maybe the filesystem 291895fab37eSRobert Watson * should update the vnode at the end as part of VOP_SETLABEL()? 291995fab37eSRobert Watson */ 292095fab37eSRobert Watson error = mac_check_vnode_relabel(cred, vp, intlabel); 292195fab37eSRobert Watson if (error) 292295fab37eSRobert Watson return (error); 292395fab37eSRobert Watson 292495fab37eSRobert Watson /* 292595fab37eSRobert Watson * VADMIN provides the opportunity for the filesystem to make 292695fab37eSRobert Watson * decisions about who is and is not able to modify labels 292795fab37eSRobert Watson * and protections on files. This might not be right. We can't 292895fab37eSRobert Watson * assume VOP_SETLABEL() will do it, because we might implement 292995fab37eSRobert Watson * that as part of vop_stdsetlabel_ea(). 293095fab37eSRobert Watson */ 293195fab37eSRobert Watson error = VOP_ACCESS(vp, VADMIN, cred, curthread); 293295fab37eSRobert Watson if (error) 293395fab37eSRobert Watson return (error); 293495fab37eSRobert Watson 293595fab37eSRobert Watson error = VOP_SETLABEL(vp, intlabel, cred, curthread); 293695fab37eSRobert Watson if (error) 293795fab37eSRobert Watson return (error); 293895fab37eSRobert Watson 293995fab37eSRobert Watson return (0); 294095fab37eSRobert Watson } 294195fab37eSRobert Watson 2942f7b951a8SRobert Watson int 2943f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 2944f7b951a8SRobert Watson { 2945f7b951a8SRobert Watson char *elements, *buffer; 2946f7b951a8SRobert Watson struct mac mac; 2947f7b951a8SRobert Watson struct proc *tproc; 2948f7b951a8SRobert Watson struct ucred *tcred; 2949f7b951a8SRobert Watson int error; 2950f7b951a8SRobert Watson 2951f7b951a8SRobert Watson error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac)); 2952f7b951a8SRobert Watson if (error) 2953f7b951a8SRobert Watson return (error); 2954f7b951a8SRobert Watson 2955f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 2956f7b951a8SRobert Watson if (error) 2957f7b951a8SRobert Watson return (error); 2958f7b951a8SRobert Watson 2959f7b951a8SRobert Watson tproc = pfind(uap->pid); 2960f7b951a8SRobert Watson if (tproc == NULL) 2961f7b951a8SRobert Watson return (ESRCH); 2962f7b951a8SRobert Watson 2963f7b951a8SRobert Watson tcred = NULL; /* Satisfy gcc. */ 2964f7b951a8SRobert Watson error = p_cansee(td, tproc); 2965f7b951a8SRobert Watson if (error == 0) 2966f7b951a8SRobert Watson tcred = crhold(tproc->p_ucred); 2967f7b951a8SRobert Watson PROC_UNLOCK(tproc); 2968f7b951a8SRobert Watson if (error) 2969f7b951a8SRobert Watson return (error); 2970f7b951a8SRobert Watson 2971f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 2972f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 2973f7b951a8SRobert Watson if (error) { 2974f7b951a8SRobert Watson free(elements, M_MACTEMP); 2975f7b951a8SRobert Watson crfree(tcred); 2976f7b951a8SRobert Watson return (error); 2977f7b951a8SRobert Watson } 2978f7b951a8SRobert Watson 2979f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 2980f7b951a8SRobert Watson error = mac_externalize_cred_label(&tcred->cr_label, elements, 2981f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 2982f7b951a8SRobert Watson if (error == 0) 2983f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 2984f7b951a8SRobert Watson 2985f7b951a8SRobert Watson free(buffer, M_MACTEMP); 2986f7b951a8SRobert Watson free(elements, M_MACTEMP); 2987f7b951a8SRobert Watson crfree(tcred); 2988f7b951a8SRobert Watson return (error); 2989f7b951a8SRobert Watson } 2990f7b951a8SRobert Watson 299195fab37eSRobert Watson /* 299295fab37eSRobert Watson * MPSAFE 299395fab37eSRobert Watson */ 299495fab37eSRobert Watson int 299595fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 299695fab37eSRobert Watson { 2997f7b951a8SRobert Watson char *elements, *buffer; 2998f7b951a8SRobert Watson struct mac mac; 299995fab37eSRobert Watson int error; 300095fab37eSRobert Watson 3001f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3002f7b951a8SRobert Watson if (error) 3003f7b951a8SRobert Watson return (error); 300495fab37eSRobert Watson 3005f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3006f7b951a8SRobert Watson if (error) 3007f7b951a8SRobert Watson return (error); 3008f7b951a8SRobert Watson 3009f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3010f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3011f7b951a8SRobert Watson if (error) { 3012f7b951a8SRobert Watson free(elements, M_MACTEMP); 3013f7b951a8SRobert Watson return (error); 3014f7b951a8SRobert Watson } 3015f7b951a8SRobert Watson 3016f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3017f7b951a8SRobert Watson error = mac_externalize_cred_label(&td->td_ucred->cr_label, 3018f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3019f7b951a8SRobert Watson if (error == 0) 3020f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3021f7b951a8SRobert Watson 3022f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3023f7b951a8SRobert Watson free(elements, M_MACTEMP); 302495fab37eSRobert Watson return (error); 302595fab37eSRobert Watson } 302695fab37eSRobert Watson 302795fab37eSRobert Watson /* 302895fab37eSRobert Watson * MPSAFE 302995fab37eSRobert Watson */ 303095fab37eSRobert Watson int 303195fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 303295fab37eSRobert Watson { 303395fab37eSRobert Watson struct ucred *newcred, *oldcred; 303495fab37eSRobert Watson struct label intlabel; 3035f7b951a8SRobert Watson struct proc *p; 3036f7b951a8SRobert Watson struct mac mac; 3037f7b951a8SRobert Watson char *buffer; 303895fab37eSRobert Watson int error; 303995fab37eSRobert Watson 3040f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 304195fab37eSRobert Watson if (error) 304295fab37eSRobert Watson return (error); 304395fab37eSRobert Watson 3044f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 304595fab37eSRobert Watson if (error) 304695fab37eSRobert Watson return (error); 304795fab37eSRobert Watson 3048f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3049f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3050f7b951a8SRobert Watson if (error) { 3051f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3052f7b951a8SRobert Watson return (error); 3053f7b951a8SRobert Watson } 3054f7b951a8SRobert Watson 3055f7b951a8SRobert Watson mac_init_cred_label(&intlabel); 3056f7b951a8SRobert Watson error = mac_internalize_cred_label(&intlabel, buffer); 3057f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3058f7b951a8SRobert Watson if (error) { 3059f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3060f7b951a8SRobert Watson return (error); 3061f7b951a8SRobert Watson } 3062f7b951a8SRobert Watson 306395fab37eSRobert Watson newcred = crget(); 306495fab37eSRobert Watson 306595fab37eSRobert Watson p = td->td_proc; 306695fab37eSRobert Watson PROC_LOCK(p); 306795fab37eSRobert Watson oldcred = p->p_ucred; 306895fab37eSRobert Watson 306995fab37eSRobert Watson error = mac_check_cred_relabel(oldcred, &intlabel); 307095fab37eSRobert Watson if (error) { 307195fab37eSRobert Watson PROC_UNLOCK(p); 307295fab37eSRobert Watson crfree(newcred); 3073f7b951a8SRobert Watson goto out; 307495fab37eSRobert Watson } 307595fab37eSRobert Watson 307695fab37eSRobert Watson setsugid(p); 307795fab37eSRobert Watson crcopy(newcred, oldcred); 307895fab37eSRobert Watson mac_relabel_cred(newcred, &intlabel); 307995fab37eSRobert Watson p->p_ucred = newcred; 3080e5cb5e37SRobert Watson 3081e5cb5e37SRobert Watson /* 3082e5cb5e37SRobert Watson * Grab additional reference for use while revoking mmaps, prior 3083e5cb5e37SRobert Watson * to releasing the proc lock and sharing the cred. 3084e5cb5e37SRobert Watson */ 3085e5cb5e37SRobert Watson crhold(newcred); 308695fab37eSRobert Watson PROC_UNLOCK(p); 3087e5cb5e37SRobert Watson 3088f7b951a8SRobert Watson if (mac_enforce_vm) { 308916140035SRobert Watson mtx_lock(&Giant); 3090e5cb5e37SRobert Watson mac_cred_mmapped_drop_perms(td, newcred); 309116140035SRobert Watson mtx_unlock(&Giant); 3092f7b951a8SRobert Watson } 3093e5cb5e37SRobert Watson 3094e5cb5e37SRobert Watson crfree(newcred); /* Free revocation reference. */ 309595fab37eSRobert Watson crfree(oldcred); 3096f7b951a8SRobert Watson 3097f7b951a8SRobert Watson out: 3098f7b951a8SRobert Watson mac_destroy_cred_label(&intlabel); 3099f7b951a8SRobert Watson return (error); 310095fab37eSRobert Watson } 310195fab37eSRobert Watson 310295fab37eSRobert Watson /* 310395fab37eSRobert Watson * MPSAFE 310495fab37eSRobert Watson */ 310595fab37eSRobert Watson int 310695fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 310795fab37eSRobert Watson { 3108f7b951a8SRobert Watson char *elements, *buffer; 3109f7b951a8SRobert Watson struct label intlabel; 311095fab37eSRobert Watson struct file *fp; 3111f7b951a8SRobert Watson struct mac mac; 311295fab37eSRobert Watson struct vnode *vp; 311395fab37eSRobert Watson struct pipe *pipe; 3114f7b951a8SRobert Watson short label_type; 311595fab37eSRobert Watson int error; 311695fab37eSRobert Watson 3117f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3118f7b951a8SRobert Watson if (error) 3119f7b951a8SRobert Watson return (error); 312095fab37eSRobert Watson 3121f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3122f7b951a8SRobert Watson if (error) 3123f7b951a8SRobert Watson return (error); 3124f7b951a8SRobert Watson 3125f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3126f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3127f7b951a8SRobert Watson if (error) { 3128f7b951a8SRobert Watson free(elements, M_MACTEMP); 3129f7b951a8SRobert Watson return (error); 3130f7b951a8SRobert Watson } 3131f7b951a8SRobert Watson 3132f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3133f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 313495fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 313595fab37eSRobert Watson if (error) 313695fab37eSRobert Watson goto out; 313795fab37eSRobert Watson 3138f7b951a8SRobert Watson label_type = fp->f_type; 313995fab37eSRobert Watson switch (fp->f_type) { 314095fab37eSRobert Watson case DTYPE_FIFO: 314195fab37eSRobert Watson case DTYPE_VNODE: 314295fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 314395fab37eSRobert Watson 3144f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3145f7b951a8SRobert Watson 314695fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3147f7b951a8SRobert Watson mac_copy_vnode_label(&vp->v_label, &intlabel); 314895fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 3149f7b951a8SRobert Watson 315095fab37eSRobert Watson break; 315195fab37eSRobert Watson case DTYPE_PIPE: 315295fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 3153f7b951a8SRobert Watson 3154f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3155f7b951a8SRobert Watson 3156f7b951a8SRobert Watson PIPE_LOCK(pipe); 3157f7b951a8SRobert Watson mac_copy_pipe_label(pipe->pipe_label, &intlabel); 3158f7b951a8SRobert Watson PIPE_UNLOCK(pipe); 315995fab37eSRobert Watson break; 316095fab37eSRobert Watson default: 316195fab37eSRobert Watson error = EINVAL; 3162f7b951a8SRobert Watson fdrop(fp, td); 3163f7b951a8SRobert Watson goto out; 3164f7b951a8SRobert Watson } 3165f7b951a8SRobert Watson fdrop(fp, td); 3166f7b951a8SRobert Watson 3167f7b951a8SRobert Watson switch (label_type) { 3168f7b951a8SRobert Watson case DTYPE_FIFO: 3169f7b951a8SRobert Watson case DTYPE_VNODE: 3170f7b951a8SRobert Watson if (error == 0) 3171f7b951a8SRobert Watson error = mac_externalize_vnode_label(&intlabel, 3172f7b951a8SRobert Watson elements, buffer, mac.m_buflen, M_WAITOK); 3173f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3174f7b951a8SRobert Watson break; 3175f7b951a8SRobert Watson case DTYPE_PIPE: 3176f7b951a8SRobert Watson error = mac_externalize_pipe_label(&intlabel, elements, 3177f7b951a8SRobert Watson buffer, mac.m_buflen, M_WAITOK); 3178f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 3179f7b951a8SRobert Watson break; 3180f7b951a8SRobert Watson default: 3181f7b951a8SRobert Watson panic("__mac_get_fd: corrupted label_type"); 318295fab37eSRobert Watson } 318395fab37eSRobert Watson 318495fab37eSRobert Watson if (error == 0) 3185f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 318695fab37eSRobert Watson 318795fab37eSRobert Watson out: 3188f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3189f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3190f7b951a8SRobert Watson free(elements, M_MACTEMP); 3191f7b951a8SRobert Watson 319295fab37eSRobert Watson return (error); 319395fab37eSRobert Watson } 319495fab37eSRobert Watson 319595fab37eSRobert Watson /* 319695fab37eSRobert Watson * MPSAFE 319795fab37eSRobert Watson */ 319895fab37eSRobert Watson int 319995fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 320095fab37eSRobert Watson { 3201f7b951a8SRobert Watson char *elements, *buffer; 320295fab37eSRobert Watson struct nameidata nd; 3203f7b951a8SRobert Watson struct label intlabel; 3204f7b951a8SRobert Watson struct mac mac; 320595fab37eSRobert Watson int error; 320695fab37eSRobert Watson 3207f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3208f7b951a8SRobert Watson if (error) 3209f7b951a8SRobert Watson return (error); 3210f7b951a8SRobert Watson 3211f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3212f7b951a8SRobert Watson if (error) 3213f7b951a8SRobert Watson return (error); 3214f7b951a8SRobert Watson 3215f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3216f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3217f7b951a8SRobert Watson if (error) { 3218f7b951a8SRobert Watson free(elements, M_MACTEMP); 3219f7b951a8SRobert Watson return (error); 3220f7b951a8SRobert Watson } 3221f7b951a8SRobert Watson 3222f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3223f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3224f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3225f7b951a8SRobert Watson td); 322695fab37eSRobert Watson error = namei(&nd); 322795fab37eSRobert Watson if (error) 322895fab37eSRobert Watson goto out; 322995fab37eSRobert Watson 3230f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3231f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3232763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3233763bbd2fSRobert Watson mac.m_buflen, M_WAITOK); 3234f7b951a8SRobert Watson 323595fab37eSRobert Watson NDFREE(&nd, 0); 3236f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3237f7b951a8SRobert Watson 3238f7b951a8SRobert Watson if (error == 0) 3239f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 3240f7b951a8SRobert Watson 3241f7b951a8SRobert Watson out: 3242f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3243f7b951a8SRobert Watson 3244f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3245f7b951a8SRobert Watson free(elements, M_MACTEMP); 3246f7b951a8SRobert Watson 3247f7b951a8SRobert Watson return (error); 3248f7b951a8SRobert Watson } 3249f7b951a8SRobert Watson 3250f7b951a8SRobert Watson /* 3251f7b951a8SRobert Watson * MPSAFE 3252f7b951a8SRobert Watson */ 3253f7b951a8SRobert Watson int 3254f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3255f7b951a8SRobert Watson { 3256f7b951a8SRobert Watson char *elements, *buffer; 3257f7b951a8SRobert Watson struct nameidata nd; 3258f7b951a8SRobert Watson struct label intlabel; 3259f7b951a8SRobert Watson struct mac mac; 3260f7b951a8SRobert Watson int error; 3261f7b951a8SRobert Watson 3262f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3263f7b951a8SRobert Watson if (error) 3264f7b951a8SRobert Watson return (error); 3265f7b951a8SRobert Watson 3266f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3267f7b951a8SRobert Watson if (error) 3268f7b951a8SRobert Watson return (error); 3269f7b951a8SRobert Watson 3270f7b951a8SRobert Watson elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3271f7b951a8SRobert Watson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 3272f7b951a8SRobert Watson if (error) { 3273f7b951a8SRobert Watson free(elements, M_MACTEMP); 3274f7b951a8SRobert Watson return (error); 3275f7b951a8SRobert Watson } 3276f7b951a8SRobert Watson 3277f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 3278f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3279f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3280f7b951a8SRobert Watson td); 3281f7b951a8SRobert Watson error = namei(&nd); 328295fab37eSRobert Watson if (error) 328395fab37eSRobert Watson goto out; 328495fab37eSRobert Watson 3285f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3286f7b951a8SRobert Watson mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 3287763bbd2fSRobert Watson error = mac_externalize_vnode_label(&intlabel, elements, buffer, 3288763bbd2fSRobert Watson mac.m_buflen, M_WAITOK); 3289f7b951a8SRobert Watson NDFREE(&nd, 0); 3290f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3291f7b951a8SRobert Watson 3292f7b951a8SRobert Watson if (error == 0) 3293f7b951a8SRobert Watson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 329495fab37eSRobert Watson 329595fab37eSRobert Watson out: 3296f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3297f7b951a8SRobert Watson 3298f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3299f7b951a8SRobert Watson free(elements, M_MACTEMP); 3300f7b951a8SRobert Watson 330195fab37eSRobert Watson return (error); 330295fab37eSRobert Watson } 330395fab37eSRobert Watson 330495fab37eSRobert Watson /* 330595fab37eSRobert Watson * MPSAFE 330695fab37eSRobert Watson */ 330795fab37eSRobert Watson int 330895fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 330995fab37eSRobert Watson { 331095fab37eSRobert Watson struct label intlabel; 3311f7b951a8SRobert Watson struct pipe *pipe; 3312f7b951a8SRobert Watson struct file *fp; 331395fab37eSRobert Watson struct mount *mp; 331495fab37eSRobert Watson struct vnode *vp; 3315f7b951a8SRobert Watson struct mac mac; 3316f7b951a8SRobert Watson char *buffer; 331795fab37eSRobert Watson int error; 331895fab37eSRobert Watson 3319f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3320f7b951a8SRobert Watson if (error) 3321f7b951a8SRobert Watson return (error); 3322f7b951a8SRobert Watson 3323f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3324f7b951a8SRobert Watson if (error) 3325f7b951a8SRobert Watson return (error); 3326f7b951a8SRobert Watson 3327f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3328f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3329f7b951a8SRobert Watson if (error) { 3330f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3331f7b951a8SRobert Watson return (error); 3332f7b951a8SRobert Watson } 3333f7b951a8SRobert Watson 3334f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3335f7b951a8SRobert Watson 333695fab37eSRobert Watson error = fget(td, SCARG(uap, fd), &fp); 333795fab37eSRobert Watson if (error) 3338f7b951a8SRobert Watson goto out; 333995fab37eSRobert Watson 334095fab37eSRobert Watson switch (fp->f_type) { 334195fab37eSRobert Watson case DTYPE_FIFO: 334295fab37eSRobert Watson case DTYPE_VNODE: 3343f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3344f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3345f7b951a8SRobert Watson if (error) { 3346f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3347f7b951a8SRobert Watson break; 3348f7b951a8SRobert Watson } 3349f7b951a8SRobert Watson 335095fab37eSRobert Watson vp = (struct vnode *)fp->f_data; 335195fab37eSRobert Watson error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3352f7b951a8SRobert Watson if (error != 0) { 3353f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 335495fab37eSRobert Watson break; 3355f7b951a8SRobert Watson } 335695fab37eSRobert Watson 335795fab37eSRobert Watson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 335895fab37eSRobert Watson error = vn_setlabel(vp, &intlabel, td->td_ucred); 335995fab37eSRobert Watson VOP_UNLOCK(vp, 0, td); 336095fab37eSRobert Watson vn_finished_write(mp); 3361f7b951a8SRobert Watson 3362f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 336395fab37eSRobert Watson break; 3364f7b951a8SRobert Watson 336595fab37eSRobert Watson case DTYPE_PIPE: 3366f7b951a8SRobert Watson mac_init_pipe_label(&intlabel); 3367f7b951a8SRobert Watson error = mac_internalize_pipe_label(&intlabel, buffer); 3368f7b951a8SRobert Watson if (error == 0) { 336995fab37eSRobert Watson pipe = (struct pipe *)fp->f_data; 33701aa37f53SRobert Watson PIPE_LOCK(pipe); 3371f7b951a8SRobert Watson error = mac_pipe_label_set(td->td_ucred, pipe, 3372f7b951a8SRobert Watson &intlabel); 33731aa37f53SRobert Watson PIPE_UNLOCK(pipe); 3374f7b951a8SRobert Watson } 3375f7b951a8SRobert Watson 3376f7b951a8SRobert Watson mac_destroy_pipe_label(&intlabel); 337795fab37eSRobert Watson break; 3378f7b951a8SRobert Watson 337995fab37eSRobert Watson default: 338095fab37eSRobert Watson error = EINVAL; 338195fab37eSRobert Watson } 338295fab37eSRobert Watson 338395fab37eSRobert Watson fdrop(fp, td); 3384f7b951a8SRobert Watson out: 3385f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3386f7b951a8SRobert Watson 3387f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3388f7b951a8SRobert Watson 338995fab37eSRobert Watson return (error); 339095fab37eSRobert Watson } 339195fab37eSRobert Watson 339295fab37eSRobert Watson /* 339395fab37eSRobert Watson * MPSAFE 339495fab37eSRobert Watson */ 339595fab37eSRobert Watson int 339695fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 339795fab37eSRobert Watson { 339895fab37eSRobert Watson struct label intlabel; 3399f7b951a8SRobert Watson struct nameidata nd; 340095fab37eSRobert Watson struct mount *mp; 3401f7b951a8SRobert Watson struct mac mac; 3402f7b951a8SRobert Watson char *buffer; 340395fab37eSRobert Watson int error; 340495fab37eSRobert Watson 3405f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 340695fab37eSRobert Watson if (error) 3407f7b951a8SRobert Watson return (error); 340895fab37eSRobert Watson 3409f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 341095fab37eSRobert Watson if (error) 3411f7b951a8SRobert Watson return (error); 341295fab37eSRobert Watson 3413f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3414f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3415f7b951a8SRobert Watson if (error) { 3416f7b951a8SRobert Watson free(buffer, M_MACTEMP); 341795fab37eSRobert Watson return (error); 341895fab37eSRobert Watson } 341995fab37eSRobert Watson 3420f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3421f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3422f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3423f7b951a8SRobert Watson if (error) { 3424f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3425f7b951a8SRobert Watson return (error); 3426f7b951a8SRobert Watson } 3427f7b951a8SRobert Watson 3428f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3429f7b951a8SRobert Watson 3430f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 3431f7b951a8SRobert Watson td); 3432f7b951a8SRobert Watson error = namei(&nd); 3433f7b951a8SRobert Watson if (error == 0) { 3434f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3435f7b951a8SRobert Watson if (error == 0) 3436f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3437f7b951a8SRobert Watson td->td_ucred); 3438f7b951a8SRobert Watson vn_finished_write(mp); 3439f7b951a8SRobert Watson } 3440f7b951a8SRobert Watson 3441f7b951a8SRobert Watson NDFREE(&nd, 0); 3442f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3443f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3444f7b951a8SRobert Watson 3445f7b951a8SRobert Watson return (error); 3446f7b951a8SRobert Watson } 3447f7b951a8SRobert Watson 3448f7b951a8SRobert Watson /* 3449f7b951a8SRobert Watson * MPSAFE 3450f7b951a8SRobert Watson */ 3451f7b951a8SRobert Watson int 3452f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3453f7b951a8SRobert Watson { 3454f7b951a8SRobert Watson struct label intlabel; 3455f7b951a8SRobert Watson struct nameidata nd; 3456f7b951a8SRobert Watson struct mount *mp; 3457f7b951a8SRobert Watson struct mac mac; 3458f7b951a8SRobert Watson char *buffer; 3459f7b951a8SRobert Watson int error; 3460f7b951a8SRobert Watson 3461f7b951a8SRobert Watson error = copyin(uap->mac_p, &mac, sizeof(mac)); 3462f7b951a8SRobert Watson if (error) 3463f7b951a8SRobert Watson return (error); 3464f7b951a8SRobert Watson 3465f7b951a8SRobert Watson error = mac_check_structmac_consistent(&mac); 3466f7b951a8SRobert Watson if (error) 3467f7b951a8SRobert Watson return (error); 3468f7b951a8SRobert Watson 3469f7b951a8SRobert Watson buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 3470f7b951a8SRobert Watson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 3471f7b951a8SRobert Watson if (error) { 3472f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3473f7b951a8SRobert Watson return (error); 3474f7b951a8SRobert Watson } 3475f7b951a8SRobert Watson 3476f7b951a8SRobert Watson mac_init_vnode_label(&intlabel); 3477f7b951a8SRobert Watson error = mac_internalize_vnode_label(&intlabel, buffer); 3478f7b951a8SRobert Watson free(buffer, M_MACTEMP); 3479f7b951a8SRobert Watson if (error) { 3480f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3481f7b951a8SRobert Watson return (error); 3482f7b951a8SRobert Watson } 3483f7b951a8SRobert Watson 3484f7b951a8SRobert Watson mtx_lock(&Giant); /* VFS */ 3485f7b951a8SRobert Watson 3486f7b951a8SRobert Watson NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 3487f7b951a8SRobert Watson td); 3488f7b951a8SRobert Watson error = namei(&nd); 3489f7b951a8SRobert Watson if (error == 0) { 3490f7b951a8SRobert Watson error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3491f7b951a8SRobert Watson if (error == 0) 3492f7b951a8SRobert Watson error = vn_setlabel(nd.ni_vp, &intlabel, 3493f7b951a8SRobert Watson td->td_ucred); 3494f7b951a8SRobert Watson vn_finished_write(mp); 3495f7b951a8SRobert Watson } 3496f7b951a8SRobert Watson 3497f7b951a8SRobert Watson NDFREE(&nd, 0); 3498f7b951a8SRobert Watson mtx_unlock(&Giant); /* VFS */ 3499f7b951a8SRobert Watson mac_destroy_vnode_label(&intlabel); 3500f7b951a8SRobert Watson 3501f7b951a8SRobert Watson return (error); 3502f7b951a8SRobert Watson } 3503f7b951a8SRobert Watson 3504f7b951a8SRobert Watson /* 3505f7b951a8SRobert Watson * MPSAFE 3506f7b951a8SRobert Watson */ 350727f2eac7SRobert Watson int 350827f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 350927f2eac7SRobert Watson { 351027f2eac7SRobert Watson struct mac_policy_conf *mpc; 351127f2eac7SRobert Watson char target[MAC_MAX_POLICY_NAME]; 351227f2eac7SRobert Watson int error; 351327f2eac7SRobert Watson 351427f2eac7SRobert Watson error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL); 351527f2eac7SRobert Watson if (error) 351627f2eac7SRobert Watson return (error); 351727f2eac7SRobert Watson 351827f2eac7SRobert Watson error = ENOSYS; 351927f2eac7SRobert Watson MAC_POLICY_LIST_BUSY(); 352027f2eac7SRobert Watson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 352127f2eac7SRobert Watson if (strcmp(mpc->mpc_name, target) == 0 && 352227f2eac7SRobert Watson mpc->mpc_ops->mpo_syscall != NULL) { 352327f2eac7SRobert Watson error = mpc->mpc_ops->mpo_syscall(td, 352427f2eac7SRobert Watson SCARG(uap, call), SCARG(uap, arg)); 352527f2eac7SRobert Watson goto out; 352627f2eac7SRobert Watson } 352727f2eac7SRobert Watson } 352827f2eac7SRobert Watson 352927f2eac7SRobert Watson out: 353027f2eac7SRobert Watson MAC_POLICY_LIST_UNBUSY(); 353127f2eac7SRobert Watson return (error); 353227f2eac7SRobert Watson } 353327f2eac7SRobert Watson 353495fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 353595fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 353695fab37eSRobert Watson 353795fab37eSRobert Watson #else /* !MAC */ 35387bc82500SRobert Watson 35397bc82500SRobert Watson int 3540f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 3541f7b951a8SRobert Watson { 3542f7b951a8SRobert Watson 3543f7b951a8SRobert Watson return (ENOSYS); 3544f7b951a8SRobert Watson } 3545f7b951a8SRobert Watson 3546f7b951a8SRobert Watson int 35477bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 35487bc82500SRobert Watson { 35497bc82500SRobert Watson 35507bc82500SRobert Watson return (ENOSYS); 35517bc82500SRobert Watson } 35527bc82500SRobert Watson 35537bc82500SRobert Watson int 35547bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 35557bc82500SRobert Watson { 35567bc82500SRobert Watson 35577bc82500SRobert Watson return (ENOSYS); 35587bc82500SRobert Watson } 35597bc82500SRobert Watson 35607bc82500SRobert Watson int 35617bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 35627bc82500SRobert Watson { 35637bc82500SRobert Watson 35647bc82500SRobert Watson return (ENOSYS); 35657bc82500SRobert Watson } 35667bc82500SRobert Watson 35677bc82500SRobert Watson int 35687bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 35697bc82500SRobert Watson { 35707bc82500SRobert Watson 35717bc82500SRobert Watson return (ENOSYS); 35727bc82500SRobert Watson } 35737bc82500SRobert Watson 35747bc82500SRobert Watson int 3575f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 3576f7b951a8SRobert Watson { 3577f7b951a8SRobert Watson 3578f7b951a8SRobert Watson return (ENOSYS); 3579f7b951a8SRobert Watson } 3580f7b951a8SRobert Watson 3581f7b951a8SRobert Watson int 35827bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 35837bc82500SRobert Watson { 35847bc82500SRobert Watson 35857bc82500SRobert Watson return (ENOSYS); 35867bc82500SRobert Watson } 35877bc82500SRobert Watson 35887bc82500SRobert Watson int 35897bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 35907bc82500SRobert Watson { 35917bc82500SRobert Watson 35927bc82500SRobert Watson return (ENOSYS); 35937bc82500SRobert Watson } 359495fab37eSRobert Watson 359527f2eac7SRobert Watson int 3596f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 3597f7b951a8SRobert Watson { 3598f7b951a8SRobert Watson 3599f7b951a8SRobert Watson return (ENOSYS); 3600f7b951a8SRobert Watson } 3601f7b951a8SRobert Watson 3602f7b951a8SRobert Watson int 360327f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap) 360427f2eac7SRobert Watson { 360527f2eac7SRobert Watson 360627f2eac7SRobert Watson return (ENOSYS); 360727f2eac7SRobert Watson } 360827f2eac7SRobert Watson 3609f7b951a8SRobert Watson #endif 3610