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