xref: /freebsd/sys/security/mac/mac_vfs.c (revision cc7b13bfe0dc4a881a42519ba6f8a959d0452d4e)
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 < 0 ||
1180 	    mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1181 		return (EINVAL);
1182 
1183 	return (0);
1184 }
1185 
1186 static int
1187 mac_externalize_cred_label(struct label *label, char *elements,
1188     char *outbuf, size_t outbuflen, int flags)
1189 {
1190 	int error;
1191 
1192 	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1193 
1194 	return (error);
1195 }
1196 
1197 static int
1198 mac_externalize_ifnet_label(struct label *label, char *elements,
1199     char *outbuf, size_t outbuflen, int flags)
1200 {
1201 	int error;
1202 
1203 	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1204 
1205 	return (error);
1206 }
1207 
1208 static int
1209 mac_externalize_pipe_label(struct label *label, char *elements,
1210     char *outbuf, size_t outbuflen, int flags)
1211 {
1212 	int error;
1213 
1214 	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1215 
1216 	return (error);
1217 }
1218 
1219 static int
1220 mac_externalize_socket_label(struct label *label, char *elements,
1221     char *outbuf, size_t outbuflen, int flags)
1222 {
1223 	int error;
1224 
1225 	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1226 
1227 	return (error);
1228 }
1229 
1230 static int
1231 mac_externalize_socket_peer_label(struct label *label, char *elements,
1232     char *outbuf, size_t outbuflen, int flags)
1233 {
1234 	int error;
1235 
1236 	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1237 
1238 	return (error);
1239 }
1240 
1241 static int
1242 mac_externalize_vnode_label(struct label *label, char *elements,
1243     char *outbuf, size_t outbuflen, int flags)
1244 {
1245 	int error;
1246 
1247 	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1248 
1249 	return (error);
1250 }
1251 
1252 static int
1253 mac_internalize_cred_label(struct label *label, char *string)
1254 {
1255 	int error;
1256 
1257 	MAC_INTERNALIZE(cred_label, label, string);
1258 
1259 	return (error);
1260 }
1261 
1262 static int
1263 mac_internalize_ifnet_label(struct label *label, char *string)
1264 {
1265 	int error;
1266 
1267 	MAC_INTERNALIZE(ifnet_label, label, string);
1268 
1269 	return (error);
1270 }
1271 
1272 static int
1273 mac_internalize_pipe_label(struct label *label, char *string)
1274 {
1275 	int error;
1276 
1277 	MAC_INTERNALIZE(pipe_label, label, string);
1278 
1279 	return (error);
1280 }
1281 
1282 static int
1283 mac_internalize_socket_label(struct label *label, char *string)
1284 {
1285 	int error;
1286 
1287 	MAC_INTERNALIZE(socket_label, label, string);
1288 
1289 	return (error);
1290 }
1291 
1292 static int
1293 mac_internalize_vnode_label(struct label *label, char *string)
1294 {
1295 	int error;
1296 
1297 	MAC_INTERNALIZE(vnode_label, label, string);
1298 
1299 	return (error);
1300 }
1301 
1302 /*
1303  * Initialize MAC label for the first kernel process, from which other
1304  * kernel processes and threads are spawned.
1305  */
1306 void
1307 mac_create_proc0(struct ucred *cred)
1308 {
1309 
1310 	MAC_PERFORM(create_proc0, cred);
1311 }
1312 
1313 /*
1314  * Initialize MAC label for the first userland process, from which other
1315  * userland processes and threads are spawned.
1316  */
1317 void
1318 mac_create_proc1(struct ucred *cred)
1319 {
1320 
1321 	MAC_PERFORM(create_proc1, cred);
1322 }
1323 
1324 void
1325 mac_thread_userret(struct thread *td)
1326 {
1327 
1328 	MAC_PERFORM(thread_userret, td);
1329 }
1330 
1331 /*
1332  * When a new process is created, its label must be initialized.  Generally,
1333  * this involves inheritence from the parent process, modulo possible
1334  * deltas.  This function allows that processing to take place.
1335  */
1336 void
1337 mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1338 {
1339 
1340 	MAC_PERFORM(create_cred, parent_cred, child_cred);
1341 }
1342 
1343 void
1344 mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1345     struct vnode *vp)
1346 {
1347 
1348 	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1349 	    &vp->v_label);
1350 }
1351 
1352 void
1353 mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1354     struct vnode *vp)
1355 {
1356 
1357 	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1358 	    &de->de_label, vp, &vp->v_label);
1359 }
1360 
1361 int
1362 mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1363 {
1364 	int error;
1365 
1366 	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1367 
1368 	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1369 	    &vp->v_label);
1370 
1371 	return (error);
1372 }
1373 
1374 void
1375 mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1376 {
1377 
1378 	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1379 	    &vp->v_label);
1380 }
1381 
1382 int
1383 mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1384     struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1385 {
1386 	int error;
1387 
1388 	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1389 	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1390 
1391 	error = VOP_OPENEXTATTR(vp, cred, curthread);
1392 	if (error == EOPNOTSUPP) {
1393 		/* XXX: Optionally abort if transactions not supported. */
1394 		if (ea_warn_once == 0) {
1395 			printf("Warning: transactions not supported "
1396 			    "in EA write.\n");
1397 			ea_warn_once = 1;
1398 		}
1399 	} else if (error)
1400 		return (error);
1401 
1402 	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1403 	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1404 
1405 	if (error) {
1406 		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1407 		return (error);
1408 	}
1409 
1410 	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1411 
1412 	if (error == EOPNOTSUPP)
1413 		error = 0;				/* XXX */
1414 
1415 	return (error);
1416 }
1417 
1418 static int
1419 mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1420     struct label *intlabel)
1421 {
1422 	int error;
1423 
1424 	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1425 
1426 	error = VOP_OPENEXTATTR(vp, cred, curthread);
1427 	if (error == EOPNOTSUPP) {
1428 		/* XXX: Optionally abort if transactions not supported. */
1429 		if (ea_warn_once == 0) {
1430 			printf("Warning: transactions not supported "
1431 			    "in EA write.\n");
1432 			ea_warn_once = 1;
1433 		}
1434 	} else if (error)
1435 		return (error);
1436 
1437 	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1438 
1439 	if (error) {
1440 		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1441 		return (error);
1442 	}
1443 
1444 	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1445 
1446 	if (error == EOPNOTSUPP)
1447 		error = 0;				/* XXX */
1448 
1449 	return (error);
1450 }
1451 
1452 int
1453 mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1454     struct label *execlabelstorage)
1455 {
1456 	struct mac mac;
1457 	char *buffer;
1458 	int error;
1459 
1460 	if (mac_p == NULL)
1461 		return (0);
1462 
1463 	error = copyin(mac_p, &mac, sizeof(mac));
1464 	if (error)
1465 		return (error);
1466 
1467 	error = mac_check_structmac_consistent(&mac);
1468 	if (error)
1469 		return (error);
1470 
1471 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1472 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1473 	if (error) {
1474 		free(buffer, M_MACTEMP);
1475 		return (error);
1476 	}
1477 
1478 	mac_init_cred_label(execlabelstorage);
1479 	error = mac_internalize_cred_label(execlabelstorage, buffer);
1480 	free(buffer, M_MACTEMP);
1481 	if (error) {
1482 		mac_destroy_cred_label(execlabelstorage);
1483 		return (error);
1484 	}
1485 	imgp->execlabel = execlabelstorage;
1486 	return (0);
1487 }
1488 
1489 void
1490 mac_execve_exit(struct image_params *imgp)
1491 {
1492 	if (imgp->execlabel != NULL)
1493 		mac_destroy_cred_label(imgp->execlabel);
1494 }
1495 
1496 void
1497 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1498     struct label *interpvnodelabel, struct image_params *imgp)
1499 {
1500 
1501 	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1502 
1503 	if (!mac_enforce_process && !mac_enforce_fs)
1504 		return;
1505 
1506 	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1507 	    interpvnodelabel, imgp, imgp->execlabel);
1508 }
1509 
1510 int
1511 mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1512     struct label *interpvnodelabel, struct image_params *imgp)
1513 {
1514 	int result;
1515 
1516 	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1517 
1518 	if (!mac_enforce_process && !mac_enforce_fs)
1519 		return (0);
1520 
1521 	result = 0;
1522 	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1523 	    interpvnodelabel, imgp, imgp->execlabel);
1524 
1525 	return (result);
1526 }
1527 
1528 int
1529 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1530 {
1531 	int error;
1532 
1533 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1534 
1535 	if (!mac_enforce_fs)
1536 		return (0);
1537 
1538 	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1539 	return (error);
1540 }
1541 
1542 int
1543 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1544 {
1545 	int error;
1546 
1547 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1548 
1549 	if (!mac_enforce_fs)
1550 		return (0);
1551 
1552 	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1553 	return (error);
1554 }
1555 
1556 int
1557 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1558 {
1559 	int error;
1560 
1561 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1562 
1563 	if (!mac_enforce_fs)
1564 		return (0);
1565 
1566 	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1567 	return (error);
1568 }
1569 
1570 int
1571 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1572     struct componentname *cnp, struct vattr *vap)
1573 {
1574 	int error;
1575 
1576 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1577 
1578 	if (!mac_enforce_fs)
1579 		return (0);
1580 
1581 	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1582 	return (error);
1583 }
1584 
1585 int
1586 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1587     struct componentname *cnp)
1588 {
1589 	int error;
1590 
1591 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1592 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1593 
1594 	if (!mac_enforce_fs)
1595 		return (0);
1596 
1597 	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1598 	    &vp->v_label, cnp);
1599 	return (error);
1600 }
1601 
1602 int
1603 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1604     acl_type_t type)
1605 {
1606 	int error;
1607 
1608 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1609 
1610 	if (!mac_enforce_fs)
1611 		return (0);
1612 
1613 	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1614 	return (error);
1615 }
1616 
1617 int
1618 mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
1619     int attrnamespace, const char *name)
1620 {
1621 	int error;
1622 
1623 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
1624 
1625 	if (!mac_enforce_fs)
1626 		return (0);
1627 
1628 	MAC_CHECK(check_vnode_deleteextattr, cred, vp, &vp->v_label,
1629 	    attrnamespace, name);
1630 	return (error);
1631 }
1632 
1633 int
1634 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1635     struct image_params *imgp)
1636 {
1637 	int error;
1638 
1639 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1640 
1641 	if (!mac_enforce_process && !mac_enforce_fs)
1642 		return (0);
1643 
1644 	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1645 	    imgp->execlabel);
1646 
1647 	return (error);
1648 }
1649 
1650 int
1651 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1652 {
1653 	int error;
1654 
1655 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1656 
1657 	if (!mac_enforce_fs)
1658 		return (0);
1659 
1660 	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1661 	return (error);
1662 }
1663 
1664 int
1665 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1666     int attrnamespace, const char *name, struct uio *uio)
1667 {
1668 	int error;
1669 
1670 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1671 
1672 	if (!mac_enforce_fs)
1673 		return (0);
1674 
1675 	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1676 	    attrnamespace, name, uio);
1677 	return (error);
1678 }
1679 
1680 int
1681 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1682     struct vnode *vp, struct componentname *cnp)
1683 {
1684 	int error;
1685 
1686 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1687 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1688 
1689 	if (!mac_enforce_fs)
1690 		return (0);
1691 
1692 	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1693 	    &vp->v_label, cnp);
1694 	return (error);
1695 }
1696 
1697 int
1698 mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
1699     int attrnamespace)
1700 {
1701 	int error;
1702 
1703 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
1704 
1705 	if (!mac_enforce_fs)
1706 		return (0);
1707 
1708 	MAC_CHECK(check_vnode_listextattr, cred, vp, &vp->v_label,
1709 	    attrnamespace);
1710 	return (error);
1711 }
1712 
1713 int
1714 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1715     struct componentname *cnp)
1716 {
1717 	int error;
1718 
1719 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1720 
1721 	if (!mac_enforce_fs)
1722 		return (0);
1723 
1724 	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1725 	return (error);
1726 }
1727 
1728 int
1729 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1730 {
1731 	int error;
1732 
1733 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1734 
1735 	if (!mac_enforce_fs || !mac_enforce_vm)
1736 		return (0);
1737 
1738 	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1739 	return (error);
1740 }
1741 
1742 void
1743 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1744 {
1745 	int result = *prot;
1746 
1747 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1748 
1749 	if (!mac_enforce_fs || !mac_enforce_vm)
1750 		return;
1751 
1752 	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1753 	    &result);
1754 
1755 	*prot = result;
1756 }
1757 
1758 int
1759 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1760 {
1761 	int error;
1762 
1763 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1764 
1765 	if (!mac_enforce_fs || !mac_enforce_vm)
1766 		return (0);
1767 
1768 	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1769 	return (error);
1770 }
1771 
1772 int
1773 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1774 {
1775 	int error;
1776 
1777 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1778 
1779 	if (!mac_enforce_fs)
1780 		return (0);
1781 
1782 	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1783 	return (error);
1784 }
1785 
1786 int
1787 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1788     struct vnode *vp)
1789 {
1790 	int error;
1791 
1792 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1793 
1794 	if (!mac_enforce_fs)
1795 		return (0);
1796 
1797 	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1798 	    &vp->v_label);
1799 
1800 	return (error);
1801 }
1802 
1803 int
1804 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1805     struct vnode *vp)
1806 {
1807 	int error;
1808 
1809 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1810 
1811 	if (!mac_enforce_fs)
1812 		return (0);
1813 
1814 	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1815 	    &vp->v_label);
1816 
1817 	return (error);
1818 }
1819 
1820 int
1821 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1822 {
1823 	int error;
1824 
1825 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1826 
1827 	if (!mac_enforce_fs)
1828 		return (0);
1829 
1830 	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1831 	return (error);
1832 }
1833 
1834 int
1835 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1836 {
1837 	int error;
1838 
1839 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1840 
1841 	if (!mac_enforce_fs)
1842 		return (0);
1843 
1844 	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1845 	return (error);
1846 }
1847 
1848 static int
1849 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1850     struct label *newlabel)
1851 {
1852 	int error;
1853 
1854 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1855 
1856 	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1857 
1858 	return (error);
1859 }
1860 
1861 int
1862 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1863     struct vnode *vp, struct componentname *cnp)
1864 {
1865 	int error;
1866 
1867 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1868 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1869 
1870 	if (!mac_enforce_fs)
1871 		return (0);
1872 
1873 	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1874 	    &vp->v_label, cnp);
1875 	return (error);
1876 }
1877 
1878 int
1879 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1880     struct vnode *vp, int samedir, struct componentname *cnp)
1881 {
1882 	int error;
1883 
1884 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1885 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1886 
1887 	if (!mac_enforce_fs)
1888 		return (0);
1889 
1890 	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1891 	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1892 	return (error);
1893 }
1894 
1895 int
1896 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1897 {
1898 	int error;
1899 
1900 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1901 
1902 	if (!mac_enforce_fs)
1903 		return (0);
1904 
1905 	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1906 	return (error);
1907 }
1908 
1909 int
1910 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1911     struct acl *acl)
1912 {
1913 	int error;
1914 
1915 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1916 
1917 	if (!mac_enforce_fs)
1918 		return (0);
1919 
1920 	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1921 	return (error);
1922 }
1923 
1924 int
1925 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1926     int attrnamespace, const char *name, struct uio *uio)
1927 {
1928 	int error;
1929 
1930 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1931 
1932 	if (!mac_enforce_fs)
1933 		return (0);
1934 
1935 	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1936 	    attrnamespace, name, uio);
1937 	return (error);
1938 }
1939 
1940 int
1941 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1942 {
1943 	int error;
1944 
1945 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1946 
1947 	if (!mac_enforce_fs)
1948 		return (0);
1949 
1950 	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1951 	return (error);
1952 }
1953 
1954 int
1955 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1956 {
1957 	int error;
1958 
1959 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1960 
1961 	if (!mac_enforce_fs)
1962 		return (0);
1963 
1964 	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1965 	return (error);
1966 }
1967 
1968 int
1969 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1970     gid_t gid)
1971 {
1972 	int error;
1973 
1974 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1975 
1976 	if (!mac_enforce_fs)
1977 		return (0);
1978 
1979 	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1980 	return (error);
1981 }
1982 
1983 int
1984 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1985     struct timespec atime, struct timespec mtime)
1986 {
1987 	int error;
1988 
1989 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1990 
1991 	if (!mac_enforce_fs)
1992 		return (0);
1993 
1994 	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1995 	    mtime);
1996 	return (error);
1997 }
1998 
1999 int
2000 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2001     struct vnode *vp)
2002 {
2003 	int error;
2004 
2005 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2006 
2007 	if (!mac_enforce_fs)
2008 		return (0);
2009 
2010 	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2011 	    &vp->v_label);
2012 	return (error);
2013 }
2014 
2015 int
2016 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2017     struct vnode *vp)
2018 {
2019 	int error;
2020 
2021 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2022 
2023 	if (!mac_enforce_fs)
2024 		return (0);
2025 
2026 	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2027 	    &vp->v_label);
2028 
2029 	return (error);
2030 }
2031 
2032 /*
2033  * When relabeling a process, call out to the policies for the maximum
2034  * permission allowed for each object type we know about in its
2035  * memory space, and revoke access (in the least surprising ways we
2036  * know) when necessary.  The process lock is not held here.
2037  */
2038 void
2039 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2040 {
2041 
2042 	/* XXX freeze all other threads */
2043 	mac_cred_mmapped_drop_perms_recurse(td, cred,
2044 	    &td->td_proc->p_vmspace->vm_map);
2045 	/* XXX allow other threads to continue */
2046 }
2047 
2048 static __inline const char *
2049 prot2str(vm_prot_t prot)
2050 {
2051 
2052 	switch (prot & VM_PROT_ALL) {
2053 	case VM_PROT_READ:
2054 		return ("r--");
2055 	case VM_PROT_READ | VM_PROT_WRITE:
2056 		return ("rw-");
2057 	case VM_PROT_READ | VM_PROT_EXECUTE:
2058 		return ("r-x");
2059 	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2060 		return ("rwx");
2061 	case VM_PROT_WRITE:
2062 		return ("-w-");
2063 	case VM_PROT_EXECUTE:
2064 		return ("--x");
2065 	case VM_PROT_WRITE | VM_PROT_EXECUTE:
2066 		return ("-wx");
2067 	default:
2068 		return ("---");
2069 	}
2070 }
2071 
2072 static void
2073 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2074     struct vm_map *map)
2075 {
2076 	struct vm_map_entry *vme;
2077 	int result;
2078 	vm_prot_t revokeperms;
2079 	vm_object_t object;
2080 	vm_ooffset_t offset;
2081 	struct vnode *vp;
2082 
2083 	if (!mac_mmap_revocation)
2084 		return;
2085 
2086 	vm_map_lock_read(map);
2087 	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2088 		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2089 			mac_cred_mmapped_drop_perms_recurse(td, cred,
2090 			    vme->object.sub_map);
2091 			continue;
2092 		}
2093 		/*
2094 		 * Skip over entries that obviously are not shared.
2095 		 */
2096 		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2097 		    !vme->max_protection)
2098 			continue;
2099 		/*
2100 		 * Drill down to the deepest backing object.
2101 		 */
2102 		offset = vme->offset;
2103 		object = vme->object.vm_object;
2104 		if (object == NULL)
2105 			continue;
2106 		while (object->backing_object != NULL) {
2107 			object = object->backing_object;
2108 			offset += object->backing_object_offset;
2109 		}
2110 		/*
2111 		 * At the moment, vm_maps and objects aren't considered
2112 		 * by the MAC system, so only things with backing by a
2113 		 * normal object (read: vnodes) are checked.
2114 		 */
2115 		if (object->type != OBJT_VNODE)
2116 			continue;
2117 		vp = (struct vnode *)object->handle;
2118 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2119 		result = vme->max_protection;
2120 		mac_check_vnode_mmap_downgrade(cred, vp, &result);
2121 		VOP_UNLOCK(vp, 0, td);
2122 		/*
2123 		 * Find out what maximum protection we may be allowing
2124 		 * now but a policy needs to get removed.
2125 		 */
2126 		revokeperms = vme->max_protection & ~result;
2127 		if (!revokeperms)
2128 			continue;
2129 		printf("pid %ld: revoking %s perms from %#lx:%ld "
2130 		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2131 		    prot2str(revokeperms), (u_long)vme->start,
2132 		    (long)(vme->end - vme->start),
2133 		    prot2str(vme->max_protection), prot2str(vme->protection));
2134 		vm_map_lock_upgrade(map);
2135 		/*
2136 		 * This is the really simple case: if a map has more
2137 		 * max_protection than is allowed, but it's not being
2138 		 * actually used (that is, the current protection is
2139 		 * still allowed), we can just wipe it out and do
2140 		 * nothing more.
2141 		 */
2142 		if ((vme->protection & revokeperms) == 0) {
2143 			vme->max_protection -= revokeperms;
2144 		} else {
2145 			if (revokeperms & VM_PROT_WRITE) {
2146 				/*
2147 				 * In the more complicated case, flush out all
2148 				 * pending changes to the object then turn it
2149 				 * copy-on-write.
2150 				 */
2151 				vm_object_reference(object);
2152 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2153 				VM_OBJECT_LOCK(object);
2154 				vm_object_page_clean(object,
2155 				    OFF_TO_IDX(offset),
2156 				    OFF_TO_IDX(offset + vme->end - vme->start +
2157 					PAGE_MASK),
2158 				    OBJPC_SYNC);
2159 				VM_OBJECT_UNLOCK(object);
2160 				VOP_UNLOCK(vp, 0, td);
2161 				vm_object_deallocate(object);
2162 				/*
2163 				 * Why bother if there's no read permissions
2164 				 * anymore?  For the rest, we need to leave
2165 				 * the write permissions on for COW, or
2166 				 * remove them entirely if configured to.
2167 				 */
2168 				if (!mac_mmap_revocation_via_cow) {
2169 					vme->max_protection &= ~VM_PROT_WRITE;
2170 					vme->protection &= ~VM_PROT_WRITE;
2171 				} if ((revokeperms & VM_PROT_READ) == 0)
2172 					vme->eflags |= MAP_ENTRY_COW |
2173 					    MAP_ENTRY_NEEDS_COPY;
2174 			}
2175 			if (revokeperms & VM_PROT_EXECUTE) {
2176 				vme->max_protection &= ~VM_PROT_EXECUTE;
2177 				vme->protection &= ~VM_PROT_EXECUTE;
2178 			}
2179 			if (revokeperms & VM_PROT_READ) {
2180 				vme->max_protection = 0;
2181 				vme->protection = 0;
2182 			}
2183 			pmap_protect(map->pmap, vme->start, vme->end,
2184 			    vme->protection & ~revokeperms);
2185 			vm_map_simplify_entry(map, vme);
2186 		}
2187 		vm_map_lock_downgrade(map);
2188 	}
2189 	vm_map_unlock_read(map);
2190 }
2191 
2192 /*
2193  * When the subject's label changes, it may require revocation of privilege
2194  * to mapped objects.  This can't be done on-the-fly later with a unified
2195  * buffer cache.
2196  */
2197 static void
2198 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2199 {
2200 
2201 	MAC_PERFORM(relabel_cred, cred, newlabel);
2202 }
2203 
2204 void
2205 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2206 {
2207 
2208 	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2209 }
2210 
2211 void
2212 mac_create_ifnet(struct ifnet *ifnet)
2213 {
2214 
2215 	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2216 }
2217 
2218 void
2219 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2220 {
2221 
2222 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2223 }
2224 
2225 void
2226 mac_create_socket(struct ucred *cred, struct socket *socket)
2227 {
2228 
2229 	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2230 }
2231 
2232 void
2233 mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2234 {
2235 
2236 	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2237 }
2238 
2239 void
2240 mac_create_socket_from_socket(struct socket *oldsocket,
2241     struct socket *newsocket)
2242 {
2243 
2244 	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2245 	    newsocket, &newsocket->so_label);
2246 }
2247 
2248 static void
2249 mac_relabel_socket(struct ucred *cred, struct socket *socket,
2250     struct label *newlabel)
2251 {
2252 
2253 	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2254 }
2255 
2256 static void
2257 mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2258 {
2259 
2260 	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2261 }
2262 
2263 void
2264 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2265 {
2266 	struct label *label;
2267 
2268 	label = mbuf_to_label(mbuf);
2269 
2270 	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
2271 	    &socket->so_peerlabel);
2272 }
2273 
2274 void
2275 mac_set_socket_peer_from_socket(struct socket *oldsocket,
2276     struct socket *newsocket)
2277 {
2278 
2279 	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2280 	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2281 }
2282 
2283 void
2284 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2285 {
2286 	struct label *label;
2287 
2288 	label = mbuf_to_label(datagram);
2289 
2290 	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2291 	    datagram, label);
2292 }
2293 
2294 void
2295 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2296 {
2297 	struct label *datagramlabel, *fragmentlabel;
2298 
2299 	datagramlabel = mbuf_to_label(datagram);
2300 	fragmentlabel = mbuf_to_label(fragment);
2301 
2302 	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
2303 	    fragmentlabel);
2304 }
2305 
2306 void
2307 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2308 {
2309 	struct label *label;
2310 
2311 	label = mbuf_to_label(fragment);
2312 
2313 	MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
2314 }
2315 
2316 void
2317 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2318 {
2319 	struct label *oldmbuflabel, *newmbuflabel;
2320 
2321 	oldmbuflabel = mbuf_to_label(oldmbuf);
2322 	newmbuflabel = mbuf_to_label(newmbuf);
2323 
2324 	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
2325 	    newmbuflabel);
2326 }
2327 
2328 void
2329 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2330 {
2331 	struct label *label;
2332 
2333 	label = mbuf_to_label(mbuf);
2334 
2335 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2336 	    label);
2337 }
2338 
2339 void
2340 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2341 {
2342 	struct label *label;
2343 
2344 	label = mbuf_to_label(mbuf);
2345 
2346 	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2347 	    label);
2348 }
2349 
2350 void
2351 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2352 {
2353 	struct label *label;
2354 
2355 	label = mbuf_to_label(mbuf);
2356 
2357 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2358 	    label);
2359 }
2360 
2361 void
2362 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2363     struct mbuf *newmbuf)
2364 {
2365 	struct label *oldmbuflabel, *newmbuflabel;
2366 
2367 	oldmbuflabel = mbuf_to_label(oldmbuf);
2368 	newmbuflabel = mbuf_to_label(newmbuf);
2369 
2370 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
2371 	    ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
2372 }
2373 
2374 void
2375 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2376 {
2377 	struct label *oldmbuflabel, *newmbuflabel;
2378 
2379 	oldmbuflabel = mbuf_to_label(oldmbuf);
2380 	newmbuflabel = mbuf_to_label(newmbuf);
2381 
2382 	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
2383 	    newmbuflabel);
2384 }
2385 
2386 int
2387 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2388 {
2389 	struct label *label;
2390 	int result;
2391 
2392 	label = mbuf_to_label(fragment);
2393 
2394 	result = 1;
2395 	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
2396 	    &ipq->ipq_label);
2397 
2398 	return (result);
2399 }
2400 
2401 void
2402 mac_reflect_mbuf_icmp(struct mbuf *m)
2403 {
2404 	struct label *label;
2405 
2406 	label = mbuf_to_label(m);
2407 
2408 	MAC_PERFORM(reflect_mbuf_icmp, m, label);
2409 }
2410 void
2411 mac_reflect_mbuf_tcp(struct mbuf *m)
2412 {
2413 	struct label *label;
2414 
2415 	label = mbuf_to_label(m);
2416 
2417 	MAC_PERFORM(reflect_mbuf_tcp, m, label);
2418 }
2419 
2420 void
2421 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2422 {
2423 	struct label *label;
2424 
2425 	label = mbuf_to_label(fragment);
2426 
2427 	MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
2428 }
2429 
2430 void
2431 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2432 {
2433 	struct label *label;
2434 
2435 	label = mbuf_to_label(mbuf);
2436 
2437 	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2438 	    label);
2439 }
2440 
2441 void
2442 mac_create_mount(struct ucred *cred, struct mount *mp)
2443 {
2444 
2445 	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2446 	    &mp->mnt_fslabel);
2447 }
2448 
2449 void
2450 mac_create_root_mount(struct ucred *cred, struct mount *mp)
2451 {
2452 
2453 	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2454 	    &mp->mnt_fslabel);
2455 }
2456 
2457 int
2458 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2459 {
2460 	int error;
2461 
2462 	if (!mac_enforce_network)
2463 		return (0);
2464 
2465 	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2466 	    &ifnet->if_label);
2467 
2468 	return (error);
2469 }
2470 
2471 static int
2472 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2473 {
2474 	int error;
2475 
2476 	MAC_CHECK(check_cred_relabel, cred, newlabel);
2477 
2478 	return (error);
2479 }
2480 
2481 int
2482 mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2483 {
2484 	int error;
2485 
2486 	if (!mac_enforce_process)
2487 		return (0);
2488 
2489 	MAC_CHECK(check_cred_visible, u1, u2);
2490 
2491 	return (error);
2492 }
2493 
2494 int
2495 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2496 {
2497 	struct label *label;
2498 	int error;
2499 
2500 	M_ASSERTPKTHDR(mbuf);
2501 
2502 	if (!mac_enforce_network)
2503 		return (0);
2504 
2505 	label = mbuf_to_label(mbuf);
2506 
2507 	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2508 	    label);
2509 
2510 	return (error);
2511 }
2512 
2513 int
2514 mac_check_kenv_dump(struct ucred *cred)
2515 {
2516 	int error;
2517 
2518 	if (!mac_enforce_system)
2519 		return (0);
2520 
2521 	MAC_CHECK(check_kenv_dump, cred);
2522 
2523 	return (error);
2524 }
2525 
2526 int
2527 mac_check_kenv_get(struct ucred *cred, char *name)
2528 {
2529 	int error;
2530 
2531 	if (!mac_enforce_system)
2532 		return (0);
2533 
2534 	MAC_CHECK(check_kenv_get, cred, name);
2535 
2536 	return (error);
2537 }
2538 
2539 int
2540 mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2541 {
2542 	int error;
2543 
2544 	if (!mac_enforce_system)
2545 		return (0);
2546 
2547 	MAC_CHECK(check_kenv_set, cred, name, value);
2548 
2549 	return (error);
2550 }
2551 
2552 int
2553 mac_check_kenv_unset(struct ucred *cred, char *name)
2554 {
2555 	int error;
2556 
2557 	if (!mac_enforce_system)
2558 		return (0);
2559 
2560 	MAC_CHECK(check_kenv_unset, cred, name);
2561 
2562 	return (error);
2563 }
2564 
2565 int
2566 mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2567 {
2568 	int error;
2569 
2570 	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2571 
2572 	if (!mac_enforce_kld)
2573 		return (0);
2574 
2575 	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2576 
2577 	return (error);
2578 }
2579 
2580 int
2581 mac_check_kld_stat(struct ucred *cred)
2582 {
2583 	int error;
2584 
2585 	if (!mac_enforce_kld)
2586 		return (0);
2587 
2588 	MAC_CHECK(check_kld_stat, cred);
2589 
2590 	return (error);
2591 }
2592 
2593 int
2594 mac_check_kld_unload(struct ucred *cred)
2595 {
2596 	int error;
2597 
2598 	if (!mac_enforce_kld)
2599 		return (0);
2600 
2601 	MAC_CHECK(check_kld_unload, cred);
2602 
2603 	return (error);
2604 }
2605 
2606 int
2607 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2608 {
2609 	int error;
2610 
2611 	if (!mac_enforce_fs)
2612 		return (0);
2613 
2614 	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2615 
2616 	return (error);
2617 }
2618 
2619 int
2620 mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2621     void *data)
2622 {
2623 	int error;
2624 
2625 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2626 
2627 	if (!mac_enforce_pipe)
2628 		return (0);
2629 
2630 	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2631 
2632 	return (error);
2633 }
2634 
2635 int
2636 mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2637 {
2638 	int error;
2639 
2640 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2641 
2642 	if (!mac_enforce_pipe)
2643 		return (0);
2644 
2645 	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2646 
2647 	return (error);
2648 }
2649 
2650 int
2651 mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2652 {
2653 	int error;
2654 
2655 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2656 
2657 	if (!mac_enforce_pipe)
2658 		return (0);
2659 
2660 	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2661 
2662 	return (error);
2663 }
2664 
2665 static int
2666 mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2667     struct label *newlabel)
2668 {
2669 	int error;
2670 
2671 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2672 
2673 	if (!mac_enforce_pipe)
2674 		return (0);
2675 
2676 	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2677 
2678 	return (error);
2679 }
2680 
2681 int
2682 mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2683 {
2684 	int error;
2685 
2686 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2687 
2688 	if (!mac_enforce_pipe)
2689 		return (0);
2690 
2691 	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2692 
2693 	return (error);
2694 }
2695 
2696 int
2697 mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2698 {
2699 	int error;
2700 
2701 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2702 
2703 	if (!mac_enforce_pipe)
2704 		return (0);
2705 
2706 	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2707 
2708 	return (error);
2709 }
2710 
2711 int
2712 mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2713 {
2714 	int error;
2715 
2716 	PROC_LOCK_ASSERT(proc, MA_OWNED);
2717 
2718 	if (!mac_enforce_process)
2719 		return (0);
2720 
2721 	MAC_CHECK(check_proc_debug, cred, proc);
2722 
2723 	return (error);
2724 }
2725 
2726 int
2727 mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2728 {
2729 	int error;
2730 
2731 	PROC_LOCK_ASSERT(proc, MA_OWNED);
2732 
2733 	if (!mac_enforce_process)
2734 		return (0);
2735 
2736 	MAC_CHECK(check_proc_sched, cred, proc);
2737 
2738 	return (error);
2739 }
2740 
2741 int
2742 mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2743 {
2744 	int error;
2745 
2746 	PROC_LOCK_ASSERT(proc, MA_OWNED);
2747 
2748 	if (!mac_enforce_process)
2749 		return (0);
2750 
2751 	MAC_CHECK(check_proc_signal, cred, proc, signum);
2752 
2753 	return (error);
2754 }
2755 
2756 int
2757 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2758     struct sockaddr *sockaddr)
2759 {
2760 	int error;
2761 
2762 	if (!mac_enforce_socket)
2763 		return (0);
2764 
2765 	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2766 	    sockaddr);
2767 
2768 	return (error);
2769 }
2770 
2771 int
2772 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2773     struct sockaddr *sockaddr)
2774 {
2775 	int error;
2776 
2777 	if (!mac_enforce_socket)
2778 		return (0);
2779 
2780 	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2781 	    sockaddr);
2782 
2783 	return (error);
2784 }
2785 
2786 int
2787 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2788 {
2789 	struct label *label;
2790 	int error;
2791 
2792 	if (!mac_enforce_socket)
2793 		return (0);
2794 
2795 	label = mbuf_to_label(mbuf);
2796 
2797 	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2798 	    label);
2799 
2800 	return (error);
2801 }
2802 
2803 int
2804 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2805 {
2806 	int error;
2807 
2808 	if (!mac_enforce_socket)
2809 		return (0);
2810 
2811 	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2812 	return (error);
2813 }
2814 
2815 int
2816 mac_check_socket_receive(struct ucred *cred, struct socket *so)
2817 {
2818 	int error;
2819 
2820 	if (!mac_enforce_socket)
2821 		return (0);
2822 
2823 	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2824 
2825 	return (error);
2826 }
2827 
2828 static int
2829 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2830     struct label *newlabel)
2831 {
2832 	int error;
2833 
2834 	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2835 	    newlabel);
2836 
2837 	return (error);
2838 }
2839 
2840 int
2841 mac_check_socket_send(struct ucred *cred, struct socket *so)
2842 {
2843 	int error;
2844 
2845 	if (!mac_enforce_socket)
2846 		return (0);
2847 
2848 	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2849 
2850 	return (error);
2851 }
2852 
2853 int
2854 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2855 {
2856 	int error;
2857 
2858 	if (!mac_enforce_socket)
2859 		return (0);
2860 
2861 	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2862 
2863 	return (error);
2864 }
2865 
2866 int
2867 mac_check_sysarch_ioperm(struct ucred *cred)
2868 {
2869 	int error;
2870 
2871 	if (!mac_enforce_system)
2872 		return (0);
2873 
2874 	MAC_CHECK(check_sysarch_ioperm, cred);
2875 	return (error);
2876 }
2877 
2878 int
2879 mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2880 {
2881 	int error;
2882 
2883 	if (vp != NULL) {
2884 		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2885 	}
2886 
2887 	if (!mac_enforce_system)
2888 		return (0);
2889 
2890 	MAC_CHECK(check_system_acct, cred, vp,
2891 	    vp != NULL ? &vp->v_label : NULL);
2892 
2893 	return (error);
2894 }
2895 
2896 int
2897 mac_check_system_nfsd(struct ucred *cred)
2898 {
2899 	int error;
2900 
2901 	if (!mac_enforce_system)
2902 		return (0);
2903 
2904 	MAC_CHECK(check_system_nfsd, cred);
2905 
2906 	return (error);
2907 }
2908 
2909 int
2910 mac_check_system_reboot(struct ucred *cred, int howto)
2911 {
2912 	int error;
2913 
2914 	if (!mac_enforce_system)
2915 		return (0);
2916 
2917 	MAC_CHECK(check_system_reboot, cred, howto);
2918 
2919 	return (error);
2920 }
2921 
2922 int
2923 mac_check_system_settime(struct ucred *cred)
2924 {
2925 	int error;
2926 
2927 	if (!mac_enforce_system)
2928 		return (0);
2929 
2930 	MAC_CHECK(check_system_settime, cred);
2931 
2932 	return (error);
2933 }
2934 
2935 int
2936 mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2937 {
2938 	int error;
2939 
2940 	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2941 
2942 	if (!mac_enforce_system)
2943 		return (0);
2944 
2945 	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2946 	return (error);
2947 }
2948 
2949 int
2950 mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2951 {
2952 	int error;
2953 
2954 	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2955 
2956 	if (!mac_enforce_system)
2957 		return (0);
2958 
2959 	MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2960 	return (error);
2961 }
2962 
2963 int
2964 mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2965     void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2966 {
2967 	int error;
2968 
2969 	/*
2970 	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2971 	 * but since it's not exported from kern_sysctl.c, we can't.
2972 	 */
2973 	if (!mac_enforce_system)
2974 		return (0);
2975 
2976 	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2977 	    inkernel, new, newlen);
2978 
2979 	return (error);
2980 }
2981 
2982 int
2983 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2984     struct ifnet *ifnet)
2985 {
2986 	char *elements, *buffer;
2987 	struct mac mac;
2988 	int error;
2989 
2990 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2991 	if (error)
2992 		return (error);
2993 
2994 	error = mac_check_structmac_consistent(&mac);
2995 	if (error)
2996 		return (error);
2997 
2998 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2999 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3000 	if (error) {
3001 		free(elements, M_MACTEMP);
3002 		return (error);
3003 	}
3004 
3005 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3006 	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3007 	    buffer, mac.m_buflen, M_WAITOK);
3008 	if (error == 0)
3009 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3010 
3011 	free(buffer, M_MACTEMP);
3012 	free(elements, M_MACTEMP);
3013 
3014 	return (error);
3015 }
3016 
3017 int
3018 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3019     struct ifnet *ifnet)
3020 {
3021 	struct label intlabel;
3022 	struct mac mac;
3023 	char *buffer;
3024 	int error;
3025 
3026 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3027 	if (error)
3028 		return (error);
3029 
3030 	error = mac_check_structmac_consistent(&mac);
3031 	if (error)
3032 		return (error);
3033 
3034 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3035 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3036 	if (error) {
3037 		free(buffer, M_MACTEMP);
3038 		return (error);
3039 	}
3040 
3041 	mac_init_ifnet_label(&intlabel);
3042 	error = mac_internalize_ifnet_label(&intlabel, buffer);
3043 	free(buffer, M_MACTEMP);
3044 	if (error) {
3045 		mac_destroy_ifnet_label(&intlabel);
3046 		return (error);
3047 	}
3048 
3049 	/*
3050 	 * XXX: Note that this is a redundant privilege check, since
3051 	 * policies impose this check themselves if required by the
3052 	 * policy.  Eventually, this should go away.
3053 	 */
3054 	error = suser_cred(cred, 0);
3055 	if (error) {
3056 		mac_destroy_ifnet_label(&intlabel);
3057 		return (error);
3058 	}
3059 
3060 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3061 	    &intlabel);
3062 	if (error) {
3063 		mac_destroy_ifnet_label(&intlabel);
3064 		return (error);
3065 	}
3066 
3067 	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3068 
3069 	mac_destroy_ifnet_label(&intlabel);
3070 	return (0);
3071 }
3072 
3073 void
3074 mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
3075 {
3076 
3077 	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
3078 }
3079 
3080 void
3081 mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3082     struct devfs_dirent *dd, struct devfs_dirent *de)
3083 {
3084 
3085 	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
3086 	    &de->de_label);
3087 }
3088 
3089 void
3090 mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
3091     struct devfs_dirent *de)
3092 {
3093 
3094 	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
3095 	    &de->de_label);
3096 }
3097 
3098 int
3099 mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3100     struct mac *mac)
3101 {
3102 	struct label intlabel;
3103 	char *buffer;
3104 	int error;
3105 
3106 	error = mac_check_structmac_consistent(mac);
3107 	if (error)
3108 		return (error);
3109 
3110 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3111 	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3112 	if (error) {
3113 		free(buffer, M_MACTEMP);
3114 		return (error);
3115 	}
3116 
3117 	mac_init_socket_label(&intlabel, M_WAITOK);
3118 	error = mac_internalize_socket_label(&intlabel, buffer);
3119 	free(buffer, M_MACTEMP);
3120 	if (error) {
3121 		mac_destroy_socket_label(&intlabel);
3122 		return (error);
3123 	}
3124 
3125 	mac_check_socket_relabel(cred, so, &intlabel);
3126 	if (error) {
3127 		mac_destroy_socket_label(&intlabel);
3128 		return (error);
3129 	}
3130 
3131 	mac_relabel_socket(cred, so, &intlabel);
3132 
3133 	mac_destroy_socket_label(&intlabel);
3134 	return (0);
3135 }
3136 
3137 int
3138 mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3139 {
3140 	int error;
3141 
3142 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3143 
3144 	error = mac_check_pipe_relabel(cred, pipe, label);
3145 	if (error)
3146 		return (error);
3147 
3148 	mac_relabel_pipe(cred, pipe, label);
3149 
3150 	return (0);
3151 }
3152 
3153 int
3154 mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3155     struct mac *mac)
3156 {
3157 	char *buffer, *elements;
3158 	int error;
3159 
3160 	error = mac_check_structmac_consistent(mac);
3161 	if (error)
3162 		return (error);
3163 
3164 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3165 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3166 	if (error) {
3167 		free(elements, M_MACTEMP);
3168 		return (error);
3169 	}
3170 
3171 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3172 	error = mac_externalize_socket_label(&so->so_label, elements,
3173 	    buffer, mac->m_buflen, M_WAITOK);
3174 	if (error == 0)
3175 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3176 
3177 	free(buffer, M_MACTEMP);
3178 	free(elements, M_MACTEMP);
3179 
3180 	return (error);
3181 }
3182 
3183 int
3184 mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3185     struct mac *mac)
3186 {
3187 	char *elements, *buffer;
3188 	int error;
3189 
3190 	error = mac_check_structmac_consistent(mac);
3191 	if (error)
3192 		return (error);
3193 
3194 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3195 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3196 	if (error) {
3197 		free(elements, M_MACTEMP);
3198 		return (error);
3199 	}
3200 
3201 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3202 	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3203 	    elements, buffer, mac->m_buflen, M_WAITOK);
3204 	if (error == 0)
3205 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3206 
3207 	free(buffer, M_MACTEMP);
3208 	free(elements, M_MACTEMP);
3209 
3210 	return (error);
3211 }
3212 
3213 /*
3214  * Implementation of VOP_SETLABEL() that relies on extended attributes
3215  * to store label data.  Can be referenced by filesystems supporting
3216  * extended attributes.
3217  */
3218 int
3219 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3220 {
3221 	struct vnode *vp = ap->a_vp;
3222 	struct label *intlabel = ap->a_label;
3223 	int error;
3224 
3225 	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3226 
3227 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3228 		return (EOPNOTSUPP);
3229 
3230 	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3231 	if (error)
3232 		return (error);
3233 
3234 	mac_relabel_vnode(ap->a_cred, vp, intlabel);
3235 
3236 	return (0);
3237 }
3238 
3239 static int
3240 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3241 {
3242 	int error;
3243 
3244 	if (vp->v_mount == NULL) {
3245 		/* printf("vn_setlabel: null v_mount\n"); */
3246 		if (vp->v_type != VNON)
3247 			printf("vn_setlabel: null v_mount with non-VNON\n");
3248 		return (EBADF);
3249 	}
3250 
3251 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3252 		return (EOPNOTSUPP);
3253 
3254 	/*
3255 	 * Multi-phase commit.  First check the policies to confirm the
3256 	 * change is OK.  Then commit via the filesystem.  Finally,
3257 	 * update the actual vnode label.  Question: maybe the filesystem
3258 	 * should update the vnode at the end as part of VOP_SETLABEL()?
3259 	 */
3260 	error = mac_check_vnode_relabel(cred, vp, intlabel);
3261 	if (error)
3262 		return (error);
3263 
3264 	/*
3265 	 * VADMIN provides the opportunity for the filesystem to make
3266 	 * decisions about who is and is not able to modify labels
3267 	 * and protections on files.  This might not be right.  We can't
3268 	 * assume VOP_SETLABEL() will do it, because we might implement
3269 	 * that as part of vop_stdsetlabel_ea().
3270 	 */
3271 	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3272 	if (error)
3273 		return (error);
3274 
3275 	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3276 	if (error)
3277 		return (error);
3278 
3279 	return (0);
3280 }
3281 
3282 int
3283 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3284 {
3285 	char *elements, *buffer;
3286 	struct mac mac;
3287 	struct proc *tproc;
3288 	struct ucred *tcred;
3289 	int error;
3290 
3291 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3292 	if (error)
3293 		return (error);
3294 
3295 	error = mac_check_structmac_consistent(&mac);
3296 	if (error)
3297 		return (error);
3298 
3299 	tproc = pfind(uap->pid);
3300 	if (tproc == NULL)
3301 		return (ESRCH);
3302 
3303 	tcred = NULL;				/* Satisfy gcc. */
3304 	error = p_cansee(td, tproc);
3305 	if (error == 0)
3306 		tcred = crhold(tproc->p_ucred);
3307 	PROC_UNLOCK(tproc);
3308 	if (error)
3309 		return (error);
3310 
3311 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3312 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3313 	if (error) {
3314 		free(elements, M_MACTEMP);
3315 		crfree(tcred);
3316 		return (error);
3317 	}
3318 
3319 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3320 	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3321 	    buffer, mac.m_buflen, M_WAITOK);
3322 	if (error == 0)
3323 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3324 
3325 	free(buffer, M_MACTEMP);
3326 	free(elements, M_MACTEMP);
3327 	crfree(tcred);
3328 	return (error);
3329 }
3330 
3331 /*
3332  * MPSAFE
3333  */
3334 int
3335 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3336 {
3337 	char *elements, *buffer;
3338 	struct mac mac;
3339 	int error;
3340 
3341 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3342 	if (error)
3343 		return (error);
3344 
3345 	error = mac_check_structmac_consistent(&mac);
3346 	if (error)
3347 		return (error);
3348 
3349 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3350 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3351 	if (error) {
3352 		free(elements, M_MACTEMP);
3353 		return (error);
3354 	}
3355 
3356 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3357 	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3358 	    elements, buffer, mac.m_buflen, M_WAITOK);
3359 	if (error == 0)
3360 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3361 
3362 	free(buffer, M_MACTEMP);
3363 	free(elements, M_MACTEMP);
3364 	return (error);
3365 }
3366 
3367 /*
3368  * MPSAFE
3369  */
3370 int
3371 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3372 {
3373 	struct ucred *newcred, *oldcred;
3374 	struct label intlabel;
3375 	struct proc *p;
3376 	struct mac mac;
3377 	char *buffer;
3378 	int error;
3379 
3380 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3381 	if (error)
3382 		return (error);
3383 
3384 	error = mac_check_structmac_consistent(&mac);
3385 	if (error)
3386 		return (error);
3387 
3388 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3389 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3390 	if (error) {
3391 		free(buffer, M_MACTEMP);
3392 		return (error);
3393 	}
3394 
3395 	mac_init_cred_label(&intlabel);
3396 	error = mac_internalize_cred_label(&intlabel, buffer);
3397 	free(buffer, M_MACTEMP);
3398 	if (error) {
3399 		mac_destroy_cred_label(&intlabel);
3400 		return (error);
3401 	}
3402 
3403 	newcred = crget();
3404 
3405 	p = td->td_proc;
3406 	PROC_LOCK(p);
3407 	oldcred = p->p_ucred;
3408 
3409 	error = mac_check_cred_relabel(oldcred, &intlabel);
3410 	if (error) {
3411 		PROC_UNLOCK(p);
3412 		crfree(newcred);
3413 		goto out;
3414 	}
3415 
3416 	setsugid(p);
3417 	crcopy(newcred, oldcred);
3418 	mac_relabel_cred(newcred, &intlabel);
3419 	p->p_ucred = newcred;
3420 
3421 	/*
3422 	 * Grab additional reference for use while revoking mmaps, prior
3423 	 * to releasing the proc lock and sharing the cred.
3424 	 */
3425 	crhold(newcred);
3426 	PROC_UNLOCK(p);
3427 
3428 	if (mac_enforce_vm) {
3429 		mtx_lock(&Giant);
3430 		mac_cred_mmapped_drop_perms(td, newcred);
3431 		mtx_unlock(&Giant);
3432 	}
3433 
3434 	crfree(newcred);	/* Free revocation reference. */
3435 	crfree(oldcred);
3436 
3437 out:
3438 	mac_destroy_cred_label(&intlabel);
3439 	return (error);
3440 }
3441 
3442 /*
3443  * MPSAFE
3444  */
3445 int
3446 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3447 {
3448 	char *elements, *buffer;
3449 	struct label intlabel;
3450 	struct file *fp;
3451 	struct mac mac;
3452 	struct vnode *vp;
3453 	struct pipe *pipe;
3454 	short label_type;
3455 	int error;
3456 
3457 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3458 	if (error)
3459 		return (error);
3460 
3461 	error = mac_check_structmac_consistent(&mac);
3462 	if (error)
3463 		return (error);
3464 
3465 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3466 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3467 	if (error) {
3468 		free(elements, M_MACTEMP);
3469 		return (error);
3470 	}
3471 
3472 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3473 	mtx_lock(&Giant);				/* VFS */
3474 	error = fget(td, uap->fd, &fp);
3475 	if (error)
3476 		goto out;
3477 
3478 	label_type = fp->f_type;
3479 	switch (fp->f_type) {
3480 	case DTYPE_FIFO:
3481 	case DTYPE_VNODE:
3482 		vp = fp->f_vnode;
3483 
3484 		mac_init_vnode_label(&intlabel);
3485 
3486 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3487 		mac_copy_vnode_label(&vp->v_label, &intlabel);
3488 		VOP_UNLOCK(vp, 0, td);
3489 
3490 		break;
3491 	case DTYPE_PIPE:
3492 		pipe = fp->f_data;
3493 
3494 		mac_init_pipe_label(&intlabel);
3495 
3496 		PIPE_LOCK(pipe);
3497 		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3498 		PIPE_UNLOCK(pipe);
3499 		break;
3500 	default:
3501 		error = EINVAL;
3502 		fdrop(fp, td);
3503 		goto out;
3504 	}
3505 	fdrop(fp, td);
3506 
3507 	switch (label_type) {
3508 	case DTYPE_FIFO:
3509 	case DTYPE_VNODE:
3510 		if (error == 0)
3511 			error = mac_externalize_vnode_label(&intlabel,
3512 			    elements, buffer, mac.m_buflen, M_WAITOK);
3513 		mac_destroy_vnode_label(&intlabel);
3514 		break;
3515 	case DTYPE_PIPE:
3516 		error = mac_externalize_pipe_label(&intlabel, elements,
3517 		    buffer, mac.m_buflen, M_WAITOK);
3518 		mac_destroy_pipe_label(&intlabel);
3519 		break;
3520 	default:
3521 		panic("__mac_get_fd: corrupted label_type");
3522 	}
3523 
3524 	if (error == 0)
3525 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3526 
3527 out:
3528 	mtx_unlock(&Giant);				/* VFS */
3529 	free(buffer, M_MACTEMP);
3530 	free(elements, M_MACTEMP);
3531 
3532 	return (error);
3533 }
3534 
3535 /*
3536  * MPSAFE
3537  */
3538 int
3539 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3540 {
3541 	char *elements, *buffer;
3542 	struct nameidata nd;
3543 	struct label intlabel;
3544 	struct mac mac;
3545 	int error;
3546 
3547 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3548 	if (error)
3549 		return (error);
3550 
3551 	error = mac_check_structmac_consistent(&mac);
3552 	if (error)
3553 		return (error);
3554 
3555 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3556 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3557 	if (error) {
3558 		free(elements, M_MACTEMP);
3559 		return (error);
3560 	}
3561 
3562 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3563 	mtx_lock(&Giant);				/* VFS */
3564 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3565 	    td);
3566 	error = namei(&nd);
3567 	if (error)
3568 		goto out;
3569 
3570 	mac_init_vnode_label(&intlabel);
3571 	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3572 	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3573 	    mac.m_buflen, M_WAITOK);
3574 
3575 	NDFREE(&nd, 0);
3576 	mac_destroy_vnode_label(&intlabel);
3577 
3578 	if (error == 0)
3579 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3580 
3581 out:
3582 	mtx_unlock(&Giant);				/* VFS */
3583 
3584 	free(buffer, M_MACTEMP);
3585 	free(elements, M_MACTEMP);
3586 
3587 	return (error);
3588 }
3589 
3590 /*
3591  * MPSAFE
3592  */
3593 int
3594 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3595 {
3596 	char *elements, *buffer;
3597 	struct nameidata nd;
3598 	struct label intlabel;
3599 	struct mac mac;
3600 	int error;
3601 
3602 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3603 	if (error)
3604 		return (error);
3605 
3606 	error = mac_check_structmac_consistent(&mac);
3607 	if (error)
3608 		return (error);
3609 
3610 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3611 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3612 	if (error) {
3613 		free(elements, M_MACTEMP);
3614 		return (error);
3615 	}
3616 
3617 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3618 	mtx_lock(&Giant);				/* VFS */
3619 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3620 	    td);
3621 	error = namei(&nd);
3622 	if (error)
3623 		goto out;
3624 
3625 	mac_init_vnode_label(&intlabel);
3626 	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3627 	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3628 	    mac.m_buflen, M_WAITOK);
3629 	NDFREE(&nd, 0);
3630 	mac_destroy_vnode_label(&intlabel);
3631 
3632 	if (error == 0)
3633 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3634 
3635 out:
3636 	mtx_unlock(&Giant);				/* VFS */
3637 
3638 	free(buffer, M_MACTEMP);
3639 	free(elements, M_MACTEMP);
3640 
3641 	return (error);
3642 }
3643 
3644 /*
3645  * MPSAFE
3646  */
3647 int
3648 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3649 {
3650 	struct label intlabel;
3651 	struct pipe *pipe;
3652 	struct file *fp;
3653 	struct mount *mp;
3654 	struct vnode *vp;
3655 	struct mac mac;
3656 	char *buffer;
3657 	int error;
3658 
3659 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3660 	if (error)
3661 		return (error);
3662 
3663 	error = mac_check_structmac_consistent(&mac);
3664 	if (error)
3665 		return (error);
3666 
3667 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3668 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3669 	if (error) {
3670 		free(buffer, M_MACTEMP);
3671 		return (error);
3672 	}
3673 
3674 	mtx_lock(&Giant);				/* VFS */
3675 
3676 	error = fget(td, uap->fd, &fp);
3677 	if (error)
3678 		goto out;
3679 
3680 	switch (fp->f_type) {
3681 	case DTYPE_FIFO:
3682 	case DTYPE_VNODE:
3683 		mac_init_vnode_label(&intlabel);
3684 		error = mac_internalize_vnode_label(&intlabel, buffer);
3685 		if (error) {
3686 			mac_destroy_vnode_label(&intlabel);
3687 			break;
3688 		}
3689 
3690 		vp = fp->f_vnode;
3691 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3692 		if (error != 0) {
3693 			mac_destroy_vnode_label(&intlabel);
3694 			break;
3695 		}
3696 
3697 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3698 		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3699 		VOP_UNLOCK(vp, 0, td);
3700 		vn_finished_write(mp);
3701 
3702 		mac_destroy_vnode_label(&intlabel);
3703 		break;
3704 
3705 	case DTYPE_PIPE:
3706 		mac_init_pipe_label(&intlabel);
3707 		error = mac_internalize_pipe_label(&intlabel, buffer);
3708 		if (error == 0) {
3709 			pipe = fp->f_data;
3710 			PIPE_LOCK(pipe);
3711 			error = mac_pipe_label_set(td->td_ucred, pipe,
3712 			    &intlabel);
3713 			PIPE_UNLOCK(pipe);
3714 		}
3715 
3716 		mac_destroy_pipe_label(&intlabel);
3717 		break;
3718 
3719 	default:
3720 		error = EINVAL;
3721 	}
3722 
3723 	fdrop(fp, td);
3724 out:
3725 	mtx_unlock(&Giant);				/* VFS */
3726 
3727 	free(buffer, M_MACTEMP);
3728 
3729 	return (error);
3730 }
3731 
3732 /*
3733  * MPSAFE
3734  */
3735 int
3736 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3737 {
3738 	struct label intlabel;
3739 	struct nameidata nd;
3740 	struct mount *mp;
3741 	struct mac mac;
3742 	char *buffer;
3743 	int error;
3744 
3745 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3746 	if (error)
3747 		return (error);
3748 
3749 	error = mac_check_structmac_consistent(&mac);
3750 	if (error)
3751 		return (error);
3752 
3753 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3754 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3755 	if (error) {
3756 		free(buffer, M_MACTEMP);
3757 		return (error);
3758 	}
3759 
3760 	mac_init_vnode_label(&intlabel);
3761 	error = mac_internalize_vnode_label(&intlabel, buffer);
3762 	free(buffer, M_MACTEMP);
3763 	if (error) {
3764 		mac_destroy_vnode_label(&intlabel);
3765 		return (error);
3766 	}
3767 
3768 	mtx_lock(&Giant);				/* VFS */
3769 
3770 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3771 	    td);
3772 	error = namei(&nd);
3773 	if (error == 0) {
3774 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3775 		if (error == 0)
3776 			error = vn_setlabel(nd.ni_vp, &intlabel,
3777 			    td->td_ucred);
3778 		vn_finished_write(mp);
3779 	}
3780 
3781 	NDFREE(&nd, 0);
3782 	mtx_unlock(&Giant);				/* VFS */
3783 	mac_destroy_vnode_label(&intlabel);
3784 
3785 	return (error);
3786 }
3787 
3788 /*
3789  * MPSAFE
3790  */
3791 int
3792 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3793 {
3794 	struct label intlabel;
3795 	struct nameidata nd;
3796 	struct mount *mp;
3797 	struct mac mac;
3798 	char *buffer;
3799 	int error;
3800 
3801 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3802 	if (error)
3803 		return (error);
3804 
3805 	error = mac_check_structmac_consistent(&mac);
3806 	if (error)
3807 		return (error);
3808 
3809 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3810 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3811 	if (error) {
3812 		free(buffer, M_MACTEMP);
3813 		return (error);
3814 	}
3815 
3816 	mac_init_vnode_label(&intlabel);
3817 	error = mac_internalize_vnode_label(&intlabel, buffer);
3818 	free(buffer, M_MACTEMP);
3819 	if (error) {
3820 		mac_destroy_vnode_label(&intlabel);
3821 		return (error);
3822 	}
3823 
3824 	mtx_lock(&Giant);				/* VFS */
3825 
3826 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3827 	    td);
3828 	error = namei(&nd);
3829 	if (error == 0) {
3830 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3831 		if (error == 0)
3832 			error = vn_setlabel(nd.ni_vp, &intlabel,
3833 			    td->td_ucred);
3834 		vn_finished_write(mp);
3835 	}
3836 
3837 	NDFREE(&nd, 0);
3838 	mtx_unlock(&Giant);				/* VFS */
3839 	mac_destroy_vnode_label(&intlabel);
3840 
3841 	return (error);
3842 }
3843 
3844 /*
3845  * MPSAFE
3846  */
3847 int
3848 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3849 {
3850 	struct mac_policy_conf *mpc;
3851 	char target[MAC_MAX_POLICY_NAME];
3852 	int entrycount, error;
3853 
3854 	error = copyinstr(uap->policy, target, sizeof(target), NULL);
3855 	if (error)
3856 		return (error);
3857 
3858 	error = ENOSYS;
3859 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
3860 		if (strcmp(mpc->mpc_name, target) == 0 &&
3861 		    mpc->mpc_ops->mpo_syscall != NULL) {
3862 			error = mpc->mpc_ops->mpo_syscall(td,
3863 			    uap->call, uap->arg);
3864 			goto out;
3865 		}
3866 	}
3867 
3868 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
3869 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3870 			if (strcmp(mpc->mpc_name, target) == 0 &&
3871 			    mpc->mpc_ops->mpo_syscall != NULL) {
3872 				error = mpc->mpc_ops->mpo_syscall(td,
3873 				    uap->call, uap->arg);
3874 				break;
3875 			}
3876 		}
3877 		mac_policy_list_unbusy();
3878 	}
3879 out:
3880 	return (error);
3881 }
3882 
3883 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3884 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3885 
3886 #else /* !MAC */
3887 
3888 int
3889 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3890 {
3891 
3892 	return (ENOSYS);
3893 }
3894 
3895 int
3896 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3897 {
3898 
3899 	return (ENOSYS);
3900 }
3901 
3902 int
3903 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3904 {
3905 
3906 	return (ENOSYS);
3907 }
3908 
3909 int
3910 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3911 {
3912 
3913 	return (ENOSYS);
3914 }
3915 
3916 int
3917 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3918 {
3919 
3920 	return (ENOSYS);
3921 }
3922 
3923 int
3924 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3925 {
3926 
3927 	return (ENOSYS);
3928 }
3929 
3930 int
3931 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3932 {
3933 
3934 	return (ENOSYS);
3935 }
3936 
3937 int
3938 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3939 {
3940 
3941 	return (ENOSYS);
3942 }
3943 
3944 int
3945 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3946 {
3947 
3948 	return (ENOSYS);
3949 }
3950 
3951 int
3952 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3953 {
3954 
3955 	return (ENOSYS);
3956 }
3957 
3958 #endif
3959