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