mac_pipe.c revision 102115
1214455Srpaulo/*- 2214455Srpaulo * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 3214455Srpaulo * Copyright (c) 2001 Ilmar S. Habibulin 4214455Srpaulo * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 5214455Srpaulo * All rights reserved. 6214455Srpaulo * 7214455Srpaulo * This software was developed by Robert Watson and Ilmar Habibulin for the 8214455Srpaulo * TrustedBSD Project. 9214455Srpaulo * 10214455Srpaulo * This software was developed for the FreeBSD Project in part by NAI Labs, 11214455Srpaulo * the Security Research Division of Network Associates, Inc. under 12214455Srpaulo * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 13214455Srpaulo * CHATS research program. 14214455Srpaulo * 15214455Srpaulo * Redistribution and use in source and binary forms, with or without 16214455Srpaulo * modification, are permitted provided that the following conditions 17214455Srpaulo * are met: 18214455Srpaulo * 1. Redistributions of source code must retain the above copyright 19214455Srpaulo * notice, this list of conditions and the following disclaimer. 20214455Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 21235426Sdelphij * notice, this list of conditions and the following disclaimer in the 22214455Srpaulo * documentation and/or other materials provided with the distribution. 23214455Srpaulo * 3. The names of the authors may not be used to endorse or promote 24214455Srpaulo * products derived from this software without specific prior written 25214455Srpaulo * permission. 26214455Srpaulo * 27214455Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 28214455Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29214455Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30214455Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 31214455Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32214455Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33214455Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34214455Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35214455Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36214455Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37214455Srpaulo * SUCH DAMAGE. 38214455Srpaulo * 39214455Srpaulo * $FreeBSD: head/sys/security/mac/mac_pipe.c 102115 2002-08-19 16:59:37Z rwatson $ 40214455Srpaulo */ 41214455Srpaulo/* 42214455Srpaulo * Developed by the TrustedBSD Project. 43214455Srpaulo * 44214455Srpaulo * Framework for extensible kernel access control. Kernel and userland 45214455Srpaulo * interface to the framework, policy registration and composition. 46214455Srpaulo */ 47214455Srpaulo 48214455Srpaulo#include "opt_mac.h" 49214455Srpaulo 50214455Srpaulo#include <sys/param.h> 51214455Srpaulo#include <sys/extattr.h> 52214455Srpaulo#include <sys/kernel.h> 53214455Srpaulo#include <sys/lock.h> 54214455Srpaulo#include <sys/mutex.h> 55214455Srpaulo#include <sys/sx.h> 56214455Srpaulo#include <sys/mac.h> 57214455Srpaulo#include <sys/module.h> 58214455Srpaulo#include <sys/proc.h> 59214455Srpaulo#include <sys/systm.h> 60214455Srpaulo#include <sys/sysproto.h> 61214455Srpaulo#include <sys/sysent.h> 62214455Srpaulo#include <sys/vnode.h> 63214455Srpaulo#include <sys/mount.h> 64214455Srpaulo#include <sys/file.h> 65214455Srpaulo#include <sys/namei.h> 66214455Srpaulo#include <sys/socket.h> 67214455Srpaulo#include <sys/pipe.h> 68214455Srpaulo#include <sys/socketvar.h> 69214455Srpaulo#include <sys/sx.h> 70214455Srpaulo#include <sys/sysctl.h> 71214455Srpaulo 72214455Srpaulo#include <vm/vm.h> 73214455Srpaulo#include <vm/pmap.h> 74214455Srpaulo#include <vm/vm_map.h> 75214455Srpaulo#include <vm/vm_object.h> 76214455Srpaulo 77214455Srpaulo#include <sys/mac_policy.h> 78214455Srpaulo 79214455Srpaulo#include <fs/devfs/devfs.h> 80214455Srpaulo 81214455Srpaulo#include <net/bpf.h> 82214455Srpaulo#include <net/bpfdesc.h> 83214455Srpaulo#include <net/if.h> 84214455Srpaulo#include <net/if_var.h> 85214455Srpaulo 86214455Srpaulo#include <netinet/in.h> 87214455Srpaulo#include <netinet/ip_var.h> 88214455Srpaulo 89214455Srpaulo#ifdef MAC 90214455Srpaulo 91214455Srpaulo/* 92214455Srpaulo * Declare that the kernel provides MAC support, version 1. This permits 93214455Srpaulo * modules to refuse to be loaded if the necessary support isn't present, 94214455Srpaulo * even if it's pre-boot. 95214455Srpaulo */ 96214455SrpauloMODULE_VERSION(kernel_mac_support, 1); 97235426Sdelphij 98235426SdelphijSYSCTL_DECL(_security); 99235426Sdelphij 100235426SdelphijSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 101235426Sdelphij "TrustedBSD MAC policy controls"); 102235426SdelphijSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 103235426Sdelphij "TrustedBSD MAC debug info"); 104235426Sdelphij 105235426Sdelphijstatic int mac_debug_label_fallback = 0; 106235426SdelphijSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW, 107235426Sdelphij &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label" 108235426Sdelphij "when label is corrupted."); 109235426SdelphijTUNABLE_INT("security.mac.debug_label_fallback", 110235426Sdelphij &mac_debug_label_fallback); 111235426Sdelphij 112235426Sdelphij#ifndef MAC_MAX_POLICIES 113235426Sdelphij#define MAC_MAX_POLICIES 8 114214455Srpaulo#endif 115214455Srpaulo#if MAC_MAX_POLICIES > 32 116214455Srpaulo#error "MAC_MAX_POLICIES too large" 117214455Srpaulo#endif 118214455Srpaulostatic unsigned int mac_max_policies = MAC_MAX_POLICIES; 119214455Srpaulostatic unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1; 120214455SrpauloSYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, 121214455Srpaulo &mac_max_policies, 0, ""); 122235426Sdelphij 123214455Srpaulostatic int mac_late = 0; 124214455Srpaulo 125214455Srpaulostatic int mac_enforce_fs = 1; 126214455SrpauloSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, 127214455Srpaulo &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); 128214455SrpauloTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs); 129214455Srpaulo 130214455Srpaulostatic int mac_enforce_network = 1; 131214455SrpauloSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW, 132214455Srpaulo &mac_enforce_network, 0, "Enforce MAC policy on network packets"); 133214455SrpauloTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network); 134214455Srpaulo 135214455Srpaulostatic int mac_enforce_process = 1; 136214455SrpauloSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW, 137214455Srpaulo &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations"); 138214455SrpauloTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process); 139214455Srpaulo 140214455Srpaulostatic int mac_enforce_socket = 1; 141214455SrpauloSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 142214455Srpaulo &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 143214455SrpauloTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 144214455Srpaulo 145214455Srpaulostatic int mac_enforce_pipe = 1; 146214455SrpauloSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 147214455Srpaulo &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 148235426Sdelphij 149235426Sdelphijstatic int mac_label_size = sizeof(struct mac); 150235426SdelphijSYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, 151235426Sdelphij &mac_label_size, 0, "Pre-compiled MAC label size"); 152235426Sdelphij 153235426Sdelphijstatic int mac_cache_fslabel_in_vnode = 1; 154214455SrpauloSYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, 155214455Srpaulo &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); 156214455SrpauloTUNABLE_INT("security.mac.cache_fslabel_in_vnode", 157214455Srpaulo &mac_cache_fslabel_in_vnode); 158235426Sdelphij 159235426Sdelphijstatic int mac_vnode_label_cache_hits = 0; 160235426SdelphijSYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, 161235426Sdelphij &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); 162235426Sdelphijstatic int mac_vnode_label_cache_misses = 0; 163235426SdelphijSYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, 164235426Sdelphij &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); 165235426Sdelphijstatic int mac_mmap_revocation_via_cow = 0; 166235426SdelphijSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW, 167235426Sdelphij &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via " 168235426Sdelphij "copy-on-write semantics, or by removing all write access"); 169235426Sdelphij 170235426Sdelphij#ifdef MAC_DEBUG 171214455Srpaulostatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs, 172214455Srpaulo nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents, 173214455Srpaulo nmacipqs, nmacpipes; 174214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, mbufs, CTLFLAG_RD, 175214455Srpaulo &nmacmbufs, 0, "number of mbufs in use"); 176214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, creds, CTLFLAG_RD, 177214455Srpaulo &nmaccreds, 0, "number of ucreds in use"); 178214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, ifnets, CTLFLAG_RD, 179214455Srpaulo &nmacifnets, 0, "number of ifnets in use"); 180214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, ipqs, CTLFLAG_RD, 181214455Srpaulo &nmacipqs, 0, "number of ipqs in use"); 182214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, bpfdescs, CTLFLAG_RD, 183214455Srpaulo &nmacbpfdescs, 0, "number of bpfdescs in use"); 184214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, sockets, CTLFLAG_RD, 185214455Srpaulo &nmacsockets, 0, "number of sockets in use"); 186214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, pipes, CTLFLAG_RD, 187214455Srpaulo &nmacpipes, 0, "number of pipes in use"); 188214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, mounts, CTLFLAG_RD, 189214455Srpaulo &nmacmounts, 0, "number of mounts in use"); 190214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, temp, CTLFLAG_RD, 191214455Srpaulo &nmactemp, 0, "number of temporary labels in use"); 192214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, vnodes, CTLFLAG_RD, 193214455Srpaulo &nmacvnodes, 0, "number of vnodes in use"); 194214455SrpauloSYSCTL_UINT(_security_mac_debug, OID_AUTO, devfsdirents, CTLFLAG_RD, 195214455Srpaulo &nmacdevfsdirents, 0, "number of devfs dirents inuse"); 196214455Srpaulo#endif 197214455Srpaulo 198214455Srpaulostatic int error_select(int error1, int error2); 199214455Srpaulostatic int mac_externalize(struct label *label, struct mac *mac); 200214455Srpaulostatic int mac_policy_register(struct mac_policy_conf *mpc); 201214455Srpaulostatic int mac_policy_unregister(struct mac_policy_conf *mpc); 202214455Srpaulo 203214455Srpaulostatic int mac_stdcreatevnode_ea(struct vnode *vp); 204214455Srpaulostatic void mac_cred_mmapped_drop_perms(struct thread *td, 205214455Srpaulo struct ucred *cred); 206214455Srpaulostatic void mac_cred_mmapped_drop_perms_recurse(struct thread *td, 207214455Srpaulo struct ucred *cred, struct vm_map *map); 208214455Srpaulo 209214455SrpauloMALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); 210214455SrpauloMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 211214455Srpaulo 212214455Srpaulo/* 213214455Srpaulo * mac_policy_list_lock protects the consistency of 'mac_policy_list', 214214455Srpaulo * the linked list of attached policy modules. Read-only consumers of 215214455Srpaulo * the list must acquire a shared lock for the duration of their use; 216214455Srpaulo * writers must acquire an exclusive lock. Note that for compound 217214455Srpaulo * operations, locks should be held for the entire compound operation, 218214455Srpaulo * and that this is not yet done for relabel requests. 219214455Srpaulo */ 220214455Srpaulostatic struct mtx mac_policy_list_lock; 221214455Srpaulostatic LIST_HEAD(, mac_policy_conf) mac_policy_list; 222214455Srpaulostatic int mac_policy_list_busy; 223214455Srpaulo#define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \ 224214455Srpaulo "mac_policy_list_lock", NULL, MTX_DEF); 225214455Srpaulo#define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock); 226214455Srpaulo#define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock); 227214455Srpaulo 228214455Srpaulo#define MAC_POLICY_LIST_BUSY() do { \ 229214455Srpaulo MAC_POLICY_LIST_LOCK(); \ 230214455Srpaulo mac_policy_list_busy++; \ 231214455Srpaulo MAC_POLICY_LIST_UNLOCK(); \ 232214455Srpaulo} while (0) 233214455Srpaulo 234214455Srpaulo#define MAC_POLICY_LIST_UNBUSY() do { \ 235214455Srpaulo MAC_POLICY_LIST_LOCK(); \ 236214455Srpaulo mac_policy_list_busy--; \ 237214455Srpaulo if (mac_policy_list_busy < 0) \ 238214455Srpaulo panic("Extra mac_policy_list_busy--"); \ 239214455Srpaulo MAC_POLICY_LIST_UNLOCK(); \ 240214455Srpaulo} while (0) 241214455Srpaulo 242214455Srpaulo/* 243214455Srpaulo * MAC_CHECK performs the designated check by walking the policy 244214455Srpaulo * module list and checking with each as to how it feels about the 245214455Srpaulo * request. Note that it returns its value via 'error' in the scope 246214455Srpaulo * of the caller. 247214455Srpaulo */ 248214455Srpaulo#define MAC_CHECK(check, args...) do { \ 249214455Srpaulo struct mac_policy_conf *mpc; \ 250214455Srpaulo \ 251214455Srpaulo error = 0; \ 252214455Srpaulo MAC_POLICY_LIST_BUSY(); \ 253214455Srpaulo LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 254214455Srpaulo if (mpc->mpc_ops->mpo_ ## check != NULL) \ 255214455Srpaulo error = error_select( \ 256214455Srpaulo mpc->mpc_ops->mpo_ ## check (args), \ 257214455Srpaulo error); \ 258214455Srpaulo } \ 259214455Srpaulo MAC_POLICY_LIST_UNBUSY(); \ 260214455Srpaulo} while (0) 261214455Srpaulo 262214455Srpaulo/* 263214455Srpaulo * MAC_BOOLEAN performs the designated boolean composition by walking 264214455Srpaulo * the module list, invoking each instance of the operation, and 265214455Srpaulo * combining the results using the passed C operator. Note that it 266214455Srpaulo * returns its value via 'result' in the scope of the caller, which 267214455Srpaulo * should be initialized by the caller in a meaningful way to get 268214455Srpaulo * a meaningful result. 269214455Srpaulo */ 270214455Srpaulo#define MAC_BOOLEAN(operation, composition, args...) do { \ 271214455Srpaulo struct mac_policy_conf *mpc; \ 272214455Srpaulo \ 273214455Srpaulo MAC_POLICY_LIST_BUSY(); \ 274214455Srpaulo LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 275214455Srpaulo if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 276214455Srpaulo result = result composition \ 277214455Srpaulo mpc->mpc_ops->mpo_ ## operation (args); \ 278214455Srpaulo } \ 279214455Srpaulo MAC_POLICY_LIST_UNBUSY(); \ 280214455Srpaulo} while (0) 281214455Srpaulo 282214455Srpaulo/* 283214455Srpaulo * MAC_PERFORM performs the designated operation by walking the policy 284214455Srpaulo * module list and invoking that operation for each policy. 285214455Srpaulo */ 286214455Srpaulo#define MAC_PERFORM(operation, args...) do { \ 287214455Srpaulo struct mac_policy_conf *mpc; \ 288214455Srpaulo \ 289214455Srpaulo MAC_POLICY_LIST_BUSY(); \ 290214455Srpaulo LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \ 291214455Srpaulo if (mpc->mpc_ops->mpo_ ## operation != NULL) \ 292214455Srpaulo mpc->mpc_ops->mpo_ ## operation (args); \ 293214455Srpaulo } \ 294214455Srpaulo MAC_POLICY_LIST_UNBUSY(); \ 295214455Srpaulo} while (0) 296214455Srpaulo 297214455Srpaulo/* 298214455Srpaulo * Initialize the MAC subsystem, including appropriate SMP locks. 299214455Srpaulo */ 300214455Srpaulostatic void 301214455Srpaulomac_init(void) 302214455Srpaulo{ 303214455Srpaulo 304214455Srpaulo LIST_INIT(&mac_policy_list); 305214455Srpaulo MAC_POLICY_LIST_LOCKINIT(); 306214455Srpaulo} 307214455Srpaulo 308214455Srpaulo/* 309214455Srpaulo * For the purposes of modules that want to know if they were loaded 310214455Srpaulo * "early", set the mac_late flag once we've processed modules either 311214455Srpaulo * linked into the kernel, or loaded before the kernel startup. 312214455Srpaulo */ 313214455Srpaulostatic void 314214455Srpaulomac_late_init(void) 315214455Srpaulo{ 316214455Srpaulo 317214455Srpaulo mac_late = 1; 318214455Srpaulo} 319214455Srpaulo 320214455Srpaulo/* 321214455Srpaulo * Allow MAC policy modules to register during boot, etc. 322214455Srpaulo */ 323214455Srpauloint 324214455Srpaulomac_policy_modevent(module_t mod, int type, void *data) 325214455Srpaulo{ 326214455Srpaulo struct mac_policy_conf *mpc; 327214455Srpaulo int error; 328214455Srpaulo 329214455Srpaulo error = 0; 330214455Srpaulo mpc = (struct mac_policy_conf *) data; 331214455Srpaulo 332214455Srpaulo switch (type) { 333214455Srpaulo case MOD_LOAD: 334214455Srpaulo if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 335214455Srpaulo mac_late) { 336214455Srpaulo printf("mac_policy_modevent: can't load %s policy " 337214455Srpaulo "after booting\n", mpc->mpc_name); 338214455Srpaulo error = EBUSY; 339214455Srpaulo break; 340214455Srpaulo } 341214455Srpaulo error = mac_policy_register(mpc); 342214455Srpaulo break; 343214455Srpaulo case MOD_UNLOAD: 344214455Srpaulo /* Don't unregister the module if it was never registered. */ 345214455Srpaulo if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 346214455Srpaulo != 0) 347214455Srpaulo error = mac_policy_unregister(mpc); 348214455Srpaulo else 349214455Srpaulo error = 0; 350214455Srpaulo break; 351214455Srpaulo default: 352214455Srpaulo break; 353214455Srpaulo } 354214455Srpaulo 355214455Srpaulo return (error); 356214455Srpaulo} 357214455Srpaulo 358214455Srpaulostatic int 359214455Srpaulomac_policy_register(struct mac_policy_conf *mpc) 360214455Srpaulo{ 361214455Srpaulo struct mac_policy_conf *tmpc; 362214455Srpaulo struct mac_policy_ops *ops; 363214455Srpaulo struct mac_policy_op_entry *mpe; 364214455Srpaulo int slot; 365214455Srpaulo 366214455Srpaulo MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*ops), M_MACOPVEC, 367214455Srpaulo M_WAITOK | M_ZERO); 368214455Srpaulo for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) { 369214455Srpaulo switch (mpe->mpe_constant) { 370214455Srpaulo case MAC_OP_LAST: 371214455Srpaulo /* 372214455Srpaulo * Doesn't actually happen, but this allows checking 373214455Srpaulo * that all enumerated values are handled. 374214455Srpaulo */ 375214455Srpaulo break; 376214455Srpaulo case MAC_DESTROY: 377214455Srpaulo mpc->mpc_ops->mpo_destroy = 378214455Srpaulo mpe->mpe_function; 379214455Srpaulo break; 380214455Srpaulo case MAC_INIT: 381214455Srpaulo mpc->mpc_ops->mpo_init = 382214455Srpaulo mpe->mpe_function; 383214455Srpaulo break; 384214455Srpaulo case MAC_INIT_BPFDESC: 385214455Srpaulo mpc->mpc_ops->mpo_init_bpfdesc = 386214455Srpaulo mpe->mpe_function; 387214455Srpaulo break; 388214455Srpaulo case MAC_INIT_CRED: 389214455Srpaulo mpc->mpc_ops->mpo_init_cred = 390214455Srpaulo mpe->mpe_function; 391214455Srpaulo break; 392214455Srpaulo case MAC_INIT_DEVFSDIRENT: 393214455Srpaulo mpc->mpc_ops->mpo_init_devfsdirent = 394214455Srpaulo mpe->mpe_function; 395214455Srpaulo break; 396214455Srpaulo case MAC_INIT_IFNET: 397214455Srpaulo mpc->mpc_ops->mpo_init_ifnet = 398214455Srpaulo mpe->mpe_function; 399214455Srpaulo break; 400214455Srpaulo case MAC_INIT_IPQ: 401214455Srpaulo mpc->mpc_ops->mpo_init_ipq = 402214455Srpaulo mpe->mpe_function; 403214455Srpaulo break; 404214455Srpaulo case MAC_INIT_MBUF: 405214455Srpaulo mpc->mpc_ops->mpo_init_mbuf = 406214455Srpaulo mpe->mpe_function; 407214455Srpaulo break; 408214455Srpaulo case MAC_INIT_MOUNT: 409214455Srpaulo mpc->mpc_ops->mpo_init_mount = 410214455Srpaulo mpe->mpe_function; 411214455Srpaulo break; 412214455Srpaulo case MAC_INIT_PIPE: 413214455Srpaulo mpc->mpc_ops->mpo_init_pipe = 414214455Srpaulo mpe->mpe_function; 415214455Srpaulo break; 416214455Srpaulo case MAC_INIT_SOCKET: 417214455Srpaulo mpc->mpc_ops->mpo_init_socket = 418214455Srpaulo mpe->mpe_function; 419214455Srpaulo break; 420214455Srpaulo case MAC_INIT_TEMP: 421214455Srpaulo mpc->mpc_ops->mpo_init_temp = 422214455Srpaulo mpe->mpe_function; 423214455Srpaulo break; 424214455Srpaulo case MAC_INIT_VNODE: 425214455Srpaulo mpc->mpc_ops->mpo_init_vnode = 426214455Srpaulo mpe->mpe_function; 427214455Srpaulo break; 428214455Srpaulo case MAC_DESTROY_BPFDESC: 429214455Srpaulo mpc->mpc_ops->mpo_destroy_bpfdesc = 430214455Srpaulo mpe->mpe_function; 431214455Srpaulo break; 432214455Srpaulo case MAC_DESTROY_CRED: 433214455Srpaulo mpc->mpc_ops->mpo_destroy_cred = 434214455Srpaulo mpe->mpe_function; 435214455Srpaulo break; 436214455Srpaulo case MAC_DESTROY_DEVFSDIRENT: 437214455Srpaulo mpc->mpc_ops->mpo_destroy_devfsdirent = 438214455Srpaulo mpe->mpe_function; 439214455Srpaulo break; 440214455Srpaulo case MAC_DESTROY_IFNET: 441214455Srpaulo mpc->mpc_ops->mpo_destroy_ifnet = 442214455Srpaulo mpe->mpe_function; 443214455Srpaulo break; 444214455Srpaulo case MAC_DESTROY_IPQ: 445214455Srpaulo mpc->mpc_ops->mpo_destroy_ipq = 446214455Srpaulo mpe->mpe_function; 447214455Srpaulo break; 448214455Srpaulo case MAC_DESTROY_MBUF: 449214455Srpaulo mpc->mpc_ops->mpo_destroy_mbuf = 450214455Srpaulo mpe->mpe_function; 451214455Srpaulo break; 452214455Srpaulo case MAC_DESTROY_MOUNT: 453214455Srpaulo mpc->mpc_ops->mpo_destroy_mount = 454214455Srpaulo mpe->mpe_function; 455214455Srpaulo break; 456214455Srpaulo case MAC_DESTROY_PIPE: 457214455Srpaulo mpc->mpc_ops->mpo_destroy_pipe = 458214455Srpaulo mpe->mpe_function; 459214455Srpaulo break; 460214455Srpaulo case MAC_DESTROY_SOCKET: 461214455Srpaulo mpc->mpc_ops->mpo_destroy_socket = 462214455Srpaulo mpe->mpe_function; 463214455Srpaulo break; 464214455Srpaulo case MAC_DESTROY_TEMP: 465214455Srpaulo mpc->mpc_ops->mpo_destroy_temp = 466214455Srpaulo mpe->mpe_function; 467214455Srpaulo break; 468214455Srpaulo case MAC_DESTROY_VNODE: 469214455Srpaulo mpc->mpc_ops->mpo_destroy_vnode = 470214455Srpaulo mpe->mpe_function; 471214455Srpaulo break; 472214455Srpaulo case MAC_EXTERNALIZE: 473214455Srpaulo mpc->mpc_ops->mpo_externalize = 474214455Srpaulo mpe->mpe_function; 475214455Srpaulo break; 476214455Srpaulo case MAC_INTERNALIZE: 477214455Srpaulo mpc->mpc_ops->mpo_internalize = 478214455Srpaulo mpe->mpe_function; 479214455Srpaulo break; 480214455Srpaulo case MAC_CREATE_DEVFS_DEVICE: 481214455Srpaulo mpc->mpc_ops->mpo_create_devfs_device = 482214455Srpaulo mpe->mpe_function; 483214455Srpaulo break; 484214455Srpaulo case MAC_CREATE_DEVFS_DIRECTORY: 485214455Srpaulo mpc->mpc_ops->mpo_create_devfs_directory = 486214455Srpaulo mpe->mpe_function; 487214455Srpaulo break; 488214455Srpaulo case MAC_CREATE_DEVFS_VNODE: 489214455Srpaulo mpc->mpc_ops->mpo_create_devfs_vnode = 490214455Srpaulo mpe->mpe_function; 491214455Srpaulo break; 492214455Srpaulo case MAC_STDCREATEVNODE_EA: 493214455Srpaulo mpc->mpc_ops->mpo_stdcreatevnode_ea = 494214455Srpaulo mpe->mpe_function; 495214455Srpaulo break; 496214455Srpaulo case MAC_CREATE_VNODE: 497214455Srpaulo mpc->mpc_ops->mpo_create_vnode = 498214455Srpaulo mpe->mpe_function; 499214455Srpaulo break; 500214455Srpaulo case MAC_CREATE_MOUNT: 501214455Srpaulo mpc->mpc_ops->mpo_create_mount = 502214455Srpaulo mpe->mpe_function; 503214455Srpaulo break; 504214455Srpaulo case MAC_CREATE_ROOT_MOUNT: 505214455Srpaulo mpc->mpc_ops->mpo_create_root_mount = 506214455Srpaulo mpe->mpe_function; 507214455Srpaulo break; 508214455Srpaulo case MAC_RELABEL_VNODE: 509214455Srpaulo mpc->mpc_ops->mpo_relabel_vnode = 510214455Srpaulo mpe->mpe_function; 511214455Srpaulo break; 512214455Srpaulo case MAC_UPDATE_DEVFSDIRENT: 513214455Srpaulo mpc->mpc_ops->mpo_update_devfsdirent = 514214455Srpaulo mpe->mpe_function; 515214455Srpaulo break; 516214455Srpaulo case MAC_UPDATE_PROCFSVNODE: 517214455Srpaulo mpc->mpc_ops->mpo_update_procfsvnode = 518214455Srpaulo mpe->mpe_function; 519214455Srpaulo break; 520214455Srpaulo case MAC_UPDATE_VNODE_FROM_EXTATTR: 521214455Srpaulo mpc->mpc_ops->mpo_update_vnode_from_extattr = 522214455Srpaulo mpe->mpe_function; 523214455Srpaulo break; 524214455Srpaulo case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: 525214455Srpaulo mpc->mpc_ops->mpo_update_vnode_from_externalized = 526214455Srpaulo mpe->mpe_function; 527214455Srpaulo break; 528214455Srpaulo case MAC_UPDATE_VNODE_FROM_MOUNT: 529214455Srpaulo mpc->mpc_ops->mpo_update_vnode_from_mount = 530214455Srpaulo mpe->mpe_function; 531214455Srpaulo break; 532214455Srpaulo case MAC_CREATE_MBUF_FROM_SOCKET: 533214455Srpaulo mpc->mpc_ops->mpo_create_mbuf_from_socket = 534214455Srpaulo mpe->mpe_function; 535214455Srpaulo break; 536214455Srpaulo case MAC_CREATE_PIPE: 537214455Srpaulo mpc->mpc_ops->mpo_create_pipe = 538214455Srpaulo mpe->mpe_function; 539214455Srpaulo break; 540214455Srpaulo case MAC_CREATE_SOCKET: 541214455Srpaulo mpc->mpc_ops->mpo_create_socket = 542214455Srpaulo mpe->mpe_function; 543214455Srpaulo break; 544214455Srpaulo case MAC_CREATE_SOCKET_FROM_SOCKET: 545214455Srpaulo mpc->mpc_ops->mpo_create_socket_from_socket = 546214455Srpaulo mpe->mpe_function; 547214455Srpaulo break; 548214455Srpaulo case MAC_RELABEL_PIPE: 549214455Srpaulo mpc->mpc_ops->mpo_relabel_pipe = 550214455Srpaulo mpe->mpe_function; 551214455Srpaulo break; 552214455Srpaulo case MAC_RELABEL_SOCKET: 553214455Srpaulo mpc->mpc_ops->mpo_relabel_socket = 554214455Srpaulo mpe->mpe_function; 555214455Srpaulo break; 556214455Srpaulo case MAC_SET_SOCKET_PEER_FROM_MBUF: 557214455Srpaulo mpc->mpc_ops->mpo_set_socket_peer_from_mbuf = 558214455Srpaulo mpe->mpe_function; 559214455Srpaulo break; 560214455Srpaulo case MAC_SET_SOCKET_PEER_FROM_SOCKET: 561214455Srpaulo mpc->mpc_ops->mpo_set_socket_peer_from_socket = 562214455Srpaulo mpe->mpe_function; 563214455Srpaulo break; 564214455Srpaulo case MAC_CREATE_BPFDESC: 565214455Srpaulo mpc->mpc_ops->mpo_create_bpfdesc = 566214455Srpaulo mpe->mpe_function; 567214455Srpaulo break; 568214455Srpaulo case MAC_CREATE_DATAGRAM_FROM_IPQ: 569214455Srpaulo mpc->mpc_ops->mpo_create_datagram_from_ipq = 570214455Srpaulo mpe->mpe_function; 571235426Sdelphij break; 572214455Srpaulo case MAC_CREATE_FRAGMENT: 573214455Srpaulo mpc->mpc_ops->mpo_create_fragment = 574214455Srpaulo mpe->mpe_function; 575214455Srpaulo break; 576214455Srpaulo case MAC_CREATE_IFNET: 577235426Sdelphij mpc->mpc_ops->mpo_create_ifnet = 578214455Srpaulo mpe->mpe_function; 579214455Srpaulo break; 580214455Srpaulo case MAC_CREATE_IPQ: 581214455Srpaulo mpc->mpc_ops->mpo_create_ipq = 582214455Srpaulo mpe->mpe_function; 583214455Srpaulo break; 584235426Sdelphij case MAC_CREATE_MBUF_FROM_MBUF: 585214455Srpaulo mpc->mpc_ops->mpo_create_mbuf_from_mbuf = 586214455Srpaulo mpe->mpe_function; 587214455Srpaulo break; 588214455Srpaulo case MAC_CREATE_MBUF_LINKLAYER: 589214455Srpaulo mpc->mpc_ops->mpo_create_mbuf_linklayer = 590214455Srpaulo mpe->mpe_function; 591235426Sdelphij break; 592214455Srpaulo case MAC_CREATE_MBUF_FROM_BPFDESC: 593214455Srpaulo mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc = 594214455Srpaulo mpe->mpe_function; 595214455Srpaulo break; 596214455Srpaulo case MAC_CREATE_MBUF_FROM_IFNET: 597235426Sdelphij mpc->mpc_ops->mpo_create_mbuf_from_ifnet = 598214455Srpaulo mpe->mpe_function; 599214455Srpaulo break; 600214455Srpaulo case MAC_CREATE_MBUF_MULTICAST_ENCAP: 601214455Srpaulo mpc->mpc_ops->mpo_create_mbuf_multicast_encap = 602214455Srpaulo mpe->mpe_function; 603235426Sdelphij break; 604214455Srpaulo case MAC_CREATE_MBUF_NETLAYER: 605214455Srpaulo mpc->mpc_ops->mpo_create_mbuf_netlayer = 606214455Srpaulo mpe->mpe_function; 607214455Srpaulo break; 608214455Srpaulo case MAC_FRAGMENT_MATCH: 609214455Srpaulo mpc->mpc_ops->mpo_fragment_match = 610214455Srpaulo mpe->mpe_function; 611214455Srpaulo break; 612214455Srpaulo case MAC_RELABEL_IFNET: 613214455Srpaulo mpc->mpc_ops->mpo_relabel_ifnet = 614214455Srpaulo mpe->mpe_function; 615214455Srpaulo break; 616214455Srpaulo case MAC_UPDATE_IPQ: 617214455Srpaulo mpc->mpc_ops->mpo_update_ipq = 618214455Srpaulo mpe->mpe_function; 619214455Srpaulo break; 620214455Srpaulo case MAC_CREATE_CRED: 621214455Srpaulo mpc->mpc_ops->mpo_create_cred = 622235426Sdelphij mpe->mpe_function; 623214455Srpaulo break; 624214455Srpaulo case MAC_EXECVE_TRANSITION: 625214455Srpaulo mpc->mpc_ops->mpo_execve_transition = 626214455Srpaulo mpe->mpe_function; 627214455Srpaulo break; 628214455Srpaulo case MAC_EXECVE_WILL_TRANSITION: 629235426Sdelphij mpc->mpc_ops->mpo_execve_will_transition = 630235426Sdelphij mpe->mpe_function; 631214455Srpaulo break; 632214455Srpaulo case MAC_CREATE_PROC0: 633214455Srpaulo mpc->mpc_ops->mpo_create_proc0 = mpe->mpe_function; 634214455Srpaulo break; 635214455Srpaulo case MAC_CREATE_PROC1: 636214455Srpaulo mpc->mpc_ops->mpo_create_proc1 = mpe->mpe_function; 637235426Sdelphij break; 638214455Srpaulo case MAC_RELABEL_CRED: 639214455Srpaulo mpc->mpc_ops->mpo_relabel_cred = 640214455Srpaulo mpe->mpe_function; 641214455Srpaulo break; 642214455Srpaulo case MAC_CHECK_BPFDESC_RECEIVE: 643214455Srpaulo mpc->mpc_ops->mpo_check_bpfdesc_receive = 644214455Srpaulo mpe->mpe_function; 645214455Srpaulo break; 646214455Srpaulo case MAC_CHECK_CRED_RELABEL: 647214455Srpaulo mpc->mpc_ops->mpo_check_cred_relabel = 648214455Srpaulo mpe->mpe_function; 649235426Sdelphij break; 650214455Srpaulo case MAC_CHECK_CRED_VISIBLE: 651214455Srpaulo mpc->mpc_ops->mpo_check_cred_visible = 652214455Srpaulo mpe->mpe_function; 653214455Srpaulo break; 654214455Srpaulo case MAC_CHECK_IFNET_RELABEL: 655214455Srpaulo mpc->mpc_ops->mpo_check_ifnet_relabel = 656214455Srpaulo mpe->mpe_function; 657214455Srpaulo break; 658214455Srpaulo case MAC_CHECK_IFNET_TRANSMIT: 659214455Srpaulo mpc->mpc_ops->mpo_check_ifnet_transmit = 660235426Sdelphij mpe->mpe_function; 661214455Srpaulo break; 662214455Srpaulo case MAC_CHECK_MOUNT_STAT: 663214455Srpaulo mpc->mpc_ops->mpo_check_mount_stat = 664214455Srpaulo mpe->mpe_function; 665214455Srpaulo break; 666214455Srpaulo case MAC_CHECK_PIPE_IOCTL: 667214455Srpaulo mpc->mpc_ops->mpo_check_pipe_ioctl = 668214455Srpaulo mpe->mpe_function; 669235426Sdelphij break; 670214455Srpaulo case MAC_CHECK_PIPE_POLL: 671214455Srpaulo mpc->mpc_ops->mpo_check_pipe_poll = 672214455Srpaulo mpe->mpe_function; 673214455Srpaulo break; 674214455Srpaulo case MAC_CHECK_PIPE_READ: 675235426Sdelphij mpc->mpc_ops->mpo_check_pipe_read = 676214455Srpaulo mpe->mpe_function; 677214455Srpaulo break; 678214455Srpaulo case MAC_CHECK_PIPE_RELABEL: 679214455Srpaulo mpc->mpc_ops->mpo_check_pipe_relabel = 680214455Srpaulo mpe->mpe_function; 681214455Srpaulo break; 682214455Srpaulo case MAC_CHECK_PIPE_STAT: 683214455Srpaulo mpc->mpc_ops->mpo_check_pipe_stat = 684214455Srpaulo mpe->mpe_function; 685214455Srpaulo break; 686214455Srpaulo case MAC_CHECK_PIPE_WRITE: 687214455Srpaulo mpc->mpc_ops->mpo_check_pipe_write = 688214455Srpaulo mpe->mpe_function; 689214455Srpaulo break; 690214455Srpaulo case MAC_CHECK_PROC_DEBUG: 691214455Srpaulo mpc->mpc_ops->mpo_check_proc_debug = 692214455Srpaulo mpe->mpe_function; 693214455Srpaulo break; 694214455Srpaulo case MAC_CHECK_PROC_SCHED: 695214455Srpaulo mpc->mpc_ops->mpo_check_proc_sched = 696214455Srpaulo mpe->mpe_function; 697214455Srpaulo break; 698214455Srpaulo case MAC_CHECK_PROC_SIGNAL: 699214455Srpaulo mpc->mpc_ops->mpo_check_proc_signal = 700214455Srpaulo mpe->mpe_function; 701214455Srpaulo break; 702214455Srpaulo case MAC_CHECK_SOCKET_BIND: 703214455Srpaulo mpc->mpc_ops->mpo_check_socket_bind = 704214455Srpaulo mpe->mpe_function; 705214455Srpaulo break; 706214455Srpaulo case MAC_CHECK_SOCKET_CONNECT: 707214455Srpaulo mpc->mpc_ops->mpo_check_socket_connect = 708214455Srpaulo mpe->mpe_function; 709214455Srpaulo break; 710214455Srpaulo case MAC_CHECK_SOCKET_DELIVER: 711214455Srpaulo mpc->mpc_ops->mpo_check_socket_deliver = 712214455Srpaulo mpe->mpe_function; 713214455Srpaulo break; 714214455Srpaulo case MAC_CHECK_SOCKET_LISTEN: 715214455Srpaulo mpc->mpc_ops->mpo_check_socket_listen = 716214455Srpaulo mpe->mpe_function; 717214455Srpaulo break; 718214455Srpaulo case MAC_CHECK_SOCKET_RELABEL: 719214455Srpaulo mpc->mpc_ops->mpo_check_socket_relabel = 720214455Srpaulo mpe->mpe_function; 721214455Srpaulo break; 722214455Srpaulo case MAC_CHECK_SOCKET_VISIBLE: 723214455Srpaulo mpc->mpc_ops->mpo_check_socket_visible = 724214455Srpaulo mpe->mpe_function; 725214455Srpaulo break; 726214455Srpaulo case MAC_CHECK_VNODE_ACCESS: 727214455Srpaulo mpc->mpc_ops->mpo_check_vnode_access = 728214455Srpaulo mpe->mpe_function; 729214455Srpaulo break; 730214455Srpaulo case MAC_CHECK_VNODE_CHDIR: 731214455Srpaulo mpc->mpc_ops->mpo_check_vnode_chdir = 732214455Srpaulo mpe->mpe_function; 733214455Srpaulo break; 734214455Srpaulo case MAC_CHECK_VNODE_CHROOT: 735214455Srpaulo mpc->mpc_ops->mpo_check_vnode_chroot = 736214455Srpaulo mpe->mpe_function; 737235426Sdelphij break; 738214455Srpaulo case MAC_CHECK_VNODE_CREATE: 739214455Srpaulo mpc->mpc_ops->mpo_check_vnode_create = 740214455Srpaulo mpe->mpe_function; 741214455Srpaulo break; 742214455Srpaulo case MAC_CHECK_VNODE_DELETE: 743214455Srpaulo mpc->mpc_ops->mpo_check_vnode_delete = 744214455Srpaulo mpe->mpe_function; 745214455Srpaulo break; 746235426Sdelphij case MAC_CHECK_VNODE_DELETEACL: 747214455Srpaulo mpc->mpc_ops->mpo_check_vnode_deleteacl = 748214455Srpaulo mpe->mpe_function; 749214455Srpaulo break; 750214455Srpaulo case MAC_CHECK_VNODE_EXEC: 751214455Srpaulo mpc->mpc_ops->mpo_check_vnode_exec = 752235426Sdelphij mpe->mpe_function; 753235426Sdelphij break; 754214455Srpaulo case MAC_CHECK_VNODE_GETACL: 755235426Sdelphij mpc->mpc_ops->mpo_check_vnode_getacl = 756235426Sdelphij mpe->mpe_function; 757235426Sdelphij break; 758235426Sdelphij case MAC_CHECK_VNODE_GETEXTATTR: 759235426Sdelphij mpc->mpc_ops->mpo_check_vnode_getextattr = 760235426Sdelphij mpe->mpe_function; 761214455Srpaulo break; 762235426Sdelphij case MAC_CHECK_VNODE_LOOKUP: 763235426Sdelphij mpc->mpc_ops->mpo_check_vnode_lookup = 764235426Sdelphij mpe->mpe_function; 765235426Sdelphij break; 766235426Sdelphij case MAC_CHECK_VNODE_MMAP_PERMS: 767235426Sdelphij mpc->mpc_ops->mpo_check_vnode_mmap_perms = 768235426Sdelphij mpe->mpe_function; 769235426Sdelphij break; 770235426Sdelphij case MAC_CHECK_VNODE_OPEN: 771235426Sdelphij mpc->mpc_ops->mpo_check_vnode_open = 772235426Sdelphij mpe->mpe_function; 773235426Sdelphij break; 774235426Sdelphij case MAC_CHECK_VNODE_POLL: 775235426Sdelphij mpc->mpc_ops->mpo_check_vnode_poll = 776235426Sdelphij mpe->mpe_function; 777235426Sdelphij break; 778235426Sdelphij case MAC_CHECK_VNODE_READ: 779235426Sdelphij mpc->mpc_ops->mpo_check_vnode_read = 780235426Sdelphij mpe->mpe_function; 781235426Sdelphij break; 782235426Sdelphij case MAC_CHECK_VNODE_READDIR: 783235426Sdelphij mpc->mpc_ops->mpo_check_vnode_readdir = 784235426Sdelphij mpe->mpe_function; 785235426Sdelphij break; 786235426Sdelphij case MAC_CHECK_VNODE_READLINK: 787235426Sdelphij mpc->mpc_ops->mpo_check_vnode_readlink = 788235426Sdelphij mpe->mpe_function; 789235426Sdelphij break; 790235426Sdelphij case MAC_CHECK_VNODE_RELABEL: 791235426Sdelphij mpc->mpc_ops->mpo_check_vnode_relabel = 792235426Sdelphij mpe->mpe_function; 793235426Sdelphij break; 794235426Sdelphij case MAC_CHECK_VNODE_RENAME_FROM: 795235426Sdelphij mpc->mpc_ops->mpo_check_vnode_rename_from = 796235426Sdelphij mpe->mpe_function; 797235426Sdelphij break; 798235426Sdelphij case MAC_CHECK_VNODE_RENAME_TO: 799235426Sdelphij mpc->mpc_ops->mpo_check_vnode_rename_to = 800235426Sdelphij mpe->mpe_function; 801235426Sdelphij break; 802235426Sdelphij case MAC_CHECK_VNODE_REVOKE: 803235426Sdelphij mpc->mpc_ops->mpo_check_vnode_revoke = 804235426Sdelphij mpe->mpe_function; 805235426Sdelphij break; 806235426Sdelphij case MAC_CHECK_VNODE_SETACL: 807235426Sdelphij mpc->mpc_ops->mpo_check_vnode_setacl = 808235426Sdelphij mpe->mpe_function; 809235426Sdelphij break; 810235426Sdelphij case MAC_CHECK_VNODE_SETEXTATTR: 811235426Sdelphij mpc->mpc_ops->mpo_check_vnode_setextattr = 812235426Sdelphij mpe->mpe_function; 813235426Sdelphij break; 814235426Sdelphij case MAC_CHECK_VNODE_SETFLAGS: 815235426Sdelphij mpc->mpc_ops->mpo_check_vnode_setflags = 816235426Sdelphij mpe->mpe_function; 817235426Sdelphij break; 818235426Sdelphij case MAC_CHECK_VNODE_SETMODE: 819235426Sdelphij mpc->mpc_ops->mpo_check_vnode_setmode = 820235426Sdelphij mpe->mpe_function; 821235426Sdelphij break; 822235426Sdelphij case MAC_CHECK_VNODE_SETOWNER: 823235426Sdelphij mpc->mpc_ops->mpo_check_vnode_setowner = 824235426Sdelphij mpe->mpe_function; 825235426Sdelphij break; 826235426Sdelphij case MAC_CHECK_VNODE_SETUTIMES: 827235426Sdelphij mpc->mpc_ops->mpo_check_vnode_setutimes = 828235426Sdelphij mpe->mpe_function; 829235426Sdelphij break; 830235426Sdelphij case MAC_CHECK_VNODE_STAT: 831235426Sdelphij mpc->mpc_ops->mpo_check_vnode_stat = 832235426Sdelphij mpe->mpe_function; 833235426Sdelphij break; 834235426Sdelphij case MAC_CHECK_VNODE_WRITE: 835235426Sdelphij mpc->mpc_ops->mpo_check_vnode_write = 836235426Sdelphij mpe->mpe_function; 837235426Sdelphij break; 838235426Sdelphij/* 839235426Sdelphij default: 840235426Sdelphij printf("MAC policy `%s': unknown operation %d\n", 841235426Sdelphij mpc->mpc_name, mpe->mpe_constant); 842235426Sdelphij return (EINVAL); 843235426Sdelphij*/ 844235426Sdelphij } 845235426Sdelphij } 846235426Sdelphij MAC_POLICY_LIST_LOCK(); 847235426Sdelphij if (mac_policy_list_busy > 0) { 848235426Sdelphij MAC_POLICY_LIST_UNLOCK(); 849235426Sdelphij FREE(mpc->mpc_ops, M_MACOPVEC); 850235426Sdelphij mpc->mpc_ops = NULL; 851235426Sdelphij return (EBUSY); 852235426Sdelphij } 853235426Sdelphij LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 854235426Sdelphij if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 855214455Srpaulo MAC_POLICY_LIST_UNLOCK(); 856214455Srpaulo FREE(mpc->mpc_ops, M_MACOPVEC); 857214455Srpaulo mpc->mpc_ops = NULL; 858214455Srpaulo return (EEXIST); 859214455Srpaulo } 860214455Srpaulo } 861214455Srpaulo if (mpc->mpc_field_off != NULL) { 862214455Srpaulo slot = ffs(mac_policy_offsets_free); 863214455Srpaulo if (slot == 0) { 864214455Srpaulo MAC_POLICY_LIST_UNLOCK(); 865214455Srpaulo FREE(mpc->mpc_ops, M_MACOPVEC); 866214455Srpaulo mpc->mpc_ops = NULL; 867214455Srpaulo return (ENOMEM); 868214455Srpaulo } 869214455Srpaulo slot--; 870235426Sdelphij mac_policy_offsets_free &= ~(1 << slot); 871214455Srpaulo *mpc->mpc_field_off = slot; 872214455Srpaulo } 873214455Srpaulo mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 874214455Srpaulo LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 875214455Srpaulo 876214455Srpaulo /* Per-policy initialization. */ 877214455Srpaulo if (mpc->mpc_ops->mpo_init != NULL) 878214455Srpaulo (*(mpc->mpc_ops->mpo_init))(mpc); 879214455Srpaulo MAC_POLICY_LIST_UNLOCK(); 880214455Srpaulo 881214455Srpaulo printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 882214455Srpaulo mpc->mpc_name); 883214455Srpaulo 884214455Srpaulo return (0); 885214455Srpaulo} 886214455Srpaulo 887214455Srpaulostatic int 888214455Srpaulomac_policy_unregister(struct mac_policy_conf *mpc) 889214455Srpaulo{ 890214455Srpaulo 891214455Srpaulo#if 0 892214455Srpaulo /* 893214455Srpaulo * Don't allow unloading modules with private data. 894214455Srpaulo */ 895214455Srpaulo if (mpc->mpc_field_off != NULL) 896214455Srpaulo return (EBUSY); 897214455Srpaulo#endif 898214455Srpaulo if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) 899214455Srpaulo return (EBUSY); 900214455Srpaulo MAC_POLICY_LIST_LOCK(); 901214455Srpaulo if (mac_policy_list_busy > 0) { 902214455Srpaulo MAC_POLICY_LIST_UNLOCK(); 903214455Srpaulo return (EBUSY); 904214455Srpaulo } 905214455Srpaulo if (mpc->mpc_ops->mpo_destroy != NULL) 906214455Srpaulo (*(mpc->mpc_ops->mpo_destroy))(mpc); 907214455Srpaulo 908214455Srpaulo LIST_REMOVE(mpc, mpc_list); 909214455Srpaulo MAC_POLICY_LIST_UNLOCK(); 910214455Srpaulo 911214455Srpaulo FREE(mpc->mpc_ops, M_MACOPVEC); 912235426Sdelphij mpc->mpc_ops = NULL; 913235426Sdelphij 914235426Sdelphij printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 915214455Srpaulo mpc->mpc_name); 916214455Srpaulo 917214455Srpaulo return (0); 918214455Srpaulo} 919214455Srpaulo 920214455Srpaulo/* 921214455Srpaulo * Define an error value precedence, and given two arguments, selects the 922214455Srpaulo * value with the higher precedence. 923214455Srpaulo */ 924214455Srpaulostatic int 925235426Sdelphijerror_select(int error1, int error2) 926235426Sdelphij{ 927235426Sdelphij 928235426Sdelphij /* Certain decision-making errors take top priority. */ 929235426Sdelphij if (error1 == EDEADLK || error2 == EDEADLK) 930235426Sdelphij return (EDEADLK); 931235426Sdelphij 932235426Sdelphij /* Invalid arguments should be reported where possible. */ 933235426Sdelphij if (error1 == EINVAL || error2 == EINVAL) 934214455Srpaulo return (EINVAL); 935214455Srpaulo 936214455Srpaulo /* Precedence goes to "visibility", with both process and file. */ 937214455Srpaulo if (error1 == ESRCH || error2 == ESRCH) 938214455Srpaulo return (ESRCH); 939214455Srpaulo 940214455Srpaulo if (error1 == ENOENT || error2 == ENOENT) 941235426Sdelphij return (ENOENT); 942235426Sdelphij 943214455Srpaulo /* Precedence goes to DAC/MAC protections. */ 944214455Srpaulo if (error1 == EACCES || error2 == EACCES) 945214455Srpaulo return (EACCES); 946214455Srpaulo 947214455Srpaulo /* Precedence goes to privilege. */ 948214455Srpaulo if (error1 == EPERM || error2 == EPERM) 949214455Srpaulo return (EPERM); 950214455Srpaulo 951214455Srpaulo /* Precedence goes to error over success; otherwise, arbitrary. */ 952235426Sdelphij if (error1 != 0) 953235426Sdelphij return (error1); 954235426Sdelphij return (error2); 955235426Sdelphij} 956235426Sdelphij 957235426Sdelphijvoid 958235426Sdelphijmac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) 959235426Sdelphij{ 960235426Sdelphij 961235426Sdelphij MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label); 962214455Srpaulo} 963214455Srpaulo 964214455Srpaulovoid 965214455Srpaulomac_update_procfsvnode(struct vnode *vp, struct ucred *cred) 966214455Srpaulo{ 967214455Srpaulo 968214455Srpaulo MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); 969214455Srpaulo} 970214455Srpaulo 971214455Srpaulo/* 972214455Srpaulo * Support callout for policies that manage their own externalization 973214455Srpaulo * using extended attributes. 974214455Srpaulo */ 975214455Srpaulostatic int 976214455Srpaulomac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) 977214455Srpaulo{ 978214455Srpaulo int error; 979214455Srpaulo 980214455Srpaulo MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, 981214455Srpaulo &mp->mnt_fslabel); 982214455Srpaulo 983214455Srpaulo return (error); 984214455Srpaulo} 985214455Srpaulo 986214455Srpaulo/* 987214455Srpaulo * Given an externalized mac label, internalize it and stamp it on a 988214455Srpaulo * vnode. 989235426Sdelphij */ 990235426Sdelphijstatic int 991235426Sdelphijmac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac) 992214455Srpaulo{ 993214455Srpaulo int error; 994235426Sdelphij 995235426Sdelphij MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); 996235426Sdelphij 997235426Sdelphij return (error); 998235426Sdelphij} 999235426Sdelphij 1000214455Srpaulo/* 1001214455Srpaulo * Call out to individual policies to update the label in a vnode from 1002214455Srpaulo * the mountpoint. 1003235426Sdelphij */ 1004235426Sdelphijvoid 1005214455Srpaulomac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) 1006214455Srpaulo{ 1007235426Sdelphij 1008235426Sdelphij MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, 1009235426Sdelphij &mp->mnt_fslabel); 1010235426Sdelphij 1011235426Sdelphij ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); 1012214455Srpaulo if (mac_cache_fslabel_in_vnode) 1013214455Srpaulo vp->v_vflag |= VV_CACHEDLABEL; 1014235426Sdelphij} 1015235426Sdelphij 1016235426Sdelphij/* 1017235426Sdelphij * Implementation of VOP_REFRESHLABEL() that relies on extended attributes 1018235426Sdelphij * to store label data. Can be referenced by filesystems supporting 1019214455Srpaulo * extended attributes. 1020214455Srpaulo */ 1021235426Sdelphijint 1022235426Sdelphijvop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) 1023235426Sdelphij{ 1024214455Srpaulo struct vnode *vp = ap->a_vp; 1025214455Srpaulo struct mac extmac; 1026235426Sdelphij int buflen, error; 1027235426Sdelphij 1028235426Sdelphij ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); 1029214455Srpaulo 1030214455Srpaulo /* 1031235426Sdelphij * Call out to external policies first. Order doesn't really 1032235426Sdelphij * matter, as long as failure of one assures failure of all. 1033235426Sdelphij */ 1034214455Srpaulo error = mac_update_vnode_from_extattr(vp, vp->v_mount); 1035214455Srpaulo if (error) 1036235426Sdelphij return (error); 1037235426Sdelphij 1038235426Sdelphij buflen = sizeof(extmac); 1039214455Srpaulo error = vn_extattr_get(vp, IO_NODELOCKED, 1040214455Srpaulo FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, 1041214455Srpaulo (char *)&extmac, curthread); 1042235426Sdelphij switch (error) { 1043235426Sdelphij case 0: 1044235426Sdelphij /* Got it */ 1045235426Sdelphij break; 1046235426Sdelphij 1047235426Sdelphij case ENOATTR: 1048235426Sdelphij /* 1049235426Sdelphij * Use the label from the mount point. 1050235426Sdelphij */ 1051235426Sdelphij mac_update_vnode_from_mount(vp, vp->v_mount); 1052235426Sdelphij return (0); 1053235426Sdelphij 1054235426Sdelphij case EOPNOTSUPP: 1055214455Srpaulo default: 1056214455Srpaulo /* Fail horribly. */ 1057214455Srpaulo return (error); 1058214455Srpaulo } 1059214455Srpaulo 1060214455Srpaulo if (buflen != sizeof(extmac)) 1061214455Srpaulo error = EPERM; /* Fail very closed. */ 1062214455Srpaulo if (error == 0) 1063214455Srpaulo error = mac_update_vnode_from_externalized(vp, &extmac); 1064235426Sdelphij if (error == 0) 1065235426Sdelphij vp->v_vflag |= VV_CACHEDLABEL; 1066214455Srpaulo else { 1067214455Srpaulo struct vattr va; 1068235426Sdelphij 1069235426Sdelphij printf("Corrupted label on %s", 1070235426Sdelphij vp->v_mount->mnt_stat.f_mntonname); 1071214455Srpaulo if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) 1072214455Srpaulo printf(" inum %ld", va.va_fileid); 1073235426Sdelphij if (mac_debug_label_fallback) { 1074235426Sdelphij printf(", falling back.\n"); 1075235426Sdelphij mac_update_vnode_from_mount(vp, vp->v_mount); 1076214455Srpaulo error = 0; 1077214455Srpaulo } else { 1078235426Sdelphij printf(".\n"); 1079235426Sdelphij error = EPERM; 1080235426Sdelphij } 1081214455Srpaulo } 1082214455Srpaulo 1083214455Srpaulo return (error); 1084235426Sdelphij} 1085235426Sdelphij 1086235426Sdelphij/* 1087235426Sdelphij * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle 1088235426Sdelphij * the labeling activity outselves. Filesystems should be careful not 1089235426Sdelphij * to change their minds regarding whether they support vop_refreshlabel() 1090235426Sdelphij * for a vnode or not. Don't cache the vnode here, allow the file 1091235426Sdelphij * system code to determine if it's safe to cache. If we update from 1092235426Sdelphij * the mount, don't cache since a change to the mount label should affect 1093235426Sdelphij * all vnodes. 1094235426Sdelphij */ 1095235426Sdelphijstatic int 1096235426Sdelphijvn_refreshlabel(struct vnode *vp, struct ucred *cred) 1097235426Sdelphij{ 1098235426Sdelphij int error; 1099235426Sdelphij 1100235426Sdelphij ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); 1101235426Sdelphij 1102235426Sdelphij if (vp->v_mount == NULL) { 1103235426Sdelphij/* 1104235426Sdelphij Eventually, we probably want to special-case refreshing 1105235426Sdelphij of deadfs vnodes, and if there's a lock-free race somewhere, 1106235426Sdelphij that case might be handled here. 1107235426Sdelphij 1108235426Sdelphij mac_update_vnode_deadfs(vp); 1109235426Sdelphij return (0); 1110214455Srpaulo */ 1111 /* printf("vn_refreshlabel: null v_mount\n"); */ 1112 if (vp->v_tag != VT_NON) 1113 printf( 1114 "vn_refreshlabel: null v_mount with non-VT_NON\n"); 1115 return (EBADF); 1116 } 1117 1118 if (vp->v_vflag & VV_CACHEDLABEL) { 1119 mac_vnode_label_cache_hits++; 1120 return (0); 1121 } else 1122 mac_vnode_label_cache_misses++; 1123 1124 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1125 mac_update_vnode_from_mount(vp, vp->v_mount); 1126 return (0); 1127 } 1128 1129 error = VOP_REFRESHLABEL(vp, cred, curthread); 1130 switch (error) { 1131 case EOPNOTSUPP: 1132 /* 1133 * If labels are not supported on this vnode, fall back to 1134 * the label in the mount and propagate it to the vnode. 1135 * There should probably be some sort of policy/flag/decision 1136 * about doing this. 1137 */ 1138 mac_update_vnode_from_mount(vp, vp->v_mount); 1139 error = 0; 1140 default: 1141 return (error); 1142 } 1143} 1144 1145/* 1146 * Helper function for file systems using the vop_std*_ea() calls. This 1147 * function must be called after EA service is available for the vnode, 1148 * but before it's hooked up to the namespace so that the node persists 1149 * if there's a crash, or before it can be accessed. On successful 1150 * commit of the label to disk (etc), do cache the label. 1151 */ 1152int 1153vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) 1154{ 1155 struct mac extmac; 1156 int error; 1157 1158 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); 1159 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { 1160 mac_update_vnode_from_mount(tvp, tvp->v_mount); 1161 } else { 1162 error = vn_refreshlabel(dvp, cred); 1163 if (error) 1164 return (error); 1165 1166 /* 1167 * Stick the label in the vnode. Then try to write to 1168 * disk. If we fail, return a failure to abort the 1169 * create operation. Really, this failure shouldn't 1170 * happen except in fairly unusual circumstances (out 1171 * of disk, etc). 1172 */ 1173 mac_create_vnode(cred, dvp, tvp); 1174 1175 error = mac_stdcreatevnode_ea(tvp); 1176 if (error) 1177 return (error); 1178 1179 /* 1180 * XXX: Eventually this will go away and all policies will 1181 * directly manage their extended attributes. 1182 */ 1183 error = mac_externalize(&tvp->v_label, &extmac); 1184 if (error) 1185 return (error); 1186 1187 error = vn_extattr_set(tvp, IO_NODELOCKED, 1188 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 1189 sizeof(extmac), (char *)&extmac, curthread); 1190 if (error == 0) 1191 tvp->v_vflag |= VV_CACHEDLABEL; 1192 else { 1193#if 0 1194 /* 1195 * In theory, we could have fall-back behavior here. 1196 * It would probably be incorrect. 1197 */ 1198#endif 1199 return (error); 1200 } 1201 } 1202 1203 return (0); 1204} 1205 1206void 1207mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) 1208{ 1209 int error; 1210 1211 ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); 1212 1213 error = vn_refreshlabel(vp, old); 1214 if (error) { 1215 printf("mac_execve_transition: vn_refreshlabel returned %d\n", 1216 error); 1217 printf("mac_execve_transition: using old vnode label\n"); 1218 } 1219 1220 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); 1221} 1222 1223int 1224mac_execve_will_transition(struct ucred *old, struct vnode *vp) 1225{ 1226 int error, result; 1227 1228 error = vn_refreshlabel(vp, old); 1229 if (error) 1230 return (error); 1231 1232 result = 0; 1233 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); 1234 1235 return (result); 1236} 1237 1238static void 1239mac_init_label(struct label *label) 1240{ 1241 1242 bzero(label, sizeof(*label)); 1243 label->l_flags = MAC_FLAG_INITIALIZED; 1244} 1245 1246static void 1247mac_init_structmac(struct mac *mac) 1248{ 1249 1250 bzero(mac, sizeof(*mac)); 1251 mac->m_macflags = MAC_FLAG_INITIALIZED; 1252} 1253 1254static void 1255mac_destroy_label(struct label *label) 1256{ 1257 1258 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 1259 ("destroying uninitialized label")); 1260 1261 bzero(label, sizeof(*label)); 1262 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 1263} 1264 1265int 1266mac_init_mbuf(struct mbuf *m, int how) 1267{ 1268 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf")); 1269 1270 /* "how" is one of M_(TRY|DONT)WAIT */ 1271 mac_init_label(&m->m_pkthdr.label); 1272 MAC_PERFORM(init_mbuf, m, how, &m->m_pkthdr.label); 1273#ifdef MAC_DEBUG 1274 atomic_add_int(&nmacmbufs, 1); 1275#endif 1276 return (0); 1277} 1278 1279void 1280mac_destroy_mbuf(struct mbuf *m) 1281{ 1282 1283 MAC_PERFORM(destroy_mbuf, m, &m->m_pkthdr.label); 1284 mac_destroy_label(&m->m_pkthdr.label); 1285#ifdef MAC_DEBUG 1286 atomic_subtract_int(&nmacmbufs, 1); 1287#endif 1288} 1289 1290void 1291mac_init_cred(struct ucred *cr) 1292{ 1293 1294 mac_init_label(&cr->cr_label); 1295 MAC_PERFORM(init_cred, cr, &cr->cr_label); 1296#ifdef MAC_DEBUG 1297 atomic_add_int(&nmaccreds, 1); 1298#endif 1299} 1300 1301void 1302mac_destroy_cred(struct ucred *cr) 1303{ 1304 1305 MAC_PERFORM(destroy_cred, cr, &cr->cr_label); 1306 mac_destroy_label(&cr->cr_label); 1307#ifdef MAC_DEBUG 1308 atomic_subtract_int(&nmaccreds, 1); 1309#endif 1310} 1311 1312void 1313mac_init_ifnet(struct ifnet *ifp) 1314{ 1315 1316 mac_init_label(&ifp->if_label); 1317 MAC_PERFORM(init_ifnet, ifp, &ifp->if_label); 1318#ifdef MAC_DEBUG 1319 atomic_add_int(&nmacifnets, 1); 1320#endif 1321} 1322 1323void 1324mac_destroy_ifnet(struct ifnet *ifp) 1325{ 1326 1327 MAC_PERFORM(destroy_ifnet, ifp, &ifp->if_label); 1328 mac_destroy_label(&ifp->if_label); 1329#ifdef MAC_DEBUG 1330 atomic_subtract_int(&nmacifnets, 1); 1331#endif 1332} 1333 1334void 1335mac_init_ipq(struct ipq *ipq) 1336{ 1337 1338 mac_init_label(&ipq->ipq_label); 1339 MAC_PERFORM(init_ipq, ipq, &ipq->ipq_label); 1340#ifdef MAC_DEBUG 1341 atomic_add_int(&nmacipqs, 1); 1342#endif 1343} 1344 1345void 1346mac_destroy_ipq(struct ipq *ipq) 1347{ 1348 1349 MAC_PERFORM(destroy_ipq, ipq, &ipq->ipq_label); 1350 mac_destroy_label(&ipq->ipq_label); 1351#ifdef MAC_DEBUG 1352 atomic_subtract_int(&nmacipqs, 1); 1353#endif 1354} 1355 1356void 1357mac_init_socket(struct socket *socket) 1358{ 1359 1360 mac_init_label(&socket->so_label); 1361 mac_init_label(&socket->so_peerlabel); 1362 MAC_PERFORM(init_socket, socket, &socket->so_label, 1363 &socket->so_peerlabel); 1364#ifdef MAC_DEBUG 1365 atomic_add_int(&nmacsockets, 1); 1366#endif 1367} 1368 1369void 1370mac_destroy_socket(struct socket *socket) 1371{ 1372 1373 MAC_PERFORM(destroy_socket, socket, &socket->so_label, 1374 &socket->so_peerlabel); 1375 mac_destroy_label(&socket->so_label); 1376 mac_destroy_label(&socket->so_peerlabel); 1377#ifdef MAC_DEBUG 1378 atomic_subtract_int(&nmacsockets, 1); 1379#endif 1380} 1381 1382void 1383mac_init_pipe(struct pipe *pipe) 1384{ 1385 struct label *label; 1386 1387 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 1388 mac_init_label(label); 1389 pipe->pipe_label = label; 1390 pipe->pipe_peer->pipe_label = label; 1391 MAC_PERFORM(init_pipe, pipe, pipe->pipe_label); 1392#ifdef MAC_DEBUG 1393 atomic_add_int(&nmacpipes, 1); 1394#endif 1395} 1396 1397void 1398mac_destroy_pipe(struct pipe *pipe) 1399{ 1400 1401 MAC_PERFORM(destroy_pipe, pipe, pipe->pipe_label); 1402 mac_destroy_label(pipe->pipe_label); 1403 free(pipe->pipe_label, M_MACPIPELABEL); 1404#ifdef MAC_DEBUG 1405 atomic_subtract_int(&nmacpipes, 1); 1406#endif 1407} 1408 1409void 1410mac_init_bpfdesc(struct bpf_d *bpf_d) 1411{ 1412 1413 mac_init_label(&bpf_d->bd_label); 1414 MAC_PERFORM(init_bpfdesc, bpf_d, &bpf_d->bd_label); 1415#ifdef MAC_DEBUG 1416 atomic_add_int(&nmacbpfdescs, 1); 1417#endif 1418} 1419 1420void 1421mac_destroy_bpfdesc(struct bpf_d *bpf_d) 1422{ 1423 1424 MAC_PERFORM(destroy_bpfdesc, bpf_d, &bpf_d->bd_label); 1425 mac_destroy_label(&bpf_d->bd_label); 1426#ifdef MAC_DEBUG 1427 atomic_subtract_int(&nmacbpfdescs, 1); 1428#endif 1429} 1430 1431void 1432mac_init_mount(struct mount *mp) 1433{ 1434 1435 mac_init_label(&mp->mnt_mntlabel); 1436 mac_init_label(&mp->mnt_fslabel); 1437 MAC_PERFORM(init_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 1438#ifdef MAC_DEBUG 1439 atomic_add_int(&nmacmounts, 1); 1440#endif 1441} 1442 1443void 1444mac_destroy_mount(struct mount *mp) 1445{ 1446 1447 MAC_PERFORM(destroy_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel); 1448 mac_destroy_label(&mp->mnt_fslabel); 1449 mac_destroy_label(&mp->mnt_mntlabel); 1450#ifdef MAC_DEBUG 1451 atomic_subtract_int(&nmacmounts, 1); 1452#endif 1453} 1454 1455static void 1456mac_init_temp(struct label *label) 1457{ 1458 1459 mac_init_label(label); 1460 MAC_PERFORM(init_temp, label); 1461#ifdef MAC_DEBUG 1462 atomic_add_int(&nmactemp, 1); 1463#endif 1464} 1465 1466static void 1467mac_destroy_temp(struct label *label) 1468{ 1469 1470 MAC_PERFORM(destroy_temp, label); 1471 mac_destroy_label(label); 1472#ifdef MAC_DEBUG 1473 atomic_subtract_int(&nmactemp, 1); 1474#endif 1475} 1476 1477void 1478mac_init_vnode(struct vnode *vp) 1479{ 1480 1481 mac_init_label(&vp->v_label); 1482 MAC_PERFORM(init_vnode, vp, &vp->v_label); 1483#ifdef MAC_DEBUG 1484 atomic_add_int(&nmacvnodes, 1); 1485#endif 1486} 1487 1488void 1489mac_destroy_vnode(struct vnode *vp) 1490{ 1491 1492 MAC_PERFORM(destroy_vnode, vp, &vp->v_label); 1493 mac_destroy_label(&vp->v_label); 1494#ifdef MAC_DEBUG 1495 atomic_subtract_int(&nmacvnodes, 1); 1496#endif 1497} 1498 1499void 1500mac_init_devfsdirent(struct devfs_dirent *de) 1501{ 1502 1503 mac_init_label(&de->de_label); 1504 MAC_PERFORM(init_devfsdirent, de, &de->de_label); 1505#ifdef MAC_DEBUG 1506 atomic_add_int(&nmacdevfsdirents, 1); 1507#endif 1508} 1509 1510void 1511mac_destroy_devfsdirent(struct devfs_dirent *de) 1512{ 1513 1514 MAC_PERFORM(destroy_devfsdirent, de, &de->de_label); 1515 mac_destroy_label(&de->de_label); 1516#ifdef MAC_DEBUG 1517 atomic_subtract_int(&nmacdevfsdirents, 1); 1518#endif 1519} 1520 1521static int 1522mac_externalize(struct label *label, struct mac *mac) 1523{ 1524 int error; 1525 1526 mac_init_structmac(mac); 1527 MAC_CHECK(externalize, label, mac); 1528 1529 return (error); 1530} 1531 1532static int 1533mac_internalize(struct label *label, struct mac *mac) 1534{ 1535 int error; 1536 1537 mac_init_temp(label); 1538 MAC_CHECK(internalize, label, mac); 1539 if (error) 1540 mac_destroy_temp(label); 1541 1542 return (error); 1543} 1544 1545/* 1546 * Initialize MAC label for the first kernel process, from which other 1547 * kernel processes and threads are spawned. 1548 */ 1549void 1550mac_create_proc0(struct ucred *cred) 1551{ 1552 1553 MAC_PERFORM(create_proc0, cred); 1554} 1555 1556/* 1557 * Initialize MAC label for the first userland process, from which other 1558 * userland processes and threads are spawned. 1559 */ 1560void 1561mac_create_proc1(struct ucred *cred) 1562{ 1563 1564 MAC_PERFORM(create_proc1, cred); 1565} 1566 1567/* 1568 * When a new process is created, its label must be initialized. Generally, 1569 * this involves inheritence from the parent process, modulo possible 1570 * deltas. This function allows that processing to take place. 1571 */ 1572void 1573mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred) 1574{ 1575 1576 MAC_PERFORM(create_cred, parent_cred, child_cred); 1577} 1578 1579int 1580mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) 1581{ 1582 int error; 1583 1584 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access"); 1585 1586 if (!mac_enforce_fs) 1587 return (0); 1588 1589 error = vn_refreshlabel(vp, cred); 1590 if (error) 1591 return (error); 1592 1593 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); 1594 return (error); 1595} 1596 1597int 1598mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) 1599{ 1600 int error; 1601 1602 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir"); 1603 1604 if (!mac_enforce_fs) 1605 return (0); 1606 1607 error = vn_refreshlabel(dvp, cred); 1608 if (error) 1609 return (error); 1610 1611 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); 1612 return (error); 1613} 1614 1615int 1616mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) 1617{ 1618 int error; 1619 1620 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot"); 1621 1622 if (!mac_enforce_fs) 1623 return (0); 1624 1625 error = vn_refreshlabel(dvp, cred); 1626 if (error) 1627 return (error); 1628 1629 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); 1630 return (error); 1631} 1632 1633int 1634mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1635 struct componentname *cnp, struct vattr *vap) 1636{ 1637 int error; 1638 1639 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create"); 1640 1641 if (!mac_enforce_fs) 1642 return (0); 1643 1644 error = vn_refreshlabel(dvp, cred); 1645 if (error) 1646 return (error); 1647 1648 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); 1649 return (error); 1650} 1651 1652int 1653mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, 1654 struct componentname *cnp) 1655{ 1656 int error; 1657 1658 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete"); 1659 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete"); 1660 1661 if (!mac_enforce_fs) 1662 return (0); 1663 1664 error = vn_refreshlabel(dvp, cred); 1665 if (error) 1666 return (error); 1667 error = vn_refreshlabel(vp, cred); 1668 if (error) 1669 return (error); 1670 1671 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, 1672 &vp->v_label, cnp); 1673 return (error); 1674} 1675 1676int 1677mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1678 acl_type_t type) 1679{ 1680 int error; 1681 1682 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl"); 1683 1684 if (!mac_enforce_fs) 1685 return (0); 1686 1687 error = vn_refreshlabel(vp, cred); 1688 if (error) 1689 return (error); 1690 1691 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); 1692 return (error); 1693} 1694 1695int 1696mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) 1697{ 1698 int error; 1699 1700 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec"); 1701 1702 if (!mac_enforce_process && !mac_enforce_fs) 1703 return (0); 1704 1705 error = vn_refreshlabel(vp, cred); 1706 if (error) 1707 return (error); 1708 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); 1709 1710 return (error); 1711} 1712 1713int 1714mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) 1715{ 1716 int error; 1717 1718 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl"); 1719 1720 if (!mac_enforce_fs) 1721 return (0); 1722 1723 error = vn_refreshlabel(vp, cred); 1724 if (error) 1725 return (error); 1726 1727 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); 1728 return (error); 1729} 1730 1731int 1732mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1733 int attrnamespace, const char *name, struct uio *uio) 1734{ 1735 int error; 1736 1737 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr"); 1738 1739 if (!mac_enforce_fs) 1740 return (0); 1741 1742 error = vn_refreshlabel(vp, cred); 1743 if (error) 1744 return (error); 1745 1746 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, 1747 attrnamespace, name, uio); 1748 return (error); 1749} 1750 1751int 1752mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1753 struct componentname *cnp) 1754{ 1755 int error; 1756 1757 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup"); 1758 1759 if (!mac_enforce_fs) 1760 return (0); 1761 1762 error = vn_refreshlabel(dvp, cred); 1763 if (error) 1764 return (error); 1765 1766 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); 1767 return (error); 1768} 1769 1770vm_prot_t 1771mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping) 1772{ 1773 vm_prot_t result = VM_PROT_ALL; 1774 1775 /* 1776 * This should be some sort of MAC_BITWISE, maybe :) 1777 */ 1778 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms"); 1779 MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label, 1780 newmapping); 1781 return (result); 1782} 1783 1784int 1785mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) 1786{ 1787 int error; 1788 1789 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open"); 1790 1791 if (!mac_enforce_fs) 1792 return (0); 1793 1794 error = vn_refreshlabel(vp, cred); 1795 if (error) 1796 return (error); 1797 1798 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); 1799 return (error); 1800} 1801 1802int 1803mac_check_vnode_poll(struct ucred *cred, struct vnode *vp) 1804{ 1805 int error; 1806 1807 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll"); 1808 1809 if (!mac_enforce_fs) 1810 return (0); 1811 1812 error = vn_refreshlabel(vp, cred); 1813 if (error) 1814 return (error); 1815 1816 MAC_CHECK(check_vnode_poll, cred, vp, &vp->v_label); 1817 1818 return (error); 1819} 1820 1821int 1822mac_check_vnode_read(struct ucred *cred, struct vnode *vp) 1823{ 1824 int error; 1825 1826 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read"); 1827 1828 if (!mac_enforce_fs) 1829 return (0); 1830 1831 error = vn_refreshlabel(vp, cred); 1832 if (error) 1833 return (error); 1834 1835 MAC_CHECK(check_vnode_read, cred, vp, &vp->v_label); 1836 1837 return (error); 1838} 1839 1840int 1841mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) 1842{ 1843 int error; 1844 1845 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir"); 1846 1847 if (!mac_enforce_fs) 1848 return (0); 1849 1850 error = vn_refreshlabel(dvp, cred); 1851 if (error) 1852 return (error); 1853 1854 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); 1855 return (error); 1856} 1857 1858int 1859mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) 1860{ 1861 int error; 1862 1863 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink"); 1864 1865 if (!mac_enforce_fs) 1866 return (0); 1867 1868 error = vn_refreshlabel(vp, cred); 1869 if (error) 1870 return (error); 1871 1872 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); 1873 return (error); 1874} 1875 1876static int 1877mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 1878 struct label *newlabel) 1879{ 1880 int error; 1881 1882 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); 1883 1884 error = vn_refreshlabel(vp, cred); 1885 if (error) 1886 return (error); 1887 1888 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); 1889 1890 return (error); 1891} 1892 1893int 1894mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 1895 struct vnode *vp, struct componentname *cnp) 1896{ 1897 int error; 1898 1899 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from"); 1900 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from"); 1901 1902 if (!mac_enforce_fs) 1903 return (0); 1904 1905 error = vn_refreshlabel(dvp, cred); 1906 if (error) 1907 return (error); 1908 error = vn_refreshlabel(vp, cred); 1909 if (error) 1910 return (error); 1911 1912 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, 1913 &vp->v_label, cnp); 1914 return (error); 1915} 1916 1917int 1918mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 1919 struct vnode *vp, int samedir, struct componentname *cnp) 1920{ 1921 int error; 1922 1923 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to"); 1924 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to"); 1925 1926 if (!mac_enforce_fs) 1927 return (0); 1928 1929 error = vn_refreshlabel(dvp, cred); 1930 if (error) 1931 return (error); 1932 if (vp != NULL) { 1933 error = vn_refreshlabel(vp, cred); 1934 if (error) 1935 return (error); 1936 } 1937 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, 1938 vp != NULL ? &vp->v_label : NULL, samedir, cnp); 1939 return (error); 1940} 1941 1942int 1943mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) 1944{ 1945 int error; 1946 1947 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke"); 1948 1949 if (!mac_enforce_fs) 1950 return (0); 1951 1952 error = vn_refreshlabel(vp, cred); 1953 if (error) 1954 return (error); 1955 1956 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); 1957 return (error); 1958} 1959 1960int 1961mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, 1962 struct acl *acl) 1963{ 1964 int error; 1965 1966 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl"); 1967 1968 if (!mac_enforce_fs) 1969 return (0); 1970 1971 error = vn_refreshlabel(vp, cred); 1972 if (error) 1973 return (error); 1974 1975 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); 1976 return (error); 1977} 1978 1979int 1980mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 1981 int attrnamespace, const char *name, struct uio *uio) 1982{ 1983 int error; 1984 1985 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr"); 1986 1987 if (!mac_enforce_fs) 1988 return (0); 1989 1990 error = vn_refreshlabel(vp, cred); 1991 if (error) 1992 return (error); 1993 1994 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, 1995 attrnamespace, name, uio); 1996 return (error); 1997} 1998 1999int 2000mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) 2001{ 2002 int error; 2003 2004 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags"); 2005 2006 if (!mac_enforce_fs) 2007 return (0); 2008 2009 error = vn_refreshlabel(vp, cred); 2010 if (error) 2011 return (error); 2012 2013 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); 2014 return (error); 2015} 2016 2017int 2018mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) 2019{ 2020 int error; 2021 2022 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode"); 2023 2024 if (!mac_enforce_fs) 2025 return (0); 2026 2027 error = vn_refreshlabel(vp, cred); 2028 if (error) 2029 return (error); 2030 2031 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); 2032 return (error); 2033} 2034 2035int 2036mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, 2037 gid_t gid) 2038{ 2039 int error; 2040 2041 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner"); 2042 2043 if (!mac_enforce_fs) 2044 return (0); 2045 2046 error = vn_refreshlabel(vp, cred); 2047 if (error) 2048 return (error); 2049 2050 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); 2051 return (error); 2052} 2053 2054int 2055mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 2056 struct timespec atime, struct timespec mtime) 2057{ 2058 int error; 2059 2060 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes"); 2061 2062 if (!mac_enforce_fs) 2063 return (0); 2064 2065 error = vn_refreshlabel(vp, cred); 2066 if (error) 2067 return (error); 2068 2069 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, 2070 mtime); 2071 return (error); 2072} 2073 2074int 2075mac_check_vnode_stat(struct ucred *cred, struct vnode *vp) 2076{ 2077 int error; 2078 2079 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat"); 2080 2081 if (!mac_enforce_fs) 2082 return (0); 2083 2084 error = vn_refreshlabel(vp, cred); 2085 if (error) 2086 return (error); 2087 2088 MAC_CHECK(check_vnode_stat, cred, vp, &vp->v_label); 2089 return (error); 2090} 2091 2092int 2093mac_check_vnode_write(struct ucred *cred, struct vnode *vp) 2094{ 2095 int error; 2096 2097 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write"); 2098 2099 if (!mac_enforce_fs) 2100 return (0); 2101 2102 error = vn_refreshlabel(vp, cred); 2103 if (error) 2104 return (error); 2105 2106 MAC_CHECK(check_vnode_write, cred, vp, &vp->v_label); 2107 2108 return (error); 2109} 2110 2111 2112/* 2113 * When relabeling a process, call out to the policies for the maximum 2114 * permission allowed for each object type we know about in its 2115 * memory space, and revoke access (in the least surprising ways we 2116 * know) when necessary. The process lock is not held here. 2117 */ 2118static void 2119mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) 2120{ 2121 2122 /* XXX freeze all other threads */ 2123 mtx_lock(&Giant); 2124 mac_cred_mmapped_drop_perms_recurse(td, cred, 2125 &td->td_proc->p_vmspace->vm_map); 2126 mtx_unlock(&Giant); 2127 /* XXX allow other threads to continue */ 2128} 2129 2130static __inline const char * 2131prot2str(vm_prot_t prot) 2132{ 2133 2134 switch (prot & VM_PROT_ALL) { 2135 case VM_PROT_READ: 2136 return ("r--"); 2137 case VM_PROT_READ | VM_PROT_WRITE: 2138 return ("rw-"); 2139 case VM_PROT_READ | VM_PROT_EXECUTE: 2140 return ("r-x"); 2141 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 2142 return ("rwx"); 2143 case VM_PROT_WRITE: 2144 return ("-w-"); 2145 case VM_PROT_EXECUTE: 2146 return ("--x"); 2147 case VM_PROT_WRITE | VM_PROT_EXECUTE: 2148 return ("-wx"); 2149 default: 2150 return ("---"); 2151 } 2152} 2153 2154static void 2155mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, 2156 struct vm_map *map) 2157{ 2158 struct vm_map_entry *vme; 2159 vm_prot_t result, revokeperms; 2160 vm_object_t object; 2161 vm_ooffset_t offset; 2162 struct vnode *vp; 2163 2164 vm_map_lock_read(map); 2165 for (vme = map->header.next; vme != &map->header; vme = vme->next) { 2166 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { 2167 mac_cred_mmapped_drop_perms_recurse(td, cred, 2168 vme->object.sub_map); 2169 continue; 2170 } 2171 /* 2172 * Skip over entries that obviously are not shared. 2173 */ 2174 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || 2175 !vme->max_protection) 2176 continue; 2177 /* 2178 * Drill down to the deepest backing object. 2179 */ 2180 offset = vme->offset; 2181 object = vme->object.vm_object; 2182 if (object == NULL) 2183 continue; 2184 while (object->backing_object != NULL) { 2185 object = object->backing_object; 2186 offset += object->backing_object_offset; 2187 } 2188 /* 2189 * At the moment, vm_maps and objects aren't considered 2190 * by the MAC system, so only things with backing by a 2191 * normal object (read: vnodes) are checked. 2192 */ 2193 if (object->type != OBJT_VNODE) 2194 continue; 2195 vp = (struct vnode *)object->handle; 2196 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2197 result = mac_check_vnode_mmap_prot(cred, vp, 0); 2198 VOP_UNLOCK(vp, 0, td); 2199 /* 2200 * Find out what maximum protection we may be allowing 2201 * now but a policy needs to get removed. 2202 */ 2203 revokeperms = vme->max_protection & ~result; 2204 if (!revokeperms) 2205 continue; 2206 printf("pid %d: revoking %s perms from %#lx:%d " 2207 "(max %s/cur %s)\n", td->td_proc->p_pid, 2208 prot2str(revokeperms), vme->start, vme->end - vme->start, 2209 prot2str(vme->max_protection), prot2str(vme->protection)); 2210 vm_map_lock_upgrade(map); 2211 /* 2212 * This is the really simple case: if a map has more 2213 * max_protection than is allowed, but it's not being 2214 * actually used (that is, the current protection is 2215 * still allowed), we can just wipe it out and do 2216 * nothing more. 2217 */ 2218 if ((vme->protection & revokeperms) == 0) { 2219 vme->max_protection -= revokeperms; 2220 } else { 2221 if (revokeperms & VM_PROT_WRITE) { 2222 /* 2223 * In the more complicated case, flush out all 2224 * pending changes to the object then turn it 2225 * copy-on-write. 2226 */ 2227 vm_object_reference(object); 2228 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2229 vm_object_page_clean(object, 2230 OFF_TO_IDX(offset), 2231 OFF_TO_IDX(offset + vme->end - vme->start + 2232 PAGE_MASK), 2233 OBJPC_SYNC); 2234 VOP_UNLOCK(vp, 0, td); 2235 vm_object_deallocate(object); 2236 /* 2237 * Why bother if there's no read permissions 2238 * anymore? For the rest, we need to leave 2239 * the write permissions on for COW, or 2240 * remove them entirely if configured to. 2241 */ 2242 if (!mac_mmap_revocation_via_cow) { 2243 vme->max_protection &= ~VM_PROT_WRITE; 2244 vme->protection &= ~VM_PROT_WRITE; 2245 } if ((revokeperms & VM_PROT_READ) == 0) 2246 vme->eflags |= MAP_ENTRY_COW | 2247 MAP_ENTRY_NEEDS_COPY; 2248 } 2249 if (revokeperms & VM_PROT_EXECUTE) { 2250 vme->max_protection &= ~VM_PROT_EXECUTE; 2251 vme->protection &= ~VM_PROT_EXECUTE; 2252 } 2253 if (revokeperms & VM_PROT_READ) { 2254 vme->max_protection = 0; 2255 vme->protection = 0; 2256 } 2257 pmap_protect(map->pmap, vme->start, vme->end, 2258 vme->protection & ~revokeperms); 2259 vm_map_simplify_entry(map, vme); 2260 } 2261 vm_map_lock_downgrade(map); 2262 } 2263 vm_map_unlock_read(map); 2264} 2265 2266/* 2267 * When the subject's label changes, it may require revocation of privilege 2268 * to mapped objects. This can't be done on-the-fly later with a unified 2269 * buffer cache. 2270 */ 2271static void 2272mac_relabel_cred(struct ucred *cred, struct label *newlabel) 2273{ 2274 2275 MAC_PERFORM(relabel_cred, cred, newlabel); 2276 mac_cred_mmapped_drop_perms(curthread, cred); 2277} 2278 2279void 2280mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel) 2281{ 2282 2283 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel); 2284} 2285 2286void 2287mac_create_ifnet(struct ifnet *ifnet) 2288{ 2289 2290 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label); 2291} 2292 2293void 2294mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d) 2295{ 2296 2297 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label); 2298} 2299 2300void 2301mac_create_socket(struct ucred *cred, struct socket *socket) 2302{ 2303 2304 MAC_PERFORM(create_socket, cred, socket, &socket->so_label); 2305} 2306 2307void 2308mac_create_pipe(struct ucred *cred, struct pipe *pipe) 2309{ 2310 2311 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 2312} 2313 2314void 2315mac_create_socket_from_socket(struct socket *oldsocket, 2316 struct socket *newsocket) 2317{ 2318 2319 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label, 2320 newsocket, &newsocket->so_label); 2321} 2322 2323static void 2324mac_relabel_socket(struct ucred *cred, struct socket *socket, 2325 struct label *newlabel) 2326{ 2327 2328 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel); 2329} 2330 2331static void 2332mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 2333{ 2334 2335 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 2336} 2337 2338void 2339mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 2340{ 2341 2342 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label, 2343 socket, &socket->so_peerlabel); 2344} 2345 2346void 2347mac_set_socket_peer_from_socket(struct socket *oldsocket, 2348 struct socket *newsocket) 2349{ 2350 2351 MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 2352 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel); 2353} 2354 2355void 2356mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram) 2357{ 2358 2359 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label, 2360 datagram, &datagram->m_pkthdr.label); 2361} 2362 2363void 2364mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment) 2365{ 2366 2367 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label, 2368 fragment, &fragment->m_pkthdr.label); 2369} 2370 2371void 2372mac_create_ipq(struct mbuf *fragment, struct ipq *ipq) 2373{ 2374 2375 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2376 &ipq->ipq_label); 2377} 2378 2379void 2380mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2381{ 2382 2383 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label, 2384 newmbuf, &newmbuf->m_pkthdr.label); 2385} 2386 2387void 2388mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf) 2389{ 2390 2391 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf, 2392 &mbuf->m_pkthdr.label); 2393} 2394 2395void 2396mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf) 2397{ 2398 2399 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf, 2400 &mbuf->m_pkthdr.label); 2401} 2402 2403void 2404mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf) 2405{ 2406 2407 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf, 2408 &mbuf->m_pkthdr.label); 2409} 2410 2411void 2412mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet, 2413 struct mbuf *newmbuf) 2414{ 2415 2416 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, 2417 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf, 2418 &newmbuf->m_pkthdr.label); 2419} 2420 2421void 2422mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf) 2423{ 2424 2425 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label, 2426 newmbuf, &newmbuf->m_pkthdr.label); 2427} 2428 2429int 2430mac_fragment_match(struct mbuf *fragment, struct ipq *ipq) 2431{ 2432 int result; 2433 2434 result = 1; 2435 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label, 2436 ipq, &ipq->ipq_label); 2437 2438 return (result); 2439} 2440 2441void 2442mac_update_ipq(struct mbuf *fragment, struct ipq *ipq) 2443{ 2444 2445 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq, 2446 &ipq->ipq_label); 2447} 2448 2449void 2450mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 2451{ 2452 2453 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf, 2454 &mbuf->m_pkthdr.label); 2455} 2456 2457void 2458mac_create_mount(struct ucred *cred, struct mount *mp) 2459{ 2460 2461 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel, 2462 &mp->mnt_fslabel); 2463} 2464 2465void 2466mac_create_root_mount(struct ucred *cred, struct mount *mp) 2467{ 2468 2469 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel, 2470 &mp->mnt_fslabel); 2471} 2472 2473int 2474mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet) 2475{ 2476 int error; 2477 2478 if (!mac_enforce_network) 2479 return (0); 2480 2481 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet, 2482 &ifnet->if_label); 2483 2484 return (error); 2485} 2486 2487static int 2488mac_check_cred_relabel(struct ucred *cred, struct label *newlabel) 2489{ 2490 int error; 2491 2492 MAC_CHECK(check_cred_relabel, cred, newlabel); 2493 2494 return (error); 2495} 2496 2497int 2498mac_check_cred_visible(struct ucred *u1, struct ucred *u2) 2499{ 2500 int error; 2501 2502 if (!mac_enforce_process) 2503 return (0); 2504 2505 MAC_CHECK(check_cred_visible, u1, u2); 2506 2507 return (error); 2508} 2509 2510int 2511mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf) 2512{ 2513 int error; 2514 2515 if (!mac_enforce_network) 2516 return (0); 2517 2518 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr")); 2519 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED)) 2520 printf("%s%d: not initialized\n", ifnet->if_name, 2521 ifnet->if_unit); 2522 2523 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf, 2524 &mbuf->m_pkthdr.label); 2525 2526 return (error); 2527} 2528 2529int 2530mac_check_mount_stat(struct ucred *cred, struct mount *mount) 2531{ 2532 int error; 2533 2534 if (!mac_enforce_fs) 2535 return (0); 2536 2537 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel); 2538 2539 return (error); 2540} 2541 2542int 2543mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 2544 void *data) 2545{ 2546 int error; 2547 2548 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 2549 2550 return (error); 2551} 2552 2553int 2554mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 2555{ 2556 int error; 2557 2558 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 2559 2560 return (error); 2561} 2562 2563int 2564mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 2565{ 2566 int error; 2567 2568 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 2569 2570 return (error); 2571} 2572 2573static int 2574mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 2575 struct label *newlabel) 2576{ 2577 int error; 2578 2579 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 2580 2581 return (error); 2582} 2583 2584int 2585mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 2586{ 2587 int error; 2588 2589 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 2590 2591 return (error); 2592} 2593 2594int 2595mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 2596{ 2597 int error; 2598 2599 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 2600 2601 return (error); 2602} 2603 2604int 2605mac_check_proc_debug(struct ucred *cred, struct proc *proc) 2606{ 2607 int error; 2608 2609 PROC_LOCK_ASSERT(proc, MA_OWNED); 2610 2611 if (!mac_enforce_process) 2612 return (0); 2613 2614 MAC_CHECK(check_proc_debug, cred, proc); 2615 2616 return (error); 2617} 2618 2619int 2620mac_check_proc_sched(struct ucred *cred, struct proc *proc) 2621{ 2622 int error; 2623 2624 PROC_LOCK_ASSERT(proc, MA_OWNED); 2625 2626 if (!mac_enforce_process) 2627 return (0); 2628 2629 MAC_CHECK(check_proc_sched, cred, proc); 2630 2631 return (error); 2632} 2633 2634int 2635mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 2636{ 2637 int error; 2638 2639 PROC_LOCK_ASSERT(proc, MA_OWNED); 2640 2641 if (!mac_enforce_process) 2642 return (0); 2643 2644 MAC_CHECK(check_proc_signal, cred, proc, signum); 2645 2646 return (error); 2647} 2648 2649int 2650mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 2651 struct sockaddr *sockaddr) 2652{ 2653 int error; 2654 2655 if (!mac_enforce_socket) 2656 return (0); 2657 2658 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label, 2659 sockaddr); 2660 2661 return (error); 2662} 2663 2664int 2665mac_check_socket_connect(struct ucred *cred, struct socket *socket, 2666 struct sockaddr *sockaddr) 2667{ 2668 int error; 2669 2670 if (!mac_enforce_socket) 2671 return (0); 2672 2673 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label, 2674 sockaddr); 2675 2676 return (error); 2677} 2678 2679int 2680mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 2681{ 2682 int error; 2683 2684 if (!mac_enforce_socket) 2685 return (0); 2686 2687 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf, 2688 &mbuf->m_pkthdr.label); 2689 2690 return (error); 2691} 2692 2693int 2694mac_check_socket_listen(struct ucred *cred, struct socket *socket) 2695{ 2696 int error; 2697 2698 if (!mac_enforce_socket) 2699 return (0); 2700 2701 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label); 2702 return (error); 2703} 2704 2705static int 2706mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 2707 struct label *newlabel) 2708{ 2709 int error; 2710 2711 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label, 2712 newlabel); 2713 2714 return (error); 2715} 2716 2717int 2718mac_check_socket_visible(struct ucred *cred, struct socket *socket) 2719{ 2720 int error; 2721 2722 if (!mac_enforce_socket) 2723 return (0); 2724 2725 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label); 2726 2727 return (error); 2728} 2729 2730int 2731mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, 2732 struct ifnet *ifnet) 2733{ 2734 struct mac label; 2735 int error; 2736 2737 error = mac_externalize(&ifnet->if_label, &label); 2738 if (error) 2739 return (error); 2740 2741 return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label))); 2742} 2743 2744int 2745mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, 2746 struct ifnet *ifnet) 2747{ 2748 struct mac newlabel; 2749 struct label intlabel; 2750 int error; 2751 2752 error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel)); 2753 if (error) 2754 return (error); 2755 2756 error = mac_internalize(&intlabel, &newlabel); 2757 if (error) 2758 return (error); 2759 2760 /* 2761 * XXX: Note that this is a redundant privilege check, since 2762 * policies impose this check themselves if required by the 2763 * policy. Eventually, this should go away. 2764 */ 2765 error = suser_cred(cred, 0); 2766 if (error) 2767 goto out; 2768 2769 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label, 2770 &intlabel); 2771 if (error) 2772 goto out; 2773 2774 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel); 2775 2776out: 2777 mac_destroy_temp(&intlabel); 2778 return (error); 2779} 2780 2781void 2782mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp) 2783{ 2784 2785 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label); 2786} 2787 2788void 2789mac_create_devfs_device(dev_t dev, struct devfs_dirent *de) 2790{ 2791 2792 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label); 2793} 2794 2795static int 2796mac_stdcreatevnode_ea(struct vnode *vp) 2797{ 2798 int error; 2799 2800 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); 2801 2802 return (error); 2803} 2804 2805void 2806mac_create_devfs_directory(char *dirname, int dirnamelen, 2807 struct devfs_dirent *de) 2808{ 2809 2810 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de, 2811 &de->de_label); 2812} 2813 2814/* 2815 * When a new vnode is created, this call will initialize its label. 2816 */ 2817void 2818mac_create_vnode(struct ucred *cred, struct vnode *parent, 2819 struct vnode *child) 2820{ 2821 int error; 2822 2823 ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); 2824 ASSERT_VOP_LOCKED(child, "mac_create_vnode"); 2825 2826 error = vn_refreshlabel(parent, cred); 2827 if (error) { 2828 printf("mac_create_vnode: vn_refreshlabel returned %d\n", 2829 error); 2830 printf("mac_create_vnode: using old vnode label\n"); 2831 } 2832 2833 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, 2834 &child->v_label); 2835} 2836 2837int 2838mac_setsockopt_label_set(struct ucred *cred, struct socket *so, 2839 struct mac *extmac) 2840{ 2841 struct label intlabel; 2842 int error; 2843 2844 error = mac_internalize(&intlabel, extmac); 2845 if (error) 2846 return (error); 2847 2848 mac_check_socket_relabel(cred, so, &intlabel); 2849 if (error) { 2850 mac_destroy_temp(&intlabel); 2851 return (error); 2852 } 2853 2854 mac_relabel_socket(cred, so, &intlabel); 2855 2856 mac_destroy_temp(&intlabel); 2857 return (0); 2858} 2859 2860int 2861mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 2862{ 2863 int error; 2864 2865 error = mac_check_pipe_relabel(cred, pipe, label); 2866 if (error) 2867 return (error); 2868 2869 mac_relabel_pipe(cred, pipe, label); 2870 2871 return (0); 2872} 2873 2874int 2875mac_getsockopt_label_get(struct ucred *cred, struct socket *so, 2876 struct mac *extmac) 2877{ 2878 2879 return (mac_externalize(&so->so_label, extmac)); 2880} 2881 2882int 2883mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, 2884 struct mac *extmac) 2885{ 2886 2887 return (mac_externalize(&so->so_peerlabel, extmac)); 2888} 2889 2890/* 2891 * Implementation of VOP_SETLABEL() that relies on extended attributes 2892 * to store label data. Can be referenced by filesystems supporting 2893 * extended attributes. 2894 */ 2895int 2896vop_stdsetlabel_ea(struct vop_setlabel_args *ap) 2897{ 2898 struct vnode *vp = ap->a_vp; 2899 struct label *intlabel = ap->a_label; 2900 struct mac extmac; 2901 int error; 2902 2903 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); 2904 2905 /* 2906 * XXX: Eventually call out to EA check/set calls here. 2907 * Be particularly careful to avoid race conditions, 2908 * consistency problems, and stability problems when 2909 * dealing with multiple EAs. In particular, we require 2910 * the ability to write multiple EAs on the same file in 2911 * a single transaction, which the current EA interface 2912 * does not provide. 2913 */ 2914 2915 error = mac_externalize(intlabel, &extmac); 2916 if (error) 2917 return (error); 2918 2919 error = vn_extattr_set(vp, IO_NODELOCKED, 2920 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, 2921 sizeof(extmac), (char *)&extmac, curthread); 2922 if (error) 2923 return (error); 2924 2925 mac_relabel_vnode(ap->a_cred, vp, intlabel); 2926 2927 vp->v_vflag |= VV_CACHEDLABEL; 2928 2929 return (0); 2930} 2931 2932static int 2933vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred) 2934{ 2935 int error; 2936 2937 if (vp->v_mount == NULL) { 2938 /* printf("vn_setlabel: null v_mount\n"); */ 2939 if (vp->v_tag != VT_NON) 2940 printf("vn_setlabel: null v_mount with non-VT_NON\n"); 2941 return (EBADF); 2942 } 2943 2944 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) 2945 return (EOPNOTSUPP); 2946 2947 /* 2948 * Multi-phase commit. First check the policies to confirm the 2949 * change is OK. Then commit via the filesystem. Finally, 2950 * update the actual vnode label. Question: maybe the filesystem 2951 * should update the vnode at the end as part of VOP_SETLABEL()? 2952 */ 2953 error = mac_check_vnode_relabel(cred, vp, intlabel); 2954 if (error) 2955 return (error); 2956 2957 /* 2958 * VADMIN provides the opportunity for the filesystem to make 2959 * decisions about who is and is not able to modify labels 2960 * and protections on files. This might not be right. We can't 2961 * assume VOP_SETLABEL() will do it, because we might implement 2962 * that as part of vop_stdsetlabel_ea(). 2963 */ 2964 error = VOP_ACCESS(vp, VADMIN, cred, curthread); 2965 if (error) 2966 return (error); 2967 2968 error = VOP_SETLABEL(vp, intlabel, cred, curthread); 2969 if (error) 2970 return (error); 2971 2972 return (0); 2973} 2974 2975/* 2976 * MPSAFE 2977 */ 2978int 2979__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 2980{ 2981 struct mac extmac; 2982 int error; 2983 2984 error = mac_externalize(&td->td_ucred->cr_label, &extmac); 2985 if (error == 0) 2986 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 2987 2988 return (error); 2989} 2990 2991/* 2992 * MPSAFE 2993 * 2994 * XXX: Needs to be re-written for proc locking. 2995 */ 2996int 2997__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 2998{ 2999 struct ucred *newcred, *oldcred; 3000 struct proc *p; 3001 struct mac extmac; 3002 struct label intlabel; 3003 int error; 3004 3005 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3006 if (error) 3007 return (error); 3008 3009 error = mac_internalize(&intlabel, &extmac); 3010 if (error) 3011 return (error); 3012 3013 newcred = crget(); 3014 3015 p = td->td_proc; 3016 PROC_LOCK(p); 3017 oldcred = p->p_ucred; 3018 3019 error = mac_check_cred_relabel(oldcred, &intlabel); 3020 if (error) { 3021 PROC_UNLOCK(p); 3022 mac_destroy_temp(&intlabel); 3023 crfree(newcred); 3024 return (error); 3025 } 3026 3027 setsugid(p); 3028 crcopy(newcred, oldcred); 3029 PROC_UNLOCK(p); 3030 mac_relabel_cred(newcred, &intlabel); 3031 3032 PROC_LOCK(p); 3033 p->p_ucred = newcred; 3034 PROC_UNLOCK(p); 3035 crfree(oldcred); 3036 mac_destroy_temp(&intlabel); 3037 return (0); 3038} 3039 3040/* 3041 * MPSAFE 3042 */ 3043int 3044__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3045{ 3046 struct file *fp; 3047 struct mac extmac; 3048 struct vnode *vp; 3049 struct pipe *pipe; 3050 int error; 3051 3052 mtx_lock(&Giant); 3053 3054 error = fget(td, SCARG(uap, fd), &fp); 3055 if (error) 3056 goto out; 3057 3058 switch (fp->f_type) { 3059 case DTYPE_FIFO: 3060 case DTYPE_VNODE: 3061 vp = (struct vnode *)fp->f_data; 3062 3063 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3064 error = vn_refreshlabel(vp, td->td_ucred); 3065 if (error == 0) 3066 error = mac_externalize(&vp->v_label, &extmac); 3067 VOP_UNLOCK(vp, 0, td); 3068 break; 3069 case DTYPE_PIPE: 3070 pipe = (struct pipe *)fp->f_data; 3071 error = mac_externalize(pipe->pipe_label, &extmac); 3072 break; 3073 default: 3074 error = EINVAL; 3075 } 3076 3077 if (error == 0) 3078 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3079 3080 fdrop(fp, td); 3081 3082out: 3083 mtx_unlock(&Giant); 3084 return (error); 3085} 3086 3087/* 3088 * MPSAFE 3089 */ 3090int 3091__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3092{ 3093 struct nameidata nd; 3094 struct mac extmac; 3095 int error; 3096 3097 mtx_lock(&Giant); 3098 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3099 SCARG(uap, path_p), td); 3100 error = namei(&nd); 3101 if (error) 3102 goto out; 3103 3104 error = vn_refreshlabel(nd.ni_vp, td->td_ucred); 3105 if (error == 0) 3106 error = mac_externalize(&nd.ni_vp->v_label, &extmac); 3107 NDFREE(&nd, 0); 3108 if (error) 3109 goto out; 3110 3111 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac)); 3112 3113out: 3114 mtx_unlock(&Giant); 3115 return (error); 3116} 3117 3118/* 3119 * MPSAFE 3120 */ 3121int 3122__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3123{ 3124 struct file *fp; 3125 struct mac extmac; 3126 struct label intlabel; 3127 struct mount *mp; 3128 struct vnode *vp; 3129 struct pipe *pipe; 3130 int error; 3131 3132 mtx_lock(&Giant); 3133 error = fget(td, SCARG(uap, fd), &fp); 3134 if (error) 3135 goto out1; 3136 3137 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3138 if (error) 3139 goto out2; 3140 3141 error = mac_internalize(&intlabel, &extmac); 3142 if (error) 3143 goto out2; 3144 3145 switch (fp->f_type) { 3146 case DTYPE_FIFO: 3147 case DTYPE_VNODE: 3148 vp = (struct vnode *)fp->f_data; 3149 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 3150 if (error != 0) 3151 break; 3152 3153 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3154 error = vn_setlabel(vp, &intlabel, td->td_ucred); 3155 VOP_UNLOCK(vp, 0, td); 3156 vn_finished_write(mp); 3157 mac_destroy_temp(&intlabel); 3158 break; 3159 case DTYPE_PIPE: 3160 pipe = (struct pipe *)fp->f_data; 3161 error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel); 3162 break; 3163 default: 3164 error = EINVAL; 3165 } 3166 3167out2: 3168 fdrop(fp, td); 3169out1: 3170 mtx_unlock(&Giant); 3171 return (error); 3172} 3173 3174/* 3175 * MPSAFE 3176 */ 3177int 3178__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3179{ 3180 struct nameidata nd; 3181 struct mac extmac; 3182 struct label intlabel; 3183 struct mount *mp; 3184 int error; 3185 3186 mtx_lock(&Giant); 3187 3188 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac)); 3189 if (error) 3190 goto out; 3191 3192 error = mac_internalize(&intlabel, &extmac); 3193 if (error) 3194 goto out; 3195 3196 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, 3197 SCARG(uap, path_p), td); 3198 error = namei(&nd); 3199 if (error) 3200 goto out2; 3201 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3202 if (error) 3203 goto out2; 3204 3205 error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred); 3206 3207 vn_finished_write(mp); 3208out2: 3209 mac_destroy_temp(&intlabel); 3210 NDFREE(&nd, 0); 3211out: 3212 mtx_unlock(&Giant); 3213 return (error); 3214} 3215 3216SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 3217SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 3218 3219#else /* !MAC */ 3220 3221int 3222__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 3223{ 3224 3225 return (ENOSYS); 3226} 3227 3228int 3229__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 3230{ 3231 3232 return (ENOSYS); 3233} 3234 3235int 3236__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 3237{ 3238 3239 return (ENOSYS); 3240} 3241 3242int 3243__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 3244{ 3245 3246 return (ENOSYS); 3247} 3248 3249int 3250__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 3251{ 3252 3253 return (ENOSYS); 3254} 3255 3256int 3257__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 3258{ 3259 3260 return (ENOSYS); 3261} 3262 3263#endif /* !MAC */ 3264