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