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