mac_syscalls.c revision 106308
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_syscalls.c 106308 2002-11-01 20:46:53Z 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_kenv_dump(struct ucred *cred)
2174{
2175	int error;
2176
2177	if (!mac_enforce_system)
2178		return (0);
2179
2180	MAC_CHECK(check_kenv_dump, cred);
2181
2182	return (error);
2183}
2184
2185int
2186mac_check_kenv_get(struct ucred *cred, char *name)
2187{
2188	int error;
2189
2190	if (!mac_enforce_system)
2191		return (0);
2192
2193	MAC_CHECK(check_kenv_get, cred, name);
2194
2195	return (error);
2196}
2197
2198int
2199mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2200{
2201	int error;
2202
2203	if (!mac_enforce_system)
2204		return (0);
2205
2206	MAC_CHECK(check_kenv_set, cred, name, value);
2207
2208	return (error);
2209}
2210
2211int
2212mac_check_kenv_unset(struct ucred *cred, char *name)
2213{
2214	int error;
2215
2216	if (!mac_enforce_system)
2217		return (0);
2218
2219	MAC_CHECK(check_kenv_unset, cred, name);
2220
2221	return (error);
2222}
2223
2224int
2225mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2226{
2227	int error;
2228
2229	if (!mac_enforce_fs)
2230		return (0);
2231
2232	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2233
2234	return (error);
2235}
2236
2237int
2238mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2239    void *data)
2240{
2241	int error;
2242
2243	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2244
2245	if (!mac_enforce_pipe)
2246		return (0);
2247
2248	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2249
2250	return (error);
2251}
2252
2253int
2254mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2255{
2256	int error;
2257
2258	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2259
2260	if (!mac_enforce_pipe)
2261		return (0);
2262
2263	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2264
2265	return (error);
2266}
2267
2268int
2269mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2270{
2271	int error;
2272
2273	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2274
2275	if (!mac_enforce_pipe)
2276		return (0);
2277
2278	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2279
2280	return (error);
2281}
2282
2283static int
2284mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2285    struct label *newlabel)
2286{
2287	int error;
2288
2289	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2290
2291	if (!mac_enforce_pipe)
2292		return (0);
2293
2294	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2295
2296	return (error);
2297}
2298
2299int
2300mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2301{
2302	int error;
2303
2304	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2305
2306	if (!mac_enforce_pipe)
2307		return (0);
2308
2309	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2310
2311	return (error);
2312}
2313
2314int
2315mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2316{
2317	int error;
2318
2319	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2320
2321	if (!mac_enforce_pipe)
2322		return (0);
2323
2324	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2325
2326	return (error);
2327}
2328
2329int
2330mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2331{
2332	int error;
2333
2334	PROC_LOCK_ASSERT(proc, MA_OWNED);
2335
2336	if (!mac_enforce_process)
2337		return (0);
2338
2339	MAC_CHECK(check_proc_debug, cred, proc);
2340
2341	return (error);
2342}
2343
2344int
2345mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2346{
2347	int error;
2348
2349	PROC_LOCK_ASSERT(proc, MA_OWNED);
2350
2351	if (!mac_enforce_process)
2352		return (0);
2353
2354	MAC_CHECK(check_proc_sched, cred, proc);
2355
2356	return (error);
2357}
2358
2359int
2360mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2361{
2362	int error;
2363
2364	PROC_LOCK_ASSERT(proc, MA_OWNED);
2365
2366	if (!mac_enforce_process)
2367		return (0);
2368
2369	MAC_CHECK(check_proc_signal, cred, proc, signum);
2370
2371	return (error);
2372}
2373
2374int
2375mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2376    struct sockaddr *sockaddr)
2377{
2378	int error;
2379
2380	if (!mac_enforce_socket)
2381		return (0);
2382
2383	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2384	    sockaddr);
2385
2386	return (error);
2387}
2388
2389int
2390mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2391    struct sockaddr *sockaddr)
2392{
2393	int error;
2394
2395	if (!mac_enforce_socket)
2396		return (0);
2397
2398	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2399	    sockaddr);
2400
2401	return (error);
2402}
2403
2404int
2405mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2406{
2407	int error;
2408
2409	if (!mac_enforce_socket)
2410		return (0);
2411
2412	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2413	    &mbuf->m_pkthdr.label);
2414
2415	return (error);
2416}
2417
2418int
2419mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2420{
2421	int error;
2422
2423	if (!mac_enforce_socket)
2424		return (0);
2425
2426	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2427	return (error);
2428}
2429
2430int
2431mac_check_socket_receive(struct ucred *cred, struct socket *so)
2432{
2433	int error;
2434
2435	if (!mac_enforce_socket)
2436		return (0);
2437
2438	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2439
2440	return (error);
2441}
2442
2443static int
2444mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2445    struct label *newlabel)
2446{
2447	int error;
2448
2449	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2450	    newlabel);
2451
2452	return (error);
2453}
2454
2455int
2456mac_check_socket_send(struct ucred *cred, struct socket *so)
2457{
2458	int error;
2459
2460	if (!mac_enforce_socket)
2461		return (0);
2462
2463	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2464
2465	return (error);
2466}
2467
2468int
2469mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2470{
2471	int error;
2472
2473	if (!mac_enforce_socket)
2474		return (0);
2475
2476	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2477
2478	return (error);
2479}
2480
2481int
2482mac_check_system_reboot(struct ucred *cred, int howto)
2483{
2484	int error;
2485
2486	if (!mac_enforce_system)
2487		return (0);
2488
2489	MAC_CHECK(check_system_reboot, cred, howto);
2490
2491	return (error);
2492}
2493
2494int
2495mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2496{
2497	int error;
2498
2499	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2500
2501	if (!mac_enforce_system)
2502		return (0);
2503
2504	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2505	return (error);
2506}
2507
2508int
2509mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2510    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2511{
2512	int error;
2513
2514	/*
2515	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2516	 * but since it's not exported from kern_sysctl.c, we can't.
2517	 */
2518	if (!mac_enforce_system)
2519		return (0);
2520
2521	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2522	    inkernel, new, newlen);
2523
2524	return (error);
2525}
2526
2527int
2528mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2529    struct ifnet *ifnet)
2530{
2531	char *elements, *buffer;
2532	struct mac mac;
2533	int error;
2534
2535	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2536	if (error)
2537		return (error);
2538
2539	error = mac_check_structmac_consistent(&mac);
2540	if (error)
2541		return (error);
2542
2543	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2544	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2545	if (error) {
2546		free(elements, M_MACTEMP);
2547		return (error);
2548	}
2549
2550	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2551	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2552	    buffer, mac.m_buflen, M_WAITOK);
2553	if (error == 0)
2554		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2555
2556	free(buffer, M_MACTEMP);
2557	free(elements, M_MACTEMP);
2558
2559	return (error);
2560}
2561
2562int
2563mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2564    struct ifnet *ifnet)
2565{
2566	struct label intlabel;
2567	struct mac mac;
2568	char *buffer;
2569	int error;
2570
2571	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2572	if (error)
2573		return (error);
2574
2575	error = mac_check_structmac_consistent(&mac);
2576	if (error)
2577		return (error);
2578
2579	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2580	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2581	if (error) {
2582		free(buffer, M_MACTEMP);
2583		return (error);
2584	}
2585
2586	mac_init_ifnet_label(&intlabel);
2587	error = mac_internalize_ifnet_label(&intlabel, buffer);
2588	free(buffer, M_MACTEMP);
2589	if (error) {
2590		mac_destroy_ifnet_label(&intlabel);
2591		return (error);
2592	}
2593
2594	/*
2595	 * XXX: Note that this is a redundant privilege check, since
2596	 * policies impose this check themselves if required by the
2597	 * policy.  Eventually, this should go away.
2598	 */
2599	error = suser_cred(cred, 0);
2600	if (error) {
2601		mac_destroy_ifnet_label(&intlabel);
2602		return (error);
2603	}
2604
2605	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2606	    &intlabel);
2607	if (error) {
2608		mac_destroy_ifnet_label(&intlabel);
2609		return (error);
2610	}
2611
2612	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2613
2614	mac_destroy_ifnet_label(&intlabel);
2615	return (0);
2616}
2617
2618void
2619mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2620{
2621
2622	MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2623}
2624
2625void
2626mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2627{
2628
2629	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2630}
2631
2632void
2633mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
2634    struct devfs_dirent *de)
2635{
2636
2637	MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
2638	    &de->de_label);
2639}
2640
2641void
2642mac_create_devfs_directory(char *dirname, int dirnamelen,
2643    struct devfs_dirent *de)
2644{
2645
2646	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2647	    &de->de_label);
2648}
2649
2650int
2651mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2652    struct mac *mac)
2653{
2654	struct label intlabel;
2655	char *buffer;
2656	int error;
2657
2658	error = mac_check_structmac_consistent(mac);
2659	if (error)
2660		return (error);
2661
2662	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2663	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2664	if (error) {
2665		free(buffer, M_MACTEMP);
2666		return (error);
2667	}
2668
2669	mac_init_socket_label(&intlabel, M_WAITOK);
2670	error = mac_internalize_socket_label(&intlabel, buffer);
2671	free(buffer, M_MACTEMP);
2672	if (error) {
2673		mac_destroy_socket_label(&intlabel);
2674		return (error);
2675	}
2676
2677	mac_check_socket_relabel(cred, so, &intlabel);
2678	if (error) {
2679		mac_destroy_socket_label(&intlabel);
2680		return (error);
2681	}
2682
2683	mac_relabel_socket(cred, so, &intlabel);
2684
2685	mac_destroy_socket_label(&intlabel);
2686	return (0);
2687}
2688
2689int
2690mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2691{
2692	int error;
2693
2694	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2695
2696	error = mac_check_pipe_relabel(cred, pipe, label);
2697	if (error)
2698		return (error);
2699
2700	mac_relabel_pipe(cred, pipe, label);
2701
2702	return (0);
2703}
2704
2705int
2706mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2707    struct mac *mac)
2708{
2709	char *buffer, *elements;
2710	int error;
2711
2712	error = mac_check_structmac_consistent(mac);
2713	if (error)
2714		return (error);
2715
2716	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2717	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2718	if (error) {
2719		free(elements, M_MACTEMP);
2720		return (error);
2721	}
2722
2723	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2724	error = mac_externalize_socket_label(&so->so_label, elements,
2725	    buffer, mac->m_buflen, M_WAITOK);
2726	if (error == 0)
2727		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2728
2729	free(buffer, M_MACTEMP);
2730	free(elements, M_MACTEMP);
2731
2732	return (error);
2733}
2734
2735int
2736mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2737    struct mac *mac)
2738{
2739	char *elements, *buffer;
2740	int error;
2741
2742	error = mac_check_structmac_consistent(mac);
2743	if (error)
2744		return (error);
2745
2746	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2747	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2748	if (error) {
2749		free(elements, M_MACTEMP);
2750		return (error);
2751	}
2752
2753	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2754	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2755	    elements, buffer, mac->m_buflen, M_WAITOK);
2756	if (error == 0)
2757		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2758
2759	free(buffer, M_MACTEMP);
2760	free(elements, M_MACTEMP);
2761
2762	return (error);
2763}
2764
2765/*
2766 * Implementation of VOP_SETLABEL() that relies on extended attributes
2767 * to store label data.  Can be referenced by filesystems supporting
2768 * extended attributes.
2769 */
2770int
2771vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2772{
2773	struct vnode *vp = ap->a_vp;
2774	struct label *intlabel = ap->a_label;
2775	int error;
2776
2777	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2778
2779	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2780		return (EOPNOTSUPP);
2781
2782	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2783	if (error)
2784		return (error);
2785
2786	mac_relabel_vnode(ap->a_cred, vp, intlabel);
2787
2788	return (0);
2789}
2790
2791static int
2792vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
2793{
2794	int error;
2795
2796	if (vp->v_mount == NULL) {
2797		/* printf("vn_setlabel: null v_mount\n"); */
2798		if (vp->v_type != VNON)
2799			printf("vn_setlabel: null v_mount with non-VNON\n");
2800		return (EBADF);
2801	}
2802
2803	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2804		return (EOPNOTSUPP);
2805
2806	/*
2807	 * Multi-phase commit.  First check the policies to confirm the
2808	 * change is OK.  Then commit via the filesystem.  Finally,
2809	 * update the actual vnode label.  Question: maybe the filesystem
2810	 * should update the vnode at the end as part of VOP_SETLABEL()?
2811	 */
2812	error = mac_check_vnode_relabel(cred, vp, intlabel);
2813	if (error)
2814		return (error);
2815
2816	/*
2817	 * VADMIN provides the opportunity for the filesystem to make
2818	 * decisions about who is and is not able to modify labels
2819	 * and protections on files.  This might not be right.  We can't
2820	 * assume VOP_SETLABEL() will do it, because we might implement
2821	 * that as part of vop_stdsetlabel_ea().
2822	 */
2823	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
2824	if (error)
2825		return (error);
2826
2827	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
2828	if (error)
2829		return (error);
2830
2831	return (0);
2832}
2833
2834int
2835__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
2836{
2837	char *elements, *buffer;
2838	struct mac mac;
2839	struct proc *tproc;
2840	struct ucred *tcred;
2841	int error;
2842
2843	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
2844	if (error)
2845		return (error);
2846
2847	error = mac_check_structmac_consistent(&mac);
2848	if (error)
2849		return (error);
2850
2851	tproc = pfind(uap->pid);
2852	if (tproc == NULL)
2853		return (ESRCH);
2854
2855	tcred = NULL;				/* Satisfy gcc. */
2856	error = p_cansee(td, tproc);
2857	if (error == 0)
2858		tcred = crhold(tproc->p_ucred);
2859	PROC_UNLOCK(tproc);
2860	if (error)
2861		return (error);
2862
2863	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2864	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2865	if (error) {
2866		free(elements, M_MACTEMP);
2867		crfree(tcred);
2868		return (error);
2869	}
2870
2871	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2872	error = mac_externalize_cred_label(&tcred->cr_label, elements,
2873	    buffer, mac.m_buflen, M_WAITOK);
2874	if (error == 0)
2875		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2876
2877	free(buffer, M_MACTEMP);
2878	free(elements, M_MACTEMP);
2879	crfree(tcred);
2880	return (error);
2881}
2882
2883/*
2884 * MPSAFE
2885 */
2886int
2887__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
2888{
2889	char *elements, *buffer;
2890	struct mac mac;
2891	int error;
2892
2893	error = copyin(uap->mac_p, &mac, sizeof(mac));
2894	if (error)
2895		return (error);
2896
2897	error = mac_check_structmac_consistent(&mac);
2898	if (error)
2899		return (error);
2900
2901	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2902	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2903	if (error) {
2904		free(elements, M_MACTEMP);
2905		return (error);
2906	}
2907
2908	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2909	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
2910	    elements, buffer, mac.m_buflen, M_WAITOK);
2911	if (error == 0)
2912		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2913
2914	free(buffer, M_MACTEMP);
2915	free(elements, M_MACTEMP);
2916	return (error);
2917}
2918
2919/*
2920 * MPSAFE
2921 */
2922int
2923__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
2924{
2925	struct ucred *newcred, *oldcred;
2926	struct label intlabel;
2927	struct proc *p;
2928	struct mac mac;
2929	char *buffer;
2930	int error;
2931
2932	error = copyin(uap->mac_p, &mac, sizeof(mac));
2933	if (error)
2934		return (error);
2935
2936	error = mac_check_structmac_consistent(&mac);
2937	if (error)
2938		return (error);
2939
2940	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2941	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2942	if (error) {
2943		free(buffer, M_MACTEMP);
2944		return (error);
2945	}
2946
2947	mac_init_cred_label(&intlabel);
2948	error = mac_internalize_cred_label(&intlabel, buffer);
2949	free(buffer, M_MACTEMP);
2950	if (error) {
2951		mac_destroy_cred_label(&intlabel);
2952		return (error);
2953	}
2954
2955	newcred = crget();
2956
2957	p = td->td_proc;
2958	PROC_LOCK(p);
2959	oldcred = p->p_ucred;
2960
2961	error = mac_check_cred_relabel(oldcred, &intlabel);
2962	if (error) {
2963		PROC_UNLOCK(p);
2964		crfree(newcred);
2965		goto out;
2966	}
2967
2968	setsugid(p);
2969	crcopy(newcred, oldcred);
2970	mac_relabel_cred(newcred, &intlabel);
2971	p->p_ucred = newcred;
2972
2973	/*
2974	 * Grab additional reference for use while revoking mmaps, prior
2975	 * to releasing the proc lock and sharing the cred.
2976	 */
2977	crhold(newcred);
2978	PROC_UNLOCK(p);
2979
2980	if (mac_enforce_vm) {
2981		mtx_lock(&Giant);
2982		mac_cred_mmapped_drop_perms(td, newcred);
2983		mtx_unlock(&Giant);
2984	}
2985
2986	crfree(newcred);	/* Free revocation reference. */
2987	crfree(oldcred);
2988
2989out:
2990	mac_destroy_cred_label(&intlabel);
2991	return (error);
2992}
2993
2994/*
2995 * MPSAFE
2996 */
2997int
2998__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
2999{
3000	char *elements, *buffer;
3001	struct label intlabel;
3002	struct file *fp;
3003	struct mac mac;
3004	struct vnode *vp;
3005	struct pipe *pipe;
3006	short label_type;
3007	int error;
3008
3009	error = copyin(uap->mac_p, &mac, sizeof(mac));
3010	if (error)
3011		return (error);
3012
3013	error = mac_check_structmac_consistent(&mac);
3014	if (error)
3015		return (error);
3016
3017	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3018	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3019	if (error) {
3020		free(elements, M_MACTEMP);
3021		return (error);
3022	}
3023
3024	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3025	mtx_lock(&Giant);				/* VFS */
3026	error = fget(td, SCARG(uap, fd), &fp);
3027	if (error)
3028		goto out;
3029
3030	label_type = fp->f_type;
3031	switch (fp->f_type) {
3032	case DTYPE_FIFO:
3033	case DTYPE_VNODE:
3034		vp = (struct vnode *)fp->f_data;
3035
3036		mac_init_vnode_label(&intlabel);
3037
3038		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3039		mac_copy_vnode_label(&vp->v_label, &intlabel);
3040		VOP_UNLOCK(vp, 0, td);
3041
3042		break;
3043	case DTYPE_PIPE:
3044		pipe = (struct pipe *)fp->f_data;
3045
3046		mac_init_pipe_label(&intlabel);
3047
3048		PIPE_LOCK(pipe);
3049		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3050		PIPE_UNLOCK(pipe);
3051		break;
3052	default:
3053		error = EINVAL;
3054		fdrop(fp, td);
3055		goto out;
3056	}
3057	fdrop(fp, td);
3058
3059	switch (label_type) {
3060	case DTYPE_FIFO:
3061	case DTYPE_VNODE:
3062		if (error == 0)
3063			error = mac_externalize_vnode_label(&intlabel,
3064			    elements, buffer, mac.m_buflen, M_WAITOK);
3065		mac_destroy_vnode_label(&intlabel);
3066		break;
3067	case DTYPE_PIPE:
3068		error = mac_externalize_pipe_label(&intlabel, elements,
3069		    buffer, mac.m_buflen, M_WAITOK);
3070		mac_destroy_pipe_label(&intlabel);
3071		break;
3072	default:
3073		panic("__mac_get_fd: corrupted label_type");
3074	}
3075
3076	if (error == 0)
3077		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3078
3079out:
3080	mtx_unlock(&Giant);				/* VFS */
3081	free(buffer, M_MACTEMP);
3082	free(elements, M_MACTEMP);
3083
3084	return (error);
3085}
3086
3087/*
3088 * MPSAFE
3089 */
3090int
3091__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3092{
3093	char *elements, *buffer;
3094	struct nameidata nd;
3095	struct label intlabel;
3096	struct mac mac;
3097	int error;
3098
3099	error = copyin(uap->mac_p, &mac, sizeof(mac));
3100	if (error)
3101		return (error);
3102
3103	error = mac_check_structmac_consistent(&mac);
3104	if (error)
3105		return (error);
3106
3107	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3108	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3109	if (error) {
3110		free(elements, M_MACTEMP);
3111		return (error);
3112	}
3113
3114	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3115	mtx_lock(&Giant);				/* VFS */
3116	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3117	    td);
3118	error = namei(&nd);
3119	if (error)
3120		goto out;
3121
3122	mac_init_vnode_label(&intlabel);
3123	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3124	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3125	    mac.m_buflen, M_WAITOK);
3126
3127	NDFREE(&nd, 0);
3128	mac_destroy_vnode_label(&intlabel);
3129
3130	if (error == 0)
3131		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3132
3133out:
3134	mtx_unlock(&Giant);				/* VFS */
3135
3136	free(buffer, M_MACTEMP);
3137	free(elements, M_MACTEMP);
3138
3139	return (error);
3140}
3141
3142/*
3143 * MPSAFE
3144 */
3145int
3146__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3147{
3148	char *elements, *buffer;
3149	struct nameidata nd;
3150	struct label intlabel;
3151	struct mac mac;
3152	int error;
3153
3154	error = copyin(uap->mac_p, &mac, sizeof(mac));
3155	if (error)
3156		return (error);
3157
3158	error = mac_check_structmac_consistent(&mac);
3159	if (error)
3160		return (error);
3161
3162	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3163	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3164	if (error) {
3165		free(elements, M_MACTEMP);
3166		return (error);
3167	}
3168
3169	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3170	mtx_lock(&Giant);				/* VFS */
3171	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3172	    td);
3173	error = namei(&nd);
3174	if (error)
3175		goto out;
3176
3177	mac_init_vnode_label(&intlabel);
3178	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3179	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3180	    mac.m_buflen, M_WAITOK);
3181	NDFREE(&nd, 0);
3182	mac_destroy_vnode_label(&intlabel);
3183
3184	if (error == 0)
3185		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3186
3187out:
3188	mtx_unlock(&Giant);				/* VFS */
3189
3190	free(buffer, M_MACTEMP);
3191	free(elements, M_MACTEMP);
3192
3193	return (error);
3194}
3195
3196/*
3197 * MPSAFE
3198 */
3199int
3200__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3201{
3202	struct label intlabel;
3203	struct pipe *pipe;
3204	struct file *fp;
3205	struct mount *mp;
3206	struct vnode *vp;
3207	struct mac mac;
3208	char *buffer;
3209	int error;
3210
3211	error = copyin(uap->mac_p, &mac, sizeof(mac));
3212	if (error)
3213		return (error);
3214
3215	error = mac_check_structmac_consistent(&mac);
3216	if (error)
3217		return (error);
3218
3219	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3220	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3221	if (error) {
3222		free(buffer, M_MACTEMP);
3223		return (error);
3224	}
3225
3226	mtx_lock(&Giant);				/* VFS */
3227
3228	error = fget(td, SCARG(uap, fd), &fp);
3229	if (error)
3230		goto out;
3231
3232	switch (fp->f_type) {
3233	case DTYPE_FIFO:
3234	case DTYPE_VNODE:
3235		mac_init_vnode_label(&intlabel);
3236		error = mac_internalize_vnode_label(&intlabel, buffer);
3237		if (error) {
3238			mac_destroy_vnode_label(&intlabel);
3239			break;
3240		}
3241
3242		vp = (struct vnode *)fp->f_data;
3243		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3244		if (error != 0) {
3245			mac_destroy_vnode_label(&intlabel);
3246			break;
3247		}
3248
3249		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3250		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3251		VOP_UNLOCK(vp, 0, td);
3252		vn_finished_write(mp);
3253
3254		mac_destroy_vnode_label(&intlabel);
3255		break;
3256
3257	case DTYPE_PIPE:
3258		mac_init_pipe_label(&intlabel);
3259		error = mac_internalize_pipe_label(&intlabel, buffer);
3260		if (error == 0) {
3261			pipe = (struct pipe *)fp->f_data;
3262			PIPE_LOCK(pipe);
3263			error = mac_pipe_label_set(td->td_ucred, pipe,
3264			    &intlabel);
3265			PIPE_UNLOCK(pipe);
3266		}
3267
3268		mac_destroy_pipe_label(&intlabel);
3269		break;
3270
3271	default:
3272		error = EINVAL;
3273	}
3274
3275	fdrop(fp, td);
3276out:
3277	mtx_unlock(&Giant);				/* VFS */
3278
3279	free(buffer, M_MACTEMP);
3280
3281	return (error);
3282}
3283
3284/*
3285 * MPSAFE
3286 */
3287int
3288__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3289{
3290	struct label intlabel;
3291	struct nameidata nd;
3292	struct mount *mp;
3293	struct mac mac;
3294	char *buffer;
3295	int error;
3296
3297	error = copyin(uap->mac_p, &mac, sizeof(mac));
3298	if (error)
3299		return (error);
3300
3301	error = mac_check_structmac_consistent(&mac);
3302	if (error)
3303		return (error);
3304
3305	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3306	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3307	if (error) {
3308		free(buffer, M_MACTEMP);
3309		return (error);
3310	}
3311
3312	mac_init_vnode_label(&intlabel);
3313	error = mac_internalize_vnode_label(&intlabel, buffer);
3314	free(buffer, M_MACTEMP);
3315	if (error) {
3316		mac_destroy_vnode_label(&intlabel);
3317		return (error);
3318	}
3319
3320	mtx_lock(&Giant);				/* VFS */
3321
3322	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3323	    td);
3324	error = namei(&nd);
3325	if (error == 0) {
3326		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3327		if (error == 0)
3328			error = vn_setlabel(nd.ni_vp, &intlabel,
3329			    td->td_ucred);
3330		vn_finished_write(mp);
3331	}
3332
3333	NDFREE(&nd, 0);
3334	mtx_unlock(&Giant);				/* VFS */
3335	mac_destroy_vnode_label(&intlabel);
3336
3337	return (error);
3338}
3339
3340/*
3341 * MPSAFE
3342 */
3343int
3344__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3345{
3346	struct label intlabel;
3347	struct nameidata nd;
3348	struct mount *mp;
3349	struct mac mac;
3350	char *buffer;
3351	int error;
3352
3353	error = copyin(uap->mac_p, &mac, sizeof(mac));
3354	if (error)
3355		return (error);
3356
3357	error = mac_check_structmac_consistent(&mac);
3358	if (error)
3359		return (error);
3360
3361	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3362	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3363	if (error) {
3364		free(buffer, M_MACTEMP);
3365		return (error);
3366	}
3367
3368	mac_init_vnode_label(&intlabel);
3369	error = mac_internalize_vnode_label(&intlabel, buffer);
3370	free(buffer, M_MACTEMP);
3371	if (error) {
3372		mac_destroy_vnode_label(&intlabel);
3373		return (error);
3374	}
3375
3376	mtx_lock(&Giant);				/* VFS */
3377
3378	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3379	    td);
3380	error = namei(&nd);
3381	if (error == 0) {
3382		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3383		if (error == 0)
3384			error = vn_setlabel(nd.ni_vp, &intlabel,
3385			    td->td_ucred);
3386		vn_finished_write(mp);
3387	}
3388
3389	NDFREE(&nd, 0);
3390	mtx_unlock(&Giant);				/* VFS */
3391	mac_destroy_vnode_label(&intlabel);
3392
3393	return (error);
3394}
3395
3396/*
3397 * MPSAFE
3398 */
3399int
3400mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3401{
3402	struct mac_policy_conf *mpc;
3403	char target[MAC_MAX_POLICY_NAME];
3404	int error;
3405
3406	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3407	if (error)
3408		return (error);
3409
3410	error = ENOSYS;
3411	MAC_POLICY_LIST_BUSY();
3412	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3413		if (strcmp(mpc->mpc_name, target) == 0 &&
3414		    mpc->mpc_ops->mpo_syscall != NULL) {
3415			error = mpc->mpc_ops->mpo_syscall(td,
3416			    SCARG(uap, call), SCARG(uap, arg));
3417			goto out;
3418		}
3419	}
3420
3421out:
3422	MAC_POLICY_LIST_UNBUSY();
3423	return (error);
3424}
3425
3426SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3427SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3428
3429#else /* !MAC */
3430
3431int
3432__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3433{
3434
3435	return (ENOSYS);
3436}
3437
3438int
3439__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3440{
3441
3442	return (ENOSYS);
3443}
3444
3445int
3446__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3447{
3448
3449	return (ENOSYS);
3450}
3451
3452int
3453__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3454{
3455
3456	return (ENOSYS);
3457}
3458
3459int
3460__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3461{
3462
3463	return (ENOSYS);
3464}
3465
3466int
3467__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3468{
3469
3470	return (ENOSYS);
3471}
3472
3473int
3474__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3475{
3476
3477	return (ENOSYS);
3478}
3479
3480int
3481__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3482{
3483
3484	return (ENOSYS);
3485}
3486
3487int
3488__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3489{
3490
3491	return (ENOSYS);
3492}
3493
3494int
3495mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3496{
3497
3498	return (ENOSYS);
3499}
3500
3501#endif
3502