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