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