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