mac_framework.c revision 260817
1109313Sobrien/*- 2110252Sobrien * Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson 3109313Sobrien * Copyright (c) 2001 Ilmar S. Habibulin 4109313Sobrien * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5109313Sobrien * Copyright (c) 2005-2006 SPARTA, Inc. 6109313Sobrien * Copyright (c) 2008-2009 Apple Inc. 7109313Sobrien * All rights reserved. 8109313Sobrien * 9109313Sobrien * This software was developed by Robert Watson and Ilmar Habibulin for the 10109313Sobrien * TrustedBSD Project. 11109313Sobrien * 12109313Sobrien * This software was developed for the FreeBSD Project in part by Network 13109313Sobrien * Associates Laboratories, the Security Research Division of Network 14109313Sobrien * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 15109313Sobrien * as part of the DARPA CHATS research program. 16109313Sobrien * 17109313Sobrien * This software was enhanced by SPARTA ISSO under SPAWAR contract 18109313Sobrien * N66001-04-C-6019 ("SEFOS"). 19109313Sobrien * 20109313Sobrien * This software was developed at the University of Cambridge Computer 21109313Sobrien * Laboratory with support from a grant from Google, Inc. 22109313Sobrien * 23109313Sobrien * Redistribution and use in source and binary forms, with or without 24109313Sobrien * modification, are permitted provided that the following conditions 25109313Sobrien * are met: 26109313Sobrien * 1. Redistributions of source code must retain the above copyright 27109313Sobrien * notice, this list of conditions and the following disclaimer. 28109313Sobrien * 2. Redistributions in binary form must reproduce the above copyright 29109313Sobrien * notice, this list of conditions and the following disclaimer in the 30109313Sobrien * documentation and/or other materials provided with the distribution. 31109313Sobrien * 32109313Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33109313Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34118680Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35109313Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36109313Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37109313Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38109313Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39110257Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40109313Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41109313Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42109313Sobrien * SUCH DAMAGE. 43109313Sobrien */ 44109313Sobrien 45109313Sobrien/*- 46109313Sobrien * Framework for extensible kernel access control. This file contains core 47109313Sobrien * kernel infrastructure for the TrustedBSD MAC Framework, including policy 48109313Sobrien * registration, versioning, locking, error composition operator, and system 49109313Sobrien * calls. 50109313Sobrien * 51109313Sobrien * The MAC Framework implements three programming interfaces: 52109313Sobrien * 53109313Sobrien * - The kernel MAC interface, defined in mac_framework.h, and invoked 54109313Sobrien * throughout the kernel to request security decisions, notify of security 55109313Sobrien * related events, etc. 56109313Sobrien * 57109313Sobrien * - The MAC policy module interface, defined in mac_policy.h, which is 58109313Sobrien * implemented by MAC policy modules and invoked by the MAC Framework to 59109313Sobrien * forward kernel security requests and notifications to policy modules. 60109313Sobrien * 61109313Sobrien * - The user MAC API, defined in mac.h, which allows user programs to query 62109313Sobrien * and set label state on objects. 63109313Sobrien * 64109313Sobrien * The majority of the MAC Framework implementation may be found in 65109313Sobrien * src/sys/security/mac. Sample policy modules may be found in 66109313Sobrien * src/sys/security/mac_*. 67109313Sobrien */ 68109313Sobrien 69109313Sobrien#include "opt_kdtrace.h" 70109313Sobrien#include "opt_mac.h" 71109313Sobrien 72109313Sobrien#include <sys/cdefs.h> 73109313Sobrien__FBSDID("$FreeBSD: stable/10/sys/security/mac/mac_framework.c 260817 2014-01-17 10:58:59Z avg $"); 74109313Sobrien 75109313Sobrien#include <sys/param.h> 76109313Sobrien#include <sys/systm.h> 77109313Sobrien#include <sys/condvar.h> 78109313Sobrien#include <sys/kernel.h> 79109313Sobrien#include <sys/lock.h> 80109313Sobrien#include <sys/mac.h> 81109313Sobrien#include <sys/module.h> 82109313Sobrien#include <sys/rmlock.h> 83109313Sobrien#include <sys/sdt.h> 84109313Sobrien#include <sys/sx.h> 85109313Sobrien#include <sys/sysctl.h> 86241737Sed 87109313Sobrien#include <security/mac/mac_framework.h> 88109313Sobrien#include <security/mac/mac_internal.h> 89109313Sobrien#include <security/mac/mac_policy.h> 90109313Sobrien 91109313Sobrien/* 92109313Sobrien * DTrace SDT providers for MAC. 93109313Sobrien */ 94109313SobrienSDT_PROVIDER_DEFINE(mac); 95109313SobrienSDT_PROVIDER_DEFINE(mac_framework); 96109313Sobrien 97109313SobrienSDT_PROBE_DEFINE2(mac, kernel, policy, modevent, "int", 98109313Sobrien "struct mac_policy_conf *"); 99109313SobrienSDT_PROBE_DEFINE1(mac, kernel, policy, register, 100109313Sobrien "struct mac_policy_conf *"); 101109313SobrienSDT_PROBE_DEFINE1(mac, kernel, policy, unregister, 102109313Sobrien "struct mac_policy_conf *"); 103109313Sobrien 104109313Sobrien/* 105109313Sobrien * Root sysctl node for all MAC and MAC policy controls. 106109313Sobrien */ 107109313SobrienSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 108109313Sobrien "TrustedBSD MAC policy controls"); 109109313Sobrien 110109313Sobrien/* 111109313Sobrien * Declare that the kernel provides MAC support, version 3 (FreeBSD 7.x). 112109313Sobrien * This permits modules to refuse to be loaded if the necessary support isn't 113109313Sobrien * present, even if it's pre-boot. 114109313Sobrien */ 115109313SobrienMODULE_VERSION(kernel_mac_support, MAC_VERSION); 116109313Sobrien 117109313Sobrienstatic unsigned int mac_version = MAC_VERSION; 118109313SobrienSYSCTL_UINT(_security_mac, OID_AUTO, version, CTLFLAG_RD, &mac_version, 0, 119109313Sobrien ""); 120119794Sschweikh 121109313Sobrien/* 122109313Sobrien * Labels consist of a indexed set of "slots", which are allocated policies 123109313Sobrien * as required. The MAC Framework maintains a bitmask of slots allocated so 124109313Sobrien * far to prevent reuse. Slots cannot be reused, as the MAC Framework 125109313Sobrien * guarantees that newly allocated slots in labels will be NULL unless 126109313Sobrien * otherwise initialized, and because we do not have a mechanism to garbage 127241737Sed * collect slots on policy unload. As labeled policies tend to be statically 128109313Sobrien * loaded during boot, and not frequently unloaded and reloaded, this is not 129109313Sobrien * generally an issue. 130109313Sobrien */ 131109313Sobrien#if MAC_MAX_SLOTS > 32 132119794Sschweikh#error "MAC_MAX_SLOTS too large" 133109313Sobrien#endif 134109313Sobrien 135109313Sobrienstatic unsigned int mac_max_slots = MAC_MAX_SLOTS; 136109313Sobrienstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 137109313SobrienSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, &mac_max_slots, 138109313Sobrien 0, ""); 139109313Sobrien 140109313Sobrien/* 141109313Sobrien * Has the kernel started generating labeled objects yet? All read/write 142109313Sobrien * access to this variable is serialized during the boot process. Following 143109313Sobrien * the end of serialization, we don't update this flag; no locking. 144109313Sobrien */ 145109313Sobrienstatic int mac_late = 0; 146109313Sobrien 147109313Sobrien/* 148109313Sobrien * Each policy declares a mask of object types requiring labels to be 149109313Sobrien * allocated for them. For convenience, we combine and cache the bitwise or 150109313Sobrien * of the per-policy object flags to track whether we will allocate a label 151109313Sobrien * for an object type at run-time. 152109313Sobrien */ 153109313Sobrienuint64_t mac_labeled; 154109313SobrienSYSCTL_UQUAD(_security_mac, OID_AUTO, labeled, CTLFLAG_RD, &mac_labeled, 0, 155109313Sobrien "Mask of object types being labeled"); 156109313Sobrien 157109313SobrienMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 158109313Sobrien 159109313Sobrien/* 160109313Sobrien * MAC policy modules are placed in one of two lists: mac_static_policy_list, 161119794Sschweikh * for policies that are loaded early and cannot be unloaded, and 162109313Sobrien * mac_policy_list, which holds policies either loaded later in the boot 163109313Sobrien * cycle or that may be unloaded. The static policy list does not require 164109313Sobrien * locks to iterate over, but the dynamic list requires synchronization. 165109313Sobrien * Support for dynamic policy loading can be compiled out using the 166109313Sobrien * MAC_STATIC kernel option. 167109313Sobrien * 168109332Sobrien * The dynamic policy list is protected by two locks: modifying the list 169110256Sobrien * requires both locks to be held exclusively. One of the locks, 170109332Sobrien * mac_policy_rm, is acquired over policy entry points that will never sleep; 171109332Sobrien * the other, mac_policy_sx, is acquire over policy entry points that may 172109332Sobrien * sleep. The former category will be used when kernel locks may be held 173109332Sobrien * over calls to the MAC Framework, during network processing in ithreads, 174109332Sobrien * etc. The latter will tend to involve potentially blocking memory 175109332Sobrien * allocations, extended attribute I/O, etc. 176109332Sobrien */ 177109332Sobrien#ifndef MAC_STATIC 178109332Sobrienstatic struct rmlock mac_policy_rm; /* Non-sleeping entry points. */ 179109332Sobrienstatic struct sx mac_policy_sx; /* Sleeping entry points. */ 180109332Sobrien#endif 181109332Sobrien 182109332Sobrienstruct mac_policy_list_head mac_policy_list; 183109332Sobrienstruct mac_policy_list_head mac_static_policy_list; 184109332Sobrienu_int mac_policy_count; /* Registered policy count. */ 185109332Sobrien 186109332Sobrienstatic void mac_policy_xlock(void); 187109332Sobrienstatic void mac_policy_xlock_assert(void); 188109332Sobrienstatic void mac_policy_xunlock(void); 189109332Sobrien 190109332Sobrienvoid 191109332Sobrienmac_policy_slock_nosleep(struct rm_priotracker *tracker) 192109332Sobrien{ 193109332Sobrien 194109332Sobrien#ifndef MAC_STATIC 195109332Sobrien if (!mac_late) 196109332Sobrien return; 197109332Sobrien 198109332Sobrien rm_rlock(&mac_policy_rm, tracker); 199109332Sobrien#endif 200109332Sobrien} 201109332Sobrien 202109332Sobrienvoid 203109332Sobrienmac_policy_slock_sleep(void) 204109332Sobrien{ 205109332Sobrien 206109332Sobrien WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 207109332Sobrien "mac_policy_slock_sleep"); 208109332Sobrien 209109332Sobrien#ifndef MAC_STATIC 210109332Sobrien if (!mac_late) 211109332Sobrien return; 212109332Sobrien 213109332Sobrien sx_slock(&mac_policy_sx); 214109332Sobrien#endif 215109332Sobrien} 216109332Sobrien 217109332Sobrienvoid 218109332Sobrienmac_policy_sunlock_nosleep(struct rm_priotracker *tracker) 219109332Sobrien{ 220109332Sobrien 221109332Sobrien#ifndef MAC_STATIC 222109332Sobrien if (!mac_late) 223109332Sobrien return; 224109332Sobrien 225109332Sobrien rm_runlock(&mac_policy_rm, tracker); 226109332Sobrien#endif 227109332Sobrien} 228109332Sobrien 229109332Sobrienvoid 230109332Sobrienmac_policy_sunlock_sleep(void) 231109332Sobrien{ 232109332Sobrien 233109332Sobrien#ifndef MAC_STATIC 234109332Sobrien if (!mac_late) 235154958Smarcel return; 236109332Sobrien 237109332Sobrien sx_sunlock(&mac_policy_sx); 238109332Sobrien#endif 239109332Sobrien} 240109332Sobrien 241119794Sschweikhstatic void 242109313Sobrienmac_policy_xlock(void) 243110256Sobrien{ 244109457Smarcel 245109457Smarcel WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 246153500Smarcel "mac_policy_xlock()"); 247153500Smarcel 248109457Smarcel#ifndef MAC_STATIC 249109457Smarcel if (!mac_late) 250109457Smarcel return; 251109457Smarcel 252109457Smarcel sx_xlock(&mac_policy_sx); 253109457Smarcel rm_wlock(&mac_policy_rm); 254109457Smarcel#endif 255109457Smarcel} 256109457Smarcel 257153500Smarcelstatic void 258153500Smarcelmac_policy_xunlock(void) 259153500Smarcel{ 260153500Smarcel 261109457Smarcel#ifndef MAC_STATIC 262153500Smarcel if (!mac_late) 263109457Smarcel return; 264153500Smarcel 265153500Smarcel rm_wunlock(&mac_policy_rm); 266153500Smarcel sx_xunlock(&mac_policy_sx); 267119794Sschweikh#endif 268109313Sobrien} 269241737Sed 270109313Sobrienstatic void 271109313Sobrienmac_policy_xlock_assert(void) 272109313Sobrien{ 273241737Sed 274109313Sobrien#ifndef MAC_STATIC 275109313Sobrien if (!mac_late) 276109313Sobrien return; 277241737Sed 278109313Sobrien /* XXXRW: rm_assert(&mac_policy_rm, RA_WLOCKED); */ 279109313Sobrien sx_assert(&mac_policy_sx, SA_XLOCKED); 280109313Sobrien#endif 281241737Sed} 282109313Sobrien 283109313Sobrien/* 284109313Sobrien * Initialize the MAC subsystem, including appropriate SMP locks. 285241737Sed */ 286109313Sobrienstatic void 287226434Smarcelmac_init(void) 288226434Smarcel{ 289226434Smarcel 290226434Smarcel LIST_INIT(&mac_static_policy_list); 291109313Sobrien LIST_INIT(&mac_policy_list); 292109313Sobrien mac_labelzone_init(); 293241737Sed 294109313Sobrien#ifndef MAC_STATIC 295126484Sjake rm_init_flags(&mac_policy_rm, "mac_policy_rm", RM_NOWITNESS | 296109313Sobrien RM_RECURSE); 297109313Sobrien sx_init_flags(&mac_policy_sx, "mac_policy_sx", SX_NOWITNESS); 298241737Sed#endif 299109313Sobrien} 300109313Sobrien 301109313Sobrien/* 302109313Sobrien * For the purposes of modules that want to know if they were loaded "early", 303109329Sobrien * set the mac_late flag once we've processed modules either linked into the 304110256Sobrien * kernel, or loaded before the kernel startup. 305109332Sobrien */ 306109329Sobrienstatic void 307109329Sobrienmac_late_init(void) 308109329Sobrien{ 309109329Sobrien 310109329Sobrien mac_late = 1; 311109329Sobrien} 312109329Sobrien 313109329Sobrien/* 314109329Sobrien * Given a policy, derive from its set of non-NULL label init methods what 315109329Sobrien * object types the policy is interested in. 316109329Sobrien */ 317109329Sobrienstatic uint64_t 318109329Sobrienmac_policy_getlabeled(struct mac_policy_conf *mpc) 319109329Sobrien{ 320109329Sobrien uint64_t labeled; 321109329Sobrien 322109329Sobrien#define MPC_FLAG(method, flag) \ 323109329Sobrien if (mpc->mpc_ops->mpo_ ## method != NULL) \ 324109332Sobrien labeled |= (flag); \ 325109329Sobrien 326211188Srpaulo labeled = 0; 327109329Sobrien MPC_FLAG(cred_init_label, MPC_OBJECT_CRED); 328109329Sobrien MPC_FLAG(proc_init_label, MPC_OBJECT_PROC); 329109329Sobrien MPC_FLAG(vnode_init_label, MPC_OBJECT_VNODE); 330109329Sobrien MPC_FLAG(inpcb_init_label, MPC_OBJECT_INPCB); 331109329Sobrien MPC_FLAG(socket_init_label, MPC_OBJECT_SOCKET); 332109332Sobrien MPC_FLAG(devfs_init_label, MPC_OBJECT_DEVFS); 333109457Smarcel MPC_FLAG(mbuf_init_label, MPC_OBJECT_MBUF); 334109457Smarcel MPC_FLAG(ipq_init_label, MPC_OBJECT_IPQ); 335109329Sobrien MPC_FLAG(ifnet_init_label, MPC_OBJECT_IFNET); 336109329Sobrien MPC_FLAG(bpfdesc_init_label, MPC_OBJECT_BPFDESC); 337109332Sobrien MPC_FLAG(pipe_init_label, MPC_OBJECT_PIPE); 338109329Sobrien MPC_FLAG(mount_init_label, MPC_OBJECT_MOUNT); 339109329Sobrien MPC_FLAG(posixsem_init_label, MPC_OBJECT_POSIXSEM); 340119795Sschweikh MPC_FLAG(posixshm_init_label, MPC_OBJECT_POSIXSHM); 341109313Sobrien MPC_FLAG(sysvmsg_init_label, MPC_OBJECT_SYSVMSG); 342241737Sed MPC_FLAG(sysvmsq_init_label, MPC_OBJECT_SYSVMSQ); 343109313Sobrien MPC_FLAG(sysvsem_init_label, MPC_OBJECT_SYSVSEM); 344109313Sobrien MPC_FLAG(sysvshm_init_label, MPC_OBJECT_SYSVSHM); 345109313Sobrien MPC_FLAG(syncache_init_label, MPC_OBJECT_SYNCACHE); 346109313Sobrien MPC_FLAG(ip6q_init_label, MPC_OBJECT_IP6Q); 347109313Sobrien 348241737Sed#undef MPC_FLAG 349109313Sobrien return (labeled); 350109313Sobrien} 351109313Sobrien 352241737Sed/* 353109313Sobrien * When policies are loaded or unloaded, walk the list of registered policies 354109313Sobrien * and built mac_labeled, a bitmask representing the union of all objects 355109313Sobrien * requiring labels across all policies. 356241737Sed */ 357241737Sedstatic void 358241737Sedmac_policy_update(void) 359241737Sed{ 360109313Sobrien struct mac_policy_conf *mpc; 361241737Sed 362241737Sed mac_policy_xlock_assert(); 363241737Sed 364241737Sed mac_labeled = 0; 365241737Sed mac_policy_count = 0; 366241737Sed LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 367241737Sed mac_labeled |= mac_policy_getlabeled(mpc); 368241737Sed mac_policy_count++; 369109313Sobrien } 370241737Sed LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 371241737Sed mac_labeled |= mac_policy_getlabeled(mpc); 372241737Sed mac_policy_count++; 373241737Sed } 374241737Sed} 375241737Sed 376241737Sedstatic int 377241737Sedmac_policy_register(struct mac_policy_conf *mpc) 378241737Sed{ 379241737Sed struct mac_policy_conf *tmpc; 380241737Sed int error, slot, static_entry; 381109313Sobrien 382241737Sed error = 0; 383109313Sobrien 384109313Sobrien /* 385109313Sobrien * We don't technically need exclusive access while !mac_late, but 386109313Sobrien * hold it for assertion consistency. 387109313Sobrien */ 388109313Sobrien mac_policy_xlock(); 389109313Sobrien 390109313Sobrien /* 391109313Sobrien * If the module can potentially be unloaded, or we're loading late, 392109313Sobrien * we have to stick it in the non-static list and pay an extra 393109313Sobrien * performance overhead. Otherwise, we can pay a light locking cost 394109313Sobrien * and stick it in the static list. 395109313Sobrien */ 396109313Sobrien static_entry = (!mac_late && 397109313Sobrien !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 398109313Sobrien 399110252Sobrien if (static_entry) { 400109313Sobrien LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 401109313Sobrien if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 402109313Sobrien error = EEXIST; 403109313Sobrien goto out; 404109313Sobrien } 405109313Sobrien } 406109313Sobrien } else { 407109313Sobrien LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 408109313Sobrien if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 409109313Sobrien error = EEXIST; 410109313Sobrien goto out; 411109313Sobrien } 412109313Sobrien } 413109313Sobrien } 414109313Sobrien if (mpc->mpc_field_off != NULL) { 415109313Sobrien slot = ffs(mac_slot_offsets_free); 416109313Sobrien if (slot == 0) { 417109313Sobrien error = ENOMEM; 418109313Sobrien goto out; 419109313Sobrien } 420109313Sobrien slot--; 421109313Sobrien mac_slot_offsets_free &= ~(1 << slot); 422109313Sobrien *mpc->mpc_field_off = slot; 423109313Sobrien } 424109313Sobrien mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 425109313Sobrien 426109313Sobrien /* 427109313Sobrien * If we're loading a MAC module after the framework has initialized, 428109313Sobrien * it has to go into the dynamic list. If we're loading it before 429109313Sobrien * we've finished initializing, it can go into the static list with 430109313Sobrien * weaker locker requirements. 431109313Sobrien */ 432109313Sobrien if (static_entry) 433109313Sobrien LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 434109313Sobrien else 435109313Sobrien LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 436109313Sobrien 437109313Sobrien /* 438109313Sobrien * Per-policy initialization. Currently, this takes place under the 439109313Sobrien * exclusive lock, so policies must not sleep in their init method. 440109313Sobrien * In the future, we may want to separate "init" from "start", with 441109313Sobrien * "init" occuring without the lock held. Likewise, on tear-down, 442109313Sobrien * breaking out "stop" from "destroy". 443109313Sobrien */ 444109313Sobrien if (mpc->mpc_ops->mpo_init != NULL) 445109313Sobrien (*(mpc->mpc_ops->mpo_init))(mpc); 446109313Sobrien mac_policy_update(); 447109313Sobrien 448109313Sobrien SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0); 449109313Sobrien printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 450109313Sobrien mpc->mpc_name); 451109313Sobrien 452109313Sobrienout: 453109313Sobrien mac_policy_xunlock(); 454109313Sobrien return (error); 455109313Sobrien} 456109313Sobrien 457109313Sobrienstatic int 458117009Srumac_policy_unregister(struct mac_policy_conf *mpc) 459109313Sobrien{ 460109313Sobrien 461109313Sobrien /* 462109313Sobrien * If we fail the load, we may get a request to unload. Check to see 463109313Sobrien * if we did the run-time registration, and if not, silently succeed. 464109313Sobrien */ 465109313Sobrien mac_policy_xlock(); 466109313Sobrien if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 467109313Sobrien mac_policy_xunlock(); 468109313Sobrien return (0); 469109313Sobrien } 470109313Sobrien#if 0 471110256Sobrien /* 472110256Sobrien * Don't allow unloading modules with private data. 473110256Sobrien */ 474110252Sobrien if (mpc->mpc_field_off != NULL) { 475110256Sobrien mac_policy_xunlock(); 476110256Sobrien return (EBUSY); 477110256Sobrien } 478109313Sobrien#endif 479110252Sobrien /* 480109313Sobrien * Only allow the unload to proceed if the module is unloadable by 481110252Sobrien * its own definition. 482109313Sobrien */ 483109313Sobrien if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 484109313Sobrien mac_policy_xunlock(); 485109313Sobrien return (EBUSY); 486109313Sobrien } 487109313Sobrien if (mpc->mpc_ops->mpo_destroy != NULL) 488109313Sobrien (*(mpc->mpc_ops->mpo_destroy))(mpc); 489110256Sobrien 490110256Sobrien LIST_REMOVE(mpc, mpc_list); 491109313Sobrien mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 492109313Sobrien mac_policy_update(); 493109313Sobrien mac_policy_xunlock(); 494109313Sobrien 495109313Sobrien SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0); 496109313Sobrien printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 497109313Sobrien mpc->mpc_name); 498109313Sobrien 499109313Sobrien return (0); 500109313Sobrien} 501109313Sobrien 502109313Sobrien/* 503109313Sobrien * Allow MAC policy modules to register during boot, etc. 504109313Sobrien */ 505109313Sobrienint 506110256Sobrienmac_policy_modevent(module_t mod, int type, void *data) 507110256Sobrien{ 508109313Sobrien struct mac_policy_conf *mpc; 509109313Sobrien int error; 510109313Sobrien 511109313Sobrien error = 0; 512109313Sobrien mpc = (struct mac_policy_conf *) data; 513109313Sobrien 514109313Sobrien#ifdef MAC_STATIC 515109313Sobrien if (mac_late) { 516109313Sobrien printf("mac_policy_modevent: MAC_STATIC and late\n"); 517109313Sobrien return (EBUSY); 518109313Sobrien } 519109313Sobrien#endif 520109313Sobrien 521109313Sobrien SDT_PROBE(mac, kernel, policy, modevent, type, mpc, 0, 0, 0); 522109313Sobrien switch (type) { 523109313Sobrien case MOD_LOAD: 524109313Sobrien if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 525109313Sobrien mac_late) { 526109313Sobrien printf("mac_policy_modevent: can't load %s policy " 527109313Sobrien "after booting\n", mpc->mpc_name); 528109313Sobrien error = EBUSY; 529109313Sobrien break; 530109313Sobrien } 531109313Sobrien error = mac_policy_register(mpc); 532109313Sobrien break; 533109313Sobrien case MOD_UNLOAD: 534109313Sobrien /* Don't unregister the module if it was never registered. */ 535109313Sobrien if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 536109313Sobrien != 0) 537109313Sobrien error = mac_policy_unregister(mpc); 538109313Sobrien else 539109313Sobrien error = 0; 540109313Sobrien break; 541109313Sobrien default: 542109313Sobrien error = EOPNOTSUPP; 543109313Sobrien break; 544109313Sobrien } 545109313Sobrien 546109313Sobrien return (error); 547109313Sobrien} 548109313Sobrien 549109313Sobrien/* 550109313Sobrien * Define an error value precedence, and given two arguments, selects the 551109313Sobrien * value with the higher precedence. 552109313Sobrien */ 553109313Sobrienint 554109313Sobrienmac_error_select(int error1, int error2) 555109313Sobrien{ 556109313Sobrien 557241737Sed /* Certain decision-making errors take top priority. */ 558110252Sobrien if (error1 == EDEADLK || error2 == EDEADLK) 559109313Sobrien return (EDEADLK); 560109313Sobrien 561109313Sobrien /* Invalid arguments should be reported where possible. */ 562109313Sobrien if (error1 == EINVAL || error2 == EINVAL) 563109313Sobrien return (EINVAL); 564109313Sobrien 565109313Sobrien /* Precedence goes to "visibility", with both process and file. */ 566109313Sobrien if (error1 == ESRCH || error2 == ESRCH) 567109313Sobrien return (ESRCH); 568109313Sobrien 569109313Sobrien if (error1 == ENOENT || error2 == ENOENT) 570109313Sobrien return (ENOENT); 571109313Sobrien 572109313Sobrien /* Precedence goes to DAC/MAC protections. */ 573109313Sobrien if (error1 == EACCES || error2 == EACCES) 574109313Sobrien return (EACCES); 575109313Sobrien 576109313Sobrien /* Precedence goes to privilege. */ 577109313Sobrien if (error1 == EPERM || error2 == EPERM) 578109313Sobrien return (EPERM); 579109313Sobrien 580109313Sobrien /* Precedence goes to error over success; otherwise, arbitrary. */ 581109313Sobrien if (error1 != 0) 582109313Sobrien return (error1); 583109313Sobrien return (error2); 584109313Sobrien} 585109313Sobrien 586109313Sobrienint 587109313Sobrienmac_check_structmac_consistent(struct mac *mac) 588109313Sobrien{ 589109313Sobrien 590109313Sobrien if (mac->m_buflen < 0 || 591109313Sobrien mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 592109313Sobrien return (EINVAL); 593109313Sobrien 594109313Sobrien return (0); 595109313Sobrien} 596109313Sobrien 597109313SobrienSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 598109457SmarcelSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 599109313Sobrien