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