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