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