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