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