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