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