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