xref: /freebsd/sys/security/mac/mac_pipe.c (revision a3e8fd0b7f663db7eafff527d5c3ca3bcfa8a537)
1 /*-
2  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3  * Copyright (c) 2001 Ilmar S. Habibulin
4  * Copyright (c) 2001, 2002 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 NAI Labs,
11  * the Security Research Division of Network Associates, Inc. under
12  * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
13  * 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  * 3. The names of the authors may not be used to endorse or promote
24  *    products derived from this software without specific prior written
25  *    permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  * $FreeBSD$
40  */
41 /*
42  * Developed by the TrustedBSD Project.
43  *
44  * Framework for extensible kernel access control.  Kernel and userland
45  * interface to the framework, policy registration and composition.
46  */
47 
48 #include "opt_mac.h"
49 #include "opt_devfs.h"
50 
51 #include <sys/param.h>
52 #include <sys/extattr.h>
53 #include <sys/kernel.h>
54 #include <sys/lock.h>
55 #include <sys/malloc.h>
56 #include <sys/mutex.h>
57 #include <sys/mac.h>
58 #include <sys/module.h>
59 #include <sys/proc.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_POLICIES > 32
103 #error "MAC_MAX_POLICIES too large"
104 #endif
105 
106 static unsigned int mac_max_policies = MAC_MAX_POLICIES;
107 static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
108 SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
109     &mac_max_policies, 0, "");
110 
111 static int	mac_late = 0;
112 
113 static int	mac_enforce_fs = 1;
114 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
115     &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
116 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
117 
118 static int	mac_enforce_network = 1;
119 SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
120     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
121 TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
122 
123 static int	mac_enforce_pipe = 1;
124 SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
125     &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
126 TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
127 
128 static int	mac_enforce_process = 1;
129 SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
130     &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
131 TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
132 
133 static int	mac_enforce_socket = 1;
134 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
135     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
136 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
137 
138 static int     mac_enforce_vm = 1;
139 SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
140     &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
141 TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
142 
143 static int	mac_label_size = sizeof(struct oldmac);
144 SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD,
145     &mac_label_size, 0, "Pre-compiled MAC label size");
146 
147 static int	mac_cache_fslabel_in_vnode = 1;
148 SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW,
149     &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode");
150 TUNABLE_INT("security.mac.cache_fslabel_in_vnode",
151     &mac_cache_fslabel_in_vnode);
152 
153 static int	mac_vnode_label_cache_hits = 0;
154 SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD,
155     &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels");
156 static int	mac_vnode_label_cache_misses = 0;
157 SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD,
158     &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels");
159 
160 static int	mac_mmap_revocation = 1;
161 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
162     &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
163     "relabel");
164 static int	mac_mmap_revocation_via_cow = 0;
165 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
166     &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
167     "copy-on-write semantics, or by removing all write access");
168 
169 #ifdef MAC_DEBUG
170 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
171     "TrustedBSD MAC debug info");
172 
173 static int	mac_debug_label_fallback = 0;
174 SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
175     &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
176     "when label is corrupted.");
177 TUNABLE_INT("security.mac.debug_label_fallback",
178     &mac_debug_label_fallback);
179 
180 SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
181     "TrustedBSD MAC object counters");
182 
183 static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
184     nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
185     nmacipqs, nmacpipes;
186 
187 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
188     &nmacmbufs, 0, "number of mbufs in use");
189 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
190     &nmaccreds, 0, "number of ucreds in use");
191 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
192     &nmacifnets, 0, "number of ifnets in use");
193 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
194     &nmacipqs, 0, "number of ipqs in use");
195 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
196     &nmacbpfdescs, 0, "number of bpfdescs in use");
197 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
198     &nmacsockets, 0, "number of sockets in use");
199 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
200     &nmacpipes, 0, "number of pipes in use");
201 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
202     &nmacmounts, 0, "number of mounts in use");
203 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
204     &nmactemp, 0, "number of temporary labels in use");
205 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
206     &nmacvnodes, 0, "number of vnodes in use");
207 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
208     &nmacdevfsdirents, 0, "number of devfs dirents inuse");
209 #endif
210 
211 static int	error_select(int error1, int error2);
212 static int	mac_externalize_vnode_oldmac(struct label *label,
213 		    struct oldmac *extmac);
214 static int	mac_policy_register(struct mac_policy_conf *mpc);
215 static int	mac_policy_unregister(struct mac_policy_conf *mpc);
216 
217 static int	mac_stdcreatevnode_ea(struct vnode *vp);
218 static void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
219 		    struct vnode *vp, int *prot);
220 static void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
221 		    struct ucred *cred, struct vm_map *map);
222 
223 static void	mac_destroy_socket_label(struct label *label);
224 
225 MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector");
226 MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
227 MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
228 
229 /*
230  * mac_policy_list_lock protects the consistency of 'mac_policy_list',
231  * the linked list of attached policy modules.  Read-only consumers of
232  * the list must acquire a shared lock for the duration of their use;
233  * writers must acquire an exclusive lock.  Note that for compound
234  * operations, locks should be held for the entire compound operation,
235  * and that this is not yet done for relabel requests.
236  */
237 static struct mtx mac_policy_list_lock;
238 static LIST_HEAD(, mac_policy_conf) mac_policy_list;
239 static int mac_policy_list_busy;
240 #define	MAC_POLICY_LIST_LOCKINIT()	mtx_init(&mac_policy_list_lock,	\
241 	"mac_policy_list_lock", NULL, MTX_DEF);
242 #define	MAC_POLICY_LIST_LOCK()	mtx_lock(&mac_policy_list_lock);
243 #define	MAC_POLICY_LIST_UNLOCK()	mtx_unlock(&mac_policy_list_lock);
244 
245 #define	MAC_POLICY_LIST_BUSY() do {					\
246 	MAC_POLICY_LIST_LOCK();						\
247 	mac_policy_list_busy++;						\
248 	MAC_POLICY_LIST_UNLOCK();					\
249 } while (0)
250 
251 #define	MAC_POLICY_LIST_UNBUSY() do {					\
252 	MAC_POLICY_LIST_LOCK();						\
253 	mac_policy_list_busy--;						\
254 	if (mac_policy_list_busy < 0)					\
255 		panic("Extra mac_policy_list_busy--");			\
256 	MAC_POLICY_LIST_UNLOCK();					\
257 } while (0)
258 
259 /*
260  * MAC_CHECK performs the designated check by walking the policy
261  * module list and checking with each as to how it feels about the
262  * request.  Note that it returns its value via 'error' in the scope
263  * of the caller.
264  */
265 #define	MAC_CHECK(check, args...) do {					\
266 	struct mac_policy_conf *mpc;					\
267 									\
268 	error = 0;							\
269 	MAC_POLICY_LIST_BUSY();						\
270 	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
271 		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
272 			error = error_select(				\
273 			    mpc->mpc_ops->mpo_ ## check (args),		\
274 			    error);					\
275 	}								\
276 	MAC_POLICY_LIST_UNBUSY();					\
277 } while (0)
278 
279 /*
280  * MAC_BOOLEAN performs the designated boolean composition by walking
281  * the module list, invoking each instance of the operation, and
282  * combining the results using the passed C operator.  Note that it
283  * returns its value via 'result' in the scope of the caller, which
284  * should be initialized by the caller in a meaningful way to get
285  * a meaningful result.
286  */
287 #define	MAC_BOOLEAN(operation, composition, args...) do {		\
288 	struct mac_policy_conf *mpc;					\
289 									\
290 	MAC_POLICY_LIST_BUSY();						\
291 	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
292 		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
293 			result = result composition			\
294 			    mpc->mpc_ops->mpo_ ## operation (args);	\
295 	}								\
296 	MAC_POLICY_LIST_UNBUSY();					\
297 } while (0)
298 
299 #define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
300     outbuflen) do {							\
301 	char *curptr, *curptr_start, *element_name, *element_temp;	\
302 	size_t left, left_start, len;					\
303 	int claimed, first, first_start, ignorenotfound;		\
304 									\
305 	error = 0;							\
306 	element_temp = elementlist;					\
307 	curptr = outbuf;						\
308 	curptr[0] = '\0';						\
309 	left = outbuflen;						\
310 	first = 1;							\
311 	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
312 		curptr_start = curptr;					\
313 		left_start = left;					\
314 		first_start = first;					\
315 		if (element_name[0] == '?') {				\
316 			element_name++;					\
317 			ignorenotfound = 1;				\
318 		} else							\
319 			ignorenotfound = 0;				\
320 		claimed = 0;						\
321 		if (first) {						\
322 			len = snprintf(curptr, left, "%s/",		\
323 			    element_name);				\
324 			first = 0;					\
325 		} else							\
326 			len = snprintf(curptr, left, ",%s/",		\
327 			    element_name);				\
328 		if (len >= left) {					\
329 			error = EINVAL;		/* XXXMAC: E2BIG */	\
330 			break;						\
331 		}							\
332 		curptr += len;						\
333 		left -= len;						\
334 									\
335 		MAC_CHECK(externalize_ ## type, label, element_name,	\
336 		    curptr, left, &len, &claimed);			\
337 		if (error)						\
338 			break;						\
339 		if (claimed == 1) {					\
340 			if (len >= outbuflen) {				\
341 				error = EINVAL;	/* XXXMAC: E2BIG */	\
342 				break;					\
343 			}						\
344 			curptr += len;					\
345 			left -= len;					\
346 		} else if (claimed == 0 && ignorenotfound) {		\
347 			/*						\
348 			 * Revert addition of the label element		\
349 			 * name.					\
350 			 */						\
351 			curptr = curptr_start;				\
352 			*curptr = '\0';					\
353 			left = left_start;				\
354 			first = first_start;				\
355 		} else {						\
356 			error = EINVAL;		/* XXXMAC: ENOLABEL */	\
357 			break;						\
358 		}							\
359 	}								\
360 } while (0)
361 
362 #define	MAC_INTERNALIZE(type, label, instring) do {			\
363 	char *element, *element_name, *element_data;			\
364 	int claimed;							\
365 									\
366 	error = 0;							\
367 	element = instring;						\
368 	while ((element_name = strsep(&element, ",")) != NULL) {	\
369 		element_data = element_name;				\
370 		element_name = strsep(&element_data, "/");		\
371 		if (element_data == NULL) {				\
372 			error = EINVAL;					\
373 			break;						\
374 		}							\
375 		claimed = 0;						\
376 		MAC_CHECK(internalize_ ## type, label, element_name,	\
377 		    element_data, &claimed);				\
378 		if (error)						\
379 			break;						\
380 		if (claimed != 1) {					\
381 			/* XXXMAC: Another error here? */		\
382 			error = EINVAL;					\
383 			break;						\
384 		}							\
385 	}								\
386 } while (0)
387 
388 /*
389  * MAC_PERFORM performs the designated operation by walking the policy
390  * module list and invoking that operation for each policy.
391  */
392 #define	MAC_PERFORM(operation, args...) do {				\
393 	struct mac_policy_conf *mpc;					\
394 									\
395 	MAC_POLICY_LIST_BUSY();						\
396 	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
397 		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
398 			mpc->mpc_ops->mpo_ ## operation (args);		\
399 	}								\
400 	MAC_POLICY_LIST_UNBUSY();					\
401 } while (0)
402 
403 /*
404  * Initialize the MAC subsystem, including appropriate SMP locks.
405  */
406 static void
407 mac_init(void)
408 {
409 
410 	LIST_INIT(&mac_policy_list);
411 	MAC_POLICY_LIST_LOCKINIT();
412 }
413 
414 /*
415  * For the purposes of modules that want to know if they were loaded
416  * "early", set the mac_late flag once we've processed modules either
417  * linked into the kernel, or loaded before the kernel startup.
418  */
419 static void
420 mac_late_init(void)
421 {
422 
423 	mac_late = 1;
424 }
425 
426 /*
427  * Allow MAC policy modules to register during boot, etc.
428  */
429 int
430 mac_policy_modevent(module_t mod, int type, void *data)
431 {
432 	struct mac_policy_conf *mpc;
433 	int error;
434 
435 	error = 0;
436 	mpc = (struct mac_policy_conf *) data;
437 
438 	switch (type) {
439 	case MOD_LOAD:
440 		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
441 		    mac_late) {
442 			printf("mac_policy_modevent: can't load %s policy "
443 			    "after booting\n", mpc->mpc_name);
444 			error = EBUSY;
445 			break;
446 		}
447 		error = mac_policy_register(mpc);
448 		break;
449 	case MOD_UNLOAD:
450 		/* Don't unregister the module if it was never registered. */
451 		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
452 		    != 0)
453 			error = mac_policy_unregister(mpc);
454 		else
455 			error = 0;
456 		break;
457 	default:
458 		break;
459 	}
460 
461 	return (error);
462 }
463 
464 static int
465 mac_policy_register(struct mac_policy_conf *mpc)
466 {
467 	struct mac_policy_conf *tmpc;
468 	struct mac_policy_op_entry *mpe;
469 	int slot;
470 
471 	MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops),
472 	    M_MACOPVEC, M_WAITOK | M_ZERO);
473 	for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) {
474 		switch (mpe->mpe_constant) {
475 		case MAC_OP_LAST:
476 			/*
477 			 * Doesn't actually happen, but this allows checking
478 			 * that all enumerated values are handled.
479 			 */
480 			break;
481 		case MAC_DESTROY:
482 			mpc->mpc_ops->mpo_destroy =
483 			    mpe->mpe_function;
484 			break;
485 		case MAC_INIT:
486 			mpc->mpc_ops->mpo_init =
487 			    mpe->mpe_function;
488 			break;
489 		case MAC_SYSCALL:
490 			mpc->mpc_ops->mpo_syscall =
491 			    mpe->mpe_function;
492 			break;
493 		case MAC_INIT_BPFDESC_LABEL:
494 			mpc->mpc_ops->mpo_init_bpfdesc_label =
495 			    mpe->mpe_function;
496 			break;
497 		case MAC_INIT_CRED_LABEL:
498 			mpc->mpc_ops->mpo_init_cred_label =
499 			    mpe->mpe_function;
500 			break;
501 		case MAC_INIT_DEVFSDIRENT_LABEL:
502 			mpc->mpc_ops->mpo_init_devfsdirent_label =
503 			    mpe->mpe_function;
504 			break;
505 		case MAC_INIT_IFNET_LABEL:
506 			mpc->mpc_ops->mpo_init_ifnet_label =
507 			    mpe->mpe_function;
508 			break;
509 		case MAC_INIT_IPQ_LABEL:
510 			mpc->mpc_ops->mpo_init_ipq_label =
511 			    mpe->mpe_function;
512 			break;
513 		case MAC_INIT_MBUF_LABEL:
514 			mpc->mpc_ops->mpo_init_mbuf_label =
515 			    mpe->mpe_function;
516 			break;
517 		case MAC_INIT_MOUNT_LABEL:
518 			mpc->mpc_ops->mpo_init_mount_label =
519 			    mpe->mpe_function;
520 			break;
521 		case MAC_INIT_MOUNT_FS_LABEL:
522 			mpc->mpc_ops->mpo_init_mount_fs_label =
523 			    mpe->mpe_function;
524 			break;
525 		case MAC_INIT_PIPE_LABEL:
526 			mpc->mpc_ops->mpo_init_pipe_label =
527 			    mpe->mpe_function;
528 			break;
529 		case MAC_INIT_SOCKET_LABEL:
530 			mpc->mpc_ops->mpo_init_socket_label =
531 			    mpe->mpe_function;
532 			break;
533 		case MAC_INIT_SOCKET_PEER_LABEL:
534 			mpc->mpc_ops->mpo_init_socket_peer_label =
535 			    mpe->mpe_function;
536 			break;
537 		case MAC_INIT_VNODE_LABEL:
538 			mpc->mpc_ops->mpo_init_vnode_label =
539 			    mpe->mpe_function;
540 			break;
541 		case MAC_DESTROY_BPFDESC_LABEL:
542 			mpc->mpc_ops->mpo_destroy_bpfdesc_label =
543 			    mpe->mpe_function;
544 			break;
545 		case MAC_DESTROY_CRED_LABEL:
546 			mpc->mpc_ops->mpo_destroy_cred_label =
547 			    mpe->mpe_function;
548 			break;
549 		case MAC_DESTROY_DEVFSDIRENT_LABEL:
550 			mpc->mpc_ops->mpo_destroy_devfsdirent_label =
551 			    mpe->mpe_function;
552 			break;
553 		case MAC_DESTROY_IFNET_LABEL:
554 			mpc->mpc_ops->mpo_destroy_ifnet_label =
555 			    mpe->mpe_function;
556 			break;
557 		case MAC_DESTROY_IPQ_LABEL:
558 			mpc->mpc_ops->mpo_destroy_ipq_label =
559 			    mpe->mpe_function;
560 			break;
561 		case MAC_DESTROY_MBUF_LABEL:
562 			mpc->mpc_ops->mpo_destroy_mbuf_label =
563 			    mpe->mpe_function;
564 			break;
565 		case MAC_DESTROY_MOUNT_LABEL:
566 			mpc->mpc_ops->mpo_destroy_mount_label =
567 			    mpe->mpe_function;
568 			break;
569 		case MAC_DESTROY_MOUNT_FS_LABEL:
570 			mpc->mpc_ops->mpo_destroy_mount_fs_label =
571 			    mpe->mpe_function;
572 			break;
573 		case MAC_DESTROY_PIPE_LABEL:
574 			mpc->mpc_ops->mpo_destroy_pipe_label =
575 			    mpe->mpe_function;
576 			break;
577 		case MAC_DESTROY_SOCKET_LABEL:
578 			mpc->mpc_ops->mpo_destroy_socket_label =
579 			    mpe->mpe_function;
580 			break;
581 		case MAC_DESTROY_SOCKET_PEER_LABEL:
582 			mpc->mpc_ops->mpo_destroy_socket_peer_label =
583 			    mpe->mpe_function;
584 			break;
585 		case MAC_DESTROY_VNODE_LABEL:
586 			mpc->mpc_ops->mpo_destroy_vnode_label =
587 			    mpe->mpe_function;
588 			break;
589 		case MAC_COPY_PIPE_LABEL:
590 			mpc->mpc_ops->mpo_copy_pipe_label =
591 			    mpe->mpe_function;
592 			break;
593 		case MAC_COPY_VNODE_LABEL:
594 			mpc->mpc_ops->mpo_copy_vnode_label =
595 			    mpe->mpe_function;
596 			break;
597 		case MAC_EXTERNALIZE_CRED_LABEL:
598 			mpc->mpc_ops->mpo_externalize_cred_label =
599 			    mpe->mpe_function;
600 			break;
601 		case MAC_EXTERNALIZE_IFNET_LABEL:
602 			mpc->mpc_ops->mpo_externalize_ifnet_label =
603 			    mpe->mpe_function;
604 			break;
605 		case MAC_EXTERNALIZE_PIPE_LABEL:
606 			mpc->mpc_ops->mpo_externalize_pipe_label =
607 			    mpe->mpe_function;
608 			break;
609 		case MAC_EXTERNALIZE_SOCKET_LABEL:
610 			mpc->mpc_ops->mpo_externalize_socket_label =
611 			    mpe->mpe_function;
612 			break;
613 		case MAC_EXTERNALIZE_SOCKET_PEER_LABEL:
614 			mpc->mpc_ops->mpo_externalize_socket_peer_label =
615 			    mpe->mpe_function;
616 			break;
617 		case MAC_EXTERNALIZE_VNODE_LABEL:
618 			mpc->mpc_ops->mpo_externalize_vnode_label =
619 			    mpe->mpe_function;
620 			break;
621 		case MAC_EXTERNALIZE_VNODE_OLDMAC:
622 			mpc->mpc_ops->mpo_externalize_vnode_oldmac =
623 			    mpe->mpe_function;
624 			break;
625 		case MAC_INTERNALIZE_CRED_LABEL:
626 			mpc->mpc_ops->mpo_internalize_cred_label =
627 			    mpe->mpe_function;
628 			break;
629 		case MAC_INTERNALIZE_IFNET_LABEL:
630 			mpc->mpc_ops->mpo_internalize_ifnet_label =
631 			    mpe->mpe_function;
632 			break;
633 		case MAC_INTERNALIZE_PIPE_LABEL:
634 			mpc->mpc_ops->mpo_internalize_pipe_label =
635 			    mpe->mpe_function;
636 			break;
637 		case MAC_INTERNALIZE_SOCKET_LABEL:
638 			mpc->mpc_ops->mpo_internalize_socket_label =
639 			    mpe->mpe_function;
640 			break;
641 		case MAC_INTERNALIZE_VNODE_LABEL:
642 			mpc->mpc_ops->mpo_internalize_vnode_label =
643 			    mpe->mpe_function;
644 			break;
645 		case MAC_CREATE_DEVFS_DEVICE:
646 			mpc->mpc_ops->mpo_create_devfs_device =
647 			    mpe->mpe_function;
648 			break;
649 		case MAC_CREATE_DEVFS_DIRECTORY:
650 			mpc->mpc_ops->mpo_create_devfs_directory =
651 			    mpe->mpe_function;
652 			break;
653 		case MAC_CREATE_DEVFS_SYMLINK:
654 			mpc->mpc_ops->mpo_create_devfs_symlink =
655 			    mpe->mpe_function;
656 			break;
657 		case MAC_CREATE_DEVFS_VNODE:
658 			mpc->mpc_ops->mpo_create_devfs_vnode =
659 			    mpe->mpe_function;
660 			break;
661 		case MAC_STDCREATEVNODE_EA:
662 			mpc->mpc_ops->mpo_stdcreatevnode_ea =
663 			    mpe->mpe_function;
664 			break;
665 		case MAC_CREATE_VNODE:
666 			mpc->mpc_ops->mpo_create_vnode =
667 			    mpe->mpe_function;
668 			break;
669 		case MAC_CREATE_MOUNT:
670 			mpc->mpc_ops->mpo_create_mount =
671 			    mpe->mpe_function;
672 			break;
673 		case MAC_CREATE_ROOT_MOUNT:
674 			mpc->mpc_ops->mpo_create_root_mount =
675 			    mpe->mpe_function;
676 			break;
677 		case MAC_RELABEL_VNODE:
678 			mpc->mpc_ops->mpo_relabel_vnode =
679 			    mpe->mpe_function;
680 			break;
681 		case MAC_UPDATE_DEVFSDIRENT:
682 			mpc->mpc_ops->mpo_update_devfsdirent =
683 			    mpe->mpe_function;
684 			break;
685 		case MAC_UPDATE_PROCFSVNODE:
686 			mpc->mpc_ops->mpo_update_procfsvnode =
687 			    mpe->mpe_function;
688 			break;
689 		case MAC_UPDATE_VNODE_FROM_EXTATTR:
690 			mpc->mpc_ops->mpo_update_vnode_from_extattr =
691 			    mpe->mpe_function;
692 			break;
693 		case MAC_UPDATE_VNODE_FROM_EXTERNALIZED:
694 			mpc->mpc_ops->mpo_update_vnode_from_externalized =
695 			    mpe->mpe_function;
696 			break;
697 		case MAC_UPDATE_VNODE_FROM_MOUNT:
698 			mpc->mpc_ops->mpo_update_vnode_from_mount =
699 			    mpe->mpe_function;
700 			break;
701 		case MAC_CREATE_MBUF_FROM_SOCKET:
702 			mpc->mpc_ops->mpo_create_mbuf_from_socket =
703 			    mpe->mpe_function;
704 			break;
705 		case MAC_CREATE_PIPE:
706 			mpc->mpc_ops->mpo_create_pipe =
707 			    mpe->mpe_function;
708 			break;
709 		case MAC_CREATE_SOCKET:
710 			mpc->mpc_ops->mpo_create_socket =
711 			    mpe->mpe_function;
712 			break;
713 		case MAC_CREATE_SOCKET_FROM_SOCKET:
714 			mpc->mpc_ops->mpo_create_socket_from_socket =
715 			    mpe->mpe_function;
716 			break;
717 		case MAC_RELABEL_PIPE:
718 			mpc->mpc_ops->mpo_relabel_pipe =
719 			    mpe->mpe_function;
720 			break;
721 		case MAC_RELABEL_SOCKET:
722 			mpc->mpc_ops->mpo_relabel_socket =
723 			    mpe->mpe_function;
724 			break;
725 		case MAC_SET_SOCKET_PEER_FROM_MBUF:
726 			mpc->mpc_ops->mpo_set_socket_peer_from_mbuf =
727 			    mpe->mpe_function;
728 			break;
729 		case MAC_SET_SOCKET_PEER_FROM_SOCKET:
730 			mpc->mpc_ops->mpo_set_socket_peer_from_socket =
731 			    mpe->mpe_function;
732 			break;
733 		case MAC_CREATE_BPFDESC:
734 			mpc->mpc_ops->mpo_create_bpfdesc =
735 			    mpe->mpe_function;
736 			break;
737 		case MAC_CREATE_DATAGRAM_FROM_IPQ:
738 			mpc->mpc_ops->mpo_create_datagram_from_ipq =
739 			    mpe->mpe_function;
740 			break;
741 		case MAC_CREATE_FRAGMENT:
742 			mpc->mpc_ops->mpo_create_fragment =
743 			    mpe->mpe_function;
744 			break;
745 		case MAC_CREATE_IFNET:
746 			mpc->mpc_ops->mpo_create_ifnet =
747 			    mpe->mpe_function;
748 			break;
749 		case MAC_CREATE_IPQ:
750 			mpc->mpc_ops->mpo_create_ipq =
751 			    mpe->mpe_function;
752 			break;
753 		case MAC_CREATE_MBUF_FROM_MBUF:
754 			mpc->mpc_ops->mpo_create_mbuf_from_mbuf =
755 			    mpe->mpe_function;
756 			break;
757 		case MAC_CREATE_MBUF_LINKLAYER:
758 			mpc->mpc_ops->mpo_create_mbuf_linklayer =
759 			    mpe->mpe_function;
760 			break;
761 		case MAC_CREATE_MBUF_FROM_BPFDESC:
762 			mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc =
763 			    mpe->mpe_function;
764 			break;
765 		case MAC_CREATE_MBUF_FROM_IFNET:
766 			mpc->mpc_ops->mpo_create_mbuf_from_ifnet =
767 			    mpe->mpe_function;
768 			break;
769 		case MAC_CREATE_MBUF_MULTICAST_ENCAP:
770 			mpc->mpc_ops->mpo_create_mbuf_multicast_encap =
771 			    mpe->mpe_function;
772 			break;
773 		case MAC_CREATE_MBUF_NETLAYER:
774 			mpc->mpc_ops->mpo_create_mbuf_netlayer =
775 			    mpe->mpe_function;
776 			break;
777 		case MAC_FRAGMENT_MATCH:
778 			mpc->mpc_ops->mpo_fragment_match =
779 			    mpe->mpe_function;
780 			break;
781 		case MAC_RELABEL_IFNET:
782 			mpc->mpc_ops->mpo_relabel_ifnet =
783 			    mpe->mpe_function;
784 			break;
785 		case MAC_UPDATE_IPQ:
786 			mpc->mpc_ops->mpo_update_ipq =
787 			    mpe->mpe_function;
788 			break;
789 		case MAC_CREATE_CRED:
790 			mpc->mpc_ops->mpo_create_cred =
791 			    mpe->mpe_function;
792 			break;
793 		case MAC_EXECVE_TRANSITION:
794 			mpc->mpc_ops->mpo_execve_transition =
795 			    mpe->mpe_function;
796 			break;
797 		case MAC_EXECVE_WILL_TRANSITION:
798 			mpc->mpc_ops->mpo_execve_will_transition =
799 			    mpe->mpe_function;
800 			break;
801 		case MAC_CREATE_PROC0:
802 			mpc->mpc_ops->mpo_create_proc0 =
803 			    mpe->mpe_function;
804 			break;
805 		case MAC_CREATE_PROC1:
806 			mpc->mpc_ops->mpo_create_proc1 =
807 			    mpe->mpe_function;
808 			break;
809 		case MAC_RELABEL_CRED:
810 			mpc->mpc_ops->mpo_relabel_cred =
811 			    mpe->mpe_function;
812 			break;
813 		case MAC_THREAD_USERRET:
814 			mpc->mpc_ops->mpo_thread_userret =
815 			    mpe->mpe_function;
816 			break;
817 		case MAC_CHECK_BPFDESC_RECEIVE:
818 			mpc->mpc_ops->mpo_check_bpfdesc_receive =
819 			    mpe->mpe_function;
820 			break;
821 		case MAC_CHECK_CRED_RELABEL:
822 			mpc->mpc_ops->mpo_check_cred_relabel =
823 			    mpe->mpe_function;
824 			break;
825 		case MAC_CHECK_CRED_VISIBLE:
826 			mpc->mpc_ops->mpo_check_cred_visible =
827 			    mpe->mpe_function;
828 			break;
829 		case MAC_CHECK_IFNET_RELABEL:
830 			mpc->mpc_ops->mpo_check_ifnet_relabel =
831 			    mpe->mpe_function;
832 			break;
833 		case MAC_CHECK_IFNET_TRANSMIT:
834 			mpc->mpc_ops->mpo_check_ifnet_transmit =
835 			    mpe->mpe_function;
836 			break;
837 		case MAC_CHECK_MOUNT_STAT:
838 			mpc->mpc_ops->mpo_check_mount_stat =
839 			    mpe->mpe_function;
840 			break;
841 		case MAC_CHECK_PIPE_IOCTL:
842 			mpc->mpc_ops->mpo_check_pipe_ioctl =
843 			    mpe->mpe_function;
844 			break;
845 		case MAC_CHECK_PIPE_POLL:
846 			mpc->mpc_ops->mpo_check_pipe_poll =
847 			    mpe->mpe_function;
848 			break;
849 		case MAC_CHECK_PIPE_READ:
850 			mpc->mpc_ops->mpo_check_pipe_read =
851 			    mpe->mpe_function;
852 			break;
853 		case MAC_CHECK_PIPE_RELABEL:
854 			mpc->mpc_ops->mpo_check_pipe_relabel =
855 			    mpe->mpe_function;
856 			break;
857 		case MAC_CHECK_PIPE_STAT:
858 			mpc->mpc_ops->mpo_check_pipe_stat =
859 			    mpe->mpe_function;
860 			break;
861 		case MAC_CHECK_PIPE_WRITE:
862 			mpc->mpc_ops->mpo_check_pipe_write =
863 			    mpe->mpe_function;
864 			break;
865 		case MAC_CHECK_PROC_DEBUG:
866 			mpc->mpc_ops->mpo_check_proc_debug =
867 			    mpe->mpe_function;
868 			break;
869 		case MAC_CHECK_PROC_SCHED:
870 			mpc->mpc_ops->mpo_check_proc_sched =
871 			    mpe->mpe_function;
872 			break;
873 		case MAC_CHECK_PROC_SIGNAL:
874 			mpc->mpc_ops->mpo_check_proc_signal =
875 			    mpe->mpe_function;
876 			break;
877 		case MAC_CHECK_SOCKET_BIND:
878 			mpc->mpc_ops->mpo_check_socket_bind =
879 			    mpe->mpe_function;
880 			break;
881 		case MAC_CHECK_SOCKET_CONNECT:
882 			mpc->mpc_ops->mpo_check_socket_connect =
883 			    mpe->mpe_function;
884 			break;
885 		case MAC_CHECK_SOCKET_DELIVER:
886 			mpc->mpc_ops->mpo_check_socket_deliver =
887 			    mpe->mpe_function;
888 			break;
889 		case MAC_CHECK_SOCKET_LISTEN:
890 			mpc->mpc_ops->mpo_check_socket_listen =
891 			    mpe->mpe_function;
892 			break;
893 		case MAC_CHECK_SOCKET_RECEIVE:
894 			mpc->mpc_ops->mpo_check_socket_receive =
895 			    mpe->mpe_function;
896 			break;
897 		case MAC_CHECK_SOCKET_RELABEL:
898 			mpc->mpc_ops->mpo_check_socket_relabel =
899 			    mpe->mpe_function;
900 			break;
901 		case MAC_CHECK_SOCKET_SEND:
902 			mpc->mpc_ops->mpo_check_socket_send =
903 			    mpe->mpe_function;
904 			break;
905 		case MAC_CHECK_SOCKET_VISIBLE:
906 			mpc->mpc_ops->mpo_check_socket_visible =
907 			    mpe->mpe_function;
908 			break;
909 		case MAC_CHECK_VNODE_ACCESS:
910 			mpc->mpc_ops->mpo_check_vnode_access =
911 			    mpe->mpe_function;
912 			break;
913 		case MAC_CHECK_VNODE_CHDIR:
914 			mpc->mpc_ops->mpo_check_vnode_chdir =
915 			    mpe->mpe_function;
916 			break;
917 		case MAC_CHECK_VNODE_CHROOT:
918 			mpc->mpc_ops->mpo_check_vnode_chroot =
919 			    mpe->mpe_function;
920 			break;
921 		case MAC_CHECK_VNODE_CREATE:
922 			mpc->mpc_ops->mpo_check_vnode_create =
923 			    mpe->mpe_function;
924 			break;
925 		case MAC_CHECK_VNODE_DELETE:
926 			mpc->mpc_ops->mpo_check_vnode_delete =
927 			    mpe->mpe_function;
928 			break;
929 		case MAC_CHECK_VNODE_DELETEACL:
930 			mpc->mpc_ops->mpo_check_vnode_deleteacl =
931 			    mpe->mpe_function;
932 			break;
933 		case MAC_CHECK_VNODE_EXEC:
934 			mpc->mpc_ops->mpo_check_vnode_exec =
935 			    mpe->mpe_function;
936 			break;
937 		case MAC_CHECK_VNODE_GETACL:
938 			mpc->mpc_ops->mpo_check_vnode_getacl =
939 			    mpe->mpe_function;
940 			break;
941 		case MAC_CHECK_VNODE_GETEXTATTR:
942 			mpc->mpc_ops->mpo_check_vnode_getextattr =
943 			    mpe->mpe_function;
944 			break;
945 		case MAC_CHECK_VNODE_LINK:
946 			mpc->mpc_ops->mpo_check_vnode_link =
947 			    mpe->mpe_function;
948 			break;
949 		case MAC_CHECK_VNODE_LOOKUP:
950 			mpc->mpc_ops->mpo_check_vnode_lookup =
951 			    mpe->mpe_function;
952 			break;
953 		case MAC_CHECK_VNODE_MMAP:
954 			mpc->mpc_ops->mpo_check_vnode_mmap =
955 			    mpe->mpe_function;
956 			break;
957 		case MAC_CHECK_VNODE_MMAP_DOWNGRADE:
958 			mpc->mpc_ops->mpo_check_vnode_mmap_downgrade =
959 			    mpe->mpe_function;
960 			break;
961 		case MAC_CHECK_VNODE_MPROTECT:
962 			mpc->mpc_ops->mpo_check_vnode_mprotect =
963 			    mpe->mpe_function;
964 			break;
965 		case MAC_CHECK_VNODE_OPEN:
966 			mpc->mpc_ops->mpo_check_vnode_open =
967 			    mpe->mpe_function;
968 			break;
969 		case MAC_CHECK_VNODE_POLL:
970 			mpc->mpc_ops->mpo_check_vnode_poll =
971 			    mpe->mpe_function;
972 			break;
973 		case MAC_CHECK_VNODE_READ:
974 			mpc->mpc_ops->mpo_check_vnode_read =
975 			    mpe->mpe_function;
976 			break;
977 		case MAC_CHECK_VNODE_READDIR:
978 			mpc->mpc_ops->mpo_check_vnode_readdir =
979 			    mpe->mpe_function;
980 			break;
981 		case MAC_CHECK_VNODE_READLINK:
982 			mpc->mpc_ops->mpo_check_vnode_readlink =
983 			    mpe->mpe_function;
984 			break;
985 		case MAC_CHECK_VNODE_RELABEL:
986 			mpc->mpc_ops->mpo_check_vnode_relabel =
987 			    mpe->mpe_function;
988 			break;
989 		case MAC_CHECK_VNODE_RENAME_FROM:
990 			mpc->mpc_ops->mpo_check_vnode_rename_from =
991 			    mpe->mpe_function;
992 			break;
993 		case MAC_CHECK_VNODE_RENAME_TO:
994 			mpc->mpc_ops->mpo_check_vnode_rename_to =
995 			    mpe->mpe_function;
996 			break;
997 		case MAC_CHECK_VNODE_REVOKE:
998 			mpc->mpc_ops->mpo_check_vnode_revoke =
999 			    mpe->mpe_function;
1000 			break;
1001 		case MAC_CHECK_VNODE_SETACL:
1002 			mpc->mpc_ops->mpo_check_vnode_setacl =
1003 			    mpe->mpe_function;
1004 			break;
1005 		case MAC_CHECK_VNODE_SETEXTATTR:
1006 			mpc->mpc_ops->mpo_check_vnode_setextattr =
1007 			    mpe->mpe_function;
1008 			break;
1009 		case MAC_CHECK_VNODE_SETFLAGS:
1010 			mpc->mpc_ops->mpo_check_vnode_setflags =
1011 			    mpe->mpe_function;
1012 			break;
1013 		case MAC_CHECK_VNODE_SETMODE:
1014 			mpc->mpc_ops->mpo_check_vnode_setmode =
1015 			    mpe->mpe_function;
1016 			break;
1017 		case MAC_CHECK_VNODE_SETOWNER:
1018 			mpc->mpc_ops->mpo_check_vnode_setowner =
1019 			    mpe->mpe_function;
1020 			break;
1021 		case MAC_CHECK_VNODE_SETUTIMES:
1022 			mpc->mpc_ops->mpo_check_vnode_setutimes =
1023 			    mpe->mpe_function;
1024 			break;
1025 		case MAC_CHECK_VNODE_STAT:
1026 			mpc->mpc_ops->mpo_check_vnode_stat =
1027 			    mpe->mpe_function;
1028 			break;
1029 		case MAC_CHECK_VNODE_SWAPON:
1030 			mpc->mpc_ops->mpo_check_vnode_swapon =
1031 			    mpe->mpe_function;
1032 			break;
1033 		case MAC_CHECK_VNODE_WRITE:
1034 			mpc->mpc_ops->mpo_check_vnode_write =
1035 			    mpe->mpe_function;
1036 			break;
1037 /*
1038 		default:
1039 			printf("MAC policy `%s': unknown operation %d\n",
1040 			    mpc->mpc_name, mpe->mpe_constant);
1041 			return (EINVAL);
1042 */
1043 		}
1044 	}
1045 	MAC_POLICY_LIST_LOCK();
1046 	if (mac_policy_list_busy > 0) {
1047 		MAC_POLICY_LIST_UNLOCK();
1048 		FREE(mpc->mpc_ops, M_MACOPVEC);
1049 		mpc->mpc_ops = NULL;
1050 		return (EBUSY);
1051 	}
1052 	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
1053 		if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
1054 			MAC_POLICY_LIST_UNLOCK();
1055 			FREE(mpc->mpc_ops, M_MACOPVEC);
1056 			mpc->mpc_ops = NULL;
1057 			return (EEXIST);
1058 		}
1059 	}
1060 	if (mpc->mpc_field_off != NULL) {
1061 		slot = ffs(mac_policy_offsets_free);
1062 		if (slot == 0) {
1063 			MAC_POLICY_LIST_UNLOCK();
1064 			FREE(mpc->mpc_ops, M_MACOPVEC);
1065 			mpc->mpc_ops = NULL;
1066 			return (ENOMEM);
1067 		}
1068 		slot--;
1069 		mac_policy_offsets_free &= ~(1 << slot);
1070 		*mpc->mpc_field_off = slot;
1071 	}
1072 	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
1073 	LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
1074 
1075 	/* Per-policy initialization. */
1076 	if (mpc->mpc_ops->mpo_init != NULL)
1077 		(*(mpc->mpc_ops->mpo_init))(mpc);
1078 	MAC_POLICY_LIST_UNLOCK();
1079 
1080 	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
1081 	    mpc->mpc_name);
1082 
1083 	return (0);
1084 }
1085 
1086 static int
1087 mac_policy_unregister(struct mac_policy_conf *mpc)
1088 {
1089 
1090 	/*
1091 	 * If we fail the load, we may get a request to unload.  Check
1092 	 * to see if we did the run-time registration, and if not,
1093 	 * silently succeed.
1094 	 */
1095 	MAC_POLICY_LIST_LOCK();
1096 	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
1097 		MAC_POLICY_LIST_UNLOCK();
1098 		return (0);
1099 	}
1100 #if 0
1101 	/*
1102 	 * Don't allow unloading modules with private data.
1103 	 */
1104 	if (mpc->mpc_field_off != NULL) {
1105 		MAC_POLICY_LIST_UNLOCK();
1106 		return (EBUSY);
1107 	}
1108 #endif
1109 	/*
1110 	 * Only allow the unload to proceed if the module is unloadable
1111 	 * by its own definition.
1112 	 */
1113 	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
1114 		MAC_POLICY_LIST_UNLOCK();
1115 		return (EBUSY);
1116 	}
1117 	/*
1118 	 * Right now, we EBUSY if the list is in use.  In the future,
1119 	 * for reliability reasons, we might want to sleep and wakeup
1120 	 * later to try again.
1121 	 */
1122 	if (mac_policy_list_busy > 0) {
1123 		MAC_POLICY_LIST_UNLOCK();
1124 		return (EBUSY);
1125 	}
1126 	if (mpc->mpc_ops->mpo_destroy != NULL)
1127 		(*(mpc->mpc_ops->mpo_destroy))(mpc);
1128 
1129 	LIST_REMOVE(mpc, mpc_list);
1130 	MAC_POLICY_LIST_UNLOCK();
1131 
1132 	FREE(mpc->mpc_ops, M_MACOPVEC);
1133 	mpc->mpc_ops = NULL;
1134 	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
1135 
1136 	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
1137 	    mpc->mpc_name);
1138 
1139 	return (0);
1140 }
1141 
1142 /*
1143  * Define an error value precedence, and given two arguments, selects the
1144  * value with the higher precedence.
1145  */
1146 static int
1147 error_select(int error1, int error2)
1148 {
1149 
1150 	/* Certain decision-making errors take top priority. */
1151 	if (error1 == EDEADLK || error2 == EDEADLK)
1152 		return (EDEADLK);
1153 
1154 	/* Invalid arguments should be reported where possible. */
1155 	if (error1 == EINVAL || error2 == EINVAL)
1156 		return (EINVAL);
1157 
1158 	/* Precedence goes to "visibility", with both process and file. */
1159 	if (error1 == ESRCH || error2 == ESRCH)
1160 		return (ESRCH);
1161 
1162 	if (error1 == ENOENT || error2 == ENOENT)
1163 		return (ENOENT);
1164 
1165 	/* Precedence goes to DAC/MAC protections. */
1166 	if (error1 == EACCES || error2 == EACCES)
1167 		return (EACCES);
1168 
1169 	/* Precedence goes to privilege. */
1170 	if (error1 == EPERM || error2 == EPERM)
1171 		return (EPERM);
1172 
1173 	/* Precedence goes to error over success; otherwise, arbitrary. */
1174 	if (error1 != 0)
1175 		return (error1);
1176 	return (error2);
1177 }
1178 
1179 static void
1180 mac_init_label(struct label *label)
1181 {
1182 
1183 	bzero(label, sizeof(*label));
1184 	label->l_flags = MAC_FLAG_INITIALIZED;
1185 }
1186 
1187 static void
1188 mac_destroy_label(struct label *label)
1189 {
1190 
1191 	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1192 	    ("destroying uninitialized label"));
1193 
1194 	bzero(label, sizeof(*label));
1195 	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1196 }
1197 
1198 void
1199 mac_init_bpfdesc(struct bpf_d *bpf_d)
1200 {
1201 
1202 	mac_init_label(&bpf_d->bd_label);
1203 	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
1204 #ifdef MAC_DEBUG
1205 	atomic_add_int(&nmacbpfdescs, 1);
1206 #endif
1207 }
1208 
1209 static void
1210 mac_init_cred_label(struct label *label)
1211 {
1212 
1213 	mac_init_label(label);
1214 	MAC_PERFORM(init_cred_label, label);
1215 #ifdef MAC_DEBUG
1216 	atomic_add_int(&nmaccreds, 1);
1217 #endif
1218 }
1219 
1220 void
1221 mac_init_cred(struct ucred *cred)
1222 {
1223 
1224 	mac_init_cred_label(&cred->cr_label);
1225 }
1226 
1227 void
1228 mac_init_devfsdirent(struct devfs_dirent *de)
1229 {
1230 
1231 	mac_init_label(&de->de_label);
1232 	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
1233 #ifdef MAC_DEBUG
1234 	atomic_add_int(&nmacdevfsdirents, 1);
1235 #endif
1236 }
1237 
1238 static void
1239 mac_init_ifnet_label(struct label *label)
1240 {
1241 
1242 	mac_init_label(label);
1243 	MAC_PERFORM(init_ifnet_label, label);
1244 #ifdef MAC_DEBUG
1245 	atomic_add_int(&nmacifnets, 1);
1246 #endif
1247 }
1248 
1249 void
1250 mac_init_ifnet(struct ifnet *ifp)
1251 {
1252 
1253 	mac_init_ifnet_label(&ifp->if_label);
1254 }
1255 
1256 void
1257 mac_init_ipq(struct ipq *ipq)
1258 {
1259 
1260 	mac_init_label(&ipq->ipq_label);
1261 	MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
1262 #ifdef MAC_DEBUG
1263 	atomic_add_int(&nmacipqs, 1);
1264 #endif
1265 }
1266 
1267 int
1268 mac_init_mbuf(struct mbuf *m, int flag)
1269 {
1270 	int error;
1271 
1272 	KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1273 
1274 	mac_init_label(&m->m_pkthdr.label);
1275 
1276 	MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
1277 	if (error) {
1278 		MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1279 		mac_destroy_label(&m->m_pkthdr.label);
1280 	}
1281 
1282 #ifdef MAC_DEBUG
1283 	if (error == 0)
1284 		atomic_add_int(&nmacmbufs, 1);
1285 #endif
1286 	return (error);
1287 }
1288 
1289 void
1290 mac_init_mount(struct mount *mp)
1291 {
1292 
1293 	mac_init_label(&mp->mnt_mntlabel);
1294 	mac_init_label(&mp->mnt_fslabel);
1295 	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
1296 	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
1297 #ifdef MAC_DEBUG
1298 	atomic_add_int(&nmacmounts, 1);
1299 #endif
1300 }
1301 
1302 static void
1303 mac_init_pipe_label(struct label *label)
1304 {
1305 
1306 	mac_init_label(label);
1307 	MAC_PERFORM(init_pipe_label, label);
1308 #ifdef MAC_DEBUG
1309 	atomic_add_int(&nmacpipes, 1);
1310 #endif
1311 }
1312 
1313 void
1314 mac_init_pipe(struct pipe *pipe)
1315 {
1316 	struct label *label;
1317 
1318 	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1319 	pipe->pipe_label = label;
1320 	pipe->pipe_peer->pipe_label = label;
1321 	mac_init_pipe_label(label);
1322 }
1323 
1324 static int
1325 mac_init_socket_label(struct label *label, int flag)
1326 {
1327 	int error;
1328 
1329 	mac_init_label(label);
1330 
1331 	MAC_CHECK(init_socket_label, label, flag);
1332 	if (error) {
1333 		MAC_PERFORM(destroy_socket_label, label);
1334 		mac_destroy_label(label);
1335 	}
1336 
1337 #ifdef MAC_DEBUG
1338 	if (error == 0)
1339 		atomic_add_int(&nmacsockets, 1);
1340 #endif
1341 
1342 	return (error);
1343 }
1344 
1345 static int
1346 mac_init_socket_peer_label(struct label *label, int flag)
1347 {
1348 	int error;
1349 
1350 	mac_init_label(label);
1351 
1352 	MAC_CHECK(init_socket_peer_label, label, flag);
1353 	if (error) {
1354 		MAC_PERFORM(destroy_socket_label, label);
1355 		mac_destroy_label(label);
1356 	}
1357 
1358 	return (error);
1359 }
1360 
1361 int
1362 mac_init_socket(struct socket *socket, int flag)
1363 {
1364 	int error;
1365 
1366 	error = mac_init_socket_label(&socket->so_label, flag);
1367 	if (error)
1368 		return (error);
1369 
1370 	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
1371 	if (error)
1372 		mac_destroy_socket_label(&socket->so_label);
1373 
1374 	return (error);
1375 }
1376 
1377 static void
1378 mac_init_vnode_label(struct label *label)
1379 {
1380 
1381 	mac_init_label(label);
1382 	MAC_PERFORM(init_vnode_label, label);
1383 #ifdef MAC_DEBUG
1384 	atomic_add_int(&nmacvnodes, 1);
1385 #endif
1386 }
1387 
1388 void
1389 mac_init_vnode(struct vnode *vp)
1390 {
1391 
1392 	mac_init_vnode_label(&vp->v_label);
1393 }
1394 
1395 void
1396 mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1397 {
1398 
1399 	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1400 	mac_destroy_label(&bpf_d->bd_label);
1401 #ifdef MAC_DEBUG
1402 	atomic_subtract_int(&nmacbpfdescs, 1);
1403 #endif
1404 }
1405 
1406 static void
1407 mac_destroy_cred_label(struct label *label)
1408 {
1409 
1410 	MAC_PERFORM(destroy_cred_label, label);
1411 	mac_destroy_label(label);
1412 #ifdef MAC_DEBUG
1413 	atomic_subtract_int(&nmaccreds, 1);
1414 #endif
1415 }
1416 
1417 void
1418 mac_destroy_cred(struct ucred *cred)
1419 {
1420 
1421 	mac_destroy_cred_label(&cred->cr_label);
1422 }
1423 
1424 void
1425 mac_destroy_devfsdirent(struct devfs_dirent *de)
1426 {
1427 
1428 	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1429 	mac_destroy_label(&de->de_label);
1430 #ifdef MAC_DEBUG
1431 	atomic_subtract_int(&nmacdevfsdirents, 1);
1432 #endif
1433 }
1434 
1435 static void
1436 mac_destroy_ifnet_label(struct label *label)
1437 {
1438 
1439 	MAC_PERFORM(destroy_ifnet_label, label);
1440 	mac_destroy_label(label);
1441 #ifdef MAC_DEBUG
1442 	atomic_subtract_int(&nmacifnets, 1);
1443 #endif
1444 }
1445 
1446 void
1447 mac_destroy_ifnet(struct ifnet *ifp)
1448 {
1449 
1450 	mac_destroy_ifnet_label(&ifp->if_label);
1451 }
1452 
1453 void
1454 mac_destroy_ipq(struct ipq *ipq)
1455 {
1456 
1457 	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1458 	mac_destroy_label(&ipq->ipq_label);
1459 #ifdef MAC_DEBUG
1460 	atomic_subtract_int(&nmacipqs, 1);
1461 #endif
1462 }
1463 
1464 void
1465 mac_destroy_mbuf(struct mbuf *m)
1466 {
1467 
1468 	MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1469 	mac_destroy_label(&m->m_pkthdr.label);
1470 #ifdef MAC_DEBUG
1471 	atomic_subtract_int(&nmacmbufs, 1);
1472 #endif
1473 }
1474 
1475 void
1476 mac_destroy_mount(struct mount *mp)
1477 {
1478 
1479 	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1480 	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1481 	mac_destroy_label(&mp->mnt_fslabel);
1482 	mac_destroy_label(&mp->mnt_mntlabel);
1483 #ifdef MAC_DEBUG
1484 	atomic_subtract_int(&nmacmounts, 1);
1485 #endif
1486 }
1487 
1488 static void
1489 mac_destroy_pipe_label(struct label *label)
1490 {
1491 
1492 	MAC_PERFORM(destroy_pipe_label, label);
1493 	mac_destroy_label(label);
1494 #ifdef MAC_DEBUG
1495 	atomic_subtract_int(&nmacpipes, 1);
1496 #endif
1497 }
1498 
1499 void
1500 mac_destroy_pipe(struct pipe *pipe)
1501 {
1502 
1503 	mac_destroy_pipe_label(pipe->pipe_label);
1504 	free(pipe->pipe_label, M_MACPIPELABEL);
1505 }
1506 
1507 static void
1508 mac_destroy_socket_label(struct label *label)
1509 {
1510 
1511 	MAC_PERFORM(destroy_socket_label, label);
1512 	mac_destroy_label(label);
1513 #ifdef MAC_DEBUG
1514 	atomic_subtract_int(&nmacsockets, 1);
1515 #endif
1516 }
1517 
1518 static void
1519 mac_destroy_socket_peer_label(struct label *label)
1520 {
1521 
1522 	MAC_PERFORM(destroy_socket_peer_label, label);
1523 	mac_destroy_label(label);
1524 }
1525 
1526 void
1527 mac_destroy_socket(struct socket *socket)
1528 {
1529 
1530 	mac_destroy_socket_label(&socket->so_label);
1531 	mac_destroy_socket_peer_label(&socket->so_peerlabel);
1532 }
1533 
1534 static void
1535 mac_destroy_vnode_label(struct label *label)
1536 {
1537 
1538 	MAC_PERFORM(destroy_vnode_label, label);
1539 	mac_destroy_label(label);
1540 #ifdef MAC_DEBUG
1541 	atomic_subtract_int(&nmacvnodes, 1);
1542 #endif
1543 }
1544 
1545 void
1546 mac_destroy_vnode(struct vnode *vp)
1547 {
1548 
1549 	mac_destroy_vnode_label(&vp->v_label);
1550 }
1551 
1552 static void
1553 mac_copy_pipe_label(struct label *src, struct label *dest)
1554 {
1555 
1556 	MAC_PERFORM(copy_pipe_label, src, dest);
1557 }
1558 
1559 static void
1560 mac_copy_vnode_label(struct label *src, struct label *dest)
1561 {
1562 
1563 	MAC_PERFORM(copy_vnode_label, src, dest);
1564 }
1565 
1566 static int
1567 mac_check_structmac_consistent(struct mac *mac)
1568 {
1569 
1570 	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1571 		return (EINVAL);
1572 
1573 	return (0);
1574 }
1575 
1576 static int
1577 mac_externalize_cred_label(struct label *label, char *elements,
1578     char *outbuf, size_t outbuflen, int flags)
1579 {
1580 	int error;
1581 
1582 	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1583 
1584 	return (error);
1585 }
1586 
1587 static int
1588 mac_externalize_ifnet_label(struct label *label, char *elements,
1589     char *outbuf, size_t outbuflen, int flags)
1590 {
1591 	int error;
1592 
1593 	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1594 
1595 	return (error);
1596 }
1597 
1598 static int
1599 mac_externalize_pipe_label(struct label *label, char *elements,
1600     char *outbuf, size_t outbuflen, int flags)
1601 {
1602 	int error;
1603 
1604 	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1605 
1606 	return (error);
1607 }
1608 
1609 static int
1610 mac_externalize_socket_label(struct label *label, char *elements,
1611     char *outbuf, size_t outbuflen, int flags)
1612 {
1613 	int error;
1614 
1615 	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1616 
1617 	return (error);
1618 }
1619 
1620 static int
1621 mac_externalize_socket_peer_label(struct label *label, char *elements,
1622     char *outbuf, size_t outbuflen, int flags)
1623 {
1624 	int error;
1625 
1626 	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1627 
1628 	return (error);
1629 }
1630 
1631 static int
1632 mac_externalize_vnode_label(struct label *label, char *elements,
1633     char *outbuf, size_t outbuflen, int flags)
1634 {
1635 	int error;
1636 
1637 	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1638 
1639 	return (error);
1640 }
1641 
1642 static int
1643 mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac)
1644 {
1645 	int error;
1646 
1647 	MAC_CHECK(externalize_vnode_oldmac, label, extmac);
1648 
1649 	return (error);
1650 }
1651 
1652 static int
1653 mac_internalize_cred_label(struct label *label, char *string)
1654 {
1655 	int error;
1656 
1657 	MAC_INTERNALIZE(cred_label, label, string);
1658 
1659 	return (error);
1660 }
1661 
1662 static int
1663 mac_internalize_ifnet_label(struct label *label, char *string)
1664 {
1665 	int error;
1666 
1667 	MAC_INTERNALIZE(ifnet_label, label, string);
1668 
1669 	return (error);
1670 }
1671 
1672 static int
1673 mac_internalize_pipe_label(struct label *label, char *string)
1674 {
1675 	int error;
1676 
1677 	MAC_INTERNALIZE(pipe_label, label, string);
1678 
1679 	return (error);
1680 }
1681 
1682 static int
1683 mac_internalize_socket_label(struct label *label, char *string)
1684 {
1685 	int error;
1686 
1687 	MAC_INTERNALIZE(socket_label, label, string);
1688 
1689 	return (error);
1690 }
1691 
1692 static int
1693 mac_internalize_vnode_label(struct label *label, char *string)
1694 {
1695 	int error;
1696 
1697 	MAC_INTERNALIZE(vnode_label, label, string);
1698 
1699 	return (error);
1700 }
1701 
1702 /*
1703  * Initialize MAC label for the first kernel process, from which other
1704  * kernel processes and threads are spawned.
1705  */
1706 void
1707 mac_create_proc0(struct ucred *cred)
1708 {
1709 
1710 	MAC_PERFORM(create_proc0, cred);
1711 }
1712 
1713 /*
1714  * Initialize MAC label for the first userland process, from which other
1715  * userland processes and threads are spawned.
1716  */
1717 void
1718 mac_create_proc1(struct ucred *cred)
1719 {
1720 
1721 	MAC_PERFORM(create_proc1, cred);
1722 }
1723 
1724 void
1725 mac_thread_userret(struct thread *td)
1726 {
1727 
1728 	MAC_PERFORM(thread_userret, td);
1729 }
1730 
1731 /*
1732  * When a new process is created, its label must be initialized.  Generally,
1733  * this involves inheritence from the parent process, modulo possible
1734  * deltas.  This function allows that processing to take place.
1735  */
1736 void
1737 mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1738 {
1739 
1740 	MAC_PERFORM(create_cred, parent_cred, child_cred);
1741 }
1742 
1743 void
1744 mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1745 {
1746 
1747 	MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1748 }
1749 
1750 void
1751 mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
1752 {
1753 
1754 	MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
1755 }
1756 
1757 /*
1758  * Support callout for policies that manage their own externalization
1759  * using extended attributes.
1760  */
1761 static int
1762 mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
1763 {
1764 	int error;
1765 
1766 	MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
1767 	    &mp->mnt_fslabel);
1768 
1769 	return (error);
1770 }
1771 
1772 /*
1773  * Given an externalized mac label, internalize it and stamp it on a
1774  * vnode.
1775  */
1776 static int
1777 mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac)
1778 {
1779 	int error;
1780 
1781 	MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
1782 
1783 	return (error);
1784 }
1785 
1786 /*
1787  * Call out to individual policies to update the label in a vnode from
1788  * the mountpoint.
1789  */
1790 void
1791 mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
1792 {
1793 
1794 	MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
1795 	    &mp->mnt_fslabel);
1796 
1797 	ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
1798 	if (mac_cache_fslabel_in_vnode)
1799 		vp->v_vflag |= VV_CACHEDLABEL;
1800 }
1801 
1802 /*
1803  * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
1804  * to store label data.  Can be referenced by filesystems supporting
1805  * extended attributes.
1806  */
1807 int
1808 vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
1809 {
1810 	struct vnode *vp = ap->a_vp;
1811 	struct oldmac extmac;
1812 	int buflen, error;
1813 
1814 	ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1815 
1816 	/*
1817 	 * Call out to external policies first.  Order doesn't really
1818 	 * matter, as long as failure of one assures failure of all.
1819 	 */
1820 	error = mac_update_vnode_from_extattr(vp, vp->v_mount);
1821 	if (error)
1822 		return (error);
1823 
1824 	buflen = sizeof(extmac);
1825 	error = vn_extattr_get(vp, IO_NODELOCKED,
1826 	    FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
1827 	    (char *)&extmac, curthread);
1828 	switch (error) {
1829 	case 0:
1830 		/* Got it */
1831 		break;
1832 
1833 	case ENOATTR:
1834 		/*
1835 		 * Use the label from the mount point.
1836 		 */
1837 		mac_update_vnode_from_mount(vp, vp->v_mount);
1838 		return (0);
1839 
1840 	case EOPNOTSUPP:
1841 	default:
1842 		/* Fail horribly. */
1843 		return (error);
1844 	}
1845 
1846 	if (buflen != sizeof(extmac))
1847 		error = EPERM;		/* Fail very closed. */
1848 	if (error == 0)
1849 		error = mac_update_vnode_from_externalized(vp, &extmac);
1850 	if (error == 0)
1851 		vp->v_vflag |= VV_CACHEDLABEL;
1852 	else {
1853 		struct vattr va;
1854 
1855 		printf("Corrupted label on %s",
1856 		    vp->v_mount->mnt_stat.f_mntonname);
1857 		if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
1858 			printf(" inum %ld", va.va_fileid);
1859 #ifdef MAC_DEBUG
1860 		if (mac_debug_label_fallback) {
1861 			printf(", falling back.\n");
1862 			mac_update_vnode_from_mount(vp, vp->v_mount);
1863 			error = 0;
1864 		} else {
1865 #endif
1866 			printf(".\n");
1867 			error = EPERM;
1868 #ifdef MAC_DEBUG
1869 		}
1870 #endif
1871 	}
1872 
1873 	return (error);
1874 }
1875 
1876 /*
1877  * Make sure the vnode label is up-to-date.  If EOPNOTSUPP, then we handle
1878  * the labeling activity outselves.  Filesystems should be careful not
1879  * to change their minds regarding whether they support vop_refreshlabel()
1880  * for a vnode or not.  Don't cache the vnode here, allow the file
1881  * system code to determine if it's safe to cache.  If we update from
1882  * the mount, don't cache since a change to the mount label should affect
1883  * all vnodes.
1884  */
1885 static int
1886 vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1887 {
1888 	int error;
1889 
1890 	ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1891 
1892 	if (vp->v_mount == NULL) {
1893 /*
1894 		Eventually, we probably want to special-case refreshing
1895 		of deadfs vnodes, and if there's a lock-free race somewhere,
1896 		that case might be handled here.
1897 
1898 		mac_update_vnode_deadfs(vp);
1899 		return (0);
1900  */
1901 		/* printf("vn_refreshlabel: null v_mount\n"); */
1902 		if (vp->v_type != VNON)
1903 			printf(
1904 			    "vn_refreshlabel: null v_mount with non-VNON\n");
1905 		return (EBADF);
1906 	}
1907 
1908 	if (vp->v_vflag & VV_CACHEDLABEL) {
1909 		mac_vnode_label_cache_hits++;
1910 		return (0);
1911 	} else
1912 		mac_vnode_label_cache_misses++;
1913 
1914 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1915 		mac_update_vnode_from_mount(vp, vp->v_mount);
1916 		return (0);
1917 	}
1918 
1919 	error = VOP_REFRESHLABEL(vp, cred, curthread);
1920 	switch (error) {
1921 	case EOPNOTSUPP:
1922 		/*
1923 		 * If labels are not supported on this vnode, fall back to
1924 		 * the label in the mount and propagate it to the vnode.
1925 		 * There should probably be some sort of policy/flag/decision
1926 		 * about doing this.
1927 		 */
1928 		mac_update_vnode_from_mount(vp, vp->v_mount);
1929 		error = 0;
1930 	default:
1931 		return (error);
1932 	}
1933 }
1934 
1935 /*
1936  * Helper function for file systems using the vop_std*_ea() calls.  This
1937  * function must be called after EA service is available for the vnode,
1938  * but before it's hooked up to the namespace so that the node persists
1939  * if there's a crash, or before it can be accessed.  On successful
1940  * commit of the label to disk (etc), do cache the label.
1941  */
1942 int
1943 vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
1944 {
1945 	struct oldmac extmac;
1946 	int error;
1947 
1948 	ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
1949 	if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1950 		mac_update_vnode_from_mount(tvp, tvp->v_mount);
1951 	} else {
1952 		error = vn_refreshlabel(dvp, cred);
1953 		if (error)
1954 			return (error);
1955 
1956 		/*
1957 		 * Stick the label in the vnode.  Then try to write to
1958 		 * disk.  If we fail, return a failure to abort the
1959 		 * create operation.  Really, this failure shouldn't
1960 		 * happen except in fairly unusual circumstances (out
1961 		 * of disk, etc).
1962 		 */
1963 		mac_create_vnode(cred, dvp, tvp);
1964 
1965 		error = mac_stdcreatevnode_ea(tvp);
1966 		if (error)
1967 			return (error);
1968 
1969 		/*
1970 		 * XXX: Eventually this will go away and all policies will
1971 		 * directly manage their extended attributes.
1972 		 */
1973 		error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac);
1974 		if (error)
1975 			return (error);
1976 
1977 		error = vn_extattr_set(tvp, IO_NODELOCKED,
1978 		    FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1979 		    sizeof(extmac), (char *)&extmac, curthread);
1980 		if (error == 0)
1981 			tvp->v_vflag |= VV_CACHEDLABEL;
1982 		else {
1983 #if 0
1984 			/*
1985 			 * In theory, we could have fall-back behavior here.
1986 			 * It would probably be incorrect.
1987 			 */
1988 #endif
1989 			return (error);
1990 		}
1991 	}
1992 
1993 	return (0);
1994 }
1995 
1996 void
1997 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1998 {
1999 	int error;
2000 
2001 	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
2002 
2003 	error = vn_refreshlabel(vp, old);
2004 	if (error) {
2005 		printf("mac_execve_transition: vn_refreshlabel returned %d\n",
2006 		    error);
2007 		printf("mac_execve_transition: using old vnode label\n");
2008 	}
2009 
2010 	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
2011 }
2012 
2013 int
2014 mac_execve_will_transition(struct ucred *old, struct vnode *vp)
2015 {
2016 	int error, result;
2017 
2018 	error = vn_refreshlabel(vp, old);
2019 	if (error)
2020 		return (error);
2021 
2022 	result = 0;
2023 	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
2024 
2025 	return (result);
2026 }
2027 
2028 int
2029 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
2030 {
2031 	int error;
2032 
2033 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
2034 
2035 	if (!mac_enforce_fs)
2036 		return (0);
2037 
2038 	error = vn_refreshlabel(vp, cred);
2039 	if (error)
2040 		return (error);
2041 
2042 	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
2043 	return (error);
2044 }
2045 
2046 int
2047 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
2048 {
2049 	int error;
2050 
2051 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
2052 
2053 	if (!mac_enforce_fs)
2054 		return (0);
2055 
2056 	error = vn_refreshlabel(dvp, cred);
2057 	if (error)
2058 		return (error);
2059 
2060 	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
2061 	return (error);
2062 }
2063 
2064 int
2065 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
2066 {
2067 	int error;
2068 
2069 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
2070 
2071 	if (!mac_enforce_fs)
2072 		return (0);
2073 
2074 	error = vn_refreshlabel(dvp, cred);
2075 	if (error)
2076 		return (error);
2077 
2078 	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
2079 	return (error);
2080 }
2081 
2082 int
2083 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2084     struct componentname *cnp, struct vattr *vap)
2085 {
2086 	int error;
2087 
2088 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
2089 
2090 	if (!mac_enforce_fs)
2091 		return (0);
2092 
2093 	error = vn_refreshlabel(dvp, cred);
2094 	if (error)
2095 		return (error);
2096 
2097 	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
2098 	return (error);
2099 }
2100 
2101 int
2102 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
2103     struct componentname *cnp)
2104 {
2105 	int error;
2106 
2107 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
2108 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
2109 
2110 	if (!mac_enforce_fs)
2111 		return (0);
2112 
2113 	error = vn_refreshlabel(dvp, cred);
2114 	if (error)
2115 		return (error);
2116 	error = vn_refreshlabel(vp, cred);
2117 	if (error)
2118 		return (error);
2119 
2120 	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
2121 	    &vp->v_label, cnp);
2122 	return (error);
2123 }
2124 
2125 int
2126 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2127     acl_type_t type)
2128 {
2129 	int error;
2130 
2131 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
2132 
2133 	if (!mac_enforce_fs)
2134 		return (0);
2135 
2136 	error = vn_refreshlabel(vp, cred);
2137 	if (error)
2138 		return (error);
2139 
2140 	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
2141 	return (error);
2142 }
2143 
2144 int
2145 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
2146 {
2147 	int error;
2148 
2149 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
2150 
2151 	if (!mac_enforce_process && !mac_enforce_fs)
2152 		return (0);
2153 
2154 	error = vn_refreshlabel(vp, cred);
2155 	if (error)
2156 		return (error);
2157 	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
2158 
2159 	return (error);
2160 }
2161 
2162 int
2163 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
2164 {
2165 	int error;
2166 
2167 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
2168 
2169 	if (!mac_enforce_fs)
2170 		return (0);
2171 
2172 	error = vn_refreshlabel(vp, cred);
2173 	if (error)
2174 		return (error);
2175 
2176 	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
2177 	return (error);
2178 }
2179 
2180 int
2181 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2182     int attrnamespace, const char *name, struct uio *uio)
2183 {
2184 	int error;
2185 
2186 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
2187 
2188 	if (!mac_enforce_fs)
2189 		return (0);
2190 
2191 	error = vn_refreshlabel(vp, cred);
2192 	if (error)
2193 		return (error);
2194 
2195 	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
2196 	    attrnamespace, name, uio);
2197 	return (error);
2198 }
2199 
2200 int
2201 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2202     struct vnode *vp, struct componentname *cnp)
2203 {
2204 	int error;
2205 
2206 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
2207 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
2208 
2209 	if (!mac_enforce_fs)
2210 		return (0);
2211 
2212 	error = vn_refreshlabel(dvp, cred);
2213 	if (error)
2214 		return (error);
2215 
2216 	error = vn_refreshlabel(vp, cred);
2217 	if (error)
2218 		return (error);
2219 
2220 	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
2221 	    &vp->v_label, cnp);
2222 	return (error);
2223 }
2224 
2225 int
2226 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2227     struct componentname *cnp)
2228 {
2229 	int error;
2230 
2231 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
2232 
2233 	if (!mac_enforce_fs)
2234 		return (0);
2235 
2236 	error = vn_refreshlabel(dvp, cred);
2237 	if (error)
2238 		return (error);
2239 
2240 	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
2241 	return (error);
2242 }
2243 
2244 int
2245 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
2246 {
2247 	int error;
2248 
2249 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
2250 
2251 	if (!mac_enforce_fs || !mac_enforce_vm)
2252 		return (0);
2253 
2254 	error = vn_refreshlabel(vp, cred);
2255 	if (error)
2256 		return (error);
2257 
2258 	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
2259 	return (error);
2260 }
2261 
2262 void
2263 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
2264 {
2265 	int result = *prot;
2266 
2267 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
2268 
2269 	if (!mac_enforce_fs || !mac_enforce_vm)
2270 		return;
2271 
2272 	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
2273 	    &result);
2274 
2275 	*prot = result;
2276 }
2277 
2278 int
2279 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
2280 {
2281 	int error;
2282 
2283 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
2284 
2285 	if (!mac_enforce_fs || !mac_enforce_vm)
2286 		return (0);
2287 
2288 	error = vn_refreshlabel(vp, cred);
2289 	if (error)
2290 		return (error);
2291 
2292 	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
2293 	return (error);
2294 }
2295 
2296 int
2297 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
2298 {
2299 	int error;
2300 
2301 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
2302 
2303 	if (!mac_enforce_fs)
2304 		return (0);
2305 
2306 	error = vn_refreshlabel(vp, cred);
2307 	if (error)
2308 		return (error);
2309 
2310 	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
2311 	return (error);
2312 }
2313 
2314 int
2315 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2316     struct vnode *vp)
2317 {
2318 	int error;
2319 
2320 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
2321 
2322 	if (!mac_enforce_fs)
2323 		return (0);
2324 
2325 	error = vn_refreshlabel(vp, active_cred);
2326 	if (error)
2327 		return (error);
2328 
2329 	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
2330 	    &vp->v_label);
2331 
2332 	return (error);
2333 }
2334 
2335 int
2336 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2337     struct vnode *vp)
2338 {
2339 	int error;
2340 
2341 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
2342 
2343 	if (!mac_enforce_fs)
2344 		return (0);
2345 
2346 	error = vn_refreshlabel(vp, active_cred);
2347 	if (error)
2348 		return (error);
2349 
2350 	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
2351 	    &vp->v_label);
2352 
2353 	return (error);
2354 }
2355 
2356 int
2357 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
2358 {
2359 	int error;
2360 
2361 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
2362 
2363 	if (!mac_enforce_fs)
2364 		return (0);
2365 
2366 	error = vn_refreshlabel(dvp, cred);
2367 	if (error)
2368 		return (error);
2369 
2370 	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
2371 	return (error);
2372 }
2373 
2374 int
2375 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
2376 {
2377 	int error;
2378 
2379 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
2380 
2381 	if (!mac_enforce_fs)
2382 		return (0);
2383 
2384 	error = vn_refreshlabel(vp, cred);
2385 	if (error)
2386 		return (error);
2387 
2388 	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
2389 	return (error);
2390 }
2391 
2392 static int
2393 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2394     struct label *newlabel)
2395 {
2396 	int error;
2397 
2398 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
2399 
2400 	error = vn_refreshlabel(vp, cred);
2401 	if (error)
2402 		return (error);
2403 
2404 	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
2405 
2406 	return (error);
2407 }
2408 
2409 int
2410 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2411     struct vnode *vp, struct componentname *cnp)
2412 {
2413 	int error;
2414 
2415 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
2416 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
2417 
2418 	if (!mac_enforce_fs)
2419 		return (0);
2420 
2421 	error = vn_refreshlabel(dvp, cred);
2422 	if (error)
2423 		return (error);
2424 	error = vn_refreshlabel(vp, cred);
2425 	if (error)
2426 		return (error);
2427 
2428 	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
2429 	    &vp->v_label, cnp);
2430 	return (error);
2431 }
2432 
2433 int
2434 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2435     struct vnode *vp, int samedir, struct componentname *cnp)
2436 {
2437 	int error;
2438 
2439 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
2440 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
2441 
2442 	if (!mac_enforce_fs)
2443 		return (0);
2444 
2445 	error = vn_refreshlabel(dvp, cred);
2446 	if (error)
2447 		return (error);
2448 	if (vp != NULL) {
2449 		error = vn_refreshlabel(vp, cred);
2450 		if (error)
2451 			return (error);
2452 	}
2453 	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
2454 	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
2455 	return (error);
2456 }
2457 
2458 int
2459 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
2460 {
2461 	int error;
2462 
2463 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
2464 
2465 	if (!mac_enforce_fs)
2466 		return (0);
2467 
2468 	error = vn_refreshlabel(vp, cred);
2469 	if (error)
2470 		return (error);
2471 
2472 	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
2473 	return (error);
2474 }
2475 
2476 int
2477 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
2478     struct acl *acl)
2479 {
2480 	int error;
2481 
2482 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2483 
2484 	if (!mac_enforce_fs)
2485 		return (0);
2486 
2487 	error = vn_refreshlabel(vp, cred);
2488 	if (error)
2489 		return (error);
2490 
2491 	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2492 	return (error);
2493 }
2494 
2495 int
2496 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2497     int attrnamespace, const char *name, struct uio *uio)
2498 {
2499 	int error;
2500 
2501 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2502 
2503 	if (!mac_enforce_fs)
2504 		return (0);
2505 
2506 	error = vn_refreshlabel(vp, cred);
2507 	if (error)
2508 		return (error);
2509 
2510 	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2511 	    attrnamespace, name, uio);
2512 	return (error);
2513 }
2514 
2515 int
2516 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2517 {
2518 	int error;
2519 
2520 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2521 
2522 	if (!mac_enforce_fs)
2523 		return (0);
2524 
2525 	error = vn_refreshlabel(vp, cred);
2526 	if (error)
2527 		return (error);
2528 
2529 	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2530 	return (error);
2531 }
2532 
2533 int
2534 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2535 {
2536 	int error;
2537 
2538 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2539 
2540 	if (!mac_enforce_fs)
2541 		return (0);
2542 
2543 	error = vn_refreshlabel(vp, cred);
2544 	if (error)
2545 		return (error);
2546 
2547 	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2548 	return (error);
2549 }
2550 
2551 int
2552 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2553     gid_t gid)
2554 {
2555 	int error;
2556 
2557 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2558 
2559 	if (!mac_enforce_fs)
2560 		return (0);
2561 
2562 	error = vn_refreshlabel(vp, cred);
2563 	if (error)
2564 		return (error);
2565 
2566 	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2567 	return (error);
2568 }
2569 
2570 int
2571 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2572     struct timespec atime, struct timespec mtime)
2573 {
2574 	int error;
2575 
2576 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2577 
2578 	if (!mac_enforce_fs)
2579 		return (0);
2580 
2581 	error = vn_refreshlabel(vp, cred);
2582 	if (error)
2583 		return (error);
2584 
2585 	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2586 	    mtime);
2587 	return (error);
2588 }
2589 
2590 int
2591 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2592     struct vnode *vp)
2593 {
2594 	int error;
2595 
2596 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2597 
2598 	if (!mac_enforce_fs)
2599 		return (0);
2600 
2601 	error = vn_refreshlabel(vp, active_cred);
2602 	if (error)
2603 		return (error);
2604 
2605 	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2606 	    &vp->v_label);
2607 	return (error);
2608 }
2609 
2610 int
2611 mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp)
2612 {
2613 	int error;
2614 
2615 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_swapon");
2616 
2617 	if (!mac_enforce_fs)
2618 		return (0);
2619 
2620 	error = vn_refreshlabel(vp, cred);
2621 	if (error)
2622 		return (error);
2623 
2624 	MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label);
2625 	return (error);
2626 }
2627 
2628 int
2629 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2630     struct vnode *vp)
2631 {
2632 	int error;
2633 
2634 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2635 
2636 	if (!mac_enforce_fs)
2637 		return (0);
2638 
2639 	error = vn_refreshlabel(vp, active_cred);
2640 	if (error)
2641 		return (error);
2642 
2643 	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2644 	    &vp->v_label);
2645 
2646 	return (error);
2647 }
2648 
2649 /*
2650  * When relabeling a process, call out to the policies for the maximum
2651  * permission allowed for each object type we know about in its
2652  * memory space, and revoke access (in the least surprising ways we
2653  * know) when necessary.  The process lock is not held here.
2654  */
2655 static void
2656 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2657 {
2658 
2659 	/* XXX freeze all other threads */
2660 	mac_cred_mmapped_drop_perms_recurse(td, cred,
2661 	    &td->td_proc->p_vmspace->vm_map);
2662 	/* XXX allow other threads to continue */
2663 }
2664 
2665 static __inline const char *
2666 prot2str(vm_prot_t prot)
2667 {
2668 
2669 	switch (prot & VM_PROT_ALL) {
2670 	case VM_PROT_READ:
2671 		return ("r--");
2672 	case VM_PROT_READ | VM_PROT_WRITE:
2673 		return ("rw-");
2674 	case VM_PROT_READ | VM_PROT_EXECUTE:
2675 		return ("r-x");
2676 	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2677 		return ("rwx");
2678 	case VM_PROT_WRITE:
2679 		return ("-w-");
2680 	case VM_PROT_EXECUTE:
2681 		return ("--x");
2682 	case VM_PROT_WRITE | VM_PROT_EXECUTE:
2683 		return ("-wx");
2684 	default:
2685 		return ("---");
2686 	}
2687 }
2688 
2689 static void
2690 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2691     struct vm_map *map)
2692 {
2693 	struct vm_map_entry *vme;
2694 	int result;
2695 	vm_prot_t revokeperms;
2696 	vm_object_t object;
2697 	vm_ooffset_t offset;
2698 	struct vnode *vp;
2699 
2700 	if (!mac_mmap_revocation)
2701 		return;
2702 
2703 	vm_map_lock_read(map);
2704 	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2705 		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2706 			mac_cred_mmapped_drop_perms_recurse(td, cred,
2707 			    vme->object.sub_map);
2708 			continue;
2709 		}
2710 		/*
2711 		 * Skip over entries that obviously are not shared.
2712 		 */
2713 		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2714 		    !vme->max_protection)
2715 			continue;
2716 		/*
2717 		 * Drill down to the deepest backing object.
2718 		 */
2719 		offset = vme->offset;
2720 		object = vme->object.vm_object;
2721 		if (object == NULL)
2722 			continue;
2723 		while (object->backing_object != NULL) {
2724 			object = object->backing_object;
2725 			offset += object->backing_object_offset;
2726 		}
2727 		/*
2728 		 * At the moment, vm_maps and objects aren't considered
2729 		 * by the MAC system, so only things with backing by a
2730 		 * normal object (read: vnodes) are checked.
2731 		 */
2732 		if (object->type != OBJT_VNODE)
2733 			continue;
2734 		vp = (struct vnode *)object->handle;
2735 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2736 		result = vme->max_protection;
2737 		mac_check_vnode_mmap_downgrade(cred, vp, &result);
2738 		VOP_UNLOCK(vp, 0, td);
2739 		/*
2740 		 * Find out what maximum protection we may be allowing
2741 		 * now but a policy needs to get removed.
2742 		 */
2743 		revokeperms = vme->max_protection & ~result;
2744 		if (!revokeperms)
2745 			continue;
2746 		printf("pid %ld: revoking %s perms from %#lx:%ld "
2747 		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2748 		    prot2str(revokeperms), (u_long)vme->start,
2749 		    (long)(vme->end - vme->start),
2750 		    prot2str(vme->max_protection), prot2str(vme->protection));
2751 		vm_map_lock_upgrade(map);
2752 		/*
2753 		 * This is the really simple case: if a map has more
2754 		 * max_protection than is allowed, but it's not being
2755 		 * actually used (that is, the current protection is
2756 		 * still allowed), we can just wipe it out and do
2757 		 * nothing more.
2758 		 */
2759 		if ((vme->protection & revokeperms) == 0) {
2760 			vme->max_protection -= revokeperms;
2761 		} else {
2762 			if (revokeperms & VM_PROT_WRITE) {
2763 				/*
2764 				 * In the more complicated case, flush out all
2765 				 * pending changes to the object then turn it
2766 				 * copy-on-write.
2767 				 */
2768 				vm_object_reference(object);
2769 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2770 				vm_object_page_clean(object,
2771 				    OFF_TO_IDX(offset),
2772 				    OFF_TO_IDX(offset + vme->end - vme->start +
2773 					PAGE_MASK),
2774 				    OBJPC_SYNC);
2775 				VOP_UNLOCK(vp, 0, td);
2776 				vm_object_deallocate(object);
2777 				/*
2778 				 * Why bother if there's no read permissions
2779 				 * anymore?  For the rest, we need to leave
2780 				 * the write permissions on for COW, or
2781 				 * remove them entirely if configured to.
2782 				 */
2783 				if (!mac_mmap_revocation_via_cow) {
2784 					vme->max_protection &= ~VM_PROT_WRITE;
2785 					vme->protection &= ~VM_PROT_WRITE;
2786 				} if ((revokeperms & VM_PROT_READ) == 0)
2787 					vme->eflags |= MAP_ENTRY_COW |
2788 					    MAP_ENTRY_NEEDS_COPY;
2789 			}
2790 			if (revokeperms & VM_PROT_EXECUTE) {
2791 				vme->max_protection &= ~VM_PROT_EXECUTE;
2792 				vme->protection &= ~VM_PROT_EXECUTE;
2793 			}
2794 			if (revokeperms & VM_PROT_READ) {
2795 				vme->max_protection = 0;
2796 				vme->protection = 0;
2797 			}
2798 			pmap_protect(map->pmap, vme->start, vme->end,
2799 			    vme->protection & ~revokeperms);
2800 			vm_map_simplify_entry(map, vme);
2801 		}
2802 		vm_map_lock_downgrade(map);
2803 	}
2804 	vm_map_unlock_read(map);
2805 }
2806 
2807 /*
2808  * When the subject's label changes, it may require revocation of privilege
2809  * to mapped objects.  This can't be done on-the-fly later with a unified
2810  * buffer cache.
2811  */
2812 static void
2813 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2814 {
2815 
2816 	MAC_PERFORM(relabel_cred, cred, newlabel);
2817 }
2818 
2819 void
2820 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2821 {
2822 
2823 	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2824 }
2825 
2826 void
2827 mac_create_ifnet(struct ifnet *ifnet)
2828 {
2829 
2830 	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2831 }
2832 
2833 void
2834 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2835 {
2836 
2837 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2838 }
2839 
2840 void
2841 mac_create_socket(struct ucred *cred, struct socket *socket)
2842 {
2843 
2844 	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2845 }
2846 
2847 void
2848 mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2849 {
2850 
2851 	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2852 }
2853 
2854 void
2855 mac_create_socket_from_socket(struct socket *oldsocket,
2856     struct socket *newsocket)
2857 {
2858 
2859 	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2860 	    newsocket, &newsocket->so_label);
2861 }
2862 
2863 static void
2864 mac_relabel_socket(struct ucred *cred, struct socket *socket,
2865     struct label *newlabel)
2866 {
2867 
2868 	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2869 }
2870 
2871 static void
2872 mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2873 {
2874 
2875 	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2876 }
2877 
2878 void
2879 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2880 {
2881 
2882 	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2883 	    socket, &socket->so_peerlabel);
2884 }
2885 
2886 void
2887 mac_set_socket_peer_from_socket(struct socket *oldsocket,
2888     struct socket *newsocket)
2889 {
2890 
2891 	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2892 	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2893 }
2894 
2895 void
2896 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2897 {
2898 
2899 	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2900 	    datagram, &datagram->m_pkthdr.label);
2901 }
2902 
2903 void
2904 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2905 {
2906 
2907 	MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2908 	    fragment, &fragment->m_pkthdr.label);
2909 }
2910 
2911 void
2912 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2913 {
2914 
2915 	MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2916 	    &ipq->ipq_label);
2917 }
2918 
2919 void
2920 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2921 {
2922 
2923 	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2924 	    newmbuf, &newmbuf->m_pkthdr.label);
2925 }
2926 
2927 void
2928 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2929 {
2930 
2931 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2932 	    &mbuf->m_pkthdr.label);
2933 }
2934 
2935 void
2936 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2937 {
2938 
2939 	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2940 	    &mbuf->m_pkthdr.label);
2941 }
2942 
2943 void
2944 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2945 {
2946 
2947 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2948 	    &mbuf->m_pkthdr.label);
2949 }
2950 
2951 void
2952 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2953     struct mbuf *newmbuf)
2954 {
2955 
2956 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2957 	    &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2958 	    &newmbuf->m_pkthdr.label);
2959 }
2960 
2961 void
2962 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2963 {
2964 
2965 	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2966 	    newmbuf, &newmbuf->m_pkthdr.label);
2967 }
2968 
2969 int
2970 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2971 {
2972 	int result;
2973 
2974 	result = 1;
2975 	MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2976 	    ipq, &ipq->ipq_label);
2977 
2978 	return (result);
2979 }
2980 
2981 void
2982 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2983 {
2984 
2985 	MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2986 	    &ipq->ipq_label);
2987 }
2988 
2989 void
2990 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2991 {
2992 
2993 	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2994 	    &mbuf->m_pkthdr.label);
2995 }
2996 
2997 void
2998 mac_create_mount(struct ucred *cred, struct mount *mp)
2999 {
3000 
3001 	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
3002 	    &mp->mnt_fslabel);
3003 }
3004 
3005 void
3006 mac_create_root_mount(struct ucred *cred, struct mount *mp)
3007 {
3008 
3009 	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
3010 	    &mp->mnt_fslabel);
3011 }
3012 
3013 int
3014 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
3015 {
3016 	int error;
3017 
3018 	if (!mac_enforce_network)
3019 		return (0);
3020 
3021 	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
3022 	    &ifnet->if_label);
3023 
3024 	return (error);
3025 }
3026 
3027 static int
3028 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
3029 {
3030 	int error;
3031 
3032 	MAC_CHECK(check_cred_relabel, cred, newlabel);
3033 
3034 	return (error);
3035 }
3036 
3037 int
3038 mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
3039 {
3040 	int error;
3041 
3042 	if (!mac_enforce_process)
3043 		return (0);
3044 
3045 	MAC_CHECK(check_cred_visible, u1, u2);
3046 
3047 	return (error);
3048 }
3049 
3050 int
3051 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
3052 {
3053 	int error;
3054 
3055 	if (!mac_enforce_network)
3056 		return (0);
3057 
3058 	KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
3059 	if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
3060 		if_printf(ifnet, "not initialized\n");
3061 
3062 	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
3063 	    &mbuf->m_pkthdr.label);
3064 
3065 	return (error);
3066 }
3067 
3068 int
3069 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
3070 {
3071 	int error;
3072 
3073 	if (!mac_enforce_fs)
3074 		return (0);
3075 
3076 	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
3077 
3078 	return (error);
3079 }
3080 
3081 int
3082 mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
3083     void *data)
3084 {
3085 	int error;
3086 
3087 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3088 
3089 	if (!mac_enforce_pipe)
3090 		return (0);
3091 
3092 	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
3093 
3094 	return (error);
3095 }
3096 
3097 int
3098 mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
3099 {
3100 	int error;
3101 
3102 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3103 
3104 	if (!mac_enforce_pipe)
3105 		return (0);
3106 
3107 	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
3108 
3109 	return (error);
3110 }
3111 
3112 int
3113 mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
3114 {
3115 	int error;
3116 
3117 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3118 
3119 	if (!mac_enforce_pipe)
3120 		return (0);
3121 
3122 	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
3123 
3124 	return (error);
3125 }
3126 
3127 static int
3128 mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
3129     struct label *newlabel)
3130 {
3131 	int error;
3132 
3133 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3134 
3135 	if (!mac_enforce_pipe)
3136 		return (0);
3137 
3138 	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
3139 
3140 	return (error);
3141 }
3142 
3143 int
3144 mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
3145 {
3146 	int error;
3147 
3148 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3149 
3150 	if (!mac_enforce_pipe)
3151 		return (0);
3152 
3153 	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
3154 
3155 	return (error);
3156 }
3157 
3158 int
3159 mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
3160 {
3161 	int error;
3162 
3163 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3164 
3165 	if (!mac_enforce_pipe)
3166 		return (0);
3167 
3168 	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
3169 
3170 	return (error);
3171 }
3172 
3173 int
3174 mac_check_proc_debug(struct ucred *cred, struct proc *proc)
3175 {
3176 	int error;
3177 
3178 	PROC_LOCK_ASSERT(proc, MA_OWNED);
3179 
3180 	if (!mac_enforce_process)
3181 		return (0);
3182 
3183 	MAC_CHECK(check_proc_debug, cred, proc);
3184 
3185 	return (error);
3186 }
3187 
3188 int
3189 mac_check_proc_sched(struct ucred *cred, struct proc *proc)
3190 {
3191 	int error;
3192 
3193 	PROC_LOCK_ASSERT(proc, MA_OWNED);
3194 
3195 	if (!mac_enforce_process)
3196 		return (0);
3197 
3198 	MAC_CHECK(check_proc_sched, cred, proc);
3199 
3200 	return (error);
3201 }
3202 
3203 int
3204 mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
3205 {
3206 	int error;
3207 
3208 	PROC_LOCK_ASSERT(proc, MA_OWNED);
3209 
3210 	if (!mac_enforce_process)
3211 		return (0);
3212 
3213 	MAC_CHECK(check_proc_signal, cred, proc, signum);
3214 
3215 	return (error);
3216 }
3217 
3218 int
3219 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
3220     struct sockaddr *sockaddr)
3221 {
3222 	int error;
3223 
3224 	if (!mac_enforce_socket)
3225 		return (0);
3226 
3227 	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
3228 	    sockaddr);
3229 
3230 	return (error);
3231 }
3232 
3233 int
3234 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
3235     struct sockaddr *sockaddr)
3236 {
3237 	int error;
3238 
3239 	if (!mac_enforce_socket)
3240 		return (0);
3241 
3242 	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
3243 	    sockaddr);
3244 
3245 	return (error);
3246 }
3247 
3248 int
3249 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
3250 {
3251 	int error;
3252 
3253 	if (!mac_enforce_socket)
3254 		return (0);
3255 
3256 	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
3257 	    &mbuf->m_pkthdr.label);
3258 
3259 	return (error);
3260 }
3261 
3262 int
3263 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
3264 {
3265 	int error;
3266 
3267 	if (!mac_enforce_socket)
3268 		return (0);
3269 
3270 	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
3271 	return (error);
3272 }
3273 
3274 int
3275 mac_check_socket_receive(struct ucred *cred, struct socket *so)
3276 {
3277 	int error;
3278 
3279 	if (!mac_enforce_socket)
3280 		return (0);
3281 
3282 	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
3283 
3284 	return (error);
3285 }
3286 
3287 static int
3288 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
3289     struct label *newlabel)
3290 {
3291 	int error;
3292 
3293 	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
3294 	    newlabel);
3295 
3296 	return (error);
3297 }
3298 
3299 int
3300 mac_check_socket_send(struct ucred *cred, struct socket *so)
3301 {
3302 	int error;
3303 
3304 	if (!mac_enforce_socket)
3305 		return (0);
3306 
3307 	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
3308 
3309 	return (error);
3310 }
3311 
3312 int
3313 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
3314 {
3315 	int error;
3316 
3317 	if (!mac_enforce_socket)
3318 		return (0);
3319 
3320 	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
3321 
3322 	return (error);
3323 }
3324 
3325 int
3326 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
3327     struct ifnet *ifnet)
3328 {
3329 	char *elements, *buffer;
3330 	struct mac mac;
3331 	int error;
3332 
3333 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3334 	if (error)
3335 		return (error);
3336 
3337 	error = mac_check_structmac_consistent(&mac);
3338 	if (error)
3339 		return (error);
3340 
3341 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3342 
3343 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3344 	if (error) {
3345 		free(elements, M_MACTEMP);
3346 		return (error);
3347 	}
3348 
3349 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3350 
3351 	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3352 	    buffer, mac.m_buflen, M_WAITOK);
3353 	if (error == 0)
3354 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3355 
3356 	free(buffer, M_MACTEMP);
3357 	free(elements, M_MACTEMP);
3358 
3359 	return (error);
3360 }
3361 
3362 int
3363 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3364     struct ifnet *ifnet)
3365 {
3366 	struct label intlabel;
3367 	struct mac mac;
3368 	char *buffer;
3369 	int error;
3370 
3371 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3372 	if (error)
3373 		return (error);
3374 
3375 	error = mac_check_structmac_consistent(&mac);
3376 	if (error)
3377 		return (error);
3378 
3379 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3380 
3381 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3382 	if (error) {
3383 		free(buffer, M_MACTEMP);
3384 		return (error);
3385 	}
3386 
3387 	mac_init_ifnet_label(&intlabel);
3388 	error = mac_internalize_ifnet_label(&intlabel, buffer);
3389 	free(buffer, M_MACTEMP);
3390 	if (error) {
3391 		mac_destroy_ifnet_label(&intlabel);
3392 		return (error);
3393 	}
3394 
3395 	/*
3396 	 * XXX: Note that this is a redundant privilege check, since
3397 	 * policies impose this check themselves if required by the
3398 	 * policy.  Eventually, this should go away.
3399 	 */
3400 	error = suser_cred(cred, 0);
3401 	if (error) {
3402 		mac_destroy_ifnet_label(&intlabel);
3403 		return (error);
3404 	}
3405 
3406 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3407 	    &intlabel);
3408 	if (error) {
3409 		mac_destroy_ifnet_label(&intlabel);
3410 		return (error);
3411 	}
3412 
3413 	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3414 
3415 	mac_destroy_ifnet_label(&intlabel);
3416 	return (0);
3417 }
3418 
3419 void
3420 mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
3421 {
3422 
3423 	MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
3424 }
3425 
3426 void
3427 mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
3428 {
3429 
3430 	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
3431 }
3432 
3433 void
3434 mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
3435     struct devfs_dirent *de)
3436 {
3437 
3438 	MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
3439 	    &de->de_label);
3440 }
3441 
3442 static int
3443 mac_stdcreatevnode_ea(struct vnode *vp)
3444 {
3445 	int error;
3446 
3447 	MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
3448 
3449 	return (error);
3450 }
3451 
3452 void
3453 mac_create_devfs_directory(char *dirname, int dirnamelen,
3454     struct devfs_dirent *de)
3455 {
3456 
3457 	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
3458 	    &de->de_label);
3459 }
3460 
3461 /*
3462  * When a new vnode is created, this call will initialize its label.
3463  */
3464 void
3465 mac_create_vnode(struct ucred *cred, struct vnode *parent,
3466     struct vnode *child)
3467 {
3468 	int error;
3469 
3470 	ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
3471 	ASSERT_VOP_LOCKED(child, "mac_create_vnode");
3472 
3473 	error = vn_refreshlabel(parent, cred);
3474 	if (error) {
3475 		printf("mac_create_vnode: vn_refreshlabel returned %d\n",
3476 		    error);
3477 		printf("mac_create_vnode: using old vnode label\n");
3478 	}
3479 
3480 	MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
3481 	    &child->v_label);
3482 }
3483 
3484 int
3485 mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3486     struct mac *mac)
3487 {
3488 	struct label intlabel;
3489 	char *buffer;
3490 	int error;
3491 
3492 	error = mac_check_structmac_consistent(mac);
3493 	if (error)
3494 		return (error);
3495 
3496 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3497 
3498 	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3499 	if (error) {
3500 		free(buffer, M_MACTEMP);
3501 		return (error);
3502 	}
3503 
3504 	mac_init_socket_label(&intlabel, M_WAITOK);
3505 	error = mac_internalize_socket_label(&intlabel, buffer);
3506 	free(buffer, M_MACTEMP);
3507 	if (error) {
3508 		mac_destroy_socket_label(&intlabel);
3509 		return (error);
3510 	}
3511 
3512 	mac_check_socket_relabel(cred, so, &intlabel);
3513 	if (error) {
3514 		mac_destroy_socket_label(&intlabel);
3515 		return (error);
3516 	}
3517 
3518 	mac_relabel_socket(cred, so, &intlabel);
3519 
3520 	mac_destroy_socket_label(&intlabel);
3521 	return (0);
3522 }
3523 
3524 int
3525 mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3526 {
3527 	int error;
3528 
3529 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3530 
3531 	error = mac_check_pipe_relabel(cred, pipe, label);
3532 	if (error)
3533 		return (error);
3534 
3535 	mac_relabel_pipe(cred, pipe, label);
3536 
3537 	return (0);
3538 }
3539 
3540 int
3541 mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3542     struct mac *mac)
3543 {
3544 	char *buffer, *elements;
3545 	int error;
3546 
3547 	error = mac_check_structmac_consistent(mac);
3548 	if (error)
3549 		return (error);
3550 
3551 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3552 
3553 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3554 	if (error) {
3555 		free(elements, M_MACTEMP);
3556 		return (error);
3557 	}
3558 
3559 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3560 
3561 	error = mac_externalize_socket_label(&so->so_label, elements,
3562 	    buffer, mac->m_buflen, M_WAITOK);
3563 	if (error == 0)
3564 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3565 
3566 	free(buffer, M_MACTEMP);
3567 	free(elements, M_MACTEMP);
3568 
3569 	return (error);
3570 }
3571 
3572 int
3573 mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3574     struct mac *mac)
3575 {
3576 	char *elements, *buffer;
3577 	int error;
3578 
3579 	error = mac_check_structmac_consistent(mac);
3580 	if (error)
3581 		return (error);
3582 
3583 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3584 
3585 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3586 	if (error) {
3587 		free(elements, M_MACTEMP);
3588 		return (error);
3589 	}
3590 
3591 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3592 
3593 	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3594 	    elements, buffer, mac->m_buflen, M_WAITOK);
3595 	if (error == 0)
3596 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3597 
3598 	free(buffer, M_MACTEMP);
3599 	free(elements, M_MACTEMP);
3600 
3601 	return (error);
3602 }
3603 
3604 /*
3605  * Implementation of VOP_SETLABEL() that relies on extended attributes
3606  * to store label data.  Can be referenced by filesystems supporting
3607  * extended attributes.
3608  */
3609 int
3610 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3611 {
3612 	struct vnode *vp = ap->a_vp;
3613 	struct label *intlabel = ap->a_label;
3614 	struct oldmac extmac;
3615 	int error;
3616 
3617 	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3618 
3619 	/*
3620 	 * XXX: Eventually call out to EA check/set calls here.
3621 	 * Be particularly careful to avoid race conditions,
3622 	 * consistency problems, and stability problems when
3623 	 * dealing with multiple EAs.  In particular, we require
3624 	 * the ability to write multiple EAs on the same file in
3625 	 * a single transaction, which the current EA interface
3626 	 * does not provide.
3627 	 */
3628 
3629 	error = mac_externalize_vnode_oldmac(intlabel, &extmac);
3630 	if (error)
3631 		return (error);
3632 
3633 	error = vn_extattr_set(vp, IO_NODELOCKED,
3634 	    FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
3635 	    sizeof(extmac), (char *)&extmac, curthread);
3636 	if (error)
3637 		return (error);
3638 
3639 	mac_relabel_vnode(ap->a_cred, vp, intlabel);
3640 
3641 	vp->v_vflag |= VV_CACHEDLABEL;
3642 
3643 	return (0);
3644 }
3645 
3646 static int
3647 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3648 {
3649 	int error;
3650 
3651 	if (vp->v_mount == NULL) {
3652 		/* printf("vn_setlabel: null v_mount\n"); */
3653 		if (vp->v_type != VNON)
3654 			printf("vn_setlabel: null v_mount with non-VNON\n");
3655 		return (EBADF);
3656 	}
3657 
3658 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3659 		return (EOPNOTSUPP);
3660 
3661 	/*
3662 	 * Multi-phase commit.  First check the policies to confirm the
3663 	 * change is OK.  Then commit via the filesystem.  Finally,
3664 	 * update the actual vnode label.  Question: maybe the filesystem
3665 	 * should update the vnode at the end as part of VOP_SETLABEL()?
3666 	 */
3667 	error = mac_check_vnode_relabel(cred, vp, intlabel);
3668 	if (error)
3669 		return (error);
3670 
3671 	/*
3672 	 * VADMIN provides the opportunity for the filesystem to make
3673 	 * decisions about who is and is not able to modify labels
3674 	 * and protections on files.  This might not be right.  We can't
3675 	 * assume VOP_SETLABEL() will do it, because we might implement
3676 	 * that as part of vop_stdsetlabel_ea().
3677 	 */
3678 	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3679 	if (error)
3680 		return (error);
3681 
3682 	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3683 	if (error)
3684 		return (error);
3685 
3686 	return (0);
3687 }
3688 
3689 int
3690 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3691 {
3692 	char *elements, *buffer;
3693 	struct mac mac;
3694 	struct proc *tproc;
3695 	struct ucred *tcred;
3696 	int error;
3697 
3698 	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3699 	if (error)
3700 		return (error);
3701 
3702 	error = mac_check_structmac_consistent(&mac);
3703 	if (error)
3704 		return (error);
3705 
3706 	tproc = pfind(uap->pid);
3707 	if (tproc == NULL)
3708 		return (ESRCH);
3709 
3710 	tcred = NULL;				/* Satisfy gcc. */
3711 	error = p_cansee(td, tproc);
3712 	if (error == 0)
3713 		tcred = crhold(tproc->p_ucred);
3714 	PROC_UNLOCK(tproc);
3715 	if (error)
3716 		return (error);
3717 
3718 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3719 
3720 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3721 	if (error) {
3722 		free(elements, M_MACTEMP);
3723 		crfree(tcred);
3724 		return (error);
3725 	}
3726 
3727 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3728 
3729 	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3730 	    buffer, mac.m_buflen, M_WAITOK);
3731 	if (error == 0)
3732 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3733 
3734 	free(buffer, M_MACTEMP);
3735 	free(elements, M_MACTEMP);
3736 	crfree(tcred);
3737 	return (error);
3738 }
3739 
3740 /*
3741  * MPSAFE
3742  */
3743 int
3744 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3745 {
3746 	char *elements, *buffer;
3747 	struct mac mac;
3748 	int error;
3749 
3750 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3751 	if (error)
3752 		return (error);
3753 
3754 	error = mac_check_structmac_consistent(&mac);
3755 	if (error)
3756 		return (error);
3757 
3758 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3759 
3760 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3761 	if (error) {
3762 		free(elements, M_MACTEMP);
3763 		return (error);
3764 	}
3765 
3766 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3767 
3768 	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3769 	    elements, buffer, mac.m_buflen, M_WAITOK);
3770 	if (error == 0)
3771 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3772 
3773 	free(buffer, M_MACTEMP);
3774 	free(elements, M_MACTEMP);
3775 	return (error);
3776 }
3777 
3778 /*
3779  * MPSAFE
3780  */
3781 int
3782 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3783 {
3784 	struct ucred *newcred, *oldcred;
3785 	struct label intlabel;
3786 	struct proc *p;
3787 	struct mac mac;
3788 	char *buffer;
3789 	int error;
3790 
3791 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3792 	if (error)
3793 		return (error);
3794 
3795 	error = mac_check_structmac_consistent(&mac);
3796 	if (error)
3797 		return (error);
3798 
3799 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3800 
3801 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3802 	if (error) {
3803 		free(buffer, M_MACTEMP);
3804 		return (error);
3805 	}
3806 
3807 	mac_init_cred_label(&intlabel);
3808 	error = mac_internalize_cred_label(&intlabel, buffer);
3809 	free(buffer, M_MACTEMP);
3810 	if (error) {
3811 		mac_destroy_cred_label(&intlabel);
3812 		return (error);
3813 	}
3814 
3815 	newcred = crget();
3816 
3817 	p = td->td_proc;
3818 	PROC_LOCK(p);
3819 	oldcred = p->p_ucred;
3820 
3821 	error = mac_check_cred_relabel(oldcred, &intlabel);
3822 	if (error) {
3823 		PROC_UNLOCK(p);
3824 		crfree(newcred);
3825 		goto out;
3826 	}
3827 
3828 	setsugid(p);
3829 	crcopy(newcred, oldcred);
3830 	mac_relabel_cred(newcred, &intlabel);
3831 	p->p_ucred = newcred;
3832 
3833 	/*
3834 	 * Grab additional reference for use while revoking mmaps, prior
3835 	 * to releasing the proc lock and sharing the cred.
3836 	 */
3837 	crhold(newcred);
3838 	PROC_UNLOCK(p);
3839 
3840 	if (mac_enforce_vm) {
3841 		mtx_lock(&Giant);
3842 		mac_cred_mmapped_drop_perms(td, newcred);
3843 		mtx_unlock(&Giant);
3844 	}
3845 
3846 	crfree(newcred);	/* Free revocation reference. */
3847 	crfree(oldcred);
3848 
3849 out:
3850 	mac_destroy_cred_label(&intlabel);
3851 	return (error);
3852 }
3853 
3854 /*
3855  * MPSAFE
3856  */
3857 int
3858 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3859 {
3860 	char *elements, *buffer;
3861 	struct label intlabel;
3862 	struct file *fp;
3863 	struct mac mac;
3864 	struct vnode *vp;
3865 	struct pipe *pipe;
3866 	short label_type;
3867 	int error;
3868 
3869 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3870 	if (error)
3871 		return (error);
3872 
3873 	error = mac_check_structmac_consistent(&mac);
3874 	if (error)
3875 		return (error);
3876 
3877 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3878 
3879 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3880 	if (error) {
3881 		free(elements, M_MACTEMP);
3882 		return (error);
3883 	}
3884 
3885 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3886 
3887 	mtx_lock(&Giant);				/* VFS */
3888 	error = fget(td, SCARG(uap, fd), &fp);
3889 	if (error)
3890 		goto out;
3891 
3892 	label_type = fp->f_type;
3893 	switch (fp->f_type) {
3894 	case DTYPE_FIFO:
3895 	case DTYPE_VNODE:
3896 		vp = (struct vnode *)fp->f_data;
3897 
3898 		mac_init_vnode_label(&intlabel);
3899 
3900 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3901 		error = vn_refreshlabel(vp, td->td_ucred);
3902 		if (error == 0)
3903 			mac_copy_vnode_label(&vp->v_label, &intlabel);
3904 		VOP_UNLOCK(vp, 0, td);
3905 
3906 		break;
3907 	case DTYPE_PIPE:
3908 		pipe = (struct pipe *)fp->f_data;
3909 
3910 		mac_init_pipe_label(&intlabel);
3911 
3912 		PIPE_LOCK(pipe);
3913 		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3914 		PIPE_UNLOCK(pipe);
3915 		break;
3916 	default:
3917 		error = EINVAL;
3918 		fdrop(fp, td);
3919 		goto out;
3920 	}
3921 	fdrop(fp, td);
3922 
3923 	switch (label_type) {
3924 	case DTYPE_FIFO:
3925 	case DTYPE_VNODE:
3926 		if (error == 0)
3927 			error = mac_externalize_vnode_label(&intlabel,
3928 			    elements, buffer, mac.m_buflen, M_WAITOK);
3929 		mac_destroy_vnode_label(&intlabel);
3930 		break;
3931 	case DTYPE_PIPE:
3932 		error = mac_externalize_pipe_label(&intlabel, elements,
3933 		    buffer, mac.m_buflen, M_WAITOK);
3934 		mac_destroy_pipe_label(&intlabel);
3935 		break;
3936 	default:
3937 		panic("__mac_get_fd: corrupted label_type");
3938 	}
3939 
3940 	if (error == 0)
3941 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3942 
3943 out:
3944 	mtx_unlock(&Giant);				/* VFS */
3945 	free(buffer, M_MACTEMP);
3946 	free(elements, M_MACTEMP);
3947 
3948 	return (error);
3949 }
3950 
3951 /*
3952  * MPSAFE
3953  */
3954 int
3955 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3956 {
3957 	char *elements, *buffer;
3958 	struct nameidata nd;
3959 	struct label intlabel;
3960 	struct mac mac;
3961 	int error;
3962 
3963 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3964 	if (error)
3965 		return (error);
3966 
3967 	error = mac_check_structmac_consistent(&mac);
3968 	if (error)
3969 		return (error);
3970 
3971 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3972 
3973 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3974 	if (error) {
3975 		free(elements, M_MACTEMP);
3976 		return (error);
3977 	}
3978 
3979 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3980 
3981 	mtx_lock(&Giant);				/* VFS */
3982 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3983 	    td);
3984 	error = namei(&nd);
3985 	if (error)
3986 		goto out;
3987 
3988 	mac_init_vnode_label(&intlabel);
3989 	error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
3990 	if (error == 0)
3991 		mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3992 	if (error == 0)
3993 		error = mac_externalize_vnode_label(&intlabel, elements,
3994 		    buffer, mac.m_buflen, M_WAITOK);
3995 
3996 	NDFREE(&nd, 0);
3997 	mac_destroy_vnode_label(&intlabel);
3998 
3999 	if (error == 0)
4000 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4001 
4002 out:
4003 	mtx_unlock(&Giant);				/* VFS */
4004 
4005 	free(buffer, M_MACTEMP);
4006 	free(elements, M_MACTEMP);
4007 
4008 	return (error);
4009 }
4010 
4011 /*
4012  * MPSAFE
4013  */
4014 int
4015 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4016 {
4017 	char *elements, *buffer;
4018 	struct nameidata nd;
4019 	struct label intlabel;
4020 	struct mac mac;
4021 	int error;
4022 
4023 	error = copyin(uap->mac_p, &mac, sizeof(mac));
4024 	if (error)
4025 		return (error);
4026 
4027 	error = mac_check_structmac_consistent(&mac);
4028 	if (error)
4029 		return (error);
4030 
4031 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4032 
4033 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
4034 	if (error) {
4035 		free(elements, M_MACTEMP);
4036 		return (error);
4037 	}
4038 
4039 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4040 
4041 	mtx_lock(&Giant);				/* VFS */
4042 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4043 	    td);
4044 	error = namei(&nd);
4045 	if (error)
4046 		goto out;
4047 
4048 	mac_init_vnode_label(&intlabel);
4049 	error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
4050 	if (error == 0)
4051 		mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
4052 	if (error == 0)
4053 		error = mac_externalize_vnode_label(&intlabel, elements,
4054 		    buffer, mac.m_buflen, M_WAITOK);
4055 	NDFREE(&nd, 0);
4056 	mac_destroy_vnode_label(&intlabel);
4057 
4058 	if (error == 0)
4059 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4060 
4061 out:
4062 	mtx_unlock(&Giant);				/* VFS */
4063 
4064 	free(buffer, M_MACTEMP);
4065 	free(elements, M_MACTEMP);
4066 
4067 	return (error);
4068 }
4069 
4070 /*
4071  * MPSAFE
4072  */
4073 int
4074 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4075 {
4076 	struct label intlabel;
4077 	struct pipe *pipe;
4078 	struct file *fp;
4079 	struct mount *mp;
4080 	struct vnode *vp;
4081 	struct mac mac;
4082 	char *buffer;
4083 	int error;
4084 
4085 	error = copyin(uap->mac_p, &mac, sizeof(mac));
4086 	if (error)
4087 		return (error);
4088 
4089 	error = mac_check_structmac_consistent(&mac);
4090 	if (error)
4091 		return (error);
4092 
4093 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4094 
4095 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4096 	if (error) {
4097 		free(buffer, M_MACTEMP);
4098 		return (error);
4099 	}
4100 
4101 	mtx_lock(&Giant);				/* VFS */
4102 
4103 	error = fget(td, SCARG(uap, fd), &fp);
4104 	if (error)
4105 		goto out;
4106 
4107 	switch (fp->f_type) {
4108 	case DTYPE_FIFO:
4109 	case DTYPE_VNODE:
4110 		mac_init_vnode_label(&intlabel);
4111 		error = mac_internalize_vnode_label(&intlabel, buffer);
4112 		if (error) {
4113 			mac_destroy_vnode_label(&intlabel);
4114 			break;
4115 		}
4116 
4117 		vp = (struct vnode *)fp->f_data;
4118 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4119 		if (error != 0) {
4120 			mac_destroy_vnode_label(&intlabel);
4121 			break;
4122 		}
4123 
4124 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4125 		error = vn_setlabel(vp, &intlabel, td->td_ucred);
4126 		VOP_UNLOCK(vp, 0, td);
4127 		vn_finished_write(mp);
4128 
4129 		mac_destroy_vnode_label(&intlabel);
4130 		break;
4131 
4132 	case DTYPE_PIPE:
4133 		mac_init_pipe_label(&intlabel);
4134 		error = mac_internalize_pipe_label(&intlabel, buffer);
4135 		if (error == 0) {
4136 			pipe = (struct pipe *)fp->f_data;
4137 			PIPE_LOCK(pipe);
4138 			error = mac_pipe_label_set(td->td_ucred, pipe,
4139 			    &intlabel);
4140 			PIPE_UNLOCK(pipe);
4141 		}
4142 
4143 		mac_destroy_pipe_label(&intlabel);
4144 		break;
4145 
4146 	default:
4147 		error = EINVAL;
4148 	}
4149 
4150 	fdrop(fp, td);
4151 out:
4152 	mtx_unlock(&Giant);				/* VFS */
4153 
4154 	free(buffer, M_MACTEMP);
4155 
4156 	return (error);
4157 }
4158 
4159 /*
4160  * MPSAFE
4161  */
4162 int
4163 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4164 {
4165 	struct label intlabel;
4166 	struct nameidata nd;
4167 	struct mount *mp;
4168 	struct mac mac;
4169 	char *buffer;
4170 	int error;
4171 
4172 	error = copyin(uap->mac_p, &mac, sizeof(mac));
4173 	if (error)
4174 		return (error);
4175 
4176 	error = mac_check_structmac_consistent(&mac);
4177 	if (error)
4178 		return (error);
4179 
4180 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4181 
4182 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4183 	if (error) {
4184 		free(buffer, M_MACTEMP);
4185 		return (error);
4186 	}
4187 
4188 	mac_init_vnode_label(&intlabel);
4189 	error = mac_internalize_vnode_label(&intlabel, buffer);
4190 	free(buffer, M_MACTEMP);
4191 	if (error) {
4192 		mac_destroy_vnode_label(&intlabel);
4193 		return (error);
4194 	}
4195 
4196 	mtx_lock(&Giant);				/* VFS */
4197 
4198 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
4199 	    td);
4200 	error = namei(&nd);
4201 	if (error == 0) {
4202 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4203 		if (error == 0)
4204 			error = vn_setlabel(nd.ni_vp, &intlabel,
4205 			    td->td_ucred);
4206 		vn_finished_write(mp);
4207 	}
4208 
4209 	NDFREE(&nd, 0);
4210 	mtx_unlock(&Giant);				/* VFS */
4211 	mac_destroy_vnode_label(&intlabel);
4212 
4213 	return (error);
4214 }
4215 
4216 /*
4217  * MPSAFE
4218  */
4219 int
4220 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4221 {
4222 	struct label intlabel;
4223 	struct nameidata nd;
4224 	struct mount *mp;
4225 	struct mac mac;
4226 	char *buffer;
4227 	int error;
4228 
4229 	error = copyin(uap->mac_p, &mac, sizeof(mac));
4230 	if (error)
4231 		return (error);
4232 
4233 	error = mac_check_structmac_consistent(&mac);
4234 	if (error)
4235 		return (error);
4236 
4237 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4238 
4239 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4240 	if (error) {
4241 		free(buffer, M_MACTEMP);
4242 		return (error);
4243 	}
4244 
4245 	mac_init_vnode_label(&intlabel);
4246 	error = mac_internalize_vnode_label(&intlabel, buffer);
4247 	free(buffer, M_MACTEMP);
4248 	if (error) {
4249 		mac_destroy_vnode_label(&intlabel);
4250 		return (error);
4251 	}
4252 
4253 	mtx_lock(&Giant);				/* VFS */
4254 
4255 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4256 	    td);
4257 	error = namei(&nd);
4258 	if (error == 0) {
4259 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4260 		if (error == 0)
4261 			error = vn_setlabel(nd.ni_vp, &intlabel,
4262 			    td->td_ucred);
4263 		vn_finished_write(mp);
4264 	}
4265 
4266 	NDFREE(&nd, 0);
4267 	mtx_unlock(&Giant);				/* VFS */
4268 	mac_destroy_vnode_label(&intlabel);
4269 
4270 	return (error);
4271 }
4272 
4273 /*
4274  * MPSAFE
4275  */
4276 int
4277 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4278 {
4279 	struct mac_policy_conf *mpc;
4280 	char target[MAC_MAX_POLICY_NAME];
4281 	int error;
4282 
4283 	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
4284 	if (error)
4285 		return (error);
4286 
4287 	error = ENOSYS;
4288 	MAC_POLICY_LIST_BUSY();
4289 	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
4290 		if (strcmp(mpc->mpc_name, target) == 0 &&
4291 		    mpc->mpc_ops->mpo_syscall != NULL) {
4292 			error = mpc->mpc_ops->mpo_syscall(td,
4293 			    SCARG(uap, call), SCARG(uap, arg));
4294 			goto out;
4295 		}
4296 	}
4297 
4298 out:
4299 	MAC_POLICY_LIST_UNBUSY();
4300 	return (error);
4301 }
4302 
4303 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
4304 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
4305 
4306 #else /* !MAC */
4307 
4308 int
4309 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
4310 {
4311 
4312 	return (ENOSYS);
4313 }
4314 
4315 int
4316 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
4317 {
4318 
4319 	return (ENOSYS);
4320 }
4321 
4322 int
4323 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
4324 {
4325 
4326 	return (ENOSYS);
4327 }
4328 
4329 int
4330 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
4331 {
4332 
4333 	return (ENOSYS);
4334 }
4335 
4336 int
4337 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
4338 {
4339 
4340 	return (ENOSYS);
4341 }
4342 
4343 int
4344 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4345 {
4346 
4347 	return (ENOSYS);
4348 }
4349 
4350 int
4351 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4352 {
4353 
4354 	return (ENOSYS);
4355 }
4356 
4357 int
4358 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4359 {
4360 
4361 	return (ENOSYS);
4362 }
4363 
4364 int
4365 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4366 {
4367 
4368 	return (ENOSYS);
4369 }
4370 
4371 int
4372 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4373 {
4374 
4375 	return (ENOSYS);
4376 }
4377 
4378 #endif
4379