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