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