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 69165645Srwatson#include "opt_mac.h" 70165645Srwatson 71116182Sobrien#include <sys/cdefs.h> 72116182Sobrien__FBSDID("$FreeBSD: stable/11/sys/security/mac/mac_framework.c 337465 2018-08-08 17:11:07Z markj $"); 73116182Sobrien 74100894Srwatson#include <sys/param.h> 75228433Savg#include <sys/systm.h> 76106856Srwatson#include <sys/condvar.h> 77100979Srwatson#include <sys/kernel.h> 78100979Srwatson#include <sys/lock.h> 79100979Srwatson#include <sys/mac.h> 80101712Srwatson#include <sys/module.h> 81192881Srwatson#include <sys/rmlock.h> 82187666Srwatson#include <sys/sdt.h> 83189797Srwatson#include <sys/sx.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 96292384SmarkjSDT_PROBE_DEFINE2(mac, , policy, modevent, "int", 97255971Smarkj "struct mac_policy_conf *"); 98292384SmarkjSDT_PROBE_DEFINE1(mac, , policy, register, 99211616Srpaulo "struct mac_policy_conf *"); 100292384SmarkjSDT_PROBE_DEFINE1(mac, , policy, unregister, 101211616Srpaulo "struct mac_policy_conf *"); 102187666Srwatson 103187666Srwatson/* 104165586Srwatson * Root sysctl node for all MAC and MAC policy controls. 105101712Srwatson */ 106100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 107100979Srwatson "TrustedBSD MAC policy controls"); 108104517Srwatson 109165411Srwatson/* 110165586Srwatson * Declare that the kernel provides MAC support, version 3 (FreeBSD 7.x). 111165586Srwatson * This permits modules to refuse to be loaded if the necessary support isn't 112165586Srwatson * present, even if it's pre-boot. 113165586Srwatson */ 114165595SrwatsonMODULE_VERSION(kernel_mac_support, MAC_VERSION); 115165595Srwatson 116165586Srwatsonstatic unsigned int mac_version = MAC_VERSION; 117165586SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, version, CTLFLAG_RD, &mac_version, 0, 118165586Srwatson ""); 119165586Srwatson 120165586Srwatson/* 121165411Srwatson * Labels consist of a indexed set of "slots", which are allocated policies 122165411Srwatson * as required. The MAC Framework maintains a bitmask of slots allocated so 123165411Srwatson * far to prevent reuse. Slots cannot be reused, as the MAC Framework 124165411Srwatson * guarantees that newly allocated slots in labels will be NULL unless 125165411Srwatson * otherwise initialized, and because we do not have a mechanism to garbage 126165411Srwatson * collect slots on policy unload. As labeled policies tend to be statically 127165411Srwatson * loaded during boot, and not frequently unloaded and reloaded, this is not 128165411Srwatson * generally an issue. 129165411Srwatson */ 130114846Srwatson#if MAC_MAX_SLOTS > 32 131114846Srwatson#error "MAC_MAX_SLOTS too large" 132100979Srwatson#endif 133105497Srwatson 134114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 135114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 136165586SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, &mac_max_slots, 137165586Srwatson 0, ""); 138100979Srwatson 139105959Srwatson/* 140105959Srwatson * Has the kernel started generating labeled objects yet? All read/write 141105959Srwatson * access to this variable is serialized during the boot process. Following 142105959Srwatson * the end of serialization, we don't update this flag; no locking. 143105959Srwatson */ 144165595Srwatsonstatic int mac_late = 0; 145100979Srwatson 146105988Srwatson/* 147182063Srwatson * Each policy declares a mask of object types requiring labels to be 148182063Srwatson * allocated for them. For convenience, we combine and cache the bitwise or 149182063Srwatson * of the per-policy object flags to track whether we will allocate a label 150182063Srwatson * for an object type at run-time. 151113487Srwatson */ 152182063Srwatsonuint64_t mac_labeled; 153217325SmdfSYSCTL_UQUAD(_security_mac, OID_AUTO, labeled, CTLFLAG_RD, &mac_labeled, 0, 154182063Srwatson "Mask of object types being labeled"); 155113487Srwatson 156105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 157100979Srwatson 158100979Srwatson/* 159189797Srwatson * MAC policy modules are placed in one of two lists: mac_static_policy_list, 160189797Srwatson * for policies that are loaded early and cannot be unloaded, and 161189797Srwatson * mac_policy_list, which holds policies either loaded later in the boot 162189797Srwatson * cycle or that may be unloaded. The static policy list does not require 163189797Srwatson * locks to iterate over, but the dynamic list requires synchronization. 164189797Srwatson * Support for dynamic policy loading can be compiled out using the 165189797Srwatson * MAC_STATIC kernel option. 166114806Srwatson * 167189797Srwatson * The dynamic policy list is protected by two locks: modifying the list 168189797Srwatson * requires both locks to be held exclusively. One of the locks, 169192881Srwatson * mac_policy_rm, is acquired over policy entry points that will never sleep; 170189797Srwatson * the other, mac_policy_sx, is acquire over policy entry points that may 171189797Srwatson * sleep. The former category will be used when kernel locks may be held 172189797Srwatson * over calls to the MAC Framework, during network processing in ithreads, 173189797Srwatson * etc. The latter will tend to involve potentially blocking memory 174189797Srwatson * allocations, extended attribute I/O, etc. 175100979Srwatson */ 176128885Srwatson#ifndef MAC_STATIC 177192881Srwatsonstatic struct rmlock mac_policy_rm; /* Non-sleeping entry points. */ 178189797Srwatsonstatic struct sx mac_policy_sx; /* Sleeping entry points. */ 179128885Srwatson#endif 180189797Srwatson 181121372Srwatsonstruct mac_policy_list_head mac_policy_list; 182121372Srwatsonstruct mac_policy_list_head mac_static_policy_list; 183193332Srwatsonu_int mac_policy_count; /* Registered policy count. */ 184100979Srwatson 185189797Srwatsonstatic void mac_policy_xlock(void); 186189797Srwatsonstatic void mac_policy_xlock_assert(void); 187189797Srwatsonstatic void mac_policy_xunlock(void); 188189797Srwatson 189121372Srwatsonvoid 190192881Srwatsonmac_policy_slock_nosleep(struct rm_priotracker *tracker) 191114806Srwatson{ 192122454Srwatson 193128885Srwatson#ifndef MAC_STATIC 194137072Srwatson if (!mac_late) 195137072Srwatson return; 196137072Srwatson 197192881Srwatson rm_rlock(&mac_policy_rm, tracker); 198128885Srwatson#endif 199114806Srwatson} 200106856Srwatson 201121372Srwatsonvoid 202189797Srwatsonmac_policy_slock_sleep(void) 203114806Srwatson{ 204122454Srwatson 205189797Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 206189797Srwatson "mac_policy_slock_sleep"); 207189797Srwatson 208128885Srwatson#ifndef MAC_STATIC 209137072Srwatson if (!mac_late) 210137072Srwatson return; 211137072Srwatson 212189797Srwatson sx_slock(&mac_policy_sx); 213128885Srwatson#endif 214114806Srwatson} 215113487Srwatson 216121372Srwatsonvoid 217192881Srwatsonmac_policy_sunlock_nosleep(struct rm_priotracker *tracker) 218114806Srwatson{ 219189797Srwatson 220165708Srwatson#ifndef MAC_STATIC 221137072Srwatson if (!mac_late) 222137072Srwatson return; 223137072Srwatson 224192881Srwatson rm_runlock(&mac_policy_rm, tracker); 225128885Srwatson#endif 226114806Srwatson} 227100979Srwatson 228121372Srwatsonvoid 229189797Srwatsonmac_policy_sunlock_sleep(void) 230114806Srwatson{ 231122454Srwatson 232128885Srwatson#ifndef MAC_STATIC 233137072Srwatson if (!mac_late) 234137072Srwatson return; 235137072Srwatson 236189797Srwatson sx_sunlock(&mac_policy_sx); 237128885Srwatson#endif 238114806Srwatson} 239114806Srwatson 240189797Srwatsonstatic void 241189797Srwatsonmac_policy_xlock(void) 242114806Srwatson{ 243189797Srwatson 244189797Srwatson WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 245189797Srwatson "mac_policy_xlock()"); 246189797Srwatson 247128885Srwatson#ifndef MAC_STATIC 248189797Srwatson if (!mac_late) 249189797Srwatson return; 250114806Srwatson 251189797Srwatson sx_xlock(&mac_policy_sx); 252192881Srwatson rm_wlock(&mac_policy_rm); 253189797Srwatson#endif 254189797Srwatson} 255189797Srwatson 256189797Srwatsonstatic void 257189797Srwatsonmac_policy_xunlock(void) 258189797Srwatson{ 259189797Srwatson 260189797Srwatson#ifndef MAC_STATIC 261137072Srwatson if (!mac_late) 262189797Srwatson return; 263137072Srwatson 264192881Srwatson rm_wunlock(&mac_policy_rm); 265189797Srwatson sx_xunlock(&mac_policy_sx); 266128885Srwatson#endif 267114806Srwatson} 268114806Srwatson 269189797Srwatsonstatic void 270189797Srwatsonmac_policy_xlock_assert(void) 271114806Srwatson{ 272189797Srwatson 273165708Srwatson#ifndef MAC_STATIC 274137072Srwatson if (!mac_late) 275137072Srwatson return; 276137072Srwatson 277192881Srwatson /* XXXRW: rm_assert(&mac_policy_rm, RA_WLOCKED); */ 278189797Srwatson sx_assert(&mac_policy_sx, SA_XLOCKED); 279128885Srwatson#endif 280114806Srwatson} 281114806Srwatson 282100979Srwatson/* 283100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks. 284100979Srwatson */ 285100979Srwatsonstatic void 286100979Srwatsonmac_init(void) 287100979Srwatson{ 288100979Srwatson 289114806Srwatson LIST_INIT(&mac_static_policy_list); 290100979Srwatson LIST_INIT(&mac_policy_list); 291122524Srwatson mac_labelzone_init(); 292114806Srwatson 293128885Srwatson#ifndef MAC_STATIC 294255945Skib rm_init_flags(&mac_policy_rm, "mac_policy_rm", RM_NOWITNESS | 295255945Skib RM_RECURSE); 296193355Srwatson sx_init_flags(&mac_policy_sx, "mac_policy_sx", SX_NOWITNESS); 297128885Srwatson#endif 298100979Srwatson} 299100979Srwatson 300100979Srwatson/* 301165411Srwatson * For the purposes of modules that want to know if they were loaded "early", 302165411Srwatson * set the mac_late flag once we've processed modules either linked into the 303165411Srwatson * kernel, or loaded before the kernel startup. 304100979Srwatson */ 305100979Srwatsonstatic void 306100979Srwatsonmac_late_init(void) 307100979Srwatson{ 308100979Srwatson 309100979Srwatson mac_late = 1; 310100979Srwatson} 311100979Srwatson 312100979Srwatson/* 313187016Srwatson * Given a policy, derive from its set of non-NULL label init methods what 314187016Srwatson * object types the policy is interested in. 315113487Srwatson */ 316187016Srwatsonstatic uint64_t 317187016Srwatsonmac_policy_getlabeled(struct mac_policy_conf *mpc) 318187016Srwatson{ 319187016Srwatson uint64_t labeled; 320187016Srwatson 321187016Srwatson#define MPC_FLAG(method, flag) \ 322187016Srwatson if (mpc->mpc_ops->mpo_ ## method != NULL) \ 323187016Srwatson labeled |= (flag); \ 324187016Srwatson 325187016Srwatson labeled = 0; 326187016Srwatson MPC_FLAG(cred_init_label, MPC_OBJECT_CRED); 327187016Srwatson MPC_FLAG(proc_init_label, MPC_OBJECT_PROC); 328187016Srwatson MPC_FLAG(vnode_init_label, MPC_OBJECT_VNODE); 329187016Srwatson MPC_FLAG(inpcb_init_label, MPC_OBJECT_INPCB); 330187016Srwatson MPC_FLAG(socket_init_label, MPC_OBJECT_SOCKET); 331187016Srwatson MPC_FLAG(devfs_init_label, MPC_OBJECT_DEVFS); 332187016Srwatson MPC_FLAG(mbuf_init_label, MPC_OBJECT_MBUF); 333187016Srwatson MPC_FLAG(ipq_init_label, MPC_OBJECT_IPQ); 334187016Srwatson MPC_FLAG(ifnet_init_label, MPC_OBJECT_IFNET); 335187016Srwatson MPC_FLAG(bpfdesc_init_label, MPC_OBJECT_BPFDESC); 336187016Srwatson MPC_FLAG(pipe_init_label, MPC_OBJECT_PIPE); 337187016Srwatson MPC_FLAG(mount_init_label, MPC_OBJECT_MOUNT); 338187016Srwatson MPC_FLAG(posixsem_init_label, MPC_OBJECT_POSIXSEM); 339187016Srwatson MPC_FLAG(posixshm_init_label, MPC_OBJECT_POSIXSHM); 340187016Srwatson MPC_FLAG(sysvmsg_init_label, MPC_OBJECT_SYSVMSG); 341187016Srwatson MPC_FLAG(sysvmsq_init_label, MPC_OBJECT_SYSVMSQ); 342187016Srwatson MPC_FLAG(sysvsem_init_label, MPC_OBJECT_SYSVSEM); 343187016Srwatson MPC_FLAG(sysvshm_init_label, MPC_OBJECT_SYSVSHM); 344187016Srwatson MPC_FLAG(syncache_init_label, MPC_OBJECT_SYNCACHE); 345187016Srwatson MPC_FLAG(ip6q_init_label, MPC_OBJECT_IP6Q); 346187016Srwatson 347187016Srwatson#undef MPC_FLAG 348187016Srwatson return (labeled); 349187016Srwatson} 350187016Srwatson 351187016Srwatson/* 352187016Srwatson * When policies are loaded or unloaded, walk the list of registered policies 353187016Srwatson * and built mac_labeled, a bitmask representing the union of all objects 354187016Srwatson * requiring labels across all policies. 355187016Srwatson */ 356113487Srwatsonstatic void 357193332Srwatsonmac_policy_update(void) 358113487Srwatson{ 359182063Srwatson struct mac_policy_conf *mpc; 360113487Srwatson 361189797Srwatson mac_policy_xlock_assert(); 362113487Srwatson 363182063Srwatson mac_labeled = 0; 364193332Srwatson mac_policy_count = 0; 365193332Srwatson LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 366187016Srwatson mac_labeled |= mac_policy_getlabeled(mpc); 367193332Srwatson mac_policy_count++; 368193332Srwatson } 369193332Srwatson LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 370187016Srwatson mac_labeled |= mac_policy_getlabeled(mpc); 371193332Srwatson mac_policy_count++; 372193332Srwatson } 373113487Srwatson} 374113487Srwatson 375100979Srwatsonstatic int 376100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc) 377100979Srwatson{ 378100979Srwatson struct mac_policy_conf *tmpc; 379114806Srwatson int error, slot, static_entry; 380100979Srwatson 381114806Srwatson error = 0; 382114806Srwatson 383114806Srwatson /* 384165411Srwatson * We don't technically need exclusive access while !mac_late, but 385165411Srwatson * hold it for assertion consistency. 386114806Srwatson */ 387189797Srwatson mac_policy_xlock(); 388114806Srwatson 389114806Srwatson /* 390165411Srwatson * If the module can potentially be unloaded, or we're loading late, 391165411Srwatson * we have to stick it in the non-static list and pay an extra 392165411Srwatson * performance overhead. Otherwise, we can pay a light locking cost 393165411Srwatson * and stick it in the static list. 394114806Srwatson */ 395114806Srwatson static_entry = (!mac_late && 396114806Srwatson !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 397114806Srwatson 398114806Srwatson if (static_entry) { 399114806Srwatson LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 400114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 401114806Srwatson error = EEXIST; 402114806Srwatson goto out; 403114806Srwatson } 404100979Srwatson } 405114806Srwatson } else { 406114806Srwatson LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 407114806Srwatson if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 408114806Srwatson error = EEXIST; 409114806Srwatson goto out; 410114806Srwatson } 411114806Srwatson } 412100979Srwatson } 413100979Srwatson if (mpc->mpc_field_off != NULL) { 414114846Srwatson slot = ffs(mac_slot_offsets_free); 415100979Srwatson if (slot == 0) { 416114806Srwatson error = ENOMEM; 417114806Srwatson goto out; 418100979Srwatson } 419100979Srwatson slot--; 420114846Srwatson mac_slot_offsets_free &= ~(1 << slot); 421100979Srwatson *mpc->mpc_field_off = slot; 422100979Srwatson } 423100979Srwatson mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 424100979Srwatson 425114806Srwatson /* 426165411Srwatson * If we're loading a MAC module after the framework has initialized, 427165411Srwatson * it has to go into the dynamic list. If we're loading it before 428165411Srwatson * we've finished initializing, it can go into the static list with 429165411Srwatson * weaker locker requirements. 430114806Srwatson */ 431114806Srwatson if (static_entry) 432114806Srwatson LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 433114806Srwatson else 434114806Srwatson LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 435114806Srwatson 436165411Srwatson /* 437165411Srwatson * Per-policy initialization. Currently, this takes place under the 438165411Srwatson * exclusive lock, so policies must not sleep in their init method. 439165411Srwatson * In the future, we may want to separate "init" from "start", with 440299187Spfg * "init" occurring without the lock held. Likewise, on tear-down, 441165411Srwatson * breaking out "stop" from "destroy". 442165411Srwatson */ 443100979Srwatson if (mpc->mpc_ops->mpo_init != NULL) 444100979Srwatson (*(mpc->mpc_ops->mpo_init))(mpc); 445193332Srwatson mac_policy_update(); 446100979Srwatson 447292384Smarkj SDT_PROBE1(mac, , policy, register, mpc); 448100979Srwatson printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 449100979Srwatson mpc->mpc_name); 450100979Srwatson 451114806Srwatsonout: 452189797Srwatson mac_policy_xunlock(); 453114806Srwatson return (error); 454100979Srwatson} 455100979Srwatson 456100979Srwatsonstatic int 457100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc) 458100979Srwatson{ 459100979Srwatson 460104520Srwatson /* 461165411Srwatson * If we fail the load, we may get a request to unload. Check to see 462165411Srwatson * if we did the run-time registration, and if not, silently succeed. 463104520Srwatson */ 464189797Srwatson mac_policy_xlock(); 465104520Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 466189797Srwatson mac_policy_xunlock(); 467104520Srwatson return (0); 468104520Srwatson } 469100979Srwatson#if 0 470100979Srwatson /* 471100979Srwatson * Don't allow unloading modules with private data. 472100979Srwatson */ 473104520Srwatson if (mpc->mpc_field_off != NULL) { 474189797Srwatson mac_policy_xunlock(); 475100979Srwatson return (EBUSY); 476104520Srwatson } 477100979Srwatson#endif 478104520Srwatson /* 479165411Srwatson * Only allow the unload to proceed if the module is unloadable by 480165411Srwatson * its own definition. 481104520Srwatson */ 482104520Srwatson if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 483189797Srwatson mac_policy_xunlock(); 484100979Srwatson return (EBUSY); 485104520Srwatson } 486100979Srwatson if (mpc->mpc_ops->mpo_destroy != NULL) 487100979Srwatson (*(mpc->mpc_ops->mpo_destroy))(mpc); 488100979Srwatson 489100979Srwatson LIST_REMOVE(mpc, mpc_list); 490106856Srwatson mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 491193332Srwatson mac_policy_update(); 492189797Srwatson mac_policy_xunlock(); 493100979Srwatson 494292384Smarkj SDT_PROBE1(mac, , policy, unregister, mpc); 495100979Srwatson printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 496100979Srwatson mpc->mpc_name); 497100979Srwatson 498100979Srwatson return (0); 499100979Srwatson} 500100979Srwatson 501100979Srwatson/* 502165646Srwatson * Allow MAC policy modules to register during boot, etc. 503165646Srwatson */ 504165646Srwatsonint 505165646Srwatsonmac_policy_modevent(module_t mod, int type, void *data) 506165646Srwatson{ 507165646Srwatson struct mac_policy_conf *mpc; 508165646Srwatson int error; 509165646Srwatson 510165646Srwatson error = 0; 511165646Srwatson mpc = (struct mac_policy_conf *) data; 512165646Srwatson 513165646Srwatson#ifdef MAC_STATIC 514165646Srwatson if (mac_late) { 515165646Srwatson printf("mac_policy_modevent: MAC_STATIC and late\n"); 516165646Srwatson return (EBUSY); 517165646Srwatson } 518165646Srwatson#endif 519165646Srwatson 520292384Smarkj SDT_PROBE2(mac, , policy, modevent, type, mpc); 521165646Srwatson switch (type) { 522165646Srwatson case MOD_LOAD: 523165646Srwatson if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 524165646Srwatson mac_late) { 525165646Srwatson printf("mac_policy_modevent: can't load %s policy " 526165646Srwatson "after booting\n", mpc->mpc_name); 527165646Srwatson error = EBUSY; 528165646Srwatson break; 529165646Srwatson } 530165646Srwatson error = mac_policy_register(mpc); 531165646Srwatson break; 532165646Srwatson case MOD_UNLOAD: 533165646Srwatson /* Don't unregister the module if it was never registered. */ 534165646Srwatson if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 535165646Srwatson != 0) 536165646Srwatson error = mac_policy_unregister(mpc); 537165646Srwatson else 538165646Srwatson error = 0; 539165646Srwatson break; 540165646Srwatson default: 541165646Srwatson error = EOPNOTSUPP; 542165646Srwatson break; 543165646Srwatson } 544165646Srwatson 545165646Srwatson return (error); 546165646Srwatson} 547165646Srwatson 548165646Srwatson/* 549100979Srwatson * Define an error value precedence, and given two arguments, selects the 550100979Srwatson * value with the higher precedence. 551100979Srwatson */ 552121371Srwatsonint 553121371Srwatsonmac_error_select(int error1, int error2) 554100979Srwatson{ 555100979Srwatson 556100979Srwatson /* Certain decision-making errors take top priority. */ 557100979Srwatson if (error1 == EDEADLK || error2 == EDEADLK) 558100979Srwatson return (EDEADLK); 559100979Srwatson 560100979Srwatson /* Invalid arguments should be reported where possible. */ 561100979Srwatson if (error1 == EINVAL || error2 == EINVAL) 562100979Srwatson return (EINVAL); 563100979Srwatson 564100979Srwatson /* Precedence goes to "visibility", with both process and file. */ 565100979Srwatson if (error1 == ESRCH || error2 == ESRCH) 566100979Srwatson return (ESRCH); 567100979Srwatson 568100979Srwatson if (error1 == ENOENT || error2 == ENOENT) 569100979Srwatson return (ENOENT); 570100979Srwatson 571100979Srwatson /* Precedence goes to DAC/MAC protections. */ 572100979Srwatson if (error1 == EACCES || error2 == EACCES) 573100979Srwatson return (EACCES); 574100979Srwatson 575100979Srwatson /* Precedence goes to privilege. */ 576100979Srwatson if (error1 == EPERM || error2 == EPERM) 577100979Srwatson return (EPERM); 578100979Srwatson 579100979Srwatson /* Precedence goes to error over success; otherwise, arbitrary. */ 580100979Srwatson if (error1 != 0) 581100979Srwatson return (error1); 582100979Srwatson return (error2); 583100979Srwatson} 584100979Srwatson 585112675Srwatsonint 586105694Srwatsonmac_check_structmac_consistent(struct mac *mac) 587104522Srwatson{ 588105694Srwatson 589337465Smarkj /* Require that labels have a non-zero length. */ 590337465Smarkj if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN || 591337465Smarkj mac->m_buflen <= sizeof("")) 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