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