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