mac_cred.c revision 113487
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002 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_process.c 113487 2003-04-14 20:39:06Z rwatson $
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, trflag;
787
788	label = (struct label *) (tag + 1);
789	mac_init_label(label);
790
791	trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
792	MAC_CHECK(init_mbuf_label, label, trflag);
793	if (error) {
794		MAC_PERFORM(destroy_mbuf_label, label);
795		mac_destroy_label(label);
796	}
797#ifdef MAC_DEBUG
798	if (error == 0)
799		atomic_add_int(&nmacmbufs, 1);
800#endif
801	return (error);
802}
803
804int
805mac_init_mbuf(struct mbuf *m, int flag)
806{
807	struct m_tag *tag;
808	int error;
809
810	M_ASSERTPKTHDR(m);
811
812#ifndef MAC_ALWAYS_LABEL_MBUF
813	/*
814	 * Don't reserve space for labels on mbufs unless we have a policy
815	 * that uses the labels.
816	 */
817	if (mac_labelmbufs) {
818#endif
819		tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
820		    flag);
821		if (tag == NULL)
822			return (ENOMEM);
823		error = mac_init_mbuf_tag(tag, flag);
824		if (error) {
825			m_tag_free(tag);
826			return (error);
827		}
828		m_tag_prepend(m, tag);
829#ifndef MAC_ALWAYS_LABEL_MBUF
830	}
831#endif
832	return (0);
833}
834
835void
836mac_init_mount(struct mount *mp)
837{
838
839	mac_init_label(&mp->mnt_mntlabel);
840	mac_init_label(&mp->mnt_fslabel);
841	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
842	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
843#ifdef MAC_DEBUG
844	atomic_add_int(&nmacmounts, 1);
845#endif
846}
847
848static void
849mac_init_pipe_label(struct label *label)
850{
851
852	mac_init_label(label);
853	MAC_PERFORM(init_pipe_label, label);
854#ifdef MAC_DEBUG
855	atomic_add_int(&nmacpipes, 1);
856#endif
857}
858
859void
860mac_init_pipe(struct pipe *pipe)
861{
862	struct label *label;
863
864	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
865	pipe->pipe_label = label;
866	pipe->pipe_peer->pipe_label = label;
867	mac_init_pipe_label(label);
868}
869
870void
871mac_init_proc(struct proc *p)
872{
873
874	mac_init_label(&p->p_label);
875	MAC_PERFORM(init_proc_label, &p->p_label);
876#ifdef MAC_DEBUG
877	atomic_add_int(&nmacprocs, 1);
878#endif
879}
880
881static int
882mac_init_socket_label(struct label *label, int flag)
883{
884	int error;
885
886	mac_init_label(label);
887
888	MAC_CHECK(init_socket_label, label, flag);
889	if (error) {
890		MAC_PERFORM(destroy_socket_label, label);
891		mac_destroy_label(label);
892	}
893
894#ifdef MAC_DEBUG
895	if (error == 0)
896		atomic_add_int(&nmacsockets, 1);
897#endif
898
899	return (error);
900}
901
902static int
903mac_init_socket_peer_label(struct label *label, int flag)
904{
905	int error;
906
907	mac_init_label(label);
908
909	MAC_CHECK(init_socket_peer_label, label, flag);
910	if (error) {
911		MAC_PERFORM(destroy_socket_label, label);
912		mac_destroy_label(label);
913	}
914
915	return (error);
916}
917
918int
919mac_init_socket(struct socket *socket, int flag)
920{
921	int error;
922
923	error = mac_init_socket_label(&socket->so_label, flag);
924	if (error)
925		return (error);
926
927	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
928	if (error)
929		mac_destroy_socket_label(&socket->so_label);
930
931	return (error);
932}
933
934void
935mac_init_vnode_label(struct label *label)
936{
937
938	mac_init_label(label);
939	MAC_PERFORM(init_vnode_label, label);
940#ifdef MAC_DEBUG
941	atomic_add_int(&nmacvnodes, 1);
942#endif
943}
944
945void
946mac_init_vnode(struct vnode *vp)
947{
948
949	mac_init_vnode_label(&vp->v_label);
950}
951
952void
953mac_destroy_bpfdesc(struct bpf_d *bpf_d)
954{
955
956	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
957	mac_destroy_label(&bpf_d->bd_label);
958#ifdef MAC_DEBUG
959	atomic_subtract_int(&nmacbpfdescs, 1);
960#endif
961}
962
963static void
964mac_destroy_cred_label(struct label *label)
965{
966
967	MAC_PERFORM(destroy_cred_label, label);
968	mac_destroy_label(label);
969#ifdef MAC_DEBUG
970	atomic_subtract_int(&nmaccreds, 1);
971#endif
972}
973
974void
975mac_destroy_cred(struct ucred *cred)
976{
977
978	mac_destroy_cred_label(&cred->cr_label);
979}
980
981void
982mac_destroy_devfsdirent(struct devfs_dirent *de)
983{
984
985	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
986	mac_destroy_label(&de->de_label);
987#ifdef MAC_DEBUG
988	atomic_subtract_int(&nmacdevfsdirents, 1);
989#endif
990}
991
992static void
993mac_destroy_ifnet_label(struct label *label)
994{
995
996	MAC_PERFORM(destroy_ifnet_label, label);
997	mac_destroy_label(label);
998#ifdef MAC_DEBUG
999	atomic_subtract_int(&nmacifnets, 1);
1000#endif
1001}
1002
1003void
1004mac_destroy_ifnet(struct ifnet *ifp)
1005{
1006
1007	mac_destroy_ifnet_label(&ifp->if_label);
1008}
1009
1010void
1011mac_destroy_ipq(struct ipq *ipq)
1012{
1013
1014	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1015	mac_destroy_label(&ipq->ipq_label);
1016#ifdef MAC_DEBUG
1017	atomic_subtract_int(&nmacipqs, 1);
1018#endif
1019}
1020
1021void
1022mac_destroy_mbuf_tag(struct m_tag *tag)
1023{
1024	struct label *label;
1025
1026	label = (struct label *)(tag+1);
1027
1028	MAC_PERFORM(destroy_mbuf_label, label);
1029	mac_destroy_label(label);
1030#ifdef MAC_DEBUG
1031	atomic_subtract_int(&nmacmbufs, 1);
1032#endif
1033}
1034
1035void
1036mac_destroy_mount(struct mount *mp)
1037{
1038
1039	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1040	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1041	mac_destroy_label(&mp->mnt_fslabel);
1042	mac_destroy_label(&mp->mnt_mntlabel);
1043#ifdef MAC_DEBUG
1044	atomic_subtract_int(&nmacmounts, 1);
1045#endif
1046}
1047
1048static void
1049mac_destroy_pipe_label(struct label *label)
1050{
1051
1052	MAC_PERFORM(destroy_pipe_label, label);
1053	mac_destroy_label(label);
1054#ifdef MAC_DEBUG
1055	atomic_subtract_int(&nmacpipes, 1);
1056#endif
1057}
1058
1059void
1060mac_destroy_pipe(struct pipe *pipe)
1061{
1062
1063	mac_destroy_pipe_label(pipe->pipe_label);
1064	free(pipe->pipe_label, M_MACPIPELABEL);
1065}
1066
1067void
1068mac_destroy_proc(struct proc *p)
1069{
1070
1071	MAC_PERFORM(destroy_proc_label, &p->p_label);
1072	mac_destroy_label(&p->p_label);
1073#ifdef MAC_DEBUG
1074	atomic_subtract_int(&nmacprocs, 1);
1075#endif
1076}
1077
1078static void
1079mac_destroy_socket_label(struct label *label)
1080{
1081
1082	MAC_PERFORM(destroy_socket_label, label);
1083	mac_destroy_label(label);
1084#ifdef MAC_DEBUG
1085	atomic_subtract_int(&nmacsockets, 1);
1086#endif
1087}
1088
1089static void
1090mac_destroy_socket_peer_label(struct label *label)
1091{
1092
1093	MAC_PERFORM(destroy_socket_peer_label, label);
1094	mac_destroy_label(label);
1095}
1096
1097void
1098mac_destroy_socket(struct socket *socket)
1099{
1100
1101	mac_destroy_socket_label(&socket->so_label);
1102	mac_destroy_socket_peer_label(&socket->so_peerlabel);
1103}
1104
1105void
1106mac_destroy_vnode_label(struct label *label)
1107{
1108
1109	MAC_PERFORM(destroy_vnode_label, label);
1110	mac_destroy_label(label);
1111#ifdef MAC_DEBUG
1112	atomic_subtract_int(&nmacvnodes, 1);
1113#endif
1114}
1115
1116void
1117mac_destroy_vnode(struct vnode *vp)
1118{
1119
1120	mac_destroy_vnode_label(&vp->v_label);
1121}
1122
1123void
1124mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
1125{
1126	struct label *src_label, *dest_label;
1127
1128	src_label = (struct label *)(src+1);
1129	dest_label = (struct label *)(dest+1);
1130
1131	/*
1132	 * mac_init_mbuf_tag() is called on the target tag in
1133	 * m_tag_copy(), so we don't need to call it here.
1134	 */
1135	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
1136}
1137
1138static void
1139mac_copy_pipe_label(struct label *src, struct label *dest)
1140{
1141
1142	MAC_PERFORM(copy_pipe_label, src, dest);
1143}
1144
1145void
1146mac_copy_vnode_label(struct label *src, struct label *dest)
1147{
1148
1149	MAC_PERFORM(copy_vnode_label, src, dest);
1150}
1151
1152static int
1153mac_check_structmac_consistent(struct mac *mac)
1154{
1155
1156	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1157		return (EINVAL);
1158
1159	return (0);
1160}
1161
1162static int
1163mac_externalize_cred_label(struct label *label, char *elements,
1164    char *outbuf, size_t outbuflen, int flags)
1165{
1166	int error;
1167
1168	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1169
1170	return (error);
1171}
1172
1173static int
1174mac_externalize_ifnet_label(struct label *label, char *elements,
1175    char *outbuf, size_t outbuflen, int flags)
1176{
1177	int error;
1178
1179	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1180
1181	return (error);
1182}
1183
1184static int
1185mac_externalize_pipe_label(struct label *label, char *elements,
1186    char *outbuf, size_t outbuflen, int flags)
1187{
1188	int error;
1189
1190	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1191
1192	return (error);
1193}
1194
1195static int
1196mac_externalize_socket_label(struct label *label, char *elements,
1197    char *outbuf, size_t outbuflen, int flags)
1198{
1199	int error;
1200
1201	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1202
1203	return (error);
1204}
1205
1206static int
1207mac_externalize_socket_peer_label(struct label *label, char *elements,
1208    char *outbuf, size_t outbuflen, int flags)
1209{
1210	int error;
1211
1212	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1213
1214	return (error);
1215}
1216
1217static int
1218mac_externalize_vnode_label(struct label *label, char *elements,
1219    char *outbuf, size_t outbuflen, int flags)
1220{
1221	int error;
1222
1223	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1224
1225	return (error);
1226}
1227
1228static int
1229mac_internalize_cred_label(struct label *label, char *string)
1230{
1231	int error;
1232
1233	MAC_INTERNALIZE(cred_label, label, string);
1234
1235	return (error);
1236}
1237
1238static int
1239mac_internalize_ifnet_label(struct label *label, char *string)
1240{
1241	int error;
1242
1243	MAC_INTERNALIZE(ifnet_label, label, string);
1244
1245	return (error);
1246}
1247
1248static int
1249mac_internalize_pipe_label(struct label *label, char *string)
1250{
1251	int error;
1252
1253	MAC_INTERNALIZE(pipe_label, label, string);
1254
1255	return (error);
1256}
1257
1258static int
1259mac_internalize_socket_label(struct label *label, char *string)
1260{
1261	int error;
1262
1263	MAC_INTERNALIZE(socket_label, label, string);
1264
1265	return (error);
1266}
1267
1268static int
1269mac_internalize_vnode_label(struct label *label, char *string)
1270{
1271	int error;
1272
1273	MAC_INTERNALIZE(vnode_label, label, string);
1274
1275	return (error);
1276}
1277
1278/*
1279 * Initialize MAC label for the first kernel process, from which other
1280 * kernel processes and threads are spawned.
1281 */
1282void
1283mac_create_proc0(struct ucred *cred)
1284{
1285
1286	MAC_PERFORM(create_proc0, cred);
1287}
1288
1289/*
1290 * Initialize MAC label for the first userland process, from which other
1291 * userland processes and threads are spawned.
1292 */
1293void
1294mac_create_proc1(struct ucred *cred)
1295{
1296
1297	MAC_PERFORM(create_proc1, cred);
1298}
1299
1300void
1301mac_thread_userret(struct thread *td)
1302{
1303
1304	MAC_PERFORM(thread_userret, td);
1305}
1306
1307/*
1308 * When a new process is created, its label must be initialized.  Generally,
1309 * this involves inheritence from the parent process, modulo possible
1310 * deltas.  This function allows that processing to take place.
1311 */
1312void
1313mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1314{
1315
1316	MAC_PERFORM(create_cred, parent_cred, child_cred);
1317}
1318
1319void
1320mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1321    struct vnode *vp)
1322{
1323
1324	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1325	    &vp->v_label);
1326}
1327
1328void
1329mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1330    struct vnode *vp)
1331{
1332
1333	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1334	    &de->de_label, vp, &vp->v_label);
1335}
1336
1337int
1338mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1339{
1340	int error;
1341
1342	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1343
1344	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1345	    &vp->v_label);
1346
1347	return (error);
1348}
1349
1350void
1351mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1352{
1353
1354	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1355	    &vp->v_label);
1356}
1357
1358int
1359mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1360    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1361{
1362	int error;
1363
1364	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1365	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1366
1367	error = VOP_OPENEXTATTR(vp, cred, curthread);
1368	if (error == EOPNOTSUPP) {
1369		/* XXX: Optionally abort if transactions not supported. */
1370		if (ea_warn_once == 0) {
1371			printf("Warning: transactions not supported "
1372			    "in EA write.\n");
1373			ea_warn_once = 1;
1374		}
1375	} else if (error)
1376		return (error);
1377
1378	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1379	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1380
1381	if (error) {
1382		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1383		return (error);
1384	}
1385
1386	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1387
1388	if (error == EOPNOTSUPP)
1389		error = 0;				/* XXX */
1390
1391	return (error);
1392}
1393
1394static int
1395mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1396    struct label *intlabel)
1397{
1398	int error;
1399
1400	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1401
1402	error = VOP_OPENEXTATTR(vp, cred, curthread);
1403	if (error == EOPNOTSUPP) {
1404		/* XXX: Optionally abort if transactions not supported. */
1405		if (ea_warn_once == 0) {
1406			printf("Warning: transactions not supported "
1407			    "in EA write.\n");
1408			ea_warn_once = 1;
1409		}
1410	} else if (error)
1411		return (error);
1412
1413	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1414
1415	if (error) {
1416		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1417		return (error);
1418	}
1419
1420	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1421
1422	if (error == EOPNOTSUPP)
1423		error = 0;				/* XXX */
1424
1425	return (error);
1426}
1427
1428int
1429mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1430    struct label *execlabelstorage)
1431{
1432	struct mac mac;
1433	char *buffer;
1434	int error;
1435
1436	if (mac_p == NULL)
1437		return (0);
1438
1439	error = copyin(mac_p, &mac, sizeof(mac));
1440	if (error)
1441		return (error);
1442
1443	error = mac_check_structmac_consistent(&mac);
1444	if (error)
1445		return (error);
1446
1447	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1448	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1449	if (error) {
1450		free(buffer, M_MACTEMP);
1451		return (error);
1452	}
1453
1454	mac_init_cred_label(execlabelstorage);
1455	error = mac_internalize_cred_label(execlabelstorage, buffer);
1456	free(buffer, M_MACTEMP);
1457	if (error) {
1458		mac_destroy_cred_label(execlabelstorage);
1459		return (error);
1460	}
1461	imgp->execlabel = execlabelstorage;
1462	return (0);
1463}
1464
1465void
1466mac_execve_exit(struct image_params *imgp)
1467{
1468	if (imgp->execlabel != NULL)
1469		mac_destroy_cred_label(imgp->execlabel);
1470}
1471
1472void
1473mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1474    struct label *interpvnodelabel, struct image_params *imgp)
1475{
1476
1477	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1478
1479	if (!mac_enforce_process && !mac_enforce_fs)
1480		return;
1481
1482	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1483	    interpvnodelabel, imgp, imgp->execlabel);
1484}
1485
1486int
1487mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1488    struct label *interpvnodelabel, struct image_params *imgp)
1489{
1490	int result;
1491
1492	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1493
1494	if (!mac_enforce_process && !mac_enforce_fs)
1495		return (0);
1496
1497	result = 0;
1498	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1499	    interpvnodelabel, imgp, imgp->execlabel);
1500
1501	return (result);
1502}
1503
1504int
1505mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1506{
1507	int error;
1508
1509	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1510
1511	if (!mac_enforce_fs)
1512		return (0);
1513
1514	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1515	return (error);
1516}
1517
1518int
1519mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1520{
1521	int error;
1522
1523	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1524
1525	if (!mac_enforce_fs)
1526		return (0);
1527
1528	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1529	return (error);
1530}
1531
1532int
1533mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1534{
1535	int error;
1536
1537	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1538
1539	if (!mac_enforce_fs)
1540		return (0);
1541
1542	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1543	return (error);
1544}
1545
1546int
1547mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1548    struct componentname *cnp, struct vattr *vap)
1549{
1550	int error;
1551
1552	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1553
1554	if (!mac_enforce_fs)
1555		return (0);
1556
1557	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1558	return (error);
1559}
1560
1561int
1562mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1563    struct componentname *cnp)
1564{
1565	int error;
1566
1567	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1568	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1569
1570	if (!mac_enforce_fs)
1571		return (0);
1572
1573	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1574	    &vp->v_label, cnp);
1575	return (error);
1576}
1577
1578int
1579mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1580    acl_type_t type)
1581{
1582	int error;
1583
1584	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1585
1586	if (!mac_enforce_fs)
1587		return (0);
1588
1589	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1590	return (error);
1591}
1592
1593int
1594mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1595    struct image_params *imgp)
1596{
1597	int error;
1598
1599	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1600
1601	if (!mac_enforce_process && !mac_enforce_fs)
1602		return (0);
1603
1604	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1605	    imgp->execlabel);
1606
1607	return (error);
1608}
1609
1610int
1611mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1612{
1613	int error;
1614
1615	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1616
1617	if (!mac_enforce_fs)
1618		return (0);
1619
1620	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1621	return (error);
1622}
1623
1624int
1625mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1626    int attrnamespace, const char *name, struct uio *uio)
1627{
1628	int error;
1629
1630	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1631
1632	if (!mac_enforce_fs)
1633		return (0);
1634
1635	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1636	    attrnamespace, name, uio);
1637	return (error);
1638}
1639
1640int
1641mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1642    struct vnode *vp, struct componentname *cnp)
1643{
1644	int error;
1645
1646	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1647	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1648
1649	if (!mac_enforce_fs)
1650		return (0);
1651
1652	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1653	    &vp->v_label, cnp);
1654	return (error);
1655}
1656
1657int
1658mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1659    struct componentname *cnp)
1660{
1661	int error;
1662
1663	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1664
1665	if (!mac_enforce_fs)
1666		return (0);
1667
1668	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1669	return (error);
1670}
1671
1672int
1673mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1674{
1675	int error;
1676
1677	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1678
1679	if (!mac_enforce_fs || !mac_enforce_vm)
1680		return (0);
1681
1682	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1683	return (error);
1684}
1685
1686void
1687mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1688{
1689	int result = *prot;
1690
1691	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1692
1693	if (!mac_enforce_fs || !mac_enforce_vm)
1694		return;
1695
1696	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1697	    &result);
1698
1699	*prot = result;
1700}
1701
1702int
1703mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1704{
1705	int error;
1706
1707	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1708
1709	if (!mac_enforce_fs || !mac_enforce_vm)
1710		return (0);
1711
1712	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1713	return (error);
1714}
1715
1716int
1717mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1718{
1719	int error;
1720
1721	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1722
1723	if (!mac_enforce_fs)
1724		return (0);
1725
1726	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1727	return (error);
1728}
1729
1730int
1731mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1732    struct vnode *vp)
1733{
1734	int error;
1735
1736	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1737
1738	if (!mac_enforce_fs)
1739		return (0);
1740
1741	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1742	    &vp->v_label);
1743
1744	return (error);
1745}
1746
1747int
1748mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1749    struct vnode *vp)
1750{
1751	int error;
1752
1753	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1754
1755	if (!mac_enforce_fs)
1756		return (0);
1757
1758	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1759	    &vp->v_label);
1760
1761	return (error);
1762}
1763
1764int
1765mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1766{
1767	int error;
1768
1769	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1770
1771	if (!mac_enforce_fs)
1772		return (0);
1773
1774	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1775	return (error);
1776}
1777
1778int
1779mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1780{
1781	int error;
1782
1783	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1784
1785	if (!mac_enforce_fs)
1786		return (0);
1787
1788	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1789	return (error);
1790}
1791
1792static int
1793mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1794    struct label *newlabel)
1795{
1796	int error;
1797
1798	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1799
1800	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1801
1802	return (error);
1803}
1804
1805int
1806mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1807    struct vnode *vp, struct componentname *cnp)
1808{
1809	int error;
1810
1811	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1812	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1813
1814	if (!mac_enforce_fs)
1815		return (0);
1816
1817	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1818	    &vp->v_label, cnp);
1819	return (error);
1820}
1821
1822int
1823mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1824    struct vnode *vp, int samedir, struct componentname *cnp)
1825{
1826	int error;
1827
1828	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1829	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1830
1831	if (!mac_enforce_fs)
1832		return (0);
1833
1834	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1835	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1836	return (error);
1837}
1838
1839int
1840mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1841{
1842	int error;
1843
1844	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1845
1846	if (!mac_enforce_fs)
1847		return (0);
1848
1849	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1850	return (error);
1851}
1852
1853int
1854mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1855    struct acl *acl)
1856{
1857	int error;
1858
1859	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1860
1861	if (!mac_enforce_fs)
1862		return (0);
1863
1864	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1865	return (error);
1866}
1867
1868int
1869mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1870    int attrnamespace, const char *name, struct uio *uio)
1871{
1872	int error;
1873
1874	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1875
1876	if (!mac_enforce_fs)
1877		return (0);
1878
1879	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1880	    attrnamespace, name, uio);
1881	return (error);
1882}
1883
1884int
1885mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1886{
1887	int error;
1888
1889	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1890
1891	if (!mac_enforce_fs)
1892		return (0);
1893
1894	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1895	return (error);
1896}
1897
1898int
1899mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1900{
1901	int error;
1902
1903	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1904
1905	if (!mac_enforce_fs)
1906		return (0);
1907
1908	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1909	return (error);
1910}
1911
1912int
1913mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1914    gid_t gid)
1915{
1916	int error;
1917
1918	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1919
1920	if (!mac_enforce_fs)
1921		return (0);
1922
1923	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1924	return (error);
1925}
1926
1927int
1928mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1929    struct timespec atime, struct timespec mtime)
1930{
1931	int error;
1932
1933	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1934
1935	if (!mac_enforce_fs)
1936		return (0);
1937
1938	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1939	    mtime);
1940	return (error);
1941}
1942
1943int
1944mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1945    struct vnode *vp)
1946{
1947	int error;
1948
1949	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1950
1951	if (!mac_enforce_fs)
1952		return (0);
1953
1954	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
1955	    &vp->v_label);
1956	return (error);
1957}
1958
1959int
1960mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1961    struct vnode *vp)
1962{
1963	int error;
1964
1965	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
1966
1967	if (!mac_enforce_fs)
1968		return (0);
1969
1970	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
1971	    &vp->v_label);
1972
1973	return (error);
1974}
1975
1976/*
1977 * When relabeling a process, call out to the policies for the maximum
1978 * permission allowed for each object type we know about in its
1979 * memory space, and revoke access (in the least surprising ways we
1980 * know) when necessary.  The process lock is not held here.
1981 */
1982void
1983mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
1984{
1985
1986	/* XXX freeze all other threads */
1987	mac_cred_mmapped_drop_perms_recurse(td, cred,
1988	    &td->td_proc->p_vmspace->vm_map);
1989	/* XXX allow other threads to continue */
1990}
1991
1992static __inline const char *
1993prot2str(vm_prot_t prot)
1994{
1995
1996	switch (prot & VM_PROT_ALL) {
1997	case VM_PROT_READ:
1998		return ("r--");
1999	case VM_PROT_READ | VM_PROT_WRITE:
2000		return ("rw-");
2001	case VM_PROT_READ | VM_PROT_EXECUTE:
2002		return ("r-x");
2003	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2004		return ("rwx");
2005	case VM_PROT_WRITE:
2006		return ("-w-");
2007	case VM_PROT_EXECUTE:
2008		return ("--x");
2009	case VM_PROT_WRITE | VM_PROT_EXECUTE:
2010		return ("-wx");
2011	default:
2012		return ("---");
2013	}
2014}
2015
2016static void
2017mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2018    struct vm_map *map)
2019{
2020	struct vm_map_entry *vme;
2021	int result;
2022	vm_prot_t revokeperms;
2023	vm_object_t object;
2024	vm_ooffset_t offset;
2025	struct vnode *vp;
2026
2027	if (!mac_mmap_revocation)
2028		return;
2029
2030	vm_map_lock_read(map);
2031	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2032		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2033			mac_cred_mmapped_drop_perms_recurse(td, cred,
2034			    vme->object.sub_map);
2035			continue;
2036		}
2037		/*
2038		 * Skip over entries that obviously are not shared.
2039		 */
2040		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2041		    !vme->max_protection)
2042			continue;
2043		/*
2044		 * Drill down to the deepest backing object.
2045		 */
2046		offset = vme->offset;
2047		object = vme->object.vm_object;
2048		if (object == NULL)
2049			continue;
2050		while (object->backing_object != NULL) {
2051			object = object->backing_object;
2052			offset += object->backing_object_offset;
2053		}
2054		/*
2055		 * At the moment, vm_maps and objects aren't considered
2056		 * by the MAC system, so only things with backing by a
2057		 * normal object (read: vnodes) are checked.
2058		 */
2059		if (object->type != OBJT_VNODE)
2060			continue;
2061		vp = (struct vnode *)object->handle;
2062		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2063		result = vme->max_protection;
2064		mac_check_vnode_mmap_downgrade(cred, vp, &result);
2065		VOP_UNLOCK(vp, 0, td);
2066		/*
2067		 * Find out what maximum protection we may be allowing
2068		 * now but a policy needs to get removed.
2069		 */
2070		revokeperms = vme->max_protection & ~result;
2071		if (!revokeperms)
2072			continue;
2073		printf("pid %ld: revoking %s perms from %#lx:%ld "
2074		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2075		    prot2str(revokeperms), (u_long)vme->start,
2076		    (long)(vme->end - vme->start),
2077		    prot2str(vme->max_protection), prot2str(vme->protection));
2078		vm_map_lock_upgrade(map);
2079		/*
2080		 * This is the really simple case: if a map has more
2081		 * max_protection than is allowed, but it's not being
2082		 * actually used (that is, the current protection is
2083		 * still allowed), we can just wipe it out and do
2084		 * nothing more.
2085		 */
2086		if ((vme->protection & revokeperms) == 0) {
2087			vme->max_protection -= revokeperms;
2088		} else {
2089			if (revokeperms & VM_PROT_WRITE) {
2090				/*
2091				 * In the more complicated case, flush out all
2092				 * pending changes to the object then turn it
2093				 * copy-on-write.
2094				 */
2095				vm_object_reference(object);
2096				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
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				VOP_UNLOCK(vp, 0, td);
2103				vm_object_deallocate(object);
2104				/*
2105				 * Why bother if there's no read permissions
2106				 * anymore?  For the rest, we need to leave
2107				 * the write permissions on for COW, or
2108				 * remove them entirely if configured to.
2109				 */
2110				if (!mac_mmap_revocation_via_cow) {
2111					vme->max_protection &= ~VM_PROT_WRITE;
2112					vme->protection &= ~VM_PROT_WRITE;
2113				} if ((revokeperms & VM_PROT_READ) == 0)
2114					vme->eflags |= MAP_ENTRY_COW |
2115					    MAP_ENTRY_NEEDS_COPY;
2116			}
2117			if (revokeperms & VM_PROT_EXECUTE) {
2118				vme->max_protection &= ~VM_PROT_EXECUTE;
2119				vme->protection &= ~VM_PROT_EXECUTE;
2120			}
2121			if (revokeperms & VM_PROT_READ) {
2122				vme->max_protection = 0;
2123				vme->protection = 0;
2124			}
2125			pmap_protect(map->pmap, vme->start, vme->end,
2126			    vme->protection & ~revokeperms);
2127			vm_map_simplify_entry(map, vme);
2128		}
2129		vm_map_lock_downgrade(map);
2130	}
2131	vm_map_unlock_read(map);
2132}
2133
2134/*
2135 * When the subject's label changes, it may require revocation of privilege
2136 * to mapped objects.  This can't be done on-the-fly later with a unified
2137 * buffer cache.
2138 */
2139static void
2140mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2141{
2142
2143	MAC_PERFORM(relabel_cred, cred, newlabel);
2144}
2145
2146void
2147mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2148{
2149
2150	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2151}
2152
2153void
2154mac_create_ifnet(struct ifnet *ifnet)
2155{
2156
2157	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2158}
2159
2160void
2161mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2162{
2163
2164	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2165}
2166
2167void
2168mac_create_socket(struct ucred *cred, struct socket *socket)
2169{
2170
2171	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2172}
2173
2174void
2175mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2176{
2177
2178	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2179}
2180
2181void
2182mac_create_socket_from_socket(struct socket *oldsocket,
2183    struct socket *newsocket)
2184{
2185
2186	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2187	    newsocket, &newsocket->so_label);
2188}
2189
2190static void
2191mac_relabel_socket(struct ucred *cred, struct socket *socket,
2192    struct label *newlabel)
2193{
2194
2195	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2196}
2197
2198static void
2199mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2200{
2201
2202	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2203}
2204
2205void
2206mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2207{
2208	struct label *label;
2209
2210	label = mbuf_to_label(mbuf);
2211
2212	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
2213	    &socket->so_peerlabel);
2214}
2215
2216void
2217mac_set_socket_peer_from_socket(struct socket *oldsocket,
2218    struct socket *newsocket)
2219{
2220
2221	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2222	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2223}
2224
2225void
2226mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2227{
2228	struct label *label;
2229
2230	label = mbuf_to_label(datagram);
2231
2232	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2233	    datagram, label);
2234}
2235
2236void
2237mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2238{
2239	struct label *datagramlabel, *fragmentlabel;
2240
2241	datagramlabel = mbuf_to_label(datagram);
2242	fragmentlabel = mbuf_to_label(fragment);
2243
2244	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
2245	    fragmentlabel);
2246}
2247
2248void
2249mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2250{
2251	struct label *label;
2252
2253	label = mbuf_to_label(fragment);
2254
2255	MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
2256}
2257
2258void
2259mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2260{
2261	struct label *oldmbuflabel, *newmbuflabel;
2262
2263	oldmbuflabel = mbuf_to_label(oldmbuf);
2264	newmbuflabel = mbuf_to_label(newmbuf);
2265
2266	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
2267	    newmbuflabel);
2268}
2269
2270void
2271mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2272{
2273	struct label *label;
2274
2275	label = mbuf_to_label(mbuf);
2276
2277	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2278	    label);
2279}
2280
2281void
2282mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2283{
2284	struct label *label;
2285
2286	label = mbuf_to_label(mbuf);
2287
2288	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2289	    label);
2290}
2291
2292void
2293mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2294{
2295	struct label *label;
2296
2297	label = mbuf_to_label(mbuf);
2298
2299	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2300	    label);
2301}
2302
2303void
2304mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2305    struct mbuf *newmbuf)
2306{
2307	struct label *oldmbuflabel, *newmbuflabel;
2308
2309	oldmbuflabel = mbuf_to_label(oldmbuf);
2310	newmbuflabel = mbuf_to_label(newmbuf);
2311
2312	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
2313	    ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
2314}
2315
2316void
2317mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2318{
2319	struct label *oldmbuflabel, *newmbuflabel;
2320
2321	oldmbuflabel = mbuf_to_label(oldmbuf);
2322	newmbuflabel = mbuf_to_label(newmbuf);
2323
2324	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
2325	    newmbuflabel);
2326}
2327
2328int
2329mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2330{
2331	struct label *label;
2332	int result;
2333
2334	label = mbuf_to_label(fragment);
2335
2336	result = 1;
2337	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
2338	    &ipq->ipq_label);
2339
2340	return (result);
2341}
2342
2343void
2344mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2345{
2346	struct label *label;
2347
2348	label = mbuf_to_label(fragment);
2349
2350	MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
2351}
2352
2353void
2354mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2355{
2356	struct label *label;
2357
2358	label = mbuf_to_label(mbuf);
2359
2360	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2361	    label);
2362}
2363
2364void
2365mac_create_mount(struct ucred *cred, struct mount *mp)
2366{
2367
2368	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2369	    &mp->mnt_fslabel);
2370}
2371
2372void
2373mac_create_root_mount(struct ucred *cred, struct mount *mp)
2374{
2375
2376	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2377	    &mp->mnt_fslabel);
2378}
2379
2380int
2381mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2382{
2383	int error;
2384
2385	if (!mac_enforce_network)
2386		return (0);
2387
2388	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2389	    &ifnet->if_label);
2390
2391	return (error);
2392}
2393
2394static int
2395mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2396{
2397	int error;
2398
2399	MAC_CHECK(check_cred_relabel, cred, newlabel);
2400
2401	return (error);
2402}
2403
2404int
2405mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2406{
2407	int error;
2408
2409	if (!mac_enforce_process)
2410		return (0);
2411
2412	MAC_CHECK(check_cred_visible, u1, u2);
2413
2414	return (error);
2415}
2416
2417int
2418mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2419{
2420	struct label *label;
2421	int error;
2422
2423	M_ASSERTPKTHDR(mbuf);
2424
2425	if (!mac_enforce_network)
2426		return (0);
2427
2428	label = mbuf_to_label(mbuf);
2429
2430	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2431	    label);
2432
2433	return (error);
2434}
2435
2436int
2437mac_check_kenv_dump(struct ucred *cred)
2438{
2439	int error;
2440
2441	if (!mac_enforce_system)
2442		return (0);
2443
2444	MAC_CHECK(check_kenv_dump, cred);
2445
2446	return (error);
2447}
2448
2449int
2450mac_check_kenv_get(struct ucred *cred, char *name)
2451{
2452	int error;
2453
2454	if (!mac_enforce_system)
2455		return (0);
2456
2457	MAC_CHECK(check_kenv_get, cred, name);
2458
2459	return (error);
2460}
2461
2462int
2463mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2464{
2465	int error;
2466
2467	if (!mac_enforce_system)
2468		return (0);
2469
2470	MAC_CHECK(check_kenv_set, cred, name, value);
2471
2472	return (error);
2473}
2474
2475int
2476mac_check_kenv_unset(struct ucred *cred, char *name)
2477{
2478	int error;
2479
2480	if (!mac_enforce_system)
2481		return (0);
2482
2483	MAC_CHECK(check_kenv_unset, cred, name);
2484
2485	return (error);
2486}
2487
2488int
2489mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2490{
2491	int error;
2492
2493	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2494
2495	if (!mac_enforce_kld)
2496		return (0);
2497
2498	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2499
2500	return (error);
2501}
2502
2503int
2504mac_check_kld_stat(struct ucred *cred)
2505{
2506	int error;
2507
2508	if (!mac_enforce_kld)
2509		return (0);
2510
2511	MAC_CHECK(check_kld_stat, cred);
2512
2513	return (error);
2514}
2515
2516int
2517mac_check_kld_unload(struct ucred *cred)
2518{
2519	int error;
2520
2521	if (!mac_enforce_kld)
2522		return (0);
2523
2524	MAC_CHECK(check_kld_unload, cred);
2525
2526	return (error);
2527}
2528
2529int
2530mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2531{
2532	int error;
2533
2534	if (!mac_enforce_fs)
2535		return (0);
2536
2537	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2538
2539	return (error);
2540}
2541
2542int
2543mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2544    void *data)
2545{
2546	int error;
2547
2548	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2549
2550	if (!mac_enforce_pipe)
2551		return (0);
2552
2553	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2554
2555	return (error);
2556}
2557
2558int
2559mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2560{
2561	int error;
2562
2563	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2564
2565	if (!mac_enforce_pipe)
2566		return (0);
2567
2568	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2569
2570	return (error);
2571}
2572
2573int
2574mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2575{
2576	int error;
2577
2578	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2579
2580	if (!mac_enforce_pipe)
2581		return (0);
2582
2583	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2584
2585	return (error);
2586}
2587
2588static int
2589mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2590    struct label *newlabel)
2591{
2592	int error;
2593
2594	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2595
2596	if (!mac_enforce_pipe)
2597		return (0);
2598
2599	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2600
2601	return (error);
2602}
2603
2604int
2605mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2606{
2607	int error;
2608
2609	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2610
2611	if (!mac_enforce_pipe)
2612		return (0);
2613
2614	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2615
2616	return (error);
2617}
2618
2619int
2620mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2621{
2622	int error;
2623
2624	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2625
2626	if (!mac_enforce_pipe)
2627		return (0);
2628
2629	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2630
2631	return (error);
2632}
2633
2634int
2635mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2636{
2637	int error;
2638
2639	PROC_LOCK_ASSERT(proc, MA_OWNED);
2640
2641	if (!mac_enforce_process)
2642		return (0);
2643
2644	MAC_CHECK(check_proc_debug, cred, proc);
2645
2646	return (error);
2647}
2648
2649int
2650mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2651{
2652	int error;
2653
2654	PROC_LOCK_ASSERT(proc, MA_OWNED);
2655
2656	if (!mac_enforce_process)
2657		return (0);
2658
2659	MAC_CHECK(check_proc_sched, cred, proc);
2660
2661	return (error);
2662}
2663
2664int
2665mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2666{
2667	int error;
2668
2669	PROC_LOCK_ASSERT(proc, MA_OWNED);
2670
2671	if (!mac_enforce_process)
2672		return (0);
2673
2674	MAC_CHECK(check_proc_signal, cred, proc, signum);
2675
2676	return (error);
2677}
2678
2679int
2680mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2681    struct sockaddr *sockaddr)
2682{
2683	int error;
2684
2685	if (!mac_enforce_socket)
2686		return (0);
2687
2688	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2689	    sockaddr);
2690
2691	return (error);
2692}
2693
2694int
2695mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2696    struct sockaddr *sockaddr)
2697{
2698	int error;
2699
2700	if (!mac_enforce_socket)
2701		return (0);
2702
2703	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2704	    sockaddr);
2705
2706	return (error);
2707}
2708
2709int
2710mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2711{
2712	struct label *label;
2713	int error;
2714
2715	if (!mac_enforce_socket)
2716		return (0);
2717
2718	label = mbuf_to_label(mbuf);
2719
2720	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2721	    label);
2722
2723	return (error);
2724}
2725
2726int
2727mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2728{
2729	int error;
2730
2731	if (!mac_enforce_socket)
2732		return (0);
2733
2734	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2735	return (error);
2736}
2737
2738int
2739mac_check_socket_receive(struct ucred *cred, struct socket *so)
2740{
2741	int error;
2742
2743	if (!mac_enforce_socket)
2744		return (0);
2745
2746	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2747
2748	return (error);
2749}
2750
2751static int
2752mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2753    struct label *newlabel)
2754{
2755	int error;
2756
2757	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2758	    newlabel);
2759
2760	return (error);
2761}
2762
2763int
2764mac_check_socket_send(struct ucred *cred, struct socket *so)
2765{
2766	int error;
2767
2768	if (!mac_enforce_socket)
2769		return (0);
2770
2771	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2772
2773	return (error);
2774}
2775
2776int
2777mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2778{
2779	int error;
2780
2781	if (!mac_enforce_socket)
2782		return (0);
2783
2784	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2785
2786	return (error);
2787}
2788
2789int
2790mac_check_sysarch_ioperm(struct ucred *cred)
2791{
2792	int error;
2793
2794	if (!mac_enforce_system)
2795		return (0);
2796
2797	MAC_CHECK(check_sysarch_ioperm, cred);
2798	return (error);
2799}
2800
2801int
2802mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2803{
2804	int error;
2805
2806	if (vp != NULL) {
2807		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2808	}
2809
2810	if (!mac_enforce_system)
2811		return (0);
2812
2813	MAC_CHECK(check_system_acct, cred, vp,
2814	    vp != NULL ? &vp->v_label : NULL);
2815
2816	return (error);
2817}
2818
2819int
2820mac_check_system_nfsd(struct ucred *cred)
2821{
2822	int error;
2823
2824	if (!mac_enforce_system)
2825		return (0);
2826
2827	MAC_CHECK(check_system_nfsd, cred);
2828
2829	return (error);
2830}
2831
2832int
2833mac_check_system_reboot(struct ucred *cred, int howto)
2834{
2835	int error;
2836
2837	if (!mac_enforce_system)
2838		return (0);
2839
2840	MAC_CHECK(check_system_reboot, cred, howto);
2841
2842	return (error);
2843}
2844
2845int
2846mac_check_system_settime(struct ucred *cred)
2847{
2848	int error;
2849
2850	if (!mac_enforce_system)
2851		return (0);
2852
2853	MAC_CHECK(check_system_settime, cred);
2854
2855	return (error);
2856}
2857
2858int
2859mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2860{
2861	int error;
2862
2863	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2864
2865	if (!mac_enforce_system)
2866		return (0);
2867
2868	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2869	return (error);
2870}
2871
2872int
2873mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2874{
2875	int error;
2876
2877	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2878
2879	if (!mac_enforce_system)
2880		return (0);
2881
2882	MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2883	return (error);
2884}
2885
2886int
2887mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2888    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2889{
2890	int error;
2891
2892	/*
2893	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2894	 * but since it's not exported from kern_sysctl.c, we can't.
2895	 */
2896	if (!mac_enforce_system)
2897		return (0);
2898
2899	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2900	    inkernel, new, newlen);
2901
2902	return (error);
2903}
2904
2905int
2906mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2907    struct ifnet *ifnet)
2908{
2909	char *elements, *buffer;
2910	struct mac mac;
2911	int error;
2912
2913	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2914	if (error)
2915		return (error);
2916
2917	error = mac_check_structmac_consistent(&mac);
2918	if (error)
2919		return (error);
2920
2921	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2922	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2923	if (error) {
2924		free(elements, M_MACTEMP);
2925		return (error);
2926	}
2927
2928	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2929	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2930	    buffer, mac.m_buflen, M_WAITOK);
2931	if (error == 0)
2932		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2933
2934	free(buffer, M_MACTEMP);
2935	free(elements, M_MACTEMP);
2936
2937	return (error);
2938}
2939
2940int
2941mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2942    struct ifnet *ifnet)
2943{
2944	struct label intlabel;
2945	struct mac mac;
2946	char *buffer;
2947	int error;
2948
2949	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2950	if (error)
2951		return (error);
2952
2953	error = mac_check_structmac_consistent(&mac);
2954	if (error)
2955		return (error);
2956
2957	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2958	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2959	if (error) {
2960		free(buffer, M_MACTEMP);
2961		return (error);
2962	}
2963
2964	mac_init_ifnet_label(&intlabel);
2965	error = mac_internalize_ifnet_label(&intlabel, buffer);
2966	free(buffer, M_MACTEMP);
2967	if (error) {
2968		mac_destroy_ifnet_label(&intlabel);
2969		return (error);
2970	}
2971
2972	/*
2973	 * XXX: Note that this is a redundant privilege check, since
2974	 * policies impose this check themselves if required by the
2975	 * policy.  Eventually, this should go away.
2976	 */
2977	error = suser_cred(cred, 0);
2978	if (error) {
2979		mac_destroy_ifnet_label(&intlabel);
2980		return (error);
2981	}
2982
2983	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2984	    &intlabel);
2985	if (error) {
2986		mac_destroy_ifnet_label(&intlabel);
2987		return (error);
2988	}
2989
2990	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2991
2992	mac_destroy_ifnet_label(&intlabel);
2993	return (0);
2994}
2995
2996void
2997mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
2998{
2999
3000	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
3001}
3002
3003void
3004mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3005    struct devfs_dirent *dd, struct devfs_dirent *de)
3006{
3007
3008	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
3009	    &de->de_label);
3010}
3011
3012void
3013mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
3014    struct devfs_dirent *de)
3015{
3016
3017	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
3018	    &de->de_label);
3019}
3020
3021int
3022mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3023    struct mac *mac)
3024{
3025	struct label intlabel;
3026	char *buffer;
3027	int error;
3028
3029	error = mac_check_structmac_consistent(mac);
3030	if (error)
3031		return (error);
3032
3033	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3034	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3035	if (error) {
3036		free(buffer, M_MACTEMP);
3037		return (error);
3038	}
3039
3040	mac_init_socket_label(&intlabel, M_WAITOK);
3041	error = mac_internalize_socket_label(&intlabel, buffer);
3042	free(buffer, M_MACTEMP);
3043	if (error) {
3044		mac_destroy_socket_label(&intlabel);
3045		return (error);
3046	}
3047
3048	mac_check_socket_relabel(cred, so, &intlabel);
3049	if (error) {
3050		mac_destroy_socket_label(&intlabel);
3051		return (error);
3052	}
3053
3054	mac_relabel_socket(cred, so, &intlabel);
3055
3056	mac_destroy_socket_label(&intlabel);
3057	return (0);
3058}
3059
3060int
3061mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3062{
3063	int error;
3064
3065	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3066
3067	error = mac_check_pipe_relabel(cred, pipe, label);
3068	if (error)
3069		return (error);
3070
3071	mac_relabel_pipe(cred, pipe, label);
3072
3073	return (0);
3074}
3075
3076int
3077mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3078    struct mac *mac)
3079{
3080	char *buffer, *elements;
3081	int error;
3082
3083	error = mac_check_structmac_consistent(mac);
3084	if (error)
3085		return (error);
3086
3087	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3088	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3089	if (error) {
3090		free(elements, M_MACTEMP);
3091		return (error);
3092	}
3093
3094	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3095	error = mac_externalize_socket_label(&so->so_label, elements,
3096	    buffer, mac->m_buflen, M_WAITOK);
3097	if (error == 0)
3098		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3099
3100	free(buffer, M_MACTEMP);
3101	free(elements, M_MACTEMP);
3102
3103	return (error);
3104}
3105
3106int
3107mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3108    struct mac *mac)
3109{
3110	char *elements, *buffer;
3111	int error;
3112
3113	error = mac_check_structmac_consistent(mac);
3114	if (error)
3115		return (error);
3116
3117	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3118	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3119	if (error) {
3120		free(elements, M_MACTEMP);
3121		return (error);
3122	}
3123
3124	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3125	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3126	    elements, buffer, mac->m_buflen, M_WAITOK);
3127	if (error == 0)
3128		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3129
3130	free(buffer, M_MACTEMP);
3131	free(elements, M_MACTEMP);
3132
3133	return (error);
3134}
3135
3136/*
3137 * Implementation of VOP_SETLABEL() that relies on extended attributes
3138 * to store label data.  Can be referenced by filesystems supporting
3139 * extended attributes.
3140 */
3141int
3142vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3143{
3144	struct vnode *vp = ap->a_vp;
3145	struct label *intlabel = ap->a_label;
3146	int error;
3147
3148	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3149
3150	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3151		return (EOPNOTSUPP);
3152
3153	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3154	if (error)
3155		return (error);
3156
3157	mac_relabel_vnode(ap->a_cred, vp, intlabel);
3158
3159	return (0);
3160}
3161
3162static int
3163vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3164{
3165	int error;
3166
3167	if (vp->v_mount == NULL) {
3168		/* printf("vn_setlabel: null v_mount\n"); */
3169		if (vp->v_type != VNON)
3170			printf("vn_setlabel: null v_mount with non-VNON\n");
3171		return (EBADF);
3172	}
3173
3174	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3175		return (EOPNOTSUPP);
3176
3177	/*
3178	 * Multi-phase commit.  First check the policies to confirm the
3179	 * change is OK.  Then commit via the filesystem.  Finally,
3180	 * update the actual vnode label.  Question: maybe the filesystem
3181	 * should update the vnode at the end as part of VOP_SETLABEL()?
3182	 */
3183	error = mac_check_vnode_relabel(cred, vp, intlabel);
3184	if (error)
3185		return (error);
3186
3187	/*
3188	 * VADMIN provides the opportunity for the filesystem to make
3189	 * decisions about who is and is not able to modify labels
3190	 * and protections on files.  This might not be right.  We can't
3191	 * assume VOP_SETLABEL() will do it, because we might implement
3192	 * that as part of vop_stdsetlabel_ea().
3193	 */
3194	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3195	if (error)
3196		return (error);
3197
3198	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3199	if (error)
3200		return (error);
3201
3202	return (0);
3203}
3204
3205int
3206__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3207{
3208	char *elements, *buffer;
3209	struct mac mac;
3210	struct proc *tproc;
3211	struct ucred *tcred;
3212	int error;
3213
3214	error = copyin(uap->mac_p, &mac, sizeof(mac));
3215	if (error)
3216		return (error);
3217
3218	error = mac_check_structmac_consistent(&mac);
3219	if (error)
3220		return (error);
3221
3222	tproc = pfind(uap->pid);
3223	if (tproc == NULL)
3224		return (ESRCH);
3225
3226	tcred = NULL;				/* Satisfy gcc. */
3227	error = p_cansee(td, tproc);
3228	if (error == 0)
3229		tcred = crhold(tproc->p_ucred);
3230	PROC_UNLOCK(tproc);
3231	if (error)
3232		return (error);
3233
3234	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3235	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3236	if (error) {
3237		free(elements, M_MACTEMP);
3238		crfree(tcred);
3239		return (error);
3240	}
3241
3242	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3243	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3244	    buffer, mac.m_buflen, M_WAITOK);
3245	if (error == 0)
3246		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3247
3248	free(buffer, M_MACTEMP);
3249	free(elements, M_MACTEMP);
3250	crfree(tcred);
3251	return (error);
3252}
3253
3254/*
3255 * MPSAFE
3256 */
3257int
3258__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3259{
3260	char *elements, *buffer;
3261	struct mac mac;
3262	int error;
3263
3264	error = copyin(uap->mac_p, &mac, sizeof(mac));
3265	if (error)
3266		return (error);
3267
3268	error = mac_check_structmac_consistent(&mac);
3269	if (error)
3270		return (error);
3271
3272	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3273	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3274	if (error) {
3275		free(elements, M_MACTEMP);
3276		return (error);
3277	}
3278
3279	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3280	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3281	    elements, buffer, mac.m_buflen, M_WAITOK);
3282	if (error == 0)
3283		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3284
3285	free(buffer, M_MACTEMP);
3286	free(elements, M_MACTEMP);
3287	return (error);
3288}
3289
3290/*
3291 * MPSAFE
3292 */
3293int
3294__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3295{
3296	struct ucred *newcred, *oldcred;
3297	struct label intlabel;
3298	struct proc *p;
3299	struct mac mac;
3300	char *buffer;
3301	int error;
3302
3303	error = copyin(uap->mac_p, &mac, sizeof(mac));
3304	if (error)
3305		return (error);
3306
3307	error = mac_check_structmac_consistent(&mac);
3308	if (error)
3309		return (error);
3310
3311	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3312	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3313	if (error) {
3314		free(buffer, M_MACTEMP);
3315		return (error);
3316	}
3317
3318	mac_init_cred_label(&intlabel);
3319	error = mac_internalize_cred_label(&intlabel, buffer);
3320	free(buffer, M_MACTEMP);
3321	if (error) {
3322		mac_destroy_cred_label(&intlabel);
3323		return (error);
3324	}
3325
3326	newcred = crget();
3327
3328	p = td->td_proc;
3329	PROC_LOCK(p);
3330	oldcred = p->p_ucred;
3331
3332	error = mac_check_cred_relabel(oldcred, &intlabel);
3333	if (error) {
3334		PROC_UNLOCK(p);
3335		crfree(newcred);
3336		goto out;
3337	}
3338
3339	setsugid(p);
3340	crcopy(newcred, oldcred);
3341	mac_relabel_cred(newcred, &intlabel);
3342	p->p_ucred = newcred;
3343
3344	/*
3345	 * Grab additional reference for use while revoking mmaps, prior
3346	 * to releasing the proc lock and sharing the cred.
3347	 */
3348	crhold(newcred);
3349	PROC_UNLOCK(p);
3350
3351	if (mac_enforce_vm) {
3352		mtx_lock(&Giant);
3353		mac_cred_mmapped_drop_perms(td, newcred);
3354		mtx_unlock(&Giant);
3355	}
3356
3357	crfree(newcred);	/* Free revocation reference. */
3358	crfree(oldcred);
3359
3360out:
3361	mac_destroy_cred_label(&intlabel);
3362	return (error);
3363}
3364
3365/*
3366 * MPSAFE
3367 */
3368int
3369__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3370{
3371	char *elements, *buffer;
3372	struct label intlabel;
3373	struct file *fp;
3374	struct mac mac;
3375	struct vnode *vp;
3376	struct pipe *pipe;
3377	short label_type;
3378	int error;
3379
3380	error = copyin(uap->mac_p, &mac, sizeof(mac));
3381	if (error)
3382		return (error);
3383
3384	error = mac_check_structmac_consistent(&mac);
3385	if (error)
3386		return (error);
3387
3388	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3389	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3390	if (error) {
3391		free(elements, M_MACTEMP);
3392		return (error);
3393	}
3394
3395	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3396	mtx_lock(&Giant);				/* VFS */
3397	error = fget(td, uap->fd, &fp);
3398	if (error)
3399		goto out;
3400
3401	label_type = fp->f_type;
3402	switch (fp->f_type) {
3403	case DTYPE_FIFO:
3404	case DTYPE_VNODE:
3405		vp = fp->f_data;
3406
3407		mac_init_vnode_label(&intlabel);
3408
3409		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3410		mac_copy_vnode_label(&vp->v_label, &intlabel);
3411		VOP_UNLOCK(vp, 0, td);
3412
3413		break;
3414	case DTYPE_PIPE:
3415		pipe = fp->f_data;
3416
3417		mac_init_pipe_label(&intlabel);
3418
3419		PIPE_LOCK(pipe);
3420		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3421		PIPE_UNLOCK(pipe);
3422		break;
3423	default:
3424		error = EINVAL;
3425		fdrop(fp, td);
3426		goto out;
3427	}
3428	fdrop(fp, td);
3429
3430	switch (label_type) {
3431	case DTYPE_FIFO:
3432	case DTYPE_VNODE:
3433		if (error == 0)
3434			error = mac_externalize_vnode_label(&intlabel,
3435			    elements, buffer, mac.m_buflen, M_WAITOK);
3436		mac_destroy_vnode_label(&intlabel);
3437		break;
3438	case DTYPE_PIPE:
3439		error = mac_externalize_pipe_label(&intlabel, elements,
3440		    buffer, mac.m_buflen, M_WAITOK);
3441		mac_destroy_pipe_label(&intlabel);
3442		break;
3443	default:
3444		panic("__mac_get_fd: corrupted label_type");
3445	}
3446
3447	if (error == 0)
3448		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3449
3450out:
3451	mtx_unlock(&Giant);				/* VFS */
3452	free(buffer, M_MACTEMP);
3453	free(elements, M_MACTEMP);
3454
3455	return (error);
3456}
3457
3458/*
3459 * MPSAFE
3460 */
3461int
3462__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3463{
3464	char *elements, *buffer;
3465	struct nameidata nd;
3466	struct label intlabel;
3467	struct mac mac;
3468	int error;
3469
3470	error = copyin(uap->mac_p, &mac, sizeof(mac));
3471	if (error)
3472		return (error);
3473
3474	error = mac_check_structmac_consistent(&mac);
3475	if (error)
3476		return (error);
3477
3478	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3479	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3480	if (error) {
3481		free(elements, M_MACTEMP);
3482		return (error);
3483	}
3484
3485	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3486	mtx_lock(&Giant);				/* VFS */
3487	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3488	    td);
3489	error = namei(&nd);
3490	if (error)
3491		goto out;
3492
3493	mac_init_vnode_label(&intlabel);
3494	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3495	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3496	    mac.m_buflen, M_WAITOK);
3497
3498	NDFREE(&nd, 0);
3499	mac_destroy_vnode_label(&intlabel);
3500
3501	if (error == 0)
3502		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3503
3504out:
3505	mtx_unlock(&Giant);				/* VFS */
3506
3507	free(buffer, M_MACTEMP);
3508	free(elements, M_MACTEMP);
3509
3510	return (error);
3511}
3512
3513/*
3514 * MPSAFE
3515 */
3516int
3517__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3518{
3519	char *elements, *buffer;
3520	struct nameidata nd;
3521	struct label intlabel;
3522	struct mac mac;
3523	int error;
3524
3525	error = copyin(uap->mac_p, &mac, sizeof(mac));
3526	if (error)
3527		return (error);
3528
3529	error = mac_check_structmac_consistent(&mac);
3530	if (error)
3531		return (error);
3532
3533	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3534	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3535	if (error) {
3536		free(elements, M_MACTEMP);
3537		return (error);
3538	}
3539
3540	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3541	mtx_lock(&Giant);				/* VFS */
3542	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3543	    td);
3544	error = namei(&nd);
3545	if (error)
3546		goto out;
3547
3548	mac_init_vnode_label(&intlabel);
3549	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3550	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3551	    mac.m_buflen, M_WAITOK);
3552	NDFREE(&nd, 0);
3553	mac_destroy_vnode_label(&intlabel);
3554
3555	if (error == 0)
3556		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3557
3558out:
3559	mtx_unlock(&Giant);				/* VFS */
3560
3561	free(buffer, M_MACTEMP);
3562	free(elements, M_MACTEMP);
3563
3564	return (error);
3565}
3566
3567/*
3568 * MPSAFE
3569 */
3570int
3571__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3572{
3573	struct label intlabel;
3574	struct pipe *pipe;
3575	struct file *fp;
3576	struct mount *mp;
3577	struct vnode *vp;
3578	struct mac mac;
3579	char *buffer;
3580	int error;
3581
3582	error = copyin(uap->mac_p, &mac, sizeof(mac));
3583	if (error)
3584		return (error);
3585
3586	error = mac_check_structmac_consistent(&mac);
3587	if (error)
3588		return (error);
3589
3590	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3591	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3592	if (error) {
3593		free(buffer, M_MACTEMP);
3594		return (error);
3595	}
3596
3597	mtx_lock(&Giant);				/* VFS */
3598
3599	error = fget(td, uap->fd, &fp);
3600	if (error)
3601		goto out;
3602
3603	switch (fp->f_type) {
3604	case DTYPE_FIFO:
3605	case DTYPE_VNODE:
3606		mac_init_vnode_label(&intlabel);
3607		error = mac_internalize_vnode_label(&intlabel, buffer);
3608		if (error) {
3609			mac_destroy_vnode_label(&intlabel);
3610			break;
3611		}
3612
3613		vp = fp->f_data;
3614		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3615		if (error != 0) {
3616			mac_destroy_vnode_label(&intlabel);
3617			break;
3618		}
3619
3620		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3621		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3622		VOP_UNLOCK(vp, 0, td);
3623		vn_finished_write(mp);
3624
3625		mac_destroy_vnode_label(&intlabel);
3626		break;
3627
3628	case DTYPE_PIPE:
3629		mac_init_pipe_label(&intlabel);
3630		error = mac_internalize_pipe_label(&intlabel, buffer);
3631		if (error == 0) {
3632			pipe = fp->f_data;
3633			PIPE_LOCK(pipe);
3634			error = mac_pipe_label_set(td->td_ucred, pipe,
3635			    &intlabel);
3636			PIPE_UNLOCK(pipe);
3637		}
3638
3639		mac_destroy_pipe_label(&intlabel);
3640		break;
3641
3642	default:
3643		error = EINVAL;
3644	}
3645
3646	fdrop(fp, td);
3647out:
3648	mtx_unlock(&Giant);				/* VFS */
3649
3650	free(buffer, M_MACTEMP);
3651
3652	return (error);
3653}
3654
3655/*
3656 * MPSAFE
3657 */
3658int
3659__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3660{
3661	struct label intlabel;
3662	struct nameidata nd;
3663	struct mount *mp;
3664	struct mac mac;
3665	char *buffer;
3666	int error;
3667
3668	error = copyin(uap->mac_p, &mac, sizeof(mac));
3669	if (error)
3670		return (error);
3671
3672	error = mac_check_structmac_consistent(&mac);
3673	if (error)
3674		return (error);
3675
3676	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3677	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3678	if (error) {
3679		free(buffer, M_MACTEMP);
3680		return (error);
3681	}
3682
3683	mac_init_vnode_label(&intlabel);
3684	error = mac_internalize_vnode_label(&intlabel, buffer);
3685	free(buffer, M_MACTEMP);
3686	if (error) {
3687		mac_destroy_vnode_label(&intlabel);
3688		return (error);
3689	}
3690
3691	mtx_lock(&Giant);				/* VFS */
3692
3693	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3694	    td);
3695	error = namei(&nd);
3696	if (error == 0) {
3697		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3698		if (error == 0)
3699			error = vn_setlabel(nd.ni_vp, &intlabel,
3700			    td->td_ucred);
3701		vn_finished_write(mp);
3702	}
3703
3704	NDFREE(&nd, 0);
3705	mtx_unlock(&Giant);				/* VFS */
3706	mac_destroy_vnode_label(&intlabel);
3707
3708	return (error);
3709}
3710
3711/*
3712 * MPSAFE
3713 */
3714int
3715__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3716{
3717	struct label intlabel;
3718	struct nameidata nd;
3719	struct mount *mp;
3720	struct mac mac;
3721	char *buffer;
3722	int error;
3723
3724	error = copyin(uap->mac_p, &mac, sizeof(mac));
3725	if (error)
3726		return (error);
3727
3728	error = mac_check_structmac_consistent(&mac);
3729	if (error)
3730		return (error);
3731
3732	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3733	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3734	if (error) {
3735		free(buffer, M_MACTEMP);
3736		return (error);
3737	}
3738
3739	mac_init_vnode_label(&intlabel);
3740	error = mac_internalize_vnode_label(&intlabel, buffer);
3741	free(buffer, M_MACTEMP);
3742	if (error) {
3743		mac_destroy_vnode_label(&intlabel);
3744		return (error);
3745	}
3746
3747	mtx_lock(&Giant);				/* VFS */
3748
3749	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3750	    td);
3751	error = namei(&nd);
3752	if (error == 0) {
3753		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3754		if (error == 0)
3755			error = vn_setlabel(nd.ni_vp, &intlabel,
3756			    td->td_ucred);
3757		vn_finished_write(mp);
3758	}
3759
3760	NDFREE(&nd, 0);
3761	mtx_unlock(&Giant);				/* VFS */
3762	mac_destroy_vnode_label(&intlabel);
3763
3764	return (error);
3765}
3766
3767/*
3768 * MPSAFE
3769 */
3770int
3771mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3772{
3773	struct mac_policy_conf *mpc;
3774	char target[MAC_MAX_POLICY_NAME];
3775	int error;
3776
3777	error = copyinstr(uap->policy, target, sizeof(target), NULL);
3778	if (error)
3779		return (error);
3780
3781	error = ENOSYS;
3782	MAC_POLICY_LIST_BUSY();
3783	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3784		if (strcmp(mpc->mpc_name, target) == 0 &&
3785		    mpc->mpc_ops->mpo_syscall != NULL) {
3786			error = mpc->mpc_ops->mpo_syscall(td,
3787			    uap->call, uap->arg);
3788			goto out;
3789		}
3790	}
3791
3792out:
3793	MAC_POLICY_LIST_UNBUSY();
3794	return (error);
3795}
3796
3797SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3798SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3799
3800#else /* !MAC */
3801
3802int
3803__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3804{
3805
3806	return (ENOSYS);
3807}
3808
3809int
3810__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3811{
3812
3813	return (ENOSYS);
3814}
3815
3816int
3817__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3818{
3819
3820	return (ENOSYS);
3821}
3822
3823int
3824__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3825{
3826
3827	return (ENOSYS);
3828}
3829
3830int
3831__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3832{
3833
3834	return (ENOSYS);
3835}
3836
3837int
3838__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3839{
3840
3841	return (ENOSYS);
3842}
3843
3844int
3845__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3846{
3847
3848	return (ENOSYS);
3849}
3850
3851int
3852__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3853{
3854
3855	return (ENOSYS);
3856}
3857
3858int
3859__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3860{
3861
3862	return (ENOSYS);
3863}
3864
3865int
3866mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3867{
3868
3869	return (ENOSYS);
3870}
3871
3872#endif
3873