mac_framework.c revision 255945
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 255945 2013-09-29 20:21:34Z kib $"); 74116182Sobrien 75100894Srwatson#include <sys/param.h> 76228433Savg#include <sys/systm.h> 77106856Srwatson#include <sys/condvar.h> 78100979Srwatson#include <sys/kernel.h> 79100979Srwatson#include <sys/lock.h> 80100979Srwatson#include <sys/mac.h> 81101712Srwatson#include <sys/module.h> 82192881Srwatson#include <sys/rmlock.h> 83187666Srwatson#include <sys/sdt.h> 84189797Srwatson#include <sys/sx.h> 85100979Srwatson#include <sys/sysctl.h> 86100894Srwatson 87163606Srwatson#include <security/mac/mac_framework.h> 88121374Srwatson#include <security/mac/mac_internal.h> 89165469Srwatson#include <security/mac/mac_policy.h> 90121374Srwatson 91101712Srwatson/* 92189503Srwatson * DTrace SDT providers for MAC. 93187666Srwatson */ 94187666SrwatsonSDT_PROVIDER_DEFINE(mac); 95189503SrwatsonSDT_PROVIDER_DEFINE(mac_framework); 96189503Srwatson 97211616SrpauloSDT_PROBE_DEFINE2(mac, kernel, policy, modevent, modevent, "int", 98187666Srwatson "struct mac_policy_conf *mpc"); 99211616SrpauloSDT_PROBE_DEFINE1(mac, kernel, policy, register, register, 100211616Srpaulo "struct mac_policy_conf *"); 101211616SrpauloSDT_PROBE_DEFINE1(mac, kernel, policy, unregister, unregister, 102211616Srpaulo "struct mac_policy_conf *"); 103187666Srwatson 104187666Srwatson/* 105165586Srwatson * Root sysctl node for all MAC and MAC policy controls. 106101712Srwatson */ 107100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 108100979Srwatson "TrustedBSD MAC policy controls"); 109104517Srwatson 110165411Srwatson/* 111165586Srwatson * Declare that the kernel provides MAC support, version 3 (FreeBSD 7.x). 112165586Srwatson * This permits modules to refuse to be loaded if the necessary support isn't 113165586Srwatson * present, even if it's pre-boot. 114165586Srwatson */ 115165595SrwatsonMODULE_VERSION(kernel_mac_support, MAC_VERSION); 116165595Srwatson 117165586Srwatsonstatic unsigned int mac_version = MAC_VERSION; 118165586SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, version, CTLFLAG_RD, &mac_version, 0, 119165586Srwatson ""); 120165586Srwatson 121165586Srwatson/* 122165411Srwatson * Labels consist of a indexed set of "slots", which are allocated policies 123165411Srwatson * as required. The MAC Framework maintains a bitmask of slots allocated so 124165411Srwatson * far to prevent reuse. Slots cannot be reused, as the MAC Framework 125165411Srwatson * guarantees that newly allocated slots in labels will be NULL unless 126165411Srwatson * otherwise initialized, and because we do not have a mechanism to garbage 127165411Srwatson * collect slots on policy unload. As labeled policies tend to be statically 128165411Srwatson * loaded during boot, and not frequently unloaded and reloaded, this is not 129165411Srwatson * generally an issue. 130165411Srwatson */ 131114846Srwatson#if MAC_MAX_SLOTS > 32 132114846Srwatson#error "MAC_MAX_SLOTS too large" 133100979Srwatson#endif 134105497Srwatson 135114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 136114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 137165586SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, &mac_max_slots, 138165586Srwatson 0, ""); 139100979Srwatson 140105959Srwatson/* 141105959Srwatson * Has the kernel started generating labeled objects yet? All read/write 142105959Srwatson * access to this variable is serialized during the boot process. Following 143105959Srwatson * the end of serialization, we don't update this flag; no locking. 144105959Srwatson */ 145165595Srwatsonstatic int mac_late = 0; 146100979Srwatson 147105988Srwatson/* 148182063Srwatson * Each policy declares a mask of object types requiring labels to be 149182063Srwatson * allocated for them. For convenience, we combine and cache the bitwise or 150182063Srwatson * of the per-policy object flags to track whether we will allocate a label 151182063Srwatson * for an object type at run-time. 152113487Srwatson */ 153182063Srwatsonuint64_t mac_labeled; 154217325SmdfSYSCTL_UQUAD(_security_mac, OID_AUTO, labeled, CTLFLAG_RD, &mac_labeled, 0, 155182063Srwatson "Mask of object types being labeled"); 156113487Srwatson 157105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 158100979Srwatson 159100979Srwatson/* 160189797Srwatson * MAC policy modules are placed in one of two lists: mac_static_policy_list, 161189797Srwatson * for policies that are loaded early and cannot be unloaded, and 162189797Srwatson * mac_policy_list, which holds policies either loaded later in the boot 163189797Srwatson * cycle or that may be unloaded. The static policy list does not require 164189797Srwatson * locks to iterate over, but the dynamic list requires synchronization. 165189797Srwatson * Support for dynamic policy loading can be compiled out using the 166189797Srwatson * MAC_STATIC kernel option. 167114806Srwatson * 168189797Srwatson * The dynamic policy list is protected by two locks: modifying the list 169189797Srwatson * requires both locks to be held exclusively. One of the locks, 170192881Srwatson * mac_policy_rm, is acquired over policy entry points that will never sleep; 171189797Srwatson * the other, mac_policy_sx, is acquire over policy entry points that may 172189797Srwatson * sleep. The former category will be used when kernel locks may be held 173189797Srwatson * over calls to the MAC Framework, during network processing in ithreads, 174189797Srwatson * etc. The latter will tend to involve potentially blocking memory 175189797Srwatson * allocations, extended attribute I/O, etc. 176100979Srwatson */ 177128885Srwatson#ifndef MAC_STATIC 178192881Srwatsonstatic struct rmlock mac_policy_rm; /* Non-sleeping entry points. */ 179189797Srwatsonstatic struct sx mac_policy_sx; /* Sleeping entry points. */ 180128885Srwatson#endif 181189797Srwatson 182121372Srwatsonstruct mac_policy_list_head mac_policy_list; 183121372Srwatsonstruct mac_policy_list_head mac_static_policy_list; 184193332Srwatsonu_int mac_policy_count; /* Registered policy count. */ 185100979Srwatson 186189797Srwatsonstatic void mac_policy_xlock(void); 187189797Srwatsonstatic void mac_policy_xlock_assert(void); 188189797Srwatsonstatic void mac_policy_xunlock(void); 189189797Srwatson 190121372Srwatsonvoid 191192881Srwatsonmac_policy_slock_nosleep(struct rm_priotracker *tracker) 192114806Srwatson{ 193122454Srwatson 194128885Srwatson#ifndef MAC_STATIC 195137072Srwatson if (!mac_late) 196137072Srwatson return; 197137072Srwatson 198192881Srwatson rm_rlock(&mac_policy_rm, tracker); 199128885Srwatson#endif 200114806Srwatson} 201106856Srwatson 202121372Srwatsonvoid 203189797Srwatsonmac_policy_slock_sleep(void) 204114806Srwatson{ 205122454Srwatson 206189797Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 207189797Srwatson "mac_policy_slock_sleep"); 208189797Srwatson 209128885Srwatson#ifndef MAC_STATIC 210137072Srwatson if (!mac_late) 211137072Srwatson return; 212137072Srwatson 213189797Srwatson sx_slock(&mac_policy_sx); 214128885Srwatson#endif 215114806Srwatson} 216113487Srwatson 217121372Srwatsonvoid 218192881Srwatsonmac_policy_sunlock_nosleep(struct rm_priotracker *tracker) 219114806Srwatson{ 220189797Srwatson 221165708Srwatson#ifndef MAC_STATIC 222137072Srwatson if (!mac_late) 223137072Srwatson return; 224137072Srwatson 225192881Srwatson rm_runlock(&mac_policy_rm, tracker); 226128885Srwatson#endif 227114806Srwatson} 228100979Srwatson 229121372Srwatsonvoid 230189797Srwatsonmac_policy_sunlock_sleep(void) 231114806Srwatson{ 232122454Srwatson 233128885Srwatson#ifndef MAC_STATIC 234137072Srwatson if (!mac_late) 235137072Srwatson return; 236137072Srwatson 237189797Srwatson sx_sunlock(&mac_policy_sx); 238128885Srwatson#endif 239114806Srwatson} 240114806Srwatson 241189797Srwatsonstatic void 242189797Srwatsonmac_policy_xlock(void) 243114806Srwatson{ 244189797Srwatson 245189797Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 246189797Srwatson "mac_policy_xlock()"); 247189797Srwatson 248128885Srwatson#ifndef MAC_STATIC 249189797Srwatson if (!mac_late) 250189797Srwatson return; 251114806Srwatson 252189797Srwatson sx_xlock(&mac_policy_sx); 253192881Srwatson rm_wlock(&mac_policy_rm); 254189797Srwatson#endif 255189797Srwatson} 256189797Srwatson 257189797Srwatsonstatic void 258189797Srwatsonmac_policy_xunlock(void) 259189797Srwatson{ 260189797Srwatson 261189797Srwatson#ifndef MAC_STATIC 262137072Srwatson if (!mac_late) 263189797Srwatson return; 264137072Srwatson 265192881Srwatson rm_wunlock(&mac_policy_rm); 266189797Srwatson sx_xunlock(&mac_policy_sx); 267128885Srwatson#endif 268114806Srwatson} 269114806Srwatson 270189797Srwatsonstatic void 271189797Srwatsonmac_policy_xlock_assert(void) 272114806Srwatson{ 273189797Srwatson 274165708Srwatson#ifndef MAC_STATIC 275137072Srwatson if (!mac_late) 276137072Srwatson return; 277137072Srwatson 278192881Srwatson /* XXXRW: rm_assert(&mac_policy_rm, RA_WLOCKED); */ 279189797Srwatson sx_assert(&mac_policy_sx, SA_XLOCKED); 280128885Srwatson#endif 281114806Srwatson} 282114806Srwatson 283100979Srwatson/* 284100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks. 285100979Srwatson */ 286100979Srwatsonstatic void 287100979Srwatsonmac_init(void) 288100979Srwatson{ 289100979Srwatson 290114806Srwatson LIST_INIT(&mac_static_policy_list); 291100979Srwatson LIST_INIT(&mac_policy_list); 292122524Srwatson mac_labelzone_init(); 293114806Srwatson 294128885Srwatson#ifndef MAC_STATIC 295255945Skib rm_init_flags(&mac_policy_rm, "mac_policy_rm", RM_NOWITNESS | 296255945Skib RM_RECURSE); 297193355Srwatson sx_init_flags(&mac_policy_sx, "mac_policy_sx", SX_NOWITNESS); 298128885Srwatson#endif 299100979Srwatson} 300100979Srwatson 301100979Srwatson/* 302165411Srwatson * For the purposes of modules that want to know if they were loaded "early", 303165411Srwatson * set the mac_late flag once we've processed modules either linked into the 304165411Srwatson * kernel, or loaded before the kernel startup. 305100979Srwatson */ 306100979Srwatsonstatic void 307100979Srwatsonmac_late_init(void) 308100979Srwatson{ 309100979Srwatson 310100979Srwatson mac_late = 1; 311100979Srwatson} 312100979Srwatson 313100979Srwatson/* 314187016Srwatson * Given a policy, derive from its set of non-NULL label init methods what 315187016Srwatson * object types the policy is interested in. 316113487Srwatson */ 317187016Srwatsonstatic uint64_t 318187016Srwatsonmac_policy_getlabeled(struct mac_policy_conf *mpc) 319187016Srwatson{ 320187016Srwatson uint64_t labeled; 321187016Srwatson 322187016Srwatson#define MPC_FLAG(method, flag) \ 323187016Srwatson if (mpc->mpc_ops->mpo_ ## method != NULL) \ 324187016Srwatson labeled |= (flag); \ 325187016Srwatson 326187016Srwatson labeled = 0; 327187016Srwatson MPC_FLAG(cred_init_label, MPC_OBJECT_CRED); 328187016Srwatson MPC_FLAG(proc_init_label, MPC_OBJECT_PROC); 329187016Srwatson MPC_FLAG(vnode_init_label, MPC_OBJECT_VNODE); 330187016Srwatson MPC_FLAG(inpcb_init_label, MPC_OBJECT_INPCB); 331187016Srwatson MPC_FLAG(socket_init_label, MPC_OBJECT_SOCKET); 332187016Srwatson MPC_FLAG(devfs_init_label, MPC_OBJECT_DEVFS); 333187016Srwatson MPC_FLAG(mbuf_init_label, MPC_OBJECT_MBUF); 334187016Srwatson MPC_FLAG(ipq_init_label, MPC_OBJECT_IPQ); 335187016Srwatson MPC_FLAG(ifnet_init_label, MPC_OBJECT_IFNET); 336187016Srwatson MPC_FLAG(bpfdesc_init_label, MPC_OBJECT_BPFDESC); 337187016Srwatson MPC_FLAG(pipe_init_label, MPC_OBJECT_PIPE); 338187016Srwatson MPC_FLAG(mount_init_label, MPC_OBJECT_MOUNT); 339187016Srwatson MPC_FLAG(posixsem_init_label, MPC_OBJECT_POSIXSEM); 340187016Srwatson MPC_FLAG(posixshm_init_label, MPC_OBJECT_POSIXSHM); 341187016Srwatson MPC_FLAG(sysvmsg_init_label, MPC_OBJECT_SYSVMSG); 342187016Srwatson MPC_FLAG(sysvmsq_init_label, MPC_OBJECT_SYSVMSQ); 343187016Srwatson MPC_FLAG(sysvsem_init_label, MPC_OBJECT_SYSVSEM); 344187016Srwatson MPC_FLAG(sysvshm_init_label, MPC_OBJECT_SYSVSHM); 345187016Srwatson MPC_FLAG(syncache_init_label, MPC_OBJECT_SYNCACHE); 346187016Srwatson MPC_FLAG(ip6q_init_label, MPC_OBJECT_IP6Q); 347187016Srwatson 348187016Srwatson#undef MPC_FLAG 349187016Srwatson return (labeled); 350187016Srwatson} 351187016Srwatson 352187016Srwatson/* 353187016Srwatson * When policies are loaded or unloaded, walk the list of registered policies 354187016Srwatson * and built mac_labeled, a bitmask representing the union of all objects 355187016Srwatson * requiring labels across all policies. 356187016Srwatson */ 357113487Srwatsonstatic void 358193332Srwatsonmac_policy_update(void) 359113487Srwatson{ 360182063Srwatson struct mac_policy_conf *mpc; 361113487Srwatson 362189797Srwatson mac_policy_xlock_assert(); 363113487Srwatson 364182063Srwatson mac_labeled = 0; 365193332Srwatson mac_policy_count = 0; 366193332Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 367187016Srwatson mac_labeled |= mac_policy_getlabeled(mpc); 368193332Srwatson mac_policy_count++; 369193332Srwatson } 370193332Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 371187016Srwatson mac_labeled |= mac_policy_getlabeled(mpc); 372193332Srwatson mac_policy_count++; 373193332Srwatson } 374113487Srwatson} 375113487Srwatson 376100979Srwatsonstatic int 377100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 378100979Srwatson{ 379100979Srwatson struct mac_policy_conf *tmpc; 380114806Srwatson int error, slot, static_entry; 381100979Srwatson 382114806Srwatson error = 0; 383114806Srwatson 384114806Srwatson /* 385165411Srwatson * We don't technically need exclusive access while !mac_late, but 386165411Srwatson * hold it for assertion consistency. 387114806Srwatson */ 388189797Srwatson mac_policy_xlock(); 389114806Srwatson 390114806Srwatson /* 391165411Srwatson * If the module can potentially be unloaded, or we're loading late, 392165411Srwatson * we have to stick it in the non-static list and pay an extra 393165411Srwatson * performance overhead. Otherwise, we can pay a light locking cost 394165411Srwatson * and stick it in the static list. 395114806Srwatson */ 396114806Srwatson static_entry = (!mac_late && 397114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 398114806Srwatson 399114806Srwatson if (static_entry) { 400114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 401114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 402114806Srwatson error = EEXIST; 403114806Srwatson goto out; 404114806Srwatson } 405100979Srwatson } 406114806Srwatson } else { 407114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 408114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 409114806Srwatson error = EEXIST; 410114806Srwatson goto out; 411114806Srwatson } 412114806Srwatson } 413100979Srwatson } 414100979Srwatson if (mpc->mpc_field_off != NULL) { 415114846Srwatson slot = ffs(mac_slot_offsets_free); 416100979Srwatson if (slot == 0) { 417114806Srwatson error = ENOMEM; 418114806Srwatson goto out; 419100979Srwatson } 420100979Srwatson slot--; 421114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 422100979Srwatson *mpc->mpc_field_off = slot; 423100979Srwatson } 424100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 425100979Srwatson 426114806Srwatson /* 427165411Srwatson * If we're loading a MAC module after the framework has initialized, 428165411Srwatson * it has to go into the dynamic list. If we're loading it before 429165411Srwatson * we've finished initializing, it can go into the static list with 430165411Srwatson * weaker locker requirements. 431114806Srwatson */ 432114806Srwatson if (static_entry) 433114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 434114806Srwatson else 435114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 436114806Srwatson 437165411Srwatson /* 438165411Srwatson * Per-policy initialization. Currently, this takes place under the 439165411Srwatson * exclusive lock, so policies must not sleep in their init method. 440165411Srwatson * In the future, we may want to separate "init" from "start", with 441165411Srwatson * "init" occuring without the lock held. Likewise, on tear-down, 442165411Srwatson * breaking out "stop" from "destroy". 443165411Srwatson */ 444100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 445100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 446193332Srwatson mac_policy_update(); 447100979Srwatson 448187666Srwatson SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0); 449100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 450100979Srwatson mpc->mpc_name); 451100979Srwatson 452114806Srwatsonout: 453189797Srwatson mac_policy_xunlock(); 454114806Srwatson return (error); 455100979Srwatson} 456100979Srwatson 457100979Srwatsonstatic int 458100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 459100979Srwatson{ 460100979Srwatson 461104520Srwatson /* 462165411Srwatson * If we fail the load, we may get a request to unload. Check to see 463165411Srwatson * if we did the run-time registration, and if not, silently succeed. 464104520Srwatson */ 465189797Srwatson mac_policy_xlock(); 466104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 467189797Srwatson mac_policy_xunlock(); 468104520Srwatson return (0); 469104520Srwatson } 470100979Srwatson#if 0 471100979Srwatson /* 472100979Srwatson * Don't allow unloading modules with private data. 473100979Srwatson */ 474104520Srwatson if (mpc->mpc_field_off != NULL) { 475189797Srwatson mac_policy_xunlock(); 476100979Srwatson return (EBUSY); 477104520Srwatson } 478100979Srwatson#endif 479104520Srwatson /* 480165411Srwatson * Only allow the unload to proceed if the module is unloadable by 481165411Srwatson * its own definition. 482104520Srwatson */ 483104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 484189797Srwatson mac_policy_xunlock(); 485100979Srwatson return (EBUSY); 486104520Srwatson } 487100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 488100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 489100979Srwatson 490100979Srwatson LIST_REMOVE(mpc, mpc_list); 491106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 492193332Srwatson mac_policy_update(); 493189797Srwatson mac_policy_xunlock(); 494100979Srwatson 495187666Srwatson SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0); 496100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 497100979Srwatson mpc->mpc_name); 498100979Srwatson 499100979Srwatson return (0); 500100979Srwatson} 501100979Srwatson 502100979Srwatson/* 503165646Srwatson * Allow MAC policy modules to register during boot, etc. 504165646Srwatson */ 505165646Srwatsonint 506165646Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 507165646Srwatson{ 508165646Srwatson struct mac_policy_conf *mpc; 509165646Srwatson int error; 510165646Srwatson 511165646Srwatson error = 0; 512165646Srwatson mpc = (struct mac_policy_conf *) data; 513165646Srwatson 514165646Srwatson#ifdef MAC_STATIC 515165646Srwatson if (mac_late) { 516165646Srwatson printf("mac_policy_modevent: MAC_STATIC and late\n"); 517165646Srwatson return (EBUSY); 518165646Srwatson } 519165646Srwatson#endif 520165646Srwatson 521187666Srwatson SDT_PROBE(mac, kernel, policy, modevent, type, mpc, 0, 0, 0); 522165646Srwatson switch (type) { 523165646Srwatson case MOD_LOAD: 524165646Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 525165646Srwatson mac_late) { 526165646Srwatson printf("mac_policy_modevent: can't load %s policy " 527165646Srwatson "after booting\n", mpc->mpc_name); 528165646Srwatson error = EBUSY; 529165646Srwatson break; 530165646Srwatson } 531165646Srwatson error = mac_policy_register(mpc); 532165646Srwatson break; 533165646Srwatson case MOD_UNLOAD: 534165646Srwatson /* Don't unregister the module if it was never registered. */ 535165646Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 536165646Srwatson != 0) 537165646Srwatson error = mac_policy_unregister(mpc); 538165646Srwatson else 539165646Srwatson error = 0; 540165646Srwatson break; 541165646Srwatson default: 542165646Srwatson error = EOPNOTSUPP; 543165646Srwatson break; 544165646Srwatson } 545165646Srwatson 546165646Srwatson return (error); 547165646Srwatson} 548165646Srwatson 549165646Srwatson/* 550100979Srwatson * Define an error value precedence, and given two arguments, selects the 551100979Srwatson * value with the higher precedence. 552100979Srwatson */ 553121371Srwatsonint 554121371Srwatsonmac_error_select(int error1, int error2) 555100979Srwatson{ 556100979Srwatson 557100979Srwatson /* Certain decision-making errors take top priority. */ 558100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 559100979Srwatson return (EDEADLK); 560100979Srwatson 561100979Srwatson /* Invalid arguments should be reported where possible. */ 562100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 563100979Srwatson return (EINVAL); 564100979Srwatson 565100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 566100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 567100979Srwatson return (ESRCH); 568100979Srwatson 569100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 570100979Srwatson return (ENOENT); 571100979Srwatson 572100979Srwatson /* Precedence goes to DAC/MAC protections. */ 573100979Srwatson if (error1 == EACCES || error2 == EACCES) 574100979Srwatson return (EACCES); 575100979Srwatson 576100979Srwatson /* Precedence goes to privilege. */ 577100979Srwatson if (error1 == EPERM || error2 == EPERM) 578100979Srwatson return (EPERM); 579100979Srwatson 580100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 581100979Srwatson if (error1 != 0) 582100979Srwatson return (error1); 583100979Srwatson return (error2); 584100979Srwatson} 585100979Srwatson 586112675Srwatsonint 587105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 588104522Srwatson{ 589105694Srwatson 590120582Srwatson if (mac->m_buflen < 0 || 591120582Srwatson mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 592105694Srwatson return (EINVAL); 593105694Srwatson 594105694Srwatson return (0); 595105694Srwatson} 596105694Srwatson 597100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 598100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 599