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