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