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