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