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