mac_framework.c revision 189529
1100894Srwatson/*- 2187666Srwatson * Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson 3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin 4145160Srwatson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5163606Srwatson * Copyright (c) 2005-2006 SPARTA, Inc. 6187016Srwatson * Copyright (c) 2008-2009 Apple Inc. 7100894Srwatson * All rights reserved. 8100894Srwatson * 9100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the 10100894Srwatson * TrustedBSD Project. 11100894Srwatson * 12106392Srwatson * This software was developed for the FreeBSD Project in part by Network 13106392Srwatson * Associates Laboratories, the Security Research Division of Network 14106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 15106392Srwatson * as part of the DARPA CHATS research program. 16100894Srwatson * 17147983Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract 18147983Srwatson * N66001-04-C-6019 ("SEFOS"). 19147983Srwatson * 20189529Srwatson * This software was developed at the University of Cambridge Computer 21189529Srwatson * Laboratory with support from a grant from Google, Inc. 22189529Srwatson * 23100894Srwatson * Redistribution and use in source and binary forms, with or without 24100894Srwatson * modification, are permitted provided that the following conditions 25100894Srwatson * are met: 26100894Srwatson * 1. Redistributions of source code must retain the above copyright 27100894Srwatson * notice, this list of conditions and the following disclaimer. 28100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright 29100894Srwatson * notice, this list of conditions and the following disclaimer in the 30100894Srwatson * documentation and/or other materials provided with the distribution. 31100894Srwatson * 32100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35100894Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42100894Srwatson * SUCH DAMAGE. 43100894Srwatson */ 44116182Sobrien 45122454Srwatson/*- 46165586Srwatson * Framework for extensible kernel access control. This file contains core 47165586Srwatson * kernel infrastructure for the TrustedBSD MAC Framework, including policy 48165586Srwatson * registration, versioning, locking, error composition operator, and system 49165586Srwatson * calls. 50165586Srwatson * 51165586Srwatson * The MAC Framework implements three programming interfaces: 52165586Srwatson * 53165586Srwatson * - The kernel MAC interface, defined in mac_framework.h, and invoked 54165586Srwatson * throughout the kernel to request security decisions, notify of security 55165586Srwatson * related events, etc. 56165586Srwatson * 57165586Srwatson * - The MAC policy module interface, defined in mac_policy.h, which is 58165586Srwatson * implemented by MAC policy modules and invoked by the MAC Framework to 59165586Srwatson * forward kernel security requests and notifications to policy modules. 60165586Srwatson * 61165586Srwatson * - The user MAC API, defined in mac.h, which allows user programs to query 62165586Srwatson * and set label state on objects. 63165586Srwatson * 64165586Srwatson * The majority of the MAC Framework implementation may be found in 65165586Srwatson * src/sys/security/mac. Sample policy modules may be found in 66145414Strhodes * src/sys/security/mac_*. 67100894Srwatson */ 68100894Srwatson 69187666Srwatson#include "opt_kdtrace.h" 70165645Srwatson#include "opt_mac.h" 71165645Srwatson 72116182Sobrien#include <sys/cdefs.h> 73116182Sobrien__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 189529 2009-03-08 10:58:37Z rwatson $"); 74116182Sobrien 75100894Srwatson#include <sys/param.h> 76106856Srwatson#include <sys/condvar.h> 77100979Srwatson#include <sys/kernel.h> 78100979Srwatson#include <sys/lock.h> 79100979Srwatson#include <sys/mutex.h> 80100979Srwatson#include <sys/mac.h> 81101712Srwatson#include <sys/module.h> 82187666Srwatson#include <sys/sdt.h> 83100979Srwatson#include <sys/systm.h> 84100979Srwatson#include <sys/sysctl.h> 85100894Srwatson 86163606Srwatson#include <security/mac/mac_framework.h> 87121374Srwatson#include <security/mac/mac_internal.h> 88165469Srwatson#include <security/mac/mac_policy.h> 89121374Srwatson 90101712Srwatson/* 91189503Srwatson * DTrace SDT providers for MAC. 92187666Srwatson */ 93187666SrwatsonSDT_PROVIDER_DEFINE(mac); 94189503SrwatsonSDT_PROVIDER_DEFINE(mac_framework); 95189503Srwatson 96189311SrwatsonSDT_PROBE_DEFINE2(mac, kernel, policy, modevent, "int", 97187666Srwatson "struct mac_policy_conf *mpc"); 98189311SrwatsonSDT_PROBE_DEFINE1(mac, kernel, policy, register, "struct mac_policy_conf *"); 99189311SrwatsonSDT_PROBE_DEFINE1(mac, kernel, policy, unregister, "struct mac_policy_conf *"); 100187666Srwatson 101187666Srwatson/* 102165586Srwatson * Root sysctl node for all MAC and MAC policy controls. 103101712Srwatson */ 104100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 105100979Srwatson "TrustedBSD MAC policy controls"); 106104517Srwatson 107165411Srwatson/* 108165586Srwatson * Declare that the kernel provides MAC support, version 3 (FreeBSD 7.x). 109165586Srwatson * This permits modules to refuse to be loaded if the necessary support isn't 110165586Srwatson * present, even if it's pre-boot. 111165586Srwatson */ 112165595SrwatsonMODULE_VERSION(kernel_mac_support, MAC_VERSION); 113165595Srwatson 114165586Srwatsonstatic unsigned int mac_version = MAC_VERSION; 115165586SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, version, CTLFLAG_RD, &mac_version, 0, 116165586Srwatson ""); 117165586Srwatson 118165586Srwatson/* 119165411Srwatson * Labels consist of a indexed set of "slots", which are allocated policies 120165411Srwatson * as required. The MAC Framework maintains a bitmask of slots allocated so 121165411Srwatson * far to prevent reuse. Slots cannot be reused, as the MAC Framework 122165411Srwatson * guarantees that newly allocated slots in labels will be NULL unless 123165411Srwatson * otherwise initialized, and because we do not have a mechanism to garbage 124165411Srwatson * collect slots on policy unload. As labeled policies tend to be statically 125165411Srwatson * loaded during boot, and not frequently unloaded and reloaded, this is not 126165411Srwatson * generally an issue. 127165411Srwatson */ 128114846Srwatson#if MAC_MAX_SLOTS > 32 129114846Srwatson#error "MAC_MAX_SLOTS too large" 130100979Srwatson#endif 131105497Srwatson 132114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 133114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 134165586SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, &mac_max_slots, 135165586Srwatson 0, ""); 136100979Srwatson 137105959Srwatson/* 138105959Srwatson * Has the kernel started generating labeled objects yet? All read/write 139105959Srwatson * access to this variable is serialized during the boot process. Following 140105959Srwatson * the end of serialization, we don't update this flag; no locking. 141105959Srwatson */ 142165595Srwatsonstatic int mac_late = 0; 143100979Srwatson 144105988Srwatson/* 145182063Srwatson * Each policy declares a mask of object types requiring labels to be 146182063Srwatson * allocated for them. For convenience, we combine and cache the bitwise or 147182063Srwatson * of the per-policy object flags to track whether we will allocate a label 148182063Srwatson * for an object type at run-time. 149113487Srwatson */ 150182063Srwatsonuint64_t mac_labeled; 151182063SrwatsonSYSCTL_QUAD(_security_mac, OID_AUTO, labeled, CTLFLAG_RD, &mac_labeled, 0, 152182063Srwatson "Mask of object types being labeled"); 153113487Srwatson 154105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 155100979Srwatson 156100979Srwatson/* 157165411Srwatson * mac_static_policy_list holds a list of policy modules that are not loaded 158165411Srwatson * while the system is "live", and cannot be unloaded. These policies can be 159165411Srwatson * invoked without holding the busy count. 160114806Srwatson * 161114806Srwatson * mac_policy_list stores the list of dynamic policies. A busy count is 162165411Srwatson * maintained for the list, stored in mac_policy_busy. The busy count is 163165411Srwatson * protected by mac_policy_mtx; the list may be modified only while the busy 164165411Srwatson * count is 0, requiring that the lock be held to prevent new references to 165165411Srwatson * the list from being acquired. For almost all operations, incrementing the 166165411Srwatson * busy count is sufficient to guarantee consistency, as the list cannot be 167165411Srwatson * modified while the busy count is elevated. For a few special operations 168165411Srwatson * involving a change to the list of active policies, the mtx itself must be 169165411Srwatson * held. A condition variable, mac_policy_cv, is used to signal potential 170165411Srwatson * exclusive consumers that they should try to acquire the lock if a first 171165411Srwatson * attempt at exclusive access fails. 172165411Srwatson * 173165411Srwatson * This design intentionally avoids fairness, and may starve attempts to 174165411Srwatson * acquire an exclusive lock on a busy system. This is required because we 175165411Srwatson * do not ever want acquiring a read reference to perform an unbounded length 176165411Srwatson * sleep. Read references are acquired in ithreads, network isrs, etc, and 177165411Srwatson * any unbounded blocking could lead quickly to deadlock. 178165411Srwatson * 179165411Srwatson * Another reason for never blocking on read references is that the MAC 180165411Srwatson * Framework may recurse: if a policy calls a VOP, for example, this might 181165411Srwatson * lead to vnode life cycle operations (such as init/destroy). 182165586Srwatson * 183165586Srwatson * If the kernel option MAC_STATIC has been compiled in, all locking becomes 184165586Srwatson * a no-op, and the global list of policies is not allowed to change after 185165586Srwatson * early boot. 186165708Srwatson * 187165708Srwatson * XXXRW: Currently, we signal mac_policy_cv every time the framework becomes 188165708Srwatson * unbusy and there is a thread waiting to enter it exclusively. Since it 189165708Srwatson * may take some time before the thread runs, we may issue a lot of signals. 190165708Srwatson * We should instead keep track of the fact that we've signalled, taking into 191165708Srwatson * account that the framework may be busy again by the time the thread runs, 192165708Srwatson * requiring us to re-signal. 193100979Srwatson */ 194128885Srwatson#ifndef MAC_STATIC 195114806Srwatsonstatic struct mtx mac_policy_mtx; 196114806Srwatsonstatic struct cv mac_policy_cv; 197114806Srwatsonstatic int mac_policy_count; 198165708Srwatsonstatic int mac_policy_wait; 199128885Srwatson#endif 200121372Srwatsonstruct mac_policy_list_head mac_policy_list; 201121372Srwatsonstruct mac_policy_list_head mac_static_policy_list; 202100979Srwatson 203106856Srwatson/* 204165411Srwatson * We manually invoke WITNESS_WARN() to allow Witness to generate warnings 205165411Srwatson * even if we don't end up ever triggering the wait at run-time. The 206165411Srwatson * consumer of the exclusive interface must not hold any locks (other than 207165411Srwatson * potentially Giant) since we may sleep for long (potentially indefinite) 208165411Srwatson * periods of time waiting for the framework to become quiescent so that a 209165411Srwatson * policy list change may be made. 210106856Srwatson */ 211121372Srwatsonvoid 212114806Srwatsonmac_policy_grab_exclusive(void) 213114806Srwatson{ 214122454Srwatson 215128885Srwatson#ifndef MAC_STATIC 216137072Srwatson if (!mac_late) 217137072Srwatson return; 218137072Srwatson 219114806Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 220114806Srwatson "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 221114806Srwatson mtx_lock(&mac_policy_mtx); 222165708Srwatson while (mac_policy_count != 0) { 223165708Srwatson mac_policy_wait++; 224114806Srwatson cv_wait(&mac_policy_cv, &mac_policy_mtx); 225165708Srwatson mac_policy_wait--; 226165708Srwatson } 227128885Srwatson#endif 228114806Srwatson} 229106856Srwatson 230121372Srwatsonvoid 231114806Srwatsonmac_policy_assert_exclusive(void) 232114806Srwatson{ 233122454Srwatson 234128885Srwatson#ifndef MAC_STATIC 235137072Srwatson if (!mac_late) 236137072Srwatson return; 237137072Srwatson 238114806Srwatson mtx_assert(&mac_policy_mtx, MA_OWNED); 239114806Srwatson KASSERT(mac_policy_count == 0, 240114806Srwatson ("mac_policy_assert_exclusive(): not exclusive")); 241128885Srwatson#endif 242114806Srwatson} 243113487Srwatson 244121372Srwatsonvoid 245114806Srwatsonmac_policy_release_exclusive(void) 246114806Srwatson{ 247165708Srwatson#ifndef MAC_STATIC 248165708Srwatson int dowakeup; 249100979Srwatson 250137072Srwatson if (!mac_late) 251137072Srwatson return; 252137072Srwatson 253114806Srwatson KASSERT(mac_policy_count == 0, 254114806Srwatson ("mac_policy_release_exclusive(): not exclusive")); 255165708Srwatson dowakeup = (mac_policy_wait != 0); 256114806Srwatson mtx_unlock(&mac_policy_mtx); 257165708Srwatson if (dowakeup) 258165708Srwatson cv_signal(&mac_policy_cv); 259128885Srwatson#endif 260114806Srwatson} 261100979Srwatson 262121372Srwatsonvoid 263114806Srwatsonmac_policy_list_busy(void) 264114806Srwatson{ 265122454Srwatson 266128885Srwatson#ifndef MAC_STATIC 267137072Srwatson if (!mac_late) 268137072Srwatson return; 269137072Srwatson 270114806Srwatson mtx_lock(&mac_policy_mtx); 271114806Srwatson mac_policy_count++; 272114806Srwatson mtx_unlock(&mac_policy_mtx); 273128885Srwatson#endif 274114806Srwatson} 275114806Srwatson 276121372Srwatsonint 277114806Srwatsonmac_policy_list_conditional_busy(void) 278114806Srwatson{ 279128885Srwatson#ifndef MAC_STATIC 280114806Srwatson int ret; 281114806Srwatson 282137072Srwatson if (!mac_late) 283137072Srwatson return (1); 284137072Srwatson 285114806Srwatson mtx_lock(&mac_policy_mtx); 286114806Srwatson if (!LIST_EMPTY(&mac_policy_list)) { 287114806Srwatson mac_policy_count++; 288114806Srwatson ret = 1; 289114806Srwatson } else 290114806Srwatson ret = 0; 291114806Srwatson mtx_unlock(&mac_policy_mtx); 292114806Srwatson return (ret); 293128885Srwatson#else 294128885Srwatson return (1); 295128885Srwatson#endif 296114806Srwatson} 297114806Srwatson 298121372Srwatsonvoid 299114806Srwatsonmac_policy_list_unbusy(void) 300114806Srwatson{ 301165708Srwatson#ifndef MAC_STATIC 302165708Srwatson int dowakeup; 303122454Srwatson 304137072Srwatson if (!mac_late) 305137072Srwatson return; 306137072Srwatson 307114806Srwatson mtx_lock(&mac_policy_mtx); 308114806Srwatson mac_policy_count--; 309114806Srwatson KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 310165708Srwatson dowakeup = (mac_policy_count == 0 && mac_policy_wait != 0); 311165708Srwatson mtx_unlock(&mac_policy_mtx); 312165708Srwatson 313165708Srwatson if (dowakeup) 314114806Srwatson cv_signal(&mac_policy_cv); 315128885Srwatson#endif 316114806Srwatson} 317114806Srwatson 318100979Srwatson/* 319100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks. 320100979Srwatson */ 321100979Srwatsonstatic void 322100979Srwatsonmac_init(void) 323100979Srwatson{ 324100979Srwatson 325114806Srwatson LIST_INIT(&mac_static_policy_list); 326100979Srwatson LIST_INIT(&mac_policy_list); 327122524Srwatson mac_labelzone_init(); 328114806Srwatson 329128885Srwatson#ifndef MAC_STATIC 330114806Srwatson mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 331114806Srwatson cv_init(&mac_policy_cv, "mac_policy_cv"); 332128885Srwatson#endif 333100979Srwatson} 334100979Srwatson 335100979Srwatson/* 336165411Srwatson * For the purposes of modules that want to know if they were loaded "early", 337165411Srwatson * set the mac_late flag once we've processed modules either linked into the 338165411Srwatson * kernel, or loaded before the kernel startup. 339100979Srwatson */ 340100979Srwatsonstatic void 341100979Srwatsonmac_late_init(void) 342100979Srwatson{ 343100979Srwatson 344100979Srwatson mac_late = 1; 345100979Srwatson} 346100979Srwatson 347100979Srwatson/* 348187016Srwatson * Given a policy, derive from its set of non-NULL label init methods what 349187016Srwatson * object types the policy is interested in. 350113487Srwatson */ 351187016Srwatsonstatic uint64_t 352187016Srwatsonmac_policy_getlabeled(struct mac_policy_conf *mpc) 353187016Srwatson{ 354187016Srwatson uint64_t labeled; 355187016Srwatson 356187016Srwatson#define MPC_FLAG(method, flag) \ 357187016Srwatson if (mpc->mpc_ops->mpo_ ## method != NULL) \ 358187016Srwatson labeled |= (flag); \ 359187016Srwatson 360187016Srwatson labeled = 0; 361187016Srwatson MPC_FLAG(cred_init_label, MPC_OBJECT_CRED); 362187016Srwatson MPC_FLAG(proc_init_label, MPC_OBJECT_PROC); 363187016Srwatson MPC_FLAG(vnode_init_label, MPC_OBJECT_VNODE); 364187016Srwatson MPC_FLAG(inpcb_init_label, MPC_OBJECT_INPCB); 365187016Srwatson MPC_FLAG(socket_init_label, MPC_OBJECT_SOCKET); 366187016Srwatson MPC_FLAG(devfs_init_label, MPC_OBJECT_DEVFS); 367187016Srwatson MPC_FLAG(mbuf_init_label, MPC_OBJECT_MBUF); 368187016Srwatson MPC_FLAG(ipq_init_label, MPC_OBJECT_IPQ); 369187016Srwatson MPC_FLAG(ifnet_init_label, MPC_OBJECT_IFNET); 370187016Srwatson MPC_FLAG(bpfdesc_init_label, MPC_OBJECT_BPFDESC); 371187016Srwatson MPC_FLAG(pipe_init_label, MPC_OBJECT_PIPE); 372187016Srwatson MPC_FLAG(mount_init_label, MPC_OBJECT_MOUNT); 373187016Srwatson MPC_FLAG(posixsem_init_label, MPC_OBJECT_POSIXSEM); 374187016Srwatson MPC_FLAG(posixshm_init_label, MPC_OBJECT_POSIXSHM); 375187016Srwatson MPC_FLAG(sysvmsg_init_label, MPC_OBJECT_SYSVMSG); 376187016Srwatson MPC_FLAG(sysvmsq_init_label, MPC_OBJECT_SYSVMSQ); 377187016Srwatson MPC_FLAG(sysvsem_init_label, MPC_OBJECT_SYSVSEM); 378187016Srwatson MPC_FLAG(sysvshm_init_label, MPC_OBJECT_SYSVSHM); 379187016Srwatson MPC_FLAG(syncache_init_label, MPC_OBJECT_SYNCACHE); 380187016Srwatson MPC_FLAG(ip6q_init_label, MPC_OBJECT_IP6Q); 381187016Srwatson 382187016Srwatson#undef MPC_FLAG 383187016Srwatson return (labeled); 384187016Srwatson} 385187016Srwatson 386187016Srwatson/* 387187016Srwatson * When policies are loaded or unloaded, walk the list of registered policies 388187016Srwatson * and built mac_labeled, a bitmask representing the union of all objects 389187016Srwatson * requiring labels across all policies. 390187016Srwatson */ 391113487Srwatsonstatic void 392113487Srwatsonmac_policy_updateflags(void) 393113487Srwatson{ 394182063Srwatson struct mac_policy_conf *mpc; 395113487Srwatson 396114806Srwatson mac_policy_assert_exclusive(); 397113487Srwatson 398182063Srwatson mac_labeled = 0; 399182063Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) 400187016Srwatson mac_labeled |= mac_policy_getlabeled(mpc); 401182063Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) 402187016Srwatson mac_labeled |= mac_policy_getlabeled(mpc); 403113487Srwatson} 404113487Srwatson 405100979Srwatsonstatic int 406100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 407100979Srwatson{ 408100979Srwatson struct mac_policy_conf *tmpc; 409114806Srwatson int error, slot, static_entry; 410100979Srwatson 411114806Srwatson error = 0; 412114806Srwatson 413114806Srwatson /* 414165411Srwatson * We don't technically need exclusive access while !mac_late, but 415165411Srwatson * hold it for assertion consistency. 416114806Srwatson */ 417114806Srwatson mac_policy_grab_exclusive(); 418114806Srwatson 419114806Srwatson /* 420165411Srwatson * If the module can potentially be unloaded, or we're loading late, 421165411Srwatson * we have to stick it in the non-static list and pay an extra 422165411Srwatson * performance overhead. Otherwise, we can pay a light locking cost 423165411Srwatson * and stick it in the static list. 424114806Srwatson */ 425114806Srwatson static_entry = (!mac_late && 426114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 427114806Srwatson 428114806Srwatson if (static_entry) { 429114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 430114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 431114806Srwatson error = EEXIST; 432114806Srwatson goto out; 433114806Srwatson } 434100979Srwatson } 435114806Srwatson } else { 436114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 437114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 438114806Srwatson error = EEXIST; 439114806Srwatson goto out; 440114806Srwatson } 441114806Srwatson } 442100979Srwatson } 443100979Srwatson if (mpc->mpc_field_off != NULL) { 444114846Srwatson slot = ffs(mac_slot_offsets_free); 445100979Srwatson if (slot == 0) { 446114806Srwatson error = ENOMEM; 447114806Srwatson goto out; 448100979Srwatson } 449100979Srwatson slot--; 450114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 451100979Srwatson *mpc->mpc_field_off = slot; 452100979Srwatson } 453100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 454100979Srwatson 455114806Srwatson /* 456165411Srwatson * If we're loading a MAC module after the framework has initialized, 457165411Srwatson * it has to go into the dynamic list. If we're loading it before 458165411Srwatson * we've finished initializing, it can go into the static list with 459165411Srwatson * weaker locker requirements. 460114806Srwatson */ 461114806Srwatson if (static_entry) 462114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 463114806Srwatson else 464114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 465114806Srwatson 466165411Srwatson /* 467165411Srwatson * Per-policy initialization. Currently, this takes place under the 468165411Srwatson * exclusive lock, so policies must not sleep in their init method. 469165411Srwatson * In the future, we may want to separate "init" from "start", with 470165411Srwatson * "init" occuring without the lock held. Likewise, on tear-down, 471165411Srwatson * breaking out "stop" from "destroy". 472165411Srwatson */ 473100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 474100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 475113487Srwatson mac_policy_updateflags(); 476100979Srwatson 477187666Srwatson SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0); 478100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 479100979Srwatson mpc->mpc_name); 480100979Srwatson 481114806Srwatsonout: 482114806Srwatson mac_policy_release_exclusive(); 483114806Srwatson return (error); 484100979Srwatson} 485100979Srwatson 486100979Srwatsonstatic int 487100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 488100979Srwatson{ 489100979Srwatson 490104520Srwatson /* 491165411Srwatson * If we fail the load, we may get a request to unload. Check to see 492165411Srwatson * if we did the run-time registration, and if not, silently succeed. 493104520Srwatson */ 494114806Srwatson mac_policy_grab_exclusive(); 495104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 496114806Srwatson mac_policy_release_exclusive(); 497104520Srwatson return (0); 498104520Srwatson } 499100979Srwatson#if 0 500100979Srwatson /* 501100979Srwatson * Don't allow unloading modules with private data. 502100979Srwatson */ 503104520Srwatson if (mpc->mpc_field_off != NULL) { 504104520Srwatson MAC_POLICY_LIST_UNLOCK(); 505100979Srwatson return (EBUSY); 506104520Srwatson } 507100979Srwatson#endif 508104520Srwatson /* 509165411Srwatson * Only allow the unload to proceed if the module is unloadable by 510165411Srwatson * its own definition. 511104520Srwatson */ 512104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 513114806Srwatson mac_policy_release_exclusive(); 514100979Srwatson return (EBUSY); 515104520Srwatson } 516100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 517100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 518100979Srwatson 519100979Srwatson LIST_REMOVE(mpc, mpc_list); 520106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 521113487Srwatson mac_policy_updateflags(); 522100979Srwatson 523114806Srwatson mac_policy_release_exclusive(); 524114806Srwatson 525187666Srwatson SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0); 526100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 527100979Srwatson mpc->mpc_name); 528100979Srwatson 529100979Srwatson return (0); 530100979Srwatson} 531100979Srwatson 532100979Srwatson/* 533165646Srwatson * Allow MAC policy modules to register during boot, etc. 534165646Srwatson */ 535165646Srwatsonint 536165646Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 537165646Srwatson{ 538165646Srwatson struct mac_policy_conf *mpc; 539165646Srwatson int error; 540165646Srwatson 541165646Srwatson error = 0; 542165646Srwatson mpc = (struct mac_policy_conf *) data; 543165646Srwatson 544165646Srwatson#ifdef MAC_STATIC 545165646Srwatson if (mac_late) { 546165646Srwatson printf("mac_policy_modevent: MAC_STATIC and late\n"); 547165646Srwatson return (EBUSY); 548165646Srwatson } 549165646Srwatson#endif 550165646Srwatson 551187666Srwatson SDT_PROBE(mac, kernel, policy, modevent, type, mpc, 0, 0, 0); 552165646Srwatson switch (type) { 553165646Srwatson case MOD_LOAD: 554165646Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 555165646Srwatson mac_late) { 556165646Srwatson printf("mac_policy_modevent: can't load %s policy " 557165646Srwatson "after booting\n", mpc->mpc_name); 558165646Srwatson error = EBUSY; 559165646Srwatson break; 560165646Srwatson } 561165646Srwatson error = mac_policy_register(mpc); 562165646Srwatson break; 563165646Srwatson case MOD_UNLOAD: 564165646Srwatson /* Don't unregister the module if it was never registered. */ 565165646Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 566165646Srwatson != 0) 567165646Srwatson error = mac_policy_unregister(mpc); 568165646Srwatson else 569165646Srwatson error = 0; 570165646Srwatson break; 571165646Srwatson default: 572165646Srwatson error = EOPNOTSUPP; 573165646Srwatson break; 574165646Srwatson } 575165646Srwatson 576165646Srwatson return (error); 577165646Srwatson} 578165646Srwatson 579165646Srwatson/* 580100979Srwatson * Define an error value precedence, and given two arguments, selects the 581100979Srwatson * value with the higher precedence. 582100979Srwatson */ 583121371Srwatsonint 584121371Srwatsonmac_error_select(int error1, int error2) 585100979Srwatson{ 586100979Srwatson 587100979Srwatson /* Certain decision-making errors take top priority. */ 588100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 589100979Srwatson return (EDEADLK); 590100979Srwatson 591100979Srwatson /* Invalid arguments should be reported where possible. */ 592100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 593100979Srwatson return (EINVAL); 594100979Srwatson 595100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 596100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 597100979Srwatson return (ESRCH); 598100979Srwatson 599100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 600100979Srwatson return (ENOENT); 601100979Srwatson 602100979Srwatson /* Precedence goes to DAC/MAC protections. */ 603100979Srwatson if (error1 == EACCES || error2 == EACCES) 604100979Srwatson return (EACCES); 605100979Srwatson 606100979Srwatson /* Precedence goes to privilege. */ 607100979Srwatson if (error1 == EPERM || error2 == EPERM) 608100979Srwatson return (EPERM); 609100979Srwatson 610100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 611100979Srwatson if (error1 != 0) 612100979Srwatson return (error1); 613100979Srwatson return (error2); 614100979Srwatson} 615100979Srwatson 616112675Srwatsonint 617105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 618104522Srwatson{ 619105694Srwatson 620120582Srwatson if (mac->m_buflen < 0 || 621120582Srwatson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 622105694Srwatson return (EINVAL); 623105694Srwatson 624105694Srwatson return (0); 625105694Srwatson} 626105694Srwatson 627100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 628100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 629