mac_framework.c revision 113955
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson and Ilmar Habibulin for the
8 * TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: head/sys/security/mac/mac_framework.c 113955 2003-04-24 04:31:25Z alc $
37 */
38/*
39 * Developed by the TrustedBSD Project.
40 *
41 * Framework for extensible kernel access control.  Kernel and userland
42 * interface to the framework, policy registration and composition.
43 */
44
45#include "opt_mac.h"
46#include "opt_devfs.h"
47
48#include <sys/param.h>
49#include <sys/condvar.h>
50#include <sys/extattr.h>
51#include <sys/imgact.h>
52#include <sys/kernel.h>
53#include <sys/lock.h>
54#include <sys/malloc.h>
55#include <sys/mutex.h>
56#include <sys/mac.h>
57#include <sys/module.h>
58#include <sys/proc.h>
59#include <sys/systm.h>
60#include <sys/sysproto.h>
61#include <sys/sysent.h>
62#include <sys/vnode.h>
63#include <sys/mount.h>
64#include <sys/file.h>
65#include <sys/namei.h>
66#include <sys/socket.h>
67#include <sys/pipe.h>
68#include <sys/socketvar.h>
69#include <sys/sysctl.h>
70
71#include <vm/vm.h>
72#include <vm/pmap.h>
73#include <vm/vm_map.h>
74#include <vm/vm_object.h>
75
76#include <sys/mac_policy.h>
77
78#include <fs/devfs/devfs.h>
79
80#include <net/bpfdesc.h>
81#include <net/if.h>
82#include <net/if_var.h>
83
84#include <netinet/in.h>
85#include <netinet/ip_var.h>
86
87#ifdef MAC
88
89/*
90 * Declare that the kernel provides MAC support, version 1.  This permits
91 * modules to refuse to be loaded if the necessary support isn't present,
92 * even if it's pre-boot.
93 */
94MODULE_VERSION(kernel_mac_support, 1);
95
96SYSCTL_DECL(_security);
97
98SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
99    "TrustedBSD MAC policy controls");
100
101#if MAC_MAX_POLICIES > 32
102#error "MAC_MAX_POLICIES too large"
103#endif
104
105static unsigned int mac_max_policies = MAC_MAX_POLICIES;
106static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
107SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
108    &mac_max_policies, 0, "");
109
110/*
111 * Has the kernel started generating labeled objects yet?  All read/write
112 * access to this variable is serialized during the boot process.  Following
113 * the end of serialization, we don't update this flag; no locking.
114 */
115static int	mac_late = 0;
116
117/*
118 * Warn about EA transactions only the first time they happen.
119 * Weak coherency, no locking.
120 */
121static int	ea_warn_once = 0;
122
123#ifndef MAC_ALWAYS_LABEL_MBUF
124/*
125 * Flag to indicate whether or not we should allocate label storage for
126 * new mbufs.  Since most dynamic policies we currently work with don't
127 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
128 * unless specifically notified of interest.  One result of this is
129 * that if a dynamically loaded policy requests mbuf labels, it must
130 * be able to deal with a NULL label being returned on any mbufs that
131 * were already in flight when the policy was loaded.  Since the policy
132 * already has to deal with uninitialized labels, this probably won't
133 * be a problem.  Note: currently no locking.  Will this be a problem?
134 */
135static int	mac_labelmbufs = 0;
136#endif
137
138static int	mac_enforce_fs = 1;
139SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
140    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
141TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
142
143static int	mac_enforce_kld = 1;
144SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
145    &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
146TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
147
148static int	mac_enforce_network = 1;
149SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
150    &mac_enforce_network, 0, "Enforce MAC policy on network packets");
151TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
152
153static int	mac_enforce_pipe = 1;
154SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
155    &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
156TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
157
158static int	mac_enforce_process = 1;
159SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
160    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
161TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
162
163static int	mac_enforce_socket = 1;
164SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
165    &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
166TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
167
168static int	mac_enforce_system = 1;
169SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
170    &mac_enforce_system, 0, "Enforce MAC policy on system operations");
171TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
172
173static int	mac_enforce_vm = 1;
174SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
175    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
176TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
177
178static int	mac_mmap_revocation = 1;
179SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
180    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
181    "relabel");
182static int	mac_mmap_revocation_via_cow = 0;
183SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
184    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
185    "copy-on-write semantics, or by removing all write access");
186
187#ifdef MAC_DEBUG
188SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
189    "TrustedBSD MAC debug info");
190
191static int	mac_debug_label_fallback = 0;
192SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
193    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
194    "when label is corrupted.");
195TUNABLE_INT("security.mac.debug_label_fallback",
196    &mac_debug_label_fallback);
197
198SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
199    "TrustedBSD MAC object counters");
200
201static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
202    nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
203    nmacipqs, nmacpipes, nmacprocs;
204
205SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
206    &nmacmbufs, 0, "number of mbufs in use");
207SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
208    &nmaccreds, 0, "number of ucreds in use");
209SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
210    &nmacifnets, 0, "number of ifnets in use");
211SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
212    &nmacipqs, 0, "number of ipqs in use");
213SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
214    &nmacbpfdescs, 0, "number of bpfdescs in use");
215SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
216    &nmacsockets, 0, "number of sockets in use");
217SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
218    &nmacpipes, 0, "number of pipes in use");
219SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
220    &nmacprocs, 0, "number of procs in use");
221SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
222    &nmacmounts, 0, "number of mounts in use");
223SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
224    &nmactemp, 0, "number of temporary labels in use");
225SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
226    &nmacvnodes, 0, "number of vnodes in use");
227SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
228    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
229#endif
230
231static int	error_select(int error1, int error2);
232static int	mac_policy_register(struct mac_policy_conf *mpc);
233static int	mac_policy_unregister(struct mac_policy_conf *mpc);
234
235static void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
236		    struct vnode *vp, int *prot);
237static void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
238		    struct ucred *cred, struct vm_map *map);
239
240static void	mac_destroy_socket_label(struct label *label);
241
242static int	mac_setlabel_vnode_extattr(struct ucred *cred,
243		    struct vnode *vp, struct label *intlabel);
244
245MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
246MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
247
248/*
249 * mac_policy_list stores the list of active policies.  A busy count is
250 * maintained for the list, stored in mac_policy_busy.  The busy count
251 * is protected by mac_policy_list_lock; the list may be modified only
252 * while the busy count is 0, requiring that the lock be held to
253 * prevent new references to the list from being acquired.  For almost
254 * all operations, incrementing the busy count is sufficient to
255 * guarantee consistency, as the list cannot be modified while the
256 * busy count is elevated.  For a few special operations involving a
257 * change to the list of active policies, the lock itself must be held.
258 * A condition variable, mac_policy_list_not_busy, is used to signal
259 * potential exclusive consumers that they should try to acquire the
260 * lock if a first attempt at exclusive access fails.
261 */
262static struct mtx mac_policy_list_lock;
263static struct cv mac_policy_list_not_busy;
264static LIST_HEAD(, mac_policy_conf) mac_policy_list;
265static int mac_policy_list_busy;
266
267#define	MAC_POLICY_LIST_LOCKINIT() do {					\
268	mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL,	\
269	    MTX_DEF);							\
270	cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy");	\
271} while (0)
272
273#define	MAC_POLICY_LIST_LOCK() do {					\
274	mtx_lock(&mac_policy_list_lock);				\
275} while (0)
276
277#define	MAC_POLICY_LIST_UNLOCK() do {					\
278	mtx_unlock(&mac_policy_list_lock);				\
279} while (0)
280
281/*
282 * We manually invoke WITNESS_WARN() to allow Witness to generate
283 * warnings even if we don't end up ever triggering the wait at
284 * run-time.  The consumer of the exclusive interface must not hold
285 * any locks (other than potentially Giant) since we may sleep for
286 * long (potentially indefinite) periods of time waiting for the
287 * framework to become quiescent so that a policy list change may
288 * be made.
289 */
290#define	MAC_POLICY_LIST_EXCLUSIVE() do {				\
291	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,			\
292 	    "mac_policy_list_exclusive() at %s:%d", __FILE__, __LINE__);\
293	mtx_lock(&mac_policy_list_lock);				\
294	while (mac_policy_list_busy != 0)				\
295		cv_wait(&mac_policy_list_not_busy,			\
296		    &mac_policy_list_lock);				\
297} while (0)
298
299#define	MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do {				\
300	mtx_assert(&mac_policy_list_lock, MA_OWNED);			\
301	KASSERT(mac_policy_list_busy == 0,				\
302	    ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()"));			\
303} while (0)
304
305#define	MAC_POLICY_LIST_BUSY() do {					\
306	MAC_POLICY_LIST_LOCK();						\
307	mac_policy_list_busy++;						\
308	MAC_POLICY_LIST_UNLOCK();					\
309} while (0)
310
311#define	MAC_POLICY_LIST_UNBUSY() do {					\
312	MAC_POLICY_LIST_LOCK();						\
313	mac_policy_list_busy--;						\
314	KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK"));	\
315	if (mac_policy_list_busy == 0)					\
316		cv_signal(&mac_policy_list_not_busy);			\
317	MAC_POLICY_LIST_UNLOCK();					\
318} while (0)
319
320/*
321 * MAC_CHECK performs the designated check by walking the policy
322 * module list and checking with each as to how it feels about the
323 * request.  Note that it returns its value via 'error' in the scope
324 * of the caller.
325 */
326#define	MAC_CHECK(check, args...) do {					\
327	struct mac_policy_conf *mpc;					\
328									\
329	error = 0;							\
330	MAC_POLICY_LIST_BUSY();						\
331	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
332		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
333			error = error_select(				\
334			    mpc->mpc_ops->mpo_ ## check (args),		\
335			    error);					\
336	}								\
337	MAC_POLICY_LIST_UNBUSY();					\
338} while (0)
339
340/*
341 * MAC_BOOLEAN performs the designated boolean composition by walking
342 * the module list, invoking each instance of the operation, and
343 * combining the results using the passed C operator.  Note that it
344 * returns its value via 'result' in the scope of the caller, which
345 * should be initialized by the caller in a meaningful way to get
346 * a meaningful result.
347 */
348#define	MAC_BOOLEAN(operation, composition, args...) do {		\
349	struct mac_policy_conf *mpc;					\
350									\
351	MAC_POLICY_LIST_BUSY();						\
352	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
353		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
354			result = result composition			\
355			    mpc->mpc_ops->mpo_ ## operation (args);	\
356	}								\
357	MAC_POLICY_LIST_UNBUSY();					\
358} while (0)
359
360#define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
361    outbuflen) do {							\
362	char *curptr, *curptr_start, *element_name, *element_temp;	\
363	size_t left, left_start, len;					\
364	int claimed, first, first_start, ignorenotfound;		\
365									\
366	error = 0;							\
367	element_temp = elementlist;					\
368	curptr = outbuf;						\
369	curptr[0] = '\0';						\
370	left = outbuflen;						\
371	first = 1;							\
372	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
373		curptr_start = curptr;					\
374		left_start = left;					\
375		first_start = first;					\
376		if (element_name[0] == '?') {				\
377			element_name++;					\
378			ignorenotfound = 1;				\
379		} else							\
380			ignorenotfound = 0;				\
381		claimed = 0;						\
382		if (first) {						\
383			len = snprintf(curptr, left, "%s/",		\
384			    element_name);				\
385			first = 0;					\
386		} else							\
387			len = snprintf(curptr, left, ",%s/",		\
388			    element_name);				\
389		if (len >= left) {					\
390			error = EINVAL;		/* XXXMAC: E2BIG */	\
391			break;						\
392		}							\
393		curptr += len;						\
394		left -= len;						\
395									\
396		MAC_CHECK(externalize_ ## type, label, element_name,	\
397		    curptr, left, &len, &claimed);			\
398		if (error)						\
399			break;						\
400		if (claimed == 1) {					\
401			if (len >= outbuflen) {				\
402				error = EINVAL;	/* XXXMAC: E2BIG */	\
403				break;					\
404			}						\
405			curptr += len;					\
406			left -= len;					\
407		} else if (claimed == 0 && ignorenotfound) {		\
408			/*						\
409			 * Revert addition of the label element		\
410			 * name.					\
411			 */						\
412			curptr = curptr_start;				\
413			*curptr = '\0';					\
414			left = left_start;				\
415			first = first_start;				\
416		} else {						\
417			error = EINVAL;		/* XXXMAC: ENOLABEL */	\
418			break;						\
419		}							\
420	}								\
421} while (0)
422
423#define	MAC_INTERNALIZE(type, label, instring) do {			\
424	char *element, *element_name, *element_data;			\
425	int claimed;							\
426									\
427	error = 0;							\
428	element = instring;						\
429	while ((element_name = strsep(&element, ",")) != NULL) {	\
430		element_data = element_name;				\
431		element_name = strsep(&element_data, "/");		\
432		if (element_data == NULL) {				\
433			error = EINVAL;					\
434			break;						\
435		}							\
436		claimed = 0;						\
437		MAC_CHECK(internalize_ ## type, label, element_name,	\
438		    element_data, &claimed);				\
439		if (error)						\
440			break;						\
441		if (claimed != 1) {					\
442			/* XXXMAC: Another error here? */		\
443			error = EINVAL;					\
444			break;						\
445		}							\
446	}								\
447} while (0)
448
449/*
450 * MAC_PERFORM performs the designated operation by walking the policy
451 * module list and invoking that operation for each policy.
452 */
453#define	MAC_PERFORM(operation, args...) do {				\
454	struct mac_policy_conf *mpc;					\
455									\
456	MAC_POLICY_LIST_BUSY();						\
457	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
458		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
459			mpc->mpc_ops->mpo_ ## operation (args);		\
460	}								\
461	MAC_POLICY_LIST_UNBUSY();					\
462} while (0)
463
464/*
465 * Initialize the MAC subsystem, including appropriate SMP locks.
466 */
467static void
468mac_init(void)
469{
470
471	LIST_INIT(&mac_policy_list);
472	MAC_POLICY_LIST_LOCKINIT();
473}
474
475/*
476 * For the purposes of modules that want to know if they were loaded
477 * "early", set the mac_late flag once we've processed modules either
478 * linked into the kernel, or loaded before the kernel startup.
479 */
480static void
481mac_late_init(void)
482{
483
484	mac_late = 1;
485}
486
487/*
488 * After the policy list has changed, walk the list to update any global
489 * flags.
490 */
491static void
492mac_policy_updateflags(void)
493{
494	struct mac_policy_conf *tmpc;
495#ifndef MAC_ALWAYS_LABEL_MBUF
496	int labelmbufs;
497#endif
498
499	MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
500
501#ifndef MAC_ALWAYS_LABEL_MBUF
502	labelmbufs = 0;
503#endif
504	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
505#ifndef MAC_ALWAYS_LABEL_MBUF
506		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
507			labelmbufs++;
508#endif
509	}
510
511#ifndef MAC_ALWAYS_LABEL_MBUF
512	mac_labelmbufs = (labelmbufs != 0);
513#endif
514}
515
516/*
517 * Allow MAC policy modules to register during boot, etc.
518 */
519int
520mac_policy_modevent(module_t mod, int type, void *data)
521{
522	struct mac_policy_conf *mpc;
523	int error;
524
525	error = 0;
526	mpc = (struct mac_policy_conf *) data;
527
528	switch (type) {
529	case MOD_LOAD:
530		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
531		    mac_late) {
532			printf("mac_policy_modevent: can't load %s policy "
533			    "after booting\n", mpc->mpc_name);
534			error = EBUSY;
535			break;
536		}
537		error = mac_policy_register(mpc);
538		break;
539	case MOD_UNLOAD:
540		/* Don't unregister the module if it was never registered. */
541		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
542		    != 0)
543			error = mac_policy_unregister(mpc);
544		else
545			error = 0;
546		break;
547	default:
548		break;
549	}
550
551	return (error);
552}
553
554static int
555mac_policy_register(struct mac_policy_conf *mpc)
556{
557	struct mac_policy_conf *tmpc;
558	int slot;
559
560	MAC_POLICY_LIST_EXCLUSIVE();
561	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
562		if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
563			MAC_POLICY_LIST_UNLOCK();
564			return (EEXIST);
565		}
566	}
567	if (mpc->mpc_field_off != NULL) {
568		slot = ffs(mac_policy_offsets_free);
569		if (slot == 0) {
570			MAC_POLICY_LIST_UNLOCK();
571			return (ENOMEM);
572		}
573		slot--;
574		mac_policy_offsets_free &= ~(1 << slot);
575		*mpc->mpc_field_off = slot;
576	}
577	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
578	LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
579
580	/* Per-policy initialization. */
581	if (mpc->mpc_ops->mpo_init != NULL)
582		(*(mpc->mpc_ops->mpo_init))(mpc);
583	mac_policy_updateflags();
584	MAC_POLICY_LIST_UNLOCK();
585
586	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
587	    mpc->mpc_name);
588
589	return (0);
590}
591
592static int
593mac_policy_unregister(struct mac_policy_conf *mpc)
594{
595
596	/*
597	 * If we fail the load, we may get a request to unload.  Check
598	 * to see if we did the run-time registration, and if not,
599	 * silently succeed.
600	 */
601	MAC_POLICY_LIST_EXCLUSIVE();
602	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
603		MAC_POLICY_LIST_UNLOCK();
604		return (0);
605	}
606#if 0
607	/*
608	 * Don't allow unloading modules with private data.
609	 */
610	if (mpc->mpc_field_off != NULL) {
611		MAC_POLICY_LIST_UNLOCK();
612		return (EBUSY);
613	}
614#endif
615	/*
616	 * Only allow the unload to proceed if the module is unloadable
617	 * by its own definition.
618	 */
619	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
620		MAC_POLICY_LIST_UNLOCK();
621		return (EBUSY);
622	}
623	if (mpc->mpc_ops->mpo_destroy != NULL)
624		(*(mpc->mpc_ops->mpo_destroy))(mpc);
625
626	LIST_REMOVE(mpc, mpc_list);
627	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
628	mac_policy_updateflags();
629	MAC_POLICY_LIST_UNLOCK();
630
631	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
632	    mpc->mpc_name);
633
634	return (0);
635}
636
637/*
638 * Define an error value precedence, and given two arguments, selects the
639 * value with the higher precedence.
640 */
641static int
642error_select(int error1, int error2)
643{
644
645	/* Certain decision-making errors take top priority. */
646	if (error1 == EDEADLK || error2 == EDEADLK)
647		return (EDEADLK);
648
649	/* Invalid arguments should be reported where possible. */
650	if (error1 == EINVAL || error2 == EINVAL)
651		return (EINVAL);
652
653	/* Precedence goes to "visibility", with both process and file. */
654	if (error1 == ESRCH || error2 == ESRCH)
655		return (ESRCH);
656
657	if (error1 == ENOENT || error2 == ENOENT)
658		return (ENOENT);
659
660	/* Precedence goes to DAC/MAC protections. */
661	if (error1 == EACCES || error2 == EACCES)
662		return (EACCES);
663
664	/* Precedence goes to privilege. */
665	if (error1 == EPERM || error2 == EPERM)
666		return (EPERM);
667
668	/* Precedence goes to error over success; otherwise, arbitrary. */
669	if (error1 != 0)
670		return (error1);
671	return (error2);
672}
673
674static struct label *
675mbuf_to_label(struct mbuf *mbuf)
676{
677	struct m_tag *tag;
678	struct label *label;
679
680	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
681	label = (struct label *)(tag+1);
682
683	return (label);
684}
685
686static void
687mac_init_label(struct label *label)
688{
689
690	bzero(label, sizeof(*label));
691	label->l_flags = MAC_FLAG_INITIALIZED;
692}
693
694static void
695mac_destroy_label(struct label *label)
696{
697
698	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
699	    ("destroying uninitialized label"));
700
701	bzero(label, sizeof(*label));
702	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
703}
704
705void
706mac_init_bpfdesc(struct bpf_d *bpf_d)
707{
708
709	mac_init_label(&bpf_d->bd_label);
710	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
711#ifdef MAC_DEBUG
712	atomic_add_int(&nmacbpfdescs, 1);
713#endif
714}
715
716static void
717mac_init_cred_label(struct label *label)
718{
719
720	mac_init_label(label);
721	MAC_PERFORM(init_cred_label, label);
722#ifdef MAC_DEBUG
723	atomic_add_int(&nmaccreds, 1);
724#endif
725}
726
727void
728mac_init_cred(struct ucred *cred)
729{
730
731	mac_init_cred_label(&cred->cr_label);
732}
733
734void
735mac_init_devfsdirent(struct devfs_dirent *de)
736{
737
738	mac_init_label(&de->de_label);
739	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
740#ifdef MAC_DEBUG
741	atomic_add_int(&nmacdevfsdirents, 1);
742#endif
743}
744
745static void
746mac_init_ifnet_label(struct label *label)
747{
748
749	mac_init_label(label);
750	MAC_PERFORM(init_ifnet_label, label);
751#ifdef MAC_DEBUG
752	atomic_add_int(&nmacifnets, 1);
753#endif
754}
755
756void
757mac_init_ifnet(struct ifnet *ifp)
758{
759
760	mac_init_ifnet_label(&ifp->if_label);
761}
762
763int
764mac_init_ipq(struct ipq *ipq, int flag)
765{
766	int error;
767
768	mac_init_label(&ipq->ipq_label);
769
770	MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag);
771	if (error) {
772		MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
773		mac_destroy_label(&ipq->ipq_label);
774	}
775#ifdef MAC_DEBUG
776	if (error == 0)
777		atomic_add_int(&nmacipqs, 1);
778#endif
779	return (error);
780}
781
782int
783mac_init_mbuf_tag(struct m_tag *tag, int flag)
784{
785	struct label *label;
786	int error;
787
788	label = (struct label *) (tag + 1);
789	mac_init_label(label);
790
791	MAC_CHECK(init_mbuf_label, label, flag);
792	if (error) {
793		MAC_PERFORM(destroy_mbuf_label, label);
794		mac_destroy_label(label);
795	}
796#ifdef MAC_DEBUG
797	if (error == 0)
798		atomic_add_int(&nmacmbufs, 1);
799#endif
800	return (error);
801}
802
803int
804mac_init_mbuf(struct mbuf *m, int flag)
805{
806	struct m_tag *tag;
807	int error;
808
809	M_ASSERTPKTHDR(m);
810
811#ifndef MAC_ALWAYS_LABEL_MBUF
812	/*
813	 * Don't reserve space for labels on mbufs unless we have a policy
814	 * that uses the labels.
815	 */
816	if (mac_labelmbufs) {
817#endif
818		tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
819		    flag);
820		if (tag == NULL)
821			return (ENOMEM);
822		error = mac_init_mbuf_tag(tag, flag);
823		if (error) {
824			m_tag_free(tag);
825			return (error);
826		}
827		m_tag_prepend(m, tag);
828#ifndef MAC_ALWAYS_LABEL_MBUF
829	}
830#endif
831	return (0);
832}
833
834void
835mac_init_mount(struct mount *mp)
836{
837
838	mac_init_label(&mp->mnt_mntlabel);
839	mac_init_label(&mp->mnt_fslabel);
840	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
841	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
842#ifdef MAC_DEBUG
843	atomic_add_int(&nmacmounts, 1);
844#endif
845}
846
847static void
848mac_init_pipe_label(struct label *label)
849{
850
851	mac_init_label(label);
852	MAC_PERFORM(init_pipe_label, label);
853#ifdef MAC_DEBUG
854	atomic_add_int(&nmacpipes, 1);
855#endif
856}
857
858void
859mac_init_pipe(struct pipe *pipe)
860{
861	struct label *label;
862
863	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
864	pipe->pipe_label = label;
865	pipe->pipe_peer->pipe_label = label;
866	mac_init_pipe_label(label);
867}
868
869void
870mac_init_proc(struct proc *p)
871{
872
873	mac_init_label(&p->p_label);
874	MAC_PERFORM(init_proc_label, &p->p_label);
875#ifdef MAC_DEBUG
876	atomic_add_int(&nmacprocs, 1);
877#endif
878}
879
880static int
881mac_init_socket_label(struct label *label, int flag)
882{
883	int error;
884
885	mac_init_label(label);
886
887	MAC_CHECK(init_socket_label, label, flag);
888	if (error) {
889		MAC_PERFORM(destroy_socket_label, label);
890		mac_destroy_label(label);
891	}
892
893#ifdef MAC_DEBUG
894	if (error == 0)
895		atomic_add_int(&nmacsockets, 1);
896#endif
897
898	return (error);
899}
900
901static int
902mac_init_socket_peer_label(struct label *label, int flag)
903{
904	int error;
905
906	mac_init_label(label);
907
908	MAC_CHECK(init_socket_peer_label, label, flag);
909	if (error) {
910		MAC_PERFORM(destroy_socket_label, label);
911		mac_destroy_label(label);
912	}
913
914	return (error);
915}
916
917int
918mac_init_socket(struct socket *socket, int flag)
919{
920	int error;
921
922	error = mac_init_socket_label(&socket->so_label, flag);
923	if (error)
924		return (error);
925
926	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
927	if (error)
928		mac_destroy_socket_label(&socket->so_label);
929
930	return (error);
931}
932
933void
934mac_init_vnode_label(struct label *label)
935{
936
937	mac_init_label(label);
938	MAC_PERFORM(init_vnode_label, label);
939#ifdef MAC_DEBUG
940	atomic_add_int(&nmacvnodes, 1);
941#endif
942}
943
944void
945mac_init_vnode(struct vnode *vp)
946{
947
948	mac_init_vnode_label(&vp->v_label);
949}
950
951void
952mac_destroy_bpfdesc(struct bpf_d *bpf_d)
953{
954
955	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
956	mac_destroy_label(&bpf_d->bd_label);
957#ifdef MAC_DEBUG
958	atomic_subtract_int(&nmacbpfdescs, 1);
959#endif
960}
961
962static void
963mac_destroy_cred_label(struct label *label)
964{
965
966	MAC_PERFORM(destroy_cred_label, label);
967	mac_destroy_label(label);
968#ifdef MAC_DEBUG
969	atomic_subtract_int(&nmaccreds, 1);
970#endif
971}
972
973void
974mac_destroy_cred(struct ucred *cred)
975{
976
977	mac_destroy_cred_label(&cred->cr_label);
978}
979
980void
981mac_destroy_devfsdirent(struct devfs_dirent *de)
982{
983
984	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
985	mac_destroy_label(&de->de_label);
986#ifdef MAC_DEBUG
987	atomic_subtract_int(&nmacdevfsdirents, 1);
988#endif
989}
990
991static void
992mac_destroy_ifnet_label(struct label *label)
993{
994
995	MAC_PERFORM(destroy_ifnet_label, label);
996	mac_destroy_label(label);
997#ifdef MAC_DEBUG
998	atomic_subtract_int(&nmacifnets, 1);
999#endif
1000}
1001
1002void
1003mac_destroy_ifnet(struct ifnet *ifp)
1004{
1005
1006	mac_destroy_ifnet_label(&ifp->if_label);
1007}
1008
1009void
1010mac_destroy_ipq(struct ipq *ipq)
1011{
1012
1013	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1014	mac_destroy_label(&ipq->ipq_label);
1015#ifdef MAC_DEBUG
1016	atomic_subtract_int(&nmacipqs, 1);
1017#endif
1018}
1019
1020void
1021mac_destroy_mbuf_tag(struct m_tag *tag)
1022{
1023	struct label *label;
1024
1025	label = (struct label *)(tag+1);
1026
1027	MAC_PERFORM(destroy_mbuf_label, label);
1028	mac_destroy_label(label);
1029#ifdef MAC_DEBUG
1030	atomic_subtract_int(&nmacmbufs, 1);
1031#endif
1032}
1033
1034void
1035mac_destroy_mount(struct mount *mp)
1036{
1037
1038	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1039	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1040	mac_destroy_label(&mp->mnt_fslabel);
1041	mac_destroy_label(&mp->mnt_mntlabel);
1042#ifdef MAC_DEBUG
1043	atomic_subtract_int(&nmacmounts, 1);
1044#endif
1045}
1046
1047static void
1048mac_destroy_pipe_label(struct label *label)
1049{
1050
1051	MAC_PERFORM(destroy_pipe_label, label);
1052	mac_destroy_label(label);
1053#ifdef MAC_DEBUG
1054	atomic_subtract_int(&nmacpipes, 1);
1055#endif
1056}
1057
1058void
1059mac_destroy_pipe(struct pipe *pipe)
1060{
1061
1062	mac_destroy_pipe_label(pipe->pipe_label);
1063	free(pipe->pipe_label, M_MACPIPELABEL);
1064}
1065
1066void
1067mac_destroy_proc(struct proc *p)
1068{
1069
1070	MAC_PERFORM(destroy_proc_label, &p->p_label);
1071	mac_destroy_label(&p->p_label);
1072#ifdef MAC_DEBUG
1073	atomic_subtract_int(&nmacprocs, 1);
1074#endif
1075}
1076
1077static void
1078mac_destroy_socket_label(struct label *label)
1079{
1080
1081	MAC_PERFORM(destroy_socket_label, label);
1082	mac_destroy_label(label);
1083#ifdef MAC_DEBUG
1084	atomic_subtract_int(&nmacsockets, 1);
1085#endif
1086}
1087
1088static void
1089mac_destroy_socket_peer_label(struct label *label)
1090{
1091
1092	MAC_PERFORM(destroy_socket_peer_label, label);
1093	mac_destroy_label(label);
1094}
1095
1096void
1097mac_destroy_socket(struct socket *socket)
1098{
1099
1100	mac_destroy_socket_label(&socket->so_label);
1101	mac_destroy_socket_peer_label(&socket->so_peerlabel);
1102}
1103
1104void
1105mac_destroy_vnode_label(struct label *label)
1106{
1107
1108	MAC_PERFORM(destroy_vnode_label, label);
1109	mac_destroy_label(label);
1110#ifdef MAC_DEBUG
1111	atomic_subtract_int(&nmacvnodes, 1);
1112#endif
1113}
1114
1115void
1116mac_destroy_vnode(struct vnode *vp)
1117{
1118
1119	mac_destroy_vnode_label(&vp->v_label);
1120}
1121
1122void
1123mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
1124{
1125	struct label *src_label, *dest_label;
1126
1127	src_label = (struct label *)(src+1);
1128	dest_label = (struct label *)(dest+1);
1129
1130	/*
1131	 * mac_init_mbuf_tag() is called on the target tag in
1132	 * m_tag_copy(), so we don't need to call it here.
1133	 */
1134	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
1135}
1136
1137static void
1138mac_copy_pipe_label(struct label *src, struct label *dest)
1139{
1140
1141	MAC_PERFORM(copy_pipe_label, src, dest);
1142}
1143
1144void
1145mac_copy_vnode_label(struct label *src, struct label *dest)
1146{
1147
1148	MAC_PERFORM(copy_vnode_label, src, dest);
1149}
1150
1151static int
1152mac_check_structmac_consistent(struct mac *mac)
1153{
1154
1155	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1156		return (EINVAL);
1157
1158	return (0);
1159}
1160
1161static int
1162mac_externalize_cred_label(struct label *label, char *elements,
1163    char *outbuf, size_t outbuflen, int flags)
1164{
1165	int error;
1166
1167	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1168
1169	return (error);
1170}
1171
1172static int
1173mac_externalize_ifnet_label(struct label *label, char *elements,
1174    char *outbuf, size_t outbuflen, int flags)
1175{
1176	int error;
1177
1178	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1179
1180	return (error);
1181}
1182
1183static int
1184mac_externalize_pipe_label(struct label *label, char *elements,
1185    char *outbuf, size_t outbuflen, int flags)
1186{
1187	int error;
1188
1189	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1190
1191	return (error);
1192}
1193
1194static int
1195mac_externalize_socket_label(struct label *label, char *elements,
1196    char *outbuf, size_t outbuflen, int flags)
1197{
1198	int error;
1199
1200	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1201
1202	return (error);
1203}
1204
1205static int
1206mac_externalize_socket_peer_label(struct label *label, char *elements,
1207    char *outbuf, size_t outbuflen, int flags)
1208{
1209	int error;
1210
1211	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1212
1213	return (error);
1214}
1215
1216static int
1217mac_externalize_vnode_label(struct label *label, char *elements,
1218    char *outbuf, size_t outbuflen, int flags)
1219{
1220	int error;
1221
1222	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1223
1224	return (error);
1225}
1226
1227static int
1228mac_internalize_cred_label(struct label *label, char *string)
1229{
1230	int error;
1231
1232	MAC_INTERNALIZE(cred_label, label, string);
1233
1234	return (error);
1235}
1236
1237static int
1238mac_internalize_ifnet_label(struct label *label, char *string)
1239{
1240	int error;
1241
1242	MAC_INTERNALIZE(ifnet_label, label, string);
1243
1244	return (error);
1245}
1246
1247static int
1248mac_internalize_pipe_label(struct label *label, char *string)
1249{
1250	int error;
1251
1252	MAC_INTERNALIZE(pipe_label, label, string);
1253
1254	return (error);
1255}
1256
1257static int
1258mac_internalize_socket_label(struct label *label, char *string)
1259{
1260	int error;
1261
1262	MAC_INTERNALIZE(socket_label, label, string);
1263
1264	return (error);
1265}
1266
1267static int
1268mac_internalize_vnode_label(struct label *label, char *string)
1269{
1270	int error;
1271
1272	MAC_INTERNALIZE(vnode_label, label, string);
1273
1274	return (error);
1275}
1276
1277/*
1278 * Initialize MAC label for the first kernel process, from which other
1279 * kernel processes and threads are spawned.
1280 */
1281void
1282mac_create_proc0(struct ucred *cred)
1283{
1284
1285	MAC_PERFORM(create_proc0, cred);
1286}
1287
1288/*
1289 * Initialize MAC label for the first userland process, from which other
1290 * userland processes and threads are spawned.
1291 */
1292void
1293mac_create_proc1(struct ucred *cred)
1294{
1295
1296	MAC_PERFORM(create_proc1, cred);
1297}
1298
1299void
1300mac_thread_userret(struct thread *td)
1301{
1302
1303	MAC_PERFORM(thread_userret, td);
1304}
1305
1306/*
1307 * When a new process is created, its label must be initialized.  Generally,
1308 * this involves inheritence from the parent process, modulo possible
1309 * deltas.  This function allows that processing to take place.
1310 */
1311void
1312mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1313{
1314
1315	MAC_PERFORM(create_cred, parent_cred, child_cred);
1316}
1317
1318void
1319mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1320    struct vnode *vp)
1321{
1322
1323	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1324	    &vp->v_label);
1325}
1326
1327void
1328mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1329    struct vnode *vp)
1330{
1331
1332	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1333	    &de->de_label, vp, &vp->v_label);
1334}
1335
1336int
1337mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1338{
1339	int error;
1340
1341	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1342
1343	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1344	    &vp->v_label);
1345
1346	return (error);
1347}
1348
1349void
1350mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1351{
1352
1353	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1354	    &vp->v_label);
1355}
1356
1357int
1358mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1359    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1360{
1361	int error;
1362
1363	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1364	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1365
1366	error = VOP_OPENEXTATTR(vp, cred, curthread);
1367	if (error == EOPNOTSUPP) {
1368		/* XXX: Optionally abort if transactions not supported. */
1369		if (ea_warn_once == 0) {
1370			printf("Warning: transactions not supported "
1371			    "in EA write.\n");
1372			ea_warn_once = 1;
1373		}
1374	} else if (error)
1375		return (error);
1376
1377	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1378	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1379
1380	if (error) {
1381		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1382		return (error);
1383	}
1384
1385	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1386
1387	if (error == EOPNOTSUPP)
1388		error = 0;				/* XXX */
1389
1390	return (error);
1391}
1392
1393static int
1394mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1395    struct label *intlabel)
1396{
1397	int error;
1398
1399	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1400
1401	error = VOP_OPENEXTATTR(vp, cred, curthread);
1402	if (error == EOPNOTSUPP) {
1403		/* XXX: Optionally abort if transactions not supported. */
1404		if (ea_warn_once == 0) {
1405			printf("Warning: transactions not supported "
1406			    "in EA write.\n");
1407			ea_warn_once = 1;
1408		}
1409	} else if (error)
1410		return (error);
1411
1412	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1413
1414	if (error) {
1415		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1416		return (error);
1417	}
1418
1419	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1420
1421	if (error == EOPNOTSUPP)
1422		error = 0;				/* XXX */
1423
1424	return (error);
1425}
1426
1427int
1428mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1429    struct label *execlabelstorage)
1430{
1431	struct mac mac;
1432	char *buffer;
1433	int error;
1434
1435	if (mac_p == NULL)
1436		return (0);
1437
1438	error = copyin(mac_p, &mac, sizeof(mac));
1439	if (error)
1440		return (error);
1441
1442	error = mac_check_structmac_consistent(&mac);
1443	if (error)
1444		return (error);
1445
1446	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1447	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1448	if (error) {
1449		free(buffer, M_MACTEMP);
1450		return (error);
1451	}
1452
1453	mac_init_cred_label(execlabelstorage);
1454	error = mac_internalize_cred_label(execlabelstorage, buffer);
1455	free(buffer, M_MACTEMP);
1456	if (error) {
1457		mac_destroy_cred_label(execlabelstorage);
1458		return (error);
1459	}
1460	imgp->execlabel = execlabelstorage;
1461	return (0);
1462}
1463
1464void
1465mac_execve_exit(struct image_params *imgp)
1466{
1467	if (imgp->execlabel != NULL)
1468		mac_destroy_cred_label(imgp->execlabel);
1469}
1470
1471void
1472mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1473    struct label *interpvnodelabel, struct image_params *imgp)
1474{
1475
1476	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1477
1478	if (!mac_enforce_process && !mac_enforce_fs)
1479		return;
1480
1481	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1482	    interpvnodelabel, imgp, imgp->execlabel);
1483}
1484
1485int
1486mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1487    struct label *interpvnodelabel, struct image_params *imgp)
1488{
1489	int result;
1490
1491	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1492
1493	if (!mac_enforce_process && !mac_enforce_fs)
1494		return (0);
1495
1496	result = 0;
1497	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1498	    interpvnodelabel, imgp, imgp->execlabel);
1499
1500	return (result);
1501}
1502
1503int
1504mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1505{
1506	int error;
1507
1508	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1509
1510	if (!mac_enforce_fs)
1511		return (0);
1512
1513	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1514	return (error);
1515}
1516
1517int
1518mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1519{
1520	int error;
1521
1522	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1523
1524	if (!mac_enforce_fs)
1525		return (0);
1526
1527	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1528	return (error);
1529}
1530
1531int
1532mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1533{
1534	int error;
1535
1536	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1537
1538	if (!mac_enforce_fs)
1539		return (0);
1540
1541	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1542	return (error);
1543}
1544
1545int
1546mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1547    struct componentname *cnp, struct vattr *vap)
1548{
1549	int error;
1550
1551	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1552
1553	if (!mac_enforce_fs)
1554		return (0);
1555
1556	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1557	return (error);
1558}
1559
1560int
1561mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1562    struct componentname *cnp)
1563{
1564	int error;
1565
1566	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1567	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1568
1569	if (!mac_enforce_fs)
1570		return (0);
1571
1572	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1573	    &vp->v_label, cnp);
1574	return (error);
1575}
1576
1577int
1578mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1579    acl_type_t type)
1580{
1581	int error;
1582
1583	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1584
1585	if (!mac_enforce_fs)
1586		return (0);
1587
1588	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1589	return (error);
1590}
1591
1592int
1593mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1594    struct image_params *imgp)
1595{
1596	int error;
1597
1598	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1599
1600	if (!mac_enforce_process && !mac_enforce_fs)
1601		return (0);
1602
1603	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1604	    imgp->execlabel);
1605
1606	return (error);
1607}
1608
1609int
1610mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1611{
1612	int error;
1613
1614	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1615
1616	if (!mac_enforce_fs)
1617		return (0);
1618
1619	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1620	return (error);
1621}
1622
1623int
1624mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1625    int attrnamespace, const char *name, struct uio *uio)
1626{
1627	int error;
1628
1629	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1630
1631	if (!mac_enforce_fs)
1632		return (0);
1633
1634	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1635	    attrnamespace, name, uio);
1636	return (error);
1637}
1638
1639int
1640mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1641    struct vnode *vp, struct componentname *cnp)
1642{
1643	int error;
1644
1645	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1646	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1647
1648	if (!mac_enforce_fs)
1649		return (0);
1650
1651	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1652	    &vp->v_label, cnp);
1653	return (error);
1654}
1655
1656int
1657mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1658    struct componentname *cnp)
1659{
1660	int error;
1661
1662	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1663
1664	if (!mac_enforce_fs)
1665		return (0);
1666
1667	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1668	return (error);
1669}
1670
1671int
1672mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1673{
1674	int error;
1675
1676	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1677
1678	if (!mac_enforce_fs || !mac_enforce_vm)
1679		return (0);
1680
1681	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1682	return (error);
1683}
1684
1685void
1686mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1687{
1688	int result = *prot;
1689
1690	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1691
1692	if (!mac_enforce_fs || !mac_enforce_vm)
1693		return;
1694
1695	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1696	    &result);
1697
1698	*prot = result;
1699}
1700
1701int
1702mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1703{
1704	int error;
1705
1706	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1707
1708	if (!mac_enforce_fs || !mac_enforce_vm)
1709		return (0);
1710
1711	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1712	return (error);
1713}
1714
1715int
1716mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1717{
1718	int error;
1719
1720	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1721
1722	if (!mac_enforce_fs)
1723		return (0);
1724
1725	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1726	return (error);
1727}
1728
1729int
1730mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1731    struct vnode *vp)
1732{
1733	int error;
1734
1735	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1736
1737	if (!mac_enforce_fs)
1738		return (0);
1739
1740	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1741	    &vp->v_label);
1742
1743	return (error);
1744}
1745
1746int
1747mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1748    struct vnode *vp)
1749{
1750	int error;
1751
1752	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1753
1754	if (!mac_enforce_fs)
1755		return (0);
1756
1757	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1758	    &vp->v_label);
1759
1760	return (error);
1761}
1762
1763int
1764mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1765{
1766	int error;
1767
1768	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1769
1770	if (!mac_enforce_fs)
1771		return (0);
1772
1773	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1774	return (error);
1775}
1776
1777int
1778mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1779{
1780	int error;
1781
1782	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1783
1784	if (!mac_enforce_fs)
1785		return (0);
1786
1787	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1788	return (error);
1789}
1790
1791static int
1792mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1793    struct label *newlabel)
1794{
1795	int error;
1796
1797	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1798
1799	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1800
1801	return (error);
1802}
1803
1804int
1805mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1806    struct vnode *vp, struct componentname *cnp)
1807{
1808	int error;
1809
1810	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1811	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1812
1813	if (!mac_enforce_fs)
1814		return (0);
1815
1816	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1817	    &vp->v_label, cnp);
1818	return (error);
1819}
1820
1821int
1822mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1823    struct vnode *vp, int samedir, struct componentname *cnp)
1824{
1825	int error;
1826
1827	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1828	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1829
1830	if (!mac_enforce_fs)
1831		return (0);
1832
1833	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1834	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1835	return (error);
1836}
1837
1838int
1839mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1840{
1841	int error;
1842
1843	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1844
1845	if (!mac_enforce_fs)
1846		return (0);
1847
1848	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1849	return (error);
1850}
1851
1852int
1853mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1854    struct acl *acl)
1855{
1856	int error;
1857
1858	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1859
1860	if (!mac_enforce_fs)
1861		return (0);
1862
1863	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1864	return (error);
1865}
1866
1867int
1868mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1869    int attrnamespace, const char *name, struct uio *uio)
1870{
1871	int error;
1872
1873	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1874
1875	if (!mac_enforce_fs)
1876		return (0);
1877
1878	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1879	    attrnamespace, name, uio);
1880	return (error);
1881}
1882
1883int
1884mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1885{
1886	int error;
1887
1888	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1889
1890	if (!mac_enforce_fs)
1891		return (0);
1892
1893	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1894	return (error);
1895}
1896
1897int
1898mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1899{
1900	int error;
1901
1902	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1903
1904	if (!mac_enforce_fs)
1905		return (0);
1906
1907	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1908	return (error);
1909}
1910
1911int
1912mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1913    gid_t gid)
1914{
1915	int error;
1916
1917	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1918
1919	if (!mac_enforce_fs)
1920		return (0);
1921
1922	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1923	return (error);
1924}
1925
1926int
1927mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1928    struct timespec atime, struct timespec mtime)
1929{
1930	int error;
1931
1932	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1933
1934	if (!mac_enforce_fs)
1935		return (0);
1936
1937	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1938	    mtime);
1939	return (error);
1940}
1941
1942int
1943mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1944    struct vnode *vp)
1945{
1946	int error;
1947
1948	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1949
1950	if (!mac_enforce_fs)
1951		return (0);
1952
1953	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
1954	    &vp->v_label);
1955	return (error);
1956}
1957
1958int
1959mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1960    struct vnode *vp)
1961{
1962	int error;
1963
1964	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
1965
1966	if (!mac_enforce_fs)
1967		return (0);
1968
1969	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
1970	    &vp->v_label);
1971
1972	return (error);
1973}
1974
1975/*
1976 * When relabeling a process, call out to the policies for the maximum
1977 * permission allowed for each object type we know about in its
1978 * memory space, and revoke access (in the least surprising ways we
1979 * know) when necessary.  The process lock is not held here.
1980 */
1981void
1982mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
1983{
1984
1985	/* XXX freeze all other threads */
1986	mac_cred_mmapped_drop_perms_recurse(td, cred,
1987	    &td->td_proc->p_vmspace->vm_map);
1988	/* XXX allow other threads to continue */
1989}
1990
1991static __inline const char *
1992prot2str(vm_prot_t prot)
1993{
1994
1995	switch (prot & VM_PROT_ALL) {
1996	case VM_PROT_READ:
1997		return ("r--");
1998	case VM_PROT_READ | VM_PROT_WRITE:
1999		return ("rw-");
2000	case VM_PROT_READ | VM_PROT_EXECUTE:
2001		return ("r-x");
2002	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2003		return ("rwx");
2004	case VM_PROT_WRITE:
2005		return ("-w-");
2006	case VM_PROT_EXECUTE:
2007		return ("--x");
2008	case VM_PROT_WRITE | VM_PROT_EXECUTE:
2009		return ("-wx");
2010	default:
2011		return ("---");
2012	}
2013}
2014
2015static void
2016mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2017    struct vm_map *map)
2018{
2019	struct vm_map_entry *vme;
2020	int result;
2021	vm_prot_t revokeperms;
2022	vm_object_t object;
2023	vm_ooffset_t offset;
2024	struct vnode *vp;
2025
2026	if (!mac_mmap_revocation)
2027		return;
2028
2029	vm_map_lock_read(map);
2030	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2031		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2032			mac_cred_mmapped_drop_perms_recurse(td, cred,
2033			    vme->object.sub_map);
2034			continue;
2035		}
2036		/*
2037		 * Skip over entries that obviously are not shared.
2038		 */
2039		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2040		    !vme->max_protection)
2041			continue;
2042		/*
2043		 * Drill down to the deepest backing object.
2044		 */
2045		offset = vme->offset;
2046		object = vme->object.vm_object;
2047		if (object == NULL)
2048			continue;
2049		while (object->backing_object != NULL) {
2050			object = object->backing_object;
2051			offset += object->backing_object_offset;
2052		}
2053		/*
2054		 * At the moment, vm_maps and objects aren't considered
2055		 * by the MAC system, so only things with backing by a
2056		 * normal object (read: vnodes) are checked.
2057		 */
2058		if (object->type != OBJT_VNODE)
2059			continue;
2060		vp = (struct vnode *)object->handle;
2061		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2062		result = vme->max_protection;
2063		mac_check_vnode_mmap_downgrade(cred, vp, &result);
2064		VOP_UNLOCK(vp, 0, td);
2065		/*
2066		 * Find out what maximum protection we may be allowing
2067		 * now but a policy needs to get removed.
2068		 */
2069		revokeperms = vme->max_protection & ~result;
2070		if (!revokeperms)
2071			continue;
2072		printf("pid %ld: revoking %s perms from %#lx:%ld "
2073		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2074		    prot2str(revokeperms), (u_long)vme->start,
2075		    (long)(vme->end - vme->start),
2076		    prot2str(vme->max_protection), prot2str(vme->protection));
2077		vm_map_lock_upgrade(map);
2078		/*
2079		 * This is the really simple case: if a map has more
2080		 * max_protection than is allowed, but it's not being
2081		 * actually used (that is, the current protection is
2082		 * still allowed), we can just wipe it out and do
2083		 * nothing more.
2084		 */
2085		if ((vme->protection & revokeperms) == 0) {
2086			vme->max_protection -= revokeperms;
2087		} else {
2088			if (revokeperms & VM_PROT_WRITE) {
2089				/*
2090				 * In the more complicated case, flush out all
2091				 * pending changes to the object then turn it
2092				 * copy-on-write.
2093				 */
2094				vm_object_reference(object);
2095				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2096				VM_OBJECT_LOCK(object);
2097				vm_object_page_clean(object,
2098				    OFF_TO_IDX(offset),
2099				    OFF_TO_IDX(offset + vme->end - vme->start +
2100					PAGE_MASK),
2101				    OBJPC_SYNC);
2102				VM_OBJECT_UNLOCK(object);
2103				VOP_UNLOCK(vp, 0, td);
2104				vm_object_deallocate(object);
2105				/*
2106				 * Why bother if there's no read permissions
2107				 * anymore?  For the rest, we need to leave
2108				 * the write permissions on for COW, or
2109				 * remove them entirely if configured to.
2110				 */
2111				if (!mac_mmap_revocation_via_cow) {
2112					vme->max_protection &= ~VM_PROT_WRITE;
2113					vme->protection &= ~VM_PROT_WRITE;
2114				} if ((revokeperms & VM_PROT_READ) == 0)
2115					vme->eflags |= MAP_ENTRY_COW |
2116					    MAP_ENTRY_NEEDS_COPY;
2117			}
2118			if (revokeperms & VM_PROT_EXECUTE) {
2119				vme->max_protection &= ~VM_PROT_EXECUTE;
2120				vme->protection &= ~VM_PROT_EXECUTE;
2121			}
2122			if (revokeperms & VM_PROT_READ) {
2123				vme->max_protection = 0;
2124				vme->protection = 0;
2125			}
2126			pmap_protect(map->pmap, vme->start, vme->end,
2127			    vme->protection & ~revokeperms);
2128			vm_map_simplify_entry(map, vme);
2129		}
2130		vm_map_lock_downgrade(map);
2131	}
2132	vm_map_unlock_read(map);
2133}
2134
2135/*
2136 * When the subject's label changes, it may require revocation of privilege
2137 * to mapped objects.  This can't be done on-the-fly later with a unified
2138 * buffer cache.
2139 */
2140static void
2141mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2142{
2143
2144	MAC_PERFORM(relabel_cred, cred, newlabel);
2145}
2146
2147void
2148mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2149{
2150
2151	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2152}
2153
2154void
2155mac_create_ifnet(struct ifnet *ifnet)
2156{
2157
2158	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2159}
2160
2161void
2162mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2163{
2164
2165	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2166}
2167
2168void
2169mac_create_socket(struct ucred *cred, struct socket *socket)
2170{
2171
2172	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2173}
2174
2175void
2176mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2177{
2178
2179	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2180}
2181
2182void
2183mac_create_socket_from_socket(struct socket *oldsocket,
2184    struct socket *newsocket)
2185{
2186
2187	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2188	    newsocket, &newsocket->so_label);
2189}
2190
2191static void
2192mac_relabel_socket(struct ucred *cred, struct socket *socket,
2193    struct label *newlabel)
2194{
2195
2196	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2197}
2198
2199static void
2200mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2201{
2202
2203	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2204}
2205
2206void
2207mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2208{
2209	struct label *label;
2210
2211	label = mbuf_to_label(mbuf);
2212
2213	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
2214	    &socket->so_peerlabel);
2215}
2216
2217void
2218mac_set_socket_peer_from_socket(struct socket *oldsocket,
2219    struct socket *newsocket)
2220{
2221
2222	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2223	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2224}
2225
2226void
2227mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2228{
2229	struct label *label;
2230
2231	label = mbuf_to_label(datagram);
2232
2233	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2234	    datagram, label);
2235}
2236
2237void
2238mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2239{
2240	struct label *datagramlabel, *fragmentlabel;
2241
2242	datagramlabel = mbuf_to_label(datagram);
2243	fragmentlabel = mbuf_to_label(fragment);
2244
2245	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
2246	    fragmentlabel);
2247}
2248
2249void
2250mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2251{
2252	struct label *label;
2253
2254	label = mbuf_to_label(fragment);
2255
2256	MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
2257}
2258
2259void
2260mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2261{
2262	struct label *oldmbuflabel, *newmbuflabel;
2263
2264	oldmbuflabel = mbuf_to_label(oldmbuf);
2265	newmbuflabel = mbuf_to_label(newmbuf);
2266
2267	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
2268	    newmbuflabel);
2269}
2270
2271void
2272mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2273{
2274	struct label *label;
2275
2276	label = mbuf_to_label(mbuf);
2277
2278	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2279	    label);
2280}
2281
2282void
2283mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2284{
2285	struct label *label;
2286
2287	label = mbuf_to_label(mbuf);
2288
2289	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2290	    label);
2291}
2292
2293void
2294mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2295{
2296	struct label *label;
2297
2298	label = mbuf_to_label(mbuf);
2299
2300	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2301	    label);
2302}
2303
2304void
2305mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2306    struct mbuf *newmbuf)
2307{
2308	struct label *oldmbuflabel, *newmbuflabel;
2309
2310	oldmbuflabel = mbuf_to_label(oldmbuf);
2311	newmbuflabel = mbuf_to_label(newmbuf);
2312
2313	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
2314	    ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
2315}
2316
2317void
2318mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2319{
2320	struct label *oldmbuflabel, *newmbuflabel;
2321
2322	oldmbuflabel = mbuf_to_label(oldmbuf);
2323	newmbuflabel = mbuf_to_label(newmbuf);
2324
2325	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
2326	    newmbuflabel);
2327}
2328
2329int
2330mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2331{
2332	struct label *label;
2333	int result;
2334
2335	label = mbuf_to_label(fragment);
2336
2337	result = 1;
2338	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
2339	    &ipq->ipq_label);
2340
2341	return (result);
2342}
2343
2344void
2345mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2346{
2347	struct label *label;
2348
2349	label = mbuf_to_label(fragment);
2350
2351	MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
2352}
2353
2354void
2355mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2356{
2357	struct label *label;
2358
2359	label = mbuf_to_label(mbuf);
2360
2361	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2362	    label);
2363}
2364
2365void
2366mac_create_mount(struct ucred *cred, struct mount *mp)
2367{
2368
2369	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2370	    &mp->mnt_fslabel);
2371}
2372
2373void
2374mac_create_root_mount(struct ucred *cred, struct mount *mp)
2375{
2376
2377	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2378	    &mp->mnt_fslabel);
2379}
2380
2381int
2382mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2383{
2384	int error;
2385
2386	if (!mac_enforce_network)
2387		return (0);
2388
2389	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2390	    &ifnet->if_label);
2391
2392	return (error);
2393}
2394
2395static int
2396mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2397{
2398	int error;
2399
2400	MAC_CHECK(check_cred_relabel, cred, newlabel);
2401
2402	return (error);
2403}
2404
2405int
2406mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2407{
2408	int error;
2409
2410	if (!mac_enforce_process)
2411		return (0);
2412
2413	MAC_CHECK(check_cred_visible, u1, u2);
2414
2415	return (error);
2416}
2417
2418int
2419mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2420{
2421	struct label *label;
2422	int error;
2423
2424	M_ASSERTPKTHDR(mbuf);
2425
2426	if (!mac_enforce_network)
2427		return (0);
2428
2429	label = mbuf_to_label(mbuf);
2430
2431	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2432	    label);
2433
2434	return (error);
2435}
2436
2437int
2438mac_check_kenv_dump(struct ucred *cred)
2439{
2440	int error;
2441
2442	if (!mac_enforce_system)
2443		return (0);
2444
2445	MAC_CHECK(check_kenv_dump, cred);
2446
2447	return (error);
2448}
2449
2450int
2451mac_check_kenv_get(struct ucred *cred, char *name)
2452{
2453	int error;
2454
2455	if (!mac_enforce_system)
2456		return (0);
2457
2458	MAC_CHECK(check_kenv_get, cred, name);
2459
2460	return (error);
2461}
2462
2463int
2464mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2465{
2466	int error;
2467
2468	if (!mac_enforce_system)
2469		return (0);
2470
2471	MAC_CHECK(check_kenv_set, cred, name, value);
2472
2473	return (error);
2474}
2475
2476int
2477mac_check_kenv_unset(struct ucred *cred, char *name)
2478{
2479	int error;
2480
2481	if (!mac_enforce_system)
2482		return (0);
2483
2484	MAC_CHECK(check_kenv_unset, cred, name);
2485
2486	return (error);
2487}
2488
2489int
2490mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2491{
2492	int error;
2493
2494	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2495
2496	if (!mac_enforce_kld)
2497		return (0);
2498
2499	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2500
2501	return (error);
2502}
2503
2504int
2505mac_check_kld_stat(struct ucred *cred)
2506{
2507	int error;
2508
2509	if (!mac_enforce_kld)
2510		return (0);
2511
2512	MAC_CHECK(check_kld_stat, cred);
2513
2514	return (error);
2515}
2516
2517int
2518mac_check_kld_unload(struct ucred *cred)
2519{
2520	int error;
2521
2522	if (!mac_enforce_kld)
2523		return (0);
2524
2525	MAC_CHECK(check_kld_unload, cred);
2526
2527	return (error);
2528}
2529
2530int
2531mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2532{
2533	int error;
2534
2535	if (!mac_enforce_fs)
2536		return (0);
2537
2538	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2539
2540	return (error);
2541}
2542
2543int
2544mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2545    void *data)
2546{
2547	int error;
2548
2549	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2550
2551	if (!mac_enforce_pipe)
2552		return (0);
2553
2554	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2555
2556	return (error);
2557}
2558
2559int
2560mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2561{
2562	int error;
2563
2564	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2565
2566	if (!mac_enforce_pipe)
2567		return (0);
2568
2569	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2570
2571	return (error);
2572}
2573
2574int
2575mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2576{
2577	int error;
2578
2579	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2580
2581	if (!mac_enforce_pipe)
2582		return (0);
2583
2584	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2585
2586	return (error);
2587}
2588
2589static int
2590mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2591    struct label *newlabel)
2592{
2593	int error;
2594
2595	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2596
2597	if (!mac_enforce_pipe)
2598		return (0);
2599
2600	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2601
2602	return (error);
2603}
2604
2605int
2606mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2607{
2608	int error;
2609
2610	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2611
2612	if (!mac_enforce_pipe)
2613		return (0);
2614
2615	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2616
2617	return (error);
2618}
2619
2620int
2621mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2622{
2623	int error;
2624
2625	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2626
2627	if (!mac_enforce_pipe)
2628		return (0);
2629
2630	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2631
2632	return (error);
2633}
2634
2635int
2636mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2637{
2638	int error;
2639
2640	PROC_LOCK_ASSERT(proc, MA_OWNED);
2641
2642	if (!mac_enforce_process)
2643		return (0);
2644
2645	MAC_CHECK(check_proc_debug, cred, proc);
2646
2647	return (error);
2648}
2649
2650int
2651mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2652{
2653	int error;
2654
2655	PROC_LOCK_ASSERT(proc, MA_OWNED);
2656
2657	if (!mac_enforce_process)
2658		return (0);
2659
2660	MAC_CHECK(check_proc_sched, cred, proc);
2661
2662	return (error);
2663}
2664
2665int
2666mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2667{
2668	int error;
2669
2670	PROC_LOCK_ASSERT(proc, MA_OWNED);
2671
2672	if (!mac_enforce_process)
2673		return (0);
2674
2675	MAC_CHECK(check_proc_signal, cred, proc, signum);
2676
2677	return (error);
2678}
2679
2680int
2681mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2682    struct sockaddr *sockaddr)
2683{
2684	int error;
2685
2686	if (!mac_enforce_socket)
2687		return (0);
2688
2689	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2690	    sockaddr);
2691
2692	return (error);
2693}
2694
2695int
2696mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2697    struct sockaddr *sockaddr)
2698{
2699	int error;
2700
2701	if (!mac_enforce_socket)
2702		return (0);
2703
2704	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2705	    sockaddr);
2706
2707	return (error);
2708}
2709
2710int
2711mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2712{
2713	struct label *label;
2714	int error;
2715
2716	if (!mac_enforce_socket)
2717		return (0);
2718
2719	label = mbuf_to_label(mbuf);
2720
2721	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2722	    label);
2723
2724	return (error);
2725}
2726
2727int
2728mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2729{
2730	int error;
2731
2732	if (!mac_enforce_socket)
2733		return (0);
2734
2735	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2736	return (error);
2737}
2738
2739int
2740mac_check_socket_receive(struct ucred *cred, struct socket *so)
2741{
2742	int error;
2743
2744	if (!mac_enforce_socket)
2745		return (0);
2746
2747	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2748
2749	return (error);
2750}
2751
2752static int
2753mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2754    struct label *newlabel)
2755{
2756	int error;
2757
2758	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2759	    newlabel);
2760
2761	return (error);
2762}
2763
2764int
2765mac_check_socket_send(struct ucred *cred, struct socket *so)
2766{
2767	int error;
2768
2769	if (!mac_enforce_socket)
2770		return (0);
2771
2772	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2773
2774	return (error);
2775}
2776
2777int
2778mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2779{
2780	int error;
2781
2782	if (!mac_enforce_socket)
2783		return (0);
2784
2785	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2786
2787	return (error);
2788}
2789
2790int
2791mac_check_sysarch_ioperm(struct ucred *cred)
2792{
2793	int error;
2794
2795	if (!mac_enforce_system)
2796		return (0);
2797
2798	MAC_CHECK(check_sysarch_ioperm, cred);
2799	return (error);
2800}
2801
2802int
2803mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2804{
2805	int error;
2806
2807	if (vp != NULL) {
2808		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2809	}
2810
2811	if (!mac_enforce_system)
2812		return (0);
2813
2814	MAC_CHECK(check_system_acct, cred, vp,
2815	    vp != NULL ? &vp->v_label : NULL);
2816
2817	return (error);
2818}
2819
2820int
2821mac_check_system_nfsd(struct ucred *cred)
2822{
2823	int error;
2824
2825	if (!mac_enforce_system)
2826		return (0);
2827
2828	MAC_CHECK(check_system_nfsd, cred);
2829
2830	return (error);
2831}
2832
2833int
2834mac_check_system_reboot(struct ucred *cred, int howto)
2835{
2836	int error;
2837
2838	if (!mac_enforce_system)
2839		return (0);
2840
2841	MAC_CHECK(check_system_reboot, cred, howto);
2842
2843	return (error);
2844}
2845
2846int
2847mac_check_system_settime(struct ucred *cred)
2848{
2849	int error;
2850
2851	if (!mac_enforce_system)
2852		return (0);
2853
2854	MAC_CHECK(check_system_settime, cred);
2855
2856	return (error);
2857}
2858
2859int
2860mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2861{
2862	int error;
2863
2864	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2865
2866	if (!mac_enforce_system)
2867		return (0);
2868
2869	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2870	return (error);
2871}
2872
2873int
2874mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2875{
2876	int error;
2877
2878	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2879
2880	if (!mac_enforce_system)
2881		return (0);
2882
2883	MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2884	return (error);
2885}
2886
2887int
2888mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2889    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2890{
2891	int error;
2892
2893	/*
2894	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2895	 * but since it's not exported from kern_sysctl.c, we can't.
2896	 */
2897	if (!mac_enforce_system)
2898		return (0);
2899
2900	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2901	    inkernel, new, newlen);
2902
2903	return (error);
2904}
2905
2906int
2907mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2908    struct ifnet *ifnet)
2909{
2910	char *elements, *buffer;
2911	struct mac mac;
2912	int error;
2913
2914	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2915	if (error)
2916		return (error);
2917
2918	error = mac_check_structmac_consistent(&mac);
2919	if (error)
2920		return (error);
2921
2922	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2923	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2924	if (error) {
2925		free(elements, M_MACTEMP);
2926		return (error);
2927	}
2928
2929	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2930	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2931	    buffer, mac.m_buflen, M_WAITOK);
2932	if (error == 0)
2933		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2934
2935	free(buffer, M_MACTEMP);
2936	free(elements, M_MACTEMP);
2937
2938	return (error);
2939}
2940
2941int
2942mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2943    struct ifnet *ifnet)
2944{
2945	struct label intlabel;
2946	struct mac mac;
2947	char *buffer;
2948	int error;
2949
2950	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2951	if (error)
2952		return (error);
2953
2954	error = mac_check_structmac_consistent(&mac);
2955	if (error)
2956		return (error);
2957
2958	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2959	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2960	if (error) {
2961		free(buffer, M_MACTEMP);
2962		return (error);
2963	}
2964
2965	mac_init_ifnet_label(&intlabel);
2966	error = mac_internalize_ifnet_label(&intlabel, buffer);
2967	free(buffer, M_MACTEMP);
2968	if (error) {
2969		mac_destroy_ifnet_label(&intlabel);
2970		return (error);
2971	}
2972
2973	/*
2974	 * XXX: Note that this is a redundant privilege check, since
2975	 * policies impose this check themselves if required by the
2976	 * policy.  Eventually, this should go away.
2977	 */
2978	error = suser_cred(cred, 0);
2979	if (error) {
2980		mac_destroy_ifnet_label(&intlabel);
2981		return (error);
2982	}
2983
2984	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2985	    &intlabel);
2986	if (error) {
2987		mac_destroy_ifnet_label(&intlabel);
2988		return (error);
2989	}
2990
2991	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2992
2993	mac_destroy_ifnet_label(&intlabel);
2994	return (0);
2995}
2996
2997void
2998mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
2999{
3000
3001	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
3002}
3003
3004void
3005mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3006    struct devfs_dirent *dd, struct devfs_dirent *de)
3007{
3008
3009	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
3010	    &de->de_label);
3011}
3012
3013void
3014mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
3015    struct devfs_dirent *de)
3016{
3017
3018	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
3019	    &de->de_label);
3020}
3021
3022int
3023mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3024    struct mac *mac)
3025{
3026	struct label intlabel;
3027	char *buffer;
3028	int error;
3029
3030	error = mac_check_structmac_consistent(mac);
3031	if (error)
3032		return (error);
3033
3034	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3035	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3036	if (error) {
3037		free(buffer, M_MACTEMP);
3038		return (error);
3039	}
3040
3041	mac_init_socket_label(&intlabel, M_WAITOK);
3042	error = mac_internalize_socket_label(&intlabel, buffer);
3043	free(buffer, M_MACTEMP);
3044	if (error) {
3045		mac_destroy_socket_label(&intlabel);
3046		return (error);
3047	}
3048
3049	mac_check_socket_relabel(cred, so, &intlabel);
3050	if (error) {
3051		mac_destroy_socket_label(&intlabel);
3052		return (error);
3053	}
3054
3055	mac_relabel_socket(cred, so, &intlabel);
3056
3057	mac_destroy_socket_label(&intlabel);
3058	return (0);
3059}
3060
3061int
3062mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3063{
3064	int error;
3065
3066	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3067
3068	error = mac_check_pipe_relabel(cred, pipe, label);
3069	if (error)
3070		return (error);
3071
3072	mac_relabel_pipe(cred, pipe, label);
3073
3074	return (0);
3075}
3076
3077int
3078mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3079    struct mac *mac)
3080{
3081	char *buffer, *elements;
3082	int error;
3083
3084	error = mac_check_structmac_consistent(mac);
3085	if (error)
3086		return (error);
3087
3088	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3089	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3090	if (error) {
3091		free(elements, M_MACTEMP);
3092		return (error);
3093	}
3094
3095	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3096	error = mac_externalize_socket_label(&so->so_label, elements,
3097	    buffer, mac->m_buflen, M_WAITOK);
3098	if (error == 0)
3099		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3100
3101	free(buffer, M_MACTEMP);
3102	free(elements, M_MACTEMP);
3103
3104	return (error);
3105}
3106
3107int
3108mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3109    struct mac *mac)
3110{
3111	char *elements, *buffer;
3112	int error;
3113
3114	error = mac_check_structmac_consistent(mac);
3115	if (error)
3116		return (error);
3117
3118	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3119	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3120	if (error) {
3121		free(elements, M_MACTEMP);
3122		return (error);
3123	}
3124
3125	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3126	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3127	    elements, buffer, mac->m_buflen, M_WAITOK);
3128	if (error == 0)
3129		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3130
3131	free(buffer, M_MACTEMP);
3132	free(elements, M_MACTEMP);
3133
3134	return (error);
3135}
3136
3137/*
3138 * Implementation of VOP_SETLABEL() that relies on extended attributes
3139 * to store label data.  Can be referenced by filesystems supporting
3140 * extended attributes.
3141 */
3142int
3143vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3144{
3145	struct vnode *vp = ap->a_vp;
3146	struct label *intlabel = ap->a_label;
3147	int error;
3148
3149	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3150
3151	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3152		return (EOPNOTSUPP);
3153
3154	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3155	if (error)
3156		return (error);
3157
3158	mac_relabel_vnode(ap->a_cred, vp, intlabel);
3159
3160	return (0);
3161}
3162
3163static int
3164vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3165{
3166	int error;
3167
3168	if (vp->v_mount == NULL) {
3169		/* printf("vn_setlabel: null v_mount\n"); */
3170		if (vp->v_type != VNON)
3171			printf("vn_setlabel: null v_mount with non-VNON\n");
3172		return (EBADF);
3173	}
3174
3175	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3176		return (EOPNOTSUPP);
3177
3178	/*
3179	 * Multi-phase commit.  First check the policies to confirm the
3180	 * change is OK.  Then commit via the filesystem.  Finally,
3181	 * update the actual vnode label.  Question: maybe the filesystem
3182	 * should update the vnode at the end as part of VOP_SETLABEL()?
3183	 */
3184	error = mac_check_vnode_relabel(cred, vp, intlabel);
3185	if (error)
3186		return (error);
3187
3188	/*
3189	 * VADMIN provides the opportunity for the filesystem to make
3190	 * decisions about who is and is not able to modify labels
3191	 * and protections on files.  This might not be right.  We can't
3192	 * assume VOP_SETLABEL() will do it, because we might implement
3193	 * that as part of vop_stdsetlabel_ea().
3194	 */
3195	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3196	if (error)
3197		return (error);
3198
3199	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3200	if (error)
3201		return (error);
3202
3203	return (0);
3204}
3205
3206int
3207__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3208{
3209	char *elements, *buffer;
3210	struct mac mac;
3211	struct proc *tproc;
3212	struct ucred *tcred;
3213	int error;
3214
3215	error = copyin(uap->mac_p, &mac, sizeof(mac));
3216	if (error)
3217		return (error);
3218
3219	error = mac_check_structmac_consistent(&mac);
3220	if (error)
3221		return (error);
3222
3223	tproc = pfind(uap->pid);
3224	if (tproc == NULL)
3225		return (ESRCH);
3226
3227	tcred = NULL;				/* Satisfy gcc. */
3228	error = p_cansee(td, tproc);
3229	if (error == 0)
3230		tcred = crhold(tproc->p_ucred);
3231	PROC_UNLOCK(tproc);
3232	if (error)
3233		return (error);
3234
3235	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3236	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3237	if (error) {
3238		free(elements, M_MACTEMP);
3239		crfree(tcred);
3240		return (error);
3241	}
3242
3243	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3244	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3245	    buffer, mac.m_buflen, M_WAITOK);
3246	if (error == 0)
3247		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3248
3249	free(buffer, M_MACTEMP);
3250	free(elements, M_MACTEMP);
3251	crfree(tcred);
3252	return (error);
3253}
3254
3255/*
3256 * MPSAFE
3257 */
3258int
3259__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3260{
3261	char *elements, *buffer;
3262	struct mac mac;
3263	int error;
3264
3265	error = copyin(uap->mac_p, &mac, sizeof(mac));
3266	if (error)
3267		return (error);
3268
3269	error = mac_check_structmac_consistent(&mac);
3270	if (error)
3271		return (error);
3272
3273	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3274	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3275	if (error) {
3276		free(elements, M_MACTEMP);
3277		return (error);
3278	}
3279
3280	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3281	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3282	    elements, buffer, mac.m_buflen, M_WAITOK);
3283	if (error == 0)
3284		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3285
3286	free(buffer, M_MACTEMP);
3287	free(elements, M_MACTEMP);
3288	return (error);
3289}
3290
3291/*
3292 * MPSAFE
3293 */
3294int
3295__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3296{
3297	struct ucred *newcred, *oldcred;
3298	struct label intlabel;
3299	struct proc *p;
3300	struct mac mac;
3301	char *buffer;
3302	int error;
3303
3304	error = copyin(uap->mac_p, &mac, sizeof(mac));
3305	if (error)
3306		return (error);
3307
3308	error = mac_check_structmac_consistent(&mac);
3309	if (error)
3310		return (error);
3311
3312	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3313	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3314	if (error) {
3315		free(buffer, M_MACTEMP);
3316		return (error);
3317	}
3318
3319	mac_init_cred_label(&intlabel);
3320	error = mac_internalize_cred_label(&intlabel, buffer);
3321	free(buffer, M_MACTEMP);
3322	if (error) {
3323		mac_destroy_cred_label(&intlabel);
3324		return (error);
3325	}
3326
3327	newcred = crget();
3328
3329	p = td->td_proc;
3330	PROC_LOCK(p);
3331	oldcred = p->p_ucred;
3332
3333	error = mac_check_cred_relabel(oldcred, &intlabel);
3334	if (error) {
3335		PROC_UNLOCK(p);
3336		crfree(newcred);
3337		goto out;
3338	}
3339
3340	setsugid(p);
3341	crcopy(newcred, oldcred);
3342	mac_relabel_cred(newcred, &intlabel);
3343	p->p_ucred = newcred;
3344
3345	/*
3346	 * Grab additional reference for use while revoking mmaps, prior
3347	 * to releasing the proc lock and sharing the cred.
3348	 */
3349	crhold(newcred);
3350	PROC_UNLOCK(p);
3351
3352	if (mac_enforce_vm) {
3353		mtx_lock(&Giant);
3354		mac_cred_mmapped_drop_perms(td, newcred);
3355		mtx_unlock(&Giant);
3356	}
3357
3358	crfree(newcred);	/* Free revocation reference. */
3359	crfree(oldcred);
3360
3361out:
3362	mac_destroy_cred_label(&intlabel);
3363	return (error);
3364}
3365
3366/*
3367 * MPSAFE
3368 */
3369int
3370__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3371{
3372	char *elements, *buffer;
3373	struct label intlabel;
3374	struct file *fp;
3375	struct mac mac;
3376	struct vnode *vp;
3377	struct pipe *pipe;
3378	short label_type;
3379	int error;
3380
3381	error = copyin(uap->mac_p, &mac, sizeof(mac));
3382	if (error)
3383		return (error);
3384
3385	error = mac_check_structmac_consistent(&mac);
3386	if (error)
3387		return (error);
3388
3389	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3390	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3391	if (error) {
3392		free(elements, M_MACTEMP);
3393		return (error);
3394	}
3395
3396	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3397	mtx_lock(&Giant);				/* VFS */
3398	error = fget(td, uap->fd, &fp);
3399	if (error)
3400		goto out;
3401
3402	label_type = fp->f_type;
3403	switch (fp->f_type) {
3404	case DTYPE_FIFO:
3405	case DTYPE_VNODE:
3406		vp = fp->f_data;
3407
3408		mac_init_vnode_label(&intlabel);
3409
3410		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3411		mac_copy_vnode_label(&vp->v_label, &intlabel);
3412		VOP_UNLOCK(vp, 0, td);
3413
3414		break;
3415	case DTYPE_PIPE:
3416		pipe = fp->f_data;
3417
3418		mac_init_pipe_label(&intlabel);
3419
3420		PIPE_LOCK(pipe);
3421		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3422		PIPE_UNLOCK(pipe);
3423		break;
3424	default:
3425		error = EINVAL;
3426		fdrop(fp, td);
3427		goto out;
3428	}
3429	fdrop(fp, td);
3430
3431	switch (label_type) {
3432	case DTYPE_FIFO:
3433	case DTYPE_VNODE:
3434		if (error == 0)
3435			error = mac_externalize_vnode_label(&intlabel,
3436			    elements, buffer, mac.m_buflen, M_WAITOK);
3437		mac_destroy_vnode_label(&intlabel);
3438		break;
3439	case DTYPE_PIPE:
3440		error = mac_externalize_pipe_label(&intlabel, elements,
3441		    buffer, mac.m_buflen, M_WAITOK);
3442		mac_destroy_pipe_label(&intlabel);
3443		break;
3444	default:
3445		panic("__mac_get_fd: corrupted label_type");
3446	}
3447
3448	if (error == 0)
3449		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3450
3451out:
3452	mtx_unlock(&Giant);				/* VFS */
3453	free(buffer, M_MACTEMP);
3454	free(elements, M_MACTEMP);
3455
3456	return (error);
3457}
3458
3459/*
3460 * MPSAFE
3461 */
3462int
3463__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3464{
3465	char *elements, *buffer;
3466	struct nameidata nd;
3467	struct label intlabel;
3468	struct mac mac;
3469	int error;
3470
3471	error = copyin(uap->mac_p, &mac, sizeof(mac));
3472	if (error)
3473		return (error);
3474
3475	error = mac_check_structmac_consistent(&mac);
3476	if (error)
3477		return (error);
3478
3479	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3480	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3481	if (error) {
3482		free(elements, M_MACTEMP);
3483		return (error);
3484	}
3485
3486	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3487	mtx_lock(&Giant);				/* VFS */
3488	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3489	    td);
3490	error = namei(&nd);
3491	if (error)
3492		goto out;
3493
3494	mac_init_vnode_label(&intlabel);
3495	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3496	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3497	    mac.m_buflen, M_WAITOK);
3498
3499	NDFREE(&nd, 0);
3500	mac_destroy_vnode_label(&intlabel);
3501
3502	if (error == 0)
3503		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3504
3505out:
3506	mtx_unlock(&Giant);				/* VFS */
3507
3508	free(buffer, M_MACTEMP);
3509	free(elements, M_MACTEMP);
3510
3511	return (error);
3512}
3513
3514/*
3515 * MPSAFE
3516 */
3517int
3518__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3519{
3520	char *elements, *buffer;
3521	struct nameidata nd;
3522	struct label intlabel;
3523	struct mac mac;
3524	int error;
3525
3526	error = copyin(uap->mac_p, &mac, sizeof(mac));
3527	if (error)
3528		return (error);
3529
3530	error = mac_check_structmac_consistent(&mac);
3531	if (error)
3532		return (error);
3533
3534	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3535	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3536	if (error) {
3537		free(elements, M_MACTEMP);
3538		return (error);
3539	}
3540
3541	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3542	mtx_lock(&Giant);				/* VFS */
3543	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3544	    td);
3545	error = namei(&nd);
3546	if (error)
3547		goto out;
3548
3549	mac_init_vnode_label(&intlabel);
3550	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3551	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3552	    mac.m_buflen, M_WAITOK);
3553	NDFREE(&nd, 0);
3554	mac_destroy_vnode_label(&intlabel);
3555
3556	if (error == 0)
3557		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3558
3559out:
3560	mtx_unlock(&Giant);				/* VFS */
3561
3562	free(buffer, M_MACTEMP);
3563	free(elements, M_MACTEMP);
3564
3565	return (error);
3566}
3567
3568/*
3569 * MPSAFE
3570 */
3571int
3572__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3573{
3574	struct label intlabel;
3575	struct pipe *pipe;
3576	struct file *fp;
3577	struct mount *mp;
3578	struct vnode *vp;
3579	struct mac mac;
3580	char *buffer;
3581	int error;
3582
3583	error = copyin(uap->mac_p, &mac, sizeof(mac));
3584	if (error)
3585		return (error);
3586
3587	error = mac_check_structmac_consistent(&mac);
3588	if (error)
3589		return (error);
3590
3591	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3592	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3593	if (error) {
3594		free(buffer, M_MACTEMP);
3595		return (error);
3596	}
3597
3598	mtx_lock(&Giant);				/* VFS */
3599
3600	error = fget(td, uap->fd, &fp);
3601	if (error)
3602		goto out;
3603
3604	switch (fp->f_type) {
3605	case DTYPE_FIFO:
3606	case DTYPE_VNODE:
3607		mac_init_vnode_label(&intlabel);
3608		error = mac_internalize_vnode_label(&intlabel, buffer);
3609		if (error) {
3610			mac_destroy_vnode_label(&intlabel);
3611			break;
3612		}
3613
3614		vp = fp->f_data;
3615		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3616		if (error != 0) {
3617			mac_destroy_vnode_label(&intlabel);
3618			break;
3619		}
3620
3621		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3622		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3623		VOP_UNLOCK(vp, 0, td);
3624		vn_finished_write(mp);
3625
3626		mac_destroy_vnode_label(&intlabel);
3627		break;
3628
3629	case DTYPE_PIPE:
3630		mac_init_pipe_label(&intlabel);
3631		error = mac_internalize_pipe_label(&intlabel, buffer);
3632		if (error == 0) {
3633			pipe = fp->f_data;
3634			PIPE_LOCK(pipe);
3635			error = mac_pipe_label_set(td->td_ucred, pipe,
3636			    &intlabel);
3637			PIPE_UNLOCK(pipe);
3638		}
3639
3640		mac_destroy_pipe_label(&intlabel);
3641		break;
3642
3643	default:
3644		error = EINVAL;
3645	}
3646
3647	fdrop(fp, td);
3648out:
3649	mtx_unlock(&Giant);				/* VFS */
3650
3651	free(buffer, M_MACTEMP);
3652
3653	return (error);
3654}
3655
3656/*
3657 * MPSAFE
3658 */
3659int
3660__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3661{
3662	struct label intlabel;
3663	struct nameidata nd;
3664	struct mount *mp;
3665	struct mac mac;
3666	char *buffer;
3667	int error;
3668
3669	error = copyin(uap->mac_p, &mac, sizeof(mac));
3670	if (error)
3671		return (error);
3672
3673	error = mac_check_structmac_consistent(&mac);
3674	if (error)
3675		return (error);
3676
3677	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3678	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3679	if (error) {
3680		free(buffer, M_MACTEMP);
3681		return (error);
3682	}
3683
3684	mac_init_vnode_label(&intlabel);
3685	error = mac_internalize_vnode_label(&intlabel, buffer);
3686	free(buffer, M_MACTEMP);
3687	if (error) {
3688		mac_destroy_vnode_label(&intlabel);
3689		return (error);
3690	}
3691
3692	mtx_lock(&Giant);				/* VFS */
3693
3694	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3695	    td);
3696	error = namei(&nd);
3697	if (error == 0) {
3698		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3699		if (error == 0)
3700			error = vn_setlabel(nd.ni_vp, &intlabel,
3701			    td->td_ucred);
3702		vn_finished_write(mp);
3703	}
3704
3705	NDFREE(&nd, 0);
3706	mtx_unlock(&Giant);				/* VFS */
3707	mac_destroy_vnode_label(&intlabel);
3708
3709	return (error);
3710}
3711
3712/*
3713 * MPSAFE
3714 */
3715int
3716__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3717{
3718	struct label intlabel;
3719	struct nameidata nd;
3720	struct mount *mp;
3721	struct mac mac;
3722	char *buffer;
3723	int error;
3724
3725	error = copyin(uap->mac_p, &mac, sizeof(mac));
3726	if (error)
3727		return (error);
3728
3729	error = mac_check_structmac_consistent(&mac);
3730	if (error)
3731		return (error);
3732
3733	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3734	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3735	if (error) {
3736		free(buffer, M_MACTEMP);
3737		return (error);
3738	}
3739
3740	mac_init_vnode_label(&intlabel);
3741	error = mac_internalize_vnode_label(&intlabel, buffer);
3742	free(buffer, M_MACTEMP);
3743	if (error) {
3744		mac_destroy_vnode_label(&intlabel);
3745		return (error);
3746	}
3747
3748	mtx_lock(&Giant);				/* VFS */
3749
3750	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3751	    td);
3752	error = namei(&nd);
3753	if (error == 0) {
3754		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3755		if (error == 0)
3756			error = vn_setlabel(nd.ni_vp, &intlabel,
3757			    td->td_ucred);
3758		vn_finished_write(mp);
3759	}
3760
3761	NDFREE(&nd, 0);
3762	mtx_unlock(&Giant);				/* VFS */
3763	mac_destroy_vnode_label(&intlabel);
3764
3765	return (error);
3766}
3767
3768/*
3769 * MPSAFE
3770 */
3771int
3772mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3773{
3774	struct mac_policy_conf *mpc;
3775	char target[MAC_MAX_POLICY_NAME];
3776	int error;
3777
3778	error = copyinstr(uap->policy, target, sizeof(target), NULL);
3779	if (error)
3780		return (error);
3781
3782	error = ENOSYS;
3783	MAC_POLICY_LIST_BUSY();
3784	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3785		if (strcmp(mpc->mpc_name, target) == 0 &&
3786		    mpc->mpc_ops->mpo_syscall != NULL) {
3787			error = mpc->mpc_ops->mpo_syscall(td,
3788			    uap->call, uap->arg);
3789			goto out;
3790		}
3791	}
3792
3793out:
3794	MAC_POLICY_LIST_UNBUSY();
3795	return (error);
3796}
3797
3798SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3799SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3800
3801#else /* !MAC */
3802
3803int
3804__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3805{
3806
3807	return (ENOSYS);
3808}
3809
3810int
3811__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3812{
3813
3814	return (ENOSYS);
3815}
3816
3817int
3818__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3819{
3820
3821	return (ENOSYS);
3822}
3823
3824int
3825__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3826{
3827
3828	return (ENOSYS);
3829}
3830
3831int
3832__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3833{
3834
3835	return (ENOSYS);
3836}
3837
3838int
3839__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3840{
3841
3842	return (ENOSYS);
3843}
3844
3845int
3846__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3847{
3848
3849	return (ENOSYS);
3850}
3851
3852int
3853__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3854{
3855
3856	return (ENOSYS);
3857}
3858
3859int
3860__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3861{
3862
3863	return (ENOSYS);
3864}
3865
3866int
3867mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3868{
3869
3870	return (ENOSYS);
3871}
3872
3873#endif
3874