mac_cred.c revision 106460
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson and Ilmar Habibulin for the
8 * TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: head/sys/security/mac/mac_process.c 106460 2002-11-05 15:11:33Z 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	if (!mac_enforce_process && !mac_enforce_fs)
1261		return;
1262
1263	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
1264}
1265
1266int
1267mac_execve_will_transition(struct ucred *old, struct vnode *vp)
1268{
1269	int result;
1270
1271	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1272
1273	if (!mac_enforce_process && !mac_enforce_fs)
1274		return (0);
1275
1276	result = 0;
1277	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
1278
1279	return (result);
1280}
1281
1282int
1283mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1284{
1285	int error;
1286
1287	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1288
1289	if (!mac_enforce_fs)
1290		return (0);
1291
1292	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1293	return (error);
1294}
1295
1296int
1297mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1298{
1299	int error;
1300
1301	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1302
1303	if (!mac_enforce_fs)
1304		return (0);
1305
1306	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1307	return (error);
1308}
1309
1310int
1311mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1312{
1313	int error;
1314
1315	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1316
1317	if (!mac_enforce_fs)
1318		return (0);
1319
1320	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1321	return (error);
1322}
1323
1324int
1325mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1326    struct componentname *cnp, struct vattr *vap)
1327{
1328	int error;
1329
1330	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1331
1332	if (!mac_enforce_fs)
1333		return (0);
1334
1335	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1336	return (error);
1337}
1338
1339int
1340mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1341    struct componentname *cnp)
1342{
1343	int error;
1344
1345	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1346	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1347
1348	if (!mac_enforce_fs)
1349		return (0);
1350
1351	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1352	    &vp->v_label, cnp);
1353	return (error);
1354}
1355
1356int
1357mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1358    acl_type_t type)
1359{
1360	int error;
1361
1362	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1363
1364	if (!mac_enforce_fs)
1365		return (0);
1366
1367	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1368	return (error);
1369}
1370
1371int
1372mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
1373{
1374	int error;
1375
1376	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1377
1378	if (!mac_enforce_process && !mac_enforce_fs)
1379		return (0);
1380
1381	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
1382
1383	return (error);
1384}
1385
1386int
1387mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1388{
1389	int error;
1390
1391	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1392
1393	if (!mac_enforce_fs)
1394		return (0);
1395
1396	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1397	return (error);
1398}
1399
1400int
1401mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1402    int attrnamespace, const char *name, struct uio *uio)
1403{
1404	int error;
1405
1406	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1407
1408	if (!mac_enforce_fs)
1409		return (0);
1410
1411	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1412	    attrnamespace, name, uio);
1413	return (error);
1414}
1415
1416int
1417mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1418    struct vnode *vp, struct componentname *cnp)
1419{
1420	int error;
1421
1422	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1423	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1424
1425	if (!mac_enforce_fs)
1426		return (0);
1427
1428	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1429	    &vp->v_label, cnp);
1430	return (error);
1431}
1432
1433int
1434mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1435    struct componentname *cnp)
1436{
1437	int error;
1438
1439	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1440
1441	if (!mac_enforce_fs)
1442		return (0);
1443
1444	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1445	return (error);
1446}
1447
1448int
1449mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1450{
1451	int error;
1452
1453	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1454
1455	if (!mac_enforce_fs || !mac_enforce_vm)
1456		return (0);
1457
1458	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1459	return (error);
1460}
1461
1462void
1463mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1464{
1465	int result = *prot;
1466
1467	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1468
1469	if (!mac_enforce_fs || !mac_enforce_vm)
1470		return;
1471
1472	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1473	    &result);
1474
1475	*prot = result;
1476}
1477
1478int
1479mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1480{
1481	int error;
1482
1483	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1484
1485	if (!mac_enforce_fs || !mac_enforce_vm)
1486		return (0);
1487
1488	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1489	return (error);
1490}
1491
1492int
1493mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1494{
1495	int error;
1496
1497	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1498
1499	if (!mac_enforce_fs)
1500		return (0);
1501
1502	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1503	return (error);
1504}
1505
1506int
1507mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1508    struct vnode *vp)
1509{
1510	int error;
1511
1512	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1513
1514	if (!mac_enforce_fs)
1515		return (0);
1516
1517	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1518	    &vp->v_label);
1519
1520	return (error);
1521}
1522
1523int
1524mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1525    struct vnode *vp)
1526{
1527	int error;
1528
1529	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1530
1531	if (!mac_enforce_fs)
1532		return (0);
1533
1534	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1535	    &vp->v_label);
1536
1537	return (error);
1538}
1539
1540int
1541mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1542{
1543	int error;
1544
1545	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1546
1547	if (!mac_enforce_fs)
1548		return (0);
1549
1550	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1551	return (error);
1552}
1553
1554int
1555mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1556{
1557	int error;
1558
1559	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1560
1561	if (!mac_enforce_fs)
1562		return (0);
1563
1564	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1565	return (error);
1566}
1567
1568static int
1569mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1570    struct label *newlabel)
1571{
1572	int error;
1573
1574	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1575
1576	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1577
1578	return (error);
1579}
1580
1581int
1582mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1583    struct vnode *vp, struct componentname *cnp)
1584{
1585	int error;
1586
1587	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1588	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1589
1590	if (!mac_enforce_fs)
1591		return (0);
1592
1593	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1594	    &vp->v_label, cnp);
1595	return (error);
1596}
1597
1598int
1599mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1600    struct vnode *vp, int samedir, struct componentname *cnp)
1601{
1602	int error;
1603
1604	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1605	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1606
1607	if (!mac_enforce_fs)
1608		return (0);
1609
1610	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1611	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1612	return (error);
1613}
1614
1615int
1616mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1617{
1618	int error;
1619
1620	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1621
1622	if (!mac_enforce_fs)
1623		return (0);
1624
1625	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1626	return (error);
1627}
1628
1629int
1630mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1631    struct acl *acl)
1632{
1633	int error;
1634
1635	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1636
1637	if (!mac_enforce_fs)
1638		return (0);
1639
1640	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1641	return (error);
1642}
1643
1644int
1645mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1646    int attrnamespace, const char *name, struct uio *uio)
1647{
1648	int error;
1649
1650	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1651
1652	if (!mac_enforce_fs)
1653		return (0);
1654
1655	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1656	    attrnamespace, name, uio);
1657	return (error);
1658}
1659
1660int
1661mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1662{
1663	int error;
1664
1665	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1666
1667	if (!mac_enforce_fs)
1668		return (0);
1669
1670	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1671	return (error);
1672}
1673
1674int
1675mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1676{
1677	int error;
1678
1679	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1680
1681	if (!mac_enforce_fs)
1682		return (0);
1683
1684	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1685	return (error);
1686}
1687
1688int
1689mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1690    gid_t gid)
1691{
1692	int error;
1693
1694	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1695
1696	if (!mac_enforce_fs)
1697		return (0);
1698
1699	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1700	return (error);
1701}
1702
1703int
1704mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1705    struct timespec atime, struct timespec mtime)
1706{
1707	int error;
1708
1709	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1710
1711	if (!mac_enforce_fs)
1712		return (0);
1713
1714	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1715	    mtime);
1716	return (error);
1717}
1718
1719int
1720mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1721    struct vnode *vp)
1722{
1723	int error;
1724
1725	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1726
1727	if (!mac_enforce_fs)
1728		return (0);
1729
1730	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
1731	    &vp->v_label);
1732	return (error);
1733}
1734
1735int
1736mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1737    struct vnode *vp)
1738{
1739	int error;
1740
1741	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
1742
1743	if (!mac_enforce_fs)
1744		return (0);
1745
1746	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
1747	    &vp->v_label);
1748
1749	return (error);
1750}
1751
1752/*
1753 * When relabeling a process, call out to the policies for the maximum
1754 * permission allowed for each object type we know about in its
1755 * memory space, and revoke access (in the least surprising ways we
1756 * know) when necessary.  The process lock is not held here.
1757 */
1758static void
1759mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
1760{
1761
1762	/* XXX freeze all other threads */
1763	mac_cred_mmapped_drop_perms_recurse(td, cred,
1764	    &td->td_proc->p_vmspace->vm_map);
1765	/* XXX allow other threads to continue */
1766}
1767
1768static __inline const char *
1769prot2str(vm_prot_t prot)
1770{
1771
1772	switch (prot & VM_PROT_ALL) {
1773	case VM_PROT_READ:
1774		return ("r--");
1775	case VM_PROT_READ | VM_PROT_WRITE:
1776		return ("rw-");
1777	case VM_PROT_READ | VM_PROT_EXECUTE:
1778		return ("r-x");
1779	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
1780		return ("rwx");
1781	case VM_PROT_WRITE:
1782		return ("-w-");
1783	case VM_PROT_EXECUTE:
1784		return ("--x");
1785	case VM_PROT_WRITE | VM_PROT_EXECUTE:
1786		return ("-wx");
1787	default:
1788		return ("---");
1789	}
1790}
1791
1792static void
1793mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
1794    struct vm_map *map)
1795{
1796	struct vm_map_entry *vme;
1797	int result;
1798	vm_prot_t revokeperms;
1799	vm_object_t object;
1800	vm_ooffset_t offset;
1801	struct vnode *vp;
1802
1803	if (!mac_mmap_revocation)
1804		return;
1805
1806	vm_map_lock_read(map);
1807	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
1808		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
1809			mac_cred_mmapped_drop_perms_recurse(td, cred,
1810			    vme->object.sub_map);
1811			continue;
1812		}
1813		/*
1814		 * Skip over entries that obviously are not shared.
1815		 */
1816		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
1817		    !vme->max_protection)
1818			continue;
1819		/*
1820		 * Drill down to the deepest backing object.
1821		 */
1822		offset = vme->offset;
1823		object = vme->object.vm_object;
1824		if (object == NULL)
1825			continue;
1826		while (object->backing_object != NULL) {
1827			object = object->backing_object;
1828			offset += object->backing_object_offset;
1829		}
1830		/*
1831		 * At the moment, vm_maps and objects aren't considered
1832		 * by the MAC system, so only things with backing by a
1833		 * normal object (read: vnodes) are checked.
1834		 */
1835		if (object->type != OBJT_VNODE)
1836			continue;
1837		vp = (struct vnode *)object->handle;
1838		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1839		result = vme->max_protection;
1840		mac_check_vnode_mmap_downgrade(cred, vp, &result);
1841		VOP_UNLOCK(vp, 0, td);
1842		/*
1843		 * Find out what maximum protection we may be allowing
1844		 * now but a policy needs to get removed.
1845		 */
1846		revokeperms = vme->max_protection & ~result;
1847		if (!revokeperms)
1848			continue;
1849		printf("pid %ld: revoking %s perms from %#lx:%ld "
1850		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
1851		    prot2str(revokeperms), (u_long)vme->start,
1852		    (long)(vme->end - vme->start),
1853		    prot2str(vme->max_protection), prot2str(vme->protection));
1854		vm_map_lock_upgrade(map);
1855		/*
1856		 * This is the really simple case: if a map has more
1857		 * max_protection than is allowed, but it's not being
1858		 * actually used (that is, the current protection is
1859		 * still allowed), we can just wipe it out and do
1860		 * nothing more.
1861		 */
1862		if ((vme->protection & revokeperms) == 0) {
1863			vme->max_protection -= revokeperms;
1864		} else {
1865			if (revokeperms & VM_PROT_WRITE) {
1866				/*
1867				 * In the more complicated case, flush out all
1868				 * pending changes to the object then turn it
1869				 * copy-on-write.
1870				 */
1871				vm_object_reference(object);
1872				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1873				vm_object_page_clean(object,
1874				    OFF_TO_IDX(offset),
1875				    OFF_TO_IDX(offset + vme->end - vme->start +
1876					PAGE_MASK),
1877				    OBJPC_SYNC);
1878				VOP_UNLOCK(vp, 0, td);
1879				vm_object_deallocate(object);
1880				/*
1881				 * Why bother if there's no read permissions
1882				 * anymore?  For the rest, we need to leave
1883				 * the write permissions on for COW, or
1884				 * remove them entirely if configured to.
1885				 */
1886				if (!mac_mmap_revocation_via_cow) {
1887					vme->max_protection &= ~VM_PROT_WRITE;
1888					vme->protection &= ~VM_PROT_WRITE;
1889				} if ((revokeperms & VM_PROT_READ) == 0)
1890					vme->eflags |= MAP_ENTRY_COW |
1891					    MAP_ENTRY_NEEDS_COPY;
1892			}
1893			if (revokeperms & VM_PROT_EXECUTE) {
1894				vme->max_protection &= ~VM_PROT_EXECUTE;
1895				vme->protection &= ~VM_PROT_EXECUTE;
1896			}
1897			if (revokeperms & VM_PROT_READ) {
1898				vme->max_protection = 0;
1899				vme->protection = 0;
1900			}
1901			pmap_protect(map->pmap, vme->start, vme->end,
1902			    vme->protection & ~revokeperms);
1903			vm_map_simplify_entry(map, vme);
1904		}
1905		vm_map_lock_downgrade(map);
1906	}
1907	vm_map_unlock_read(map);
1908}
1909
1910/*
1911 * When the subject's label changes, it may require revocation of privilege
1912 * to mapped objects.  This can't be done on-the-fly later with a unified
1913 * buffer cache.
1914 */
1915static void
1916mac_relabel_cred(struct ucred *cred, struct label *newlabel)
1917{
1918
1919	MAC_PERFORM(relabel_cred, cred, newlabel);
1920}
1921
1922void
1923mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
1924{
1925
1926	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
1927}
1928
1929void
1930mac_create_ifnet(struct ifnet *ifnet)
1931{
1932
1933	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
1934}
1935
1936void
1937mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
1938{
1939
1940	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
1941}
1942
1943void
1944mac_create_socket(struct ucred *cred, struct socket *socket)
1945{
1946
1947	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
1948}
1949
1950void
1951mac_create_pipe(struct ucred *cred, struct pipe *pipe)
1952{
1953
1954	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
1955}
1956
1957void
1958mac_create_socket_from_socket(struct socket *oldsocket,
1959    struct socket *newsocket)
1960{
1961
1962	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
1963	    newsocket, &newsocket->so_label);
1964}
1965
1966static void
1967mac_relabel_socket(struct ucred *cred, struct socket *socket,
1968    struct label *newlabel)
1969{
1970
1971	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
1972}
1973
1974static void
1975mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
1976{
1977
1978	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
1979}
1980
1981void
1982mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
1983{
1984
1985	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
1986	    socket, &socket->so_peerlabel);
1987}
1988
1989void
1990mac_set_socket_peer_from_socket(struct socket *oldsocket,
1991    struct socket *newsocket)
1992{
1993
1994	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
1995	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
1996}
1997
1998void
1999mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2000{
2001
2002	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2003	    datagram, &datagram->m_pkthdr.label);
2004}
2005
2006void
2007mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2008{
2009
2010	MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2011	    fragment, &fragment->m_pkthdr.label);
2012}
2013
2014void
2015mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2016{
2017
2018	MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2019	    &ipq->ipq_label);
2020}
2021
2022void
2023mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2024{
2025
2026	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2027	    newmbuf, &newmbuf->m_pkthdr.label);
2028}
2029
2030void
2031mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2032{
2033
2034	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2035	    &mbuf->m_pkthdr.label);
2036}
2037
2038void
2039mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2040{
2041
2042	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2043	    &mbuf->m_pkthdr.label);
2044}
2045
2046void
2047mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2048{
2049
2050	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2051	    &mbuf->m_pkthdr.label);
2052}
2053
2054void
2055mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2056    struct mbuf *newmbuf)
2057{
2058
2059	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2060	    &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2061	    &newmbuf->m_pkthdr.label);
2062}
2063
2064void
2065mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2066{
2067
2068	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2069	    newmbuf, &newmbuf->m_pkthdr.label);
2070}
2071
2072int
2073mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2074{
2075	int result;
2076
2077	result = 1;
2078	MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2079	    ipq, &ipq->ipq_label);
2080
2081	return (result);
2082}
2083
2084void
2085mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2086{
2087
2088	MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2089	    &ipq->ipq_label);
2090}
2091
2092void
2093mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2094{
2095
2096	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2097	    &mbuf->m_pkthdr.label);
2098}
2099
2100void
2101mac_create_mount(struct ucred *cred, struct mount *mp)
2102{
2103
2104	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2105	    &mp->mnt_fslabel);
2106}
2107
2108void
2109mac_create_root_mount(struct ucred *cred, struct mount *mp)
2110{
2111
2112	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2113	    &mp->mnt_fslabel);
2114}
2115
2116int
2117mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2118{
2119	int error;
2120
2121	if (!mac_enforce_network)
2122		return (0);
2123
2124	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2125	    &ifnet->if_label);
2126
2127	return (error);
2128}
2129
2130static int
2131mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2132{
2133	int error;
2134
2135	MAC_CHECK(check_cred_relabel, cred, newlabel);
2136
2137	return (error);
2138}
2139
2140int
2141mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2142{
2143	int error;
2144
2145	if (!mac_enforce_process)
2146		return (0);
2147
2148	MAC_CHECK(check_cred_visible, u1, u2);
2149
2150	return (error);
2151}
2152
2153int
2154mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2155{
2156	int error;
2157
2158	if (!mac_enforce_network)
2159		return (0);
2160
2161	KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2162	if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2163		if_printf(ifnet, "not initialized\n");
2164
2165	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2166	    &mbuf->m_pkthdr.label);
2167
2168	return (error);
2169}
2170
2171int
2172mac_check_kenv_dump(struct ucred *cred)
2173{
2174	int error;
2175
2176	if (!mac_enforce_system)
2177		return (0);
2178
2179	MAC_CHECK(check_kenv_dump, cred);
2180
2181	return (error);
2182}
2183
2184int
2185mac_check_kenv_get(struct ucred *cred, char *name)
2186{
2187	int error;
2188
2189	if (!mac_enforce_system)
2190		return (0);
2191
2192	MAC_CHECK(check_kenv_get, cred, name);
2193
2194	return (error);
2195}
2196
2197int
2198mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2199{
2200	int error;
2201
2202	if (!mac_enforce_system)
2203		return (0);
2204
2205	MAC_CHECK(check_kenv_set, cred, name, value);
2206
2207	return (error);
2208}
2209
2210int
2211mac_check_kenv_unset(struct ucred *cred, char *name)
2212{
2213	int error;
2214
2215	if (!mac_enforce_system)
2216		return (0);
2217
2218	MAC_CHECK(check_kenv_unset, cred, name);
2219
2220	return (error);
2221}
2222
2223int
2224mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2225{
2226	int error;
2227
2228	if (!mac_enforce_fs)
2229		return (0);
2230
2231	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2232
2233	return (error);
2234}
2235
2236int
2237mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2238    void *data)
2239{
2240	int error;
2241
2242	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2243
2244	if (!mac_enforce_pipe)
2245		return (0);
2246
2247	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2248
2249	return (error);
2250}
2251
2252int
2253mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2254{
2255	int error;
2256
2257	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2258
2259	if (!mac_enforce_pipe)
2260		return (0);
2261
2262	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2263
2264	return (error);
2265}
2266
2267int
2268mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2269{
2270	int error;
2271
2272	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2273
2274	if (!mac_enforce_pipe)
2275		return (0);
2276
2277	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2278
2279	return (error);
2280}
2281
2282static int
2283mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2284    struct label *newlabel)
2285{
2286	int error;
2287
2288	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2289
2290	if (!mac_enforce_pipe)
2291		return (0);
2292
2293	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2294
2295	return (error);
2296}
2297
2298int
2299mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2300{
2301	int error;
2302
2303	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2304
2305	if (!mac_enforce_pipe)
2306		return (0);
2307
2308	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2309
2310	return (error);
2311}
2312
2313int
2314mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2315{
2316	int error;
2317
2318	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2319
2320	if (!mac_enforce_pipe)
2321		return (0);
2322
2323	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2324
2325	return (error);
2326}
2327
2328int
2329mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2330{
2331	int error;
2332
2333	PROC_LOCK_ASSERT(proc, MA_OWNED);
2334
2335	if (!mac_enforce_process)
2336		return (0);
2337
2338	MAC_CHECK(check_proc_debug, cred, proc);
2339
2340	return (error);
2341}
2342
2343int
2344mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2345{
2346	int error;
2347
2348	PROC_LOCK_ASSERT(proc, MA_OWNED);
2349
2350	if (!mac_enforce_process)
2351		return (0);
2352
2353	MAC_CHECK(check_proc_sched, cred, proc);
2354
2355	return (error);
2356}
2357
2358int
2359mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2360{
2361	int error;
2362
2363	PROC_LOCK_ASSERT(proc, MA_OWNED);
2364
2365	if (!mac_enforce_process)
2366		return (0);
2367
2368	MAC_CHECK(check_proc_signal, cred, proc, signum);
2369
2370	return (error);
2371}
2372
2373int
2374mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2375    struct sockaddr *sockaddr)
2376{
2377	int error;
2378
2379	if (!mac_enforce_socket)
2380		return (0);
2381
2382	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2383	    sockaddr);
2384
2385	return (error);
2386}
2387
2388int
2389mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2390    struct sockaddr *sockaddr)
2391{
2392	int error;
2393
2394	if (!mac_enforce_socket)
2395		return (0);
2396
2397	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2398	    sockaddr);
2399
2400	return (error);
2401}
2402
2403int
2404mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2405{
2406	int error;
2407
2408	if (!mac_enforce_socket)
2409		return (0);
2410
2411	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2412	    &mbuf->m_pkthdr.label);
2413
2414	return (error);
2415}
2416
2417int
2418mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2419{
2420	int error;
2421
2422	if (!mac_enforce_socket)
2423		return (0);
2424
2425	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2426	return (error);
2427}
2428
2429int
2430mac_check_socket_receive(struct ucred *cred, struct socket *so)
2431{
2432	int error;
2433
2434	if (!mac_enforce_socket)
2435		return (0);
2436
2437	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2438
2439	return (error);
2440}
2441
2442static int
2443mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2444    struct label *newlabel)
2445{
2446	int error;
2447
2448	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2449	    newlabel);
2450
2451	return (error);
2452}
2453
2454int
2455mac_check_socket_send(struct ucred *cred, struct socket *so)
2456{
2457	int error;
2458
2459	if (!mac_enforce_socket)
2460		return (0);
2461
2462	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2463
2464	return (error);
2465}
2466
2467int
2468mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2469{
2470	int error;
2471
2472	if (!mac_enforce_socket)
2473		return (0);
2474
2475	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2476
2477	return (error);
2478}
2479
2480int
2481mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2482{
2483	int error;
2484
2485	if (vp != NULL) {
2486		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2487	}
2488
2489	if (!mac_enforce_system)
2490		return (0);
2491
2492	MAC_CHECK(check_system_acct, cred, vp,
2493	    vp != NULL ? &vp->v_label : NULL);
2494
2495	return (error);
2496}
2497
2498int
2499mac_check_system_nfsd(struct ucred *cred)
2500{
2501	int error;
2502
2503	if (!mac_enforce_system)
2504		return (0);
2505
2506	MAC_CHECK(check_system_nfsd, cred);
2507
2508	return (error);
2509}
2510
2511int
2512mac_check_system_reboot(struct ucred *cred, int howto)
2513{
2514	int error;
2515
2516	if (!mac_enforce_system)
2517		return (0);
2518
2519	MAC_CHECK(check_system_reboot, cred, howto);
2520
2521	return (error);
2522}
2523
2524int
2525mac_check_system_settime(struct ucred *cred)
2526{
2527	int error;
2528
2529	if (!mac_enforce_system)
2530		return (0);
2531
2532	MAC_CHECK(check_system_settime, cred);
2533
2534	return (error);
2535}
2536
2537int
2538mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2539{
2540	int error;
2541
2542	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2543
2544	if (!mac_enforce_system)
2545		return (0);
2546
2547	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2548	return (error);
2549}
2550
2551int
2552mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2553    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2554{
2555	int error;
2556
2557	/*
2558	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2559	 * but since it's not exported from kern_sysctl.c, we can't.
2560	 */
2561	if (!mac_enforce_system)
2562		return (0);
2563
2564	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2565	    inkernel, new, newlen);
2566
2567	return (error);
2568}
2569
2570int
2571mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2572    struct ifnet *ifnet)
2573{
2574	char *elements, *buffer;
2575	struct mac mac;
2576	int error;
2577
2578	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2579	if (error)
2580		return (error);
2581
2582	error = mac_check_structmac_consistent(&mac);
2583	if (error)
2584		return (error);
2585
2586	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2587	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2588	if (error) {
2589		free(elements, M_MACTEMP);
2590		return (error);
2591	}
2592
2593	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2594	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2595	    buffer, mac.m_buflen, M_WAITOK);
2596	if (error == 0)
2597		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2598
2599	free(buffer, M_MACTEMP);
2600	free(elements, M_MACTEMP);
2601
2602	return (error);
2603}
2604
2605int
2606mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2607    struct ifnet *ifnet)
2608{
2609	struct label intlabel;
2610	struct mac mac;
2611	char *buffer;
2612	int error;
2613
2614	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2615	if (error)
2616		return (error);
2617
2618	error = mac_check_structmac_consistent(&mac);
2619	if (error)
2620		return (error);
2621
2622	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2623	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2624	if (error) {
2625		free(buffer, M_MACTEMP);
2626		return (error);
2627	}
2628
2629	mac_init_ifnet_label(&intlabel);
2630	error = mac_internalize_ifnet_label(&intlabel, buffer);
2631	free(buffer, M_MACTEMP);
2632	if (error) {
2633		mac_destroy_ifnet_label(&intlabel);
2634		return (error);
2635	}
2636
2637	/*
2638	 * XXX: Note that this is a redundant privilege check, since
2639	 * policies impose this check themselves if required by the
2640	 * policy.  Eventually, this should go away.
2641	 */
2642	error = suser_cred(cred, 0);
2643	if (error) {
2644		mac_destroy_ifnet_label(&intlabel);
2645		return (error);
2646	}
2647
2648	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2649	    &intlabel);
2650	if (error) {
2651		mac_destroy_ifnet_label(&intlabel);
2652		return (error);
2653	}
2654
2655	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2656
2657	mac_destroy_ifnet_label(&intlabel);
2658	return (0);
2659}
2660
2661void
2662mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2663{
2664
2665	MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2666}
2667
2668void
2669mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2670{
2671
2672	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2673}
2674
2675void
2676mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
2677    struct devfs_dirent *de)
2678{
2679
2680	MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
2681	    &de->de_label);
2682}
2683
2684void
2685mac_create_devfs_directory(char *dirname, int dirnamelen,
2686    struct devfs_dirent *de)
2687{
2688
2689	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2690	    &de->de_label);
2691}
2692
2693int
2694mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2695    struct mac *mac)
2696{
2697	struct label intlabel;
2698	char *buffer;
2699	int error;
2700
2701	error = mac_check_structmac_consistent(mac);
2702	if (error)
2703		return (error);
2704
2705	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2706	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2707	if (error) {
2708		free(buffer, M_MACTEMP);
2709		return (error);
2710	}
2711
2712	mac_init_socket_label(&intlabel, M_WAITOK);
2713	error = mac_internalize_socket_label(&intlabel, buffer);
2714	free(buffer, M_MACTEMP);
2715	if (error) {
2716		mac_destroy_socket_label(&intlabel);
2717		return (error);
2718	}
2719
2720	mac_check_socket_relabel(cred, so, &intlabel);
2721	if (error) {
2722		mac_destroy_socket_label(&intlabel);
2723		return (error);
2724	}
2725
2726	mac_relabel_socket(cred, so, &intlabel);
2727
2728	mac_destroy_socket_label(&intlabel);
2729	return (0);
2730}
2731
2732int
2733mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2734{
2735	int error;
2736
2737	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2738
2739	error = mac_check_pipe_relabel(cred, pipe, label);
2740	if (error)
2741		return (error);
2742
2743	mac_relabel_pipe(cred, pipe, label);
2744
2745	return (0);
2746}
2747
2748int
2749mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2750    struct mac *mac)
2751{
2752	char *buffer, *elements;
2753	int error;
2754
2755	error = mac_check_structmac_consistent(mac);
2756	if (error)
2757		return (error);
2758
2759	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2760	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2761	if (error) {
2762		free(elements, M_MACTEMP);
2763		return (error);
2764	}
2765
2766	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2767	error = mac_externalize_socket_label(&so->so_label, elements,
2768	    buffer, mac->m_buflen, M_WAITOK);
2769	if (error == 0)
2770		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2771
2772	free(buffer, M_MACTEMP);
2773	free(elements, M_MACTEMP);
2774
2775	return (error);
2776}
2777
2778int
2779mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2780    struct mac *mac)
2781{
2782	char *elements, *buffer;
2783	int error;
2784
2785	error = mac_check_structmac_consistent(mac);
2786	if (error)
2787		return (error);
2788
2789	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2790	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2791	if (error) {
2792		free(elements, M_MACTEMP);
2793		return (error);
2794	}
2795
2796	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2797	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2798	    elements, buffer, mac->m_buflen, M_WAITOK);
2799	if (error == 0)
2800		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2801
2802	free(buffer, M_MACTEMP);
2803	free(elements, M_MACTEMP);
2804
2805	return (error);
2806}
2807
2808/*
2809 * Implementation of VOP_SETLABEL() that relies on extended attributes
2810 * to store label data.  Can be referenced by filesystems supporting
2811 * extended attributes.
2812 */
2813int
2814vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2815{
2816	struct vnode *vp = ap->a_vp;
2817	struct label *intlabel = ap->a_label;
2818	int error;
2819
2820	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2821
2822	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2823		return (EOPNOTSUPP);
2824
2825	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2826	if (error)
2827		return (error);
2828
2829	mac_relabel_vnode(ap->a_cred, vp, intlabel);
2830
2831	return (0);
2832}
2833
2834static int
2835vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
2836{
2837	int error;
2838
2839	if (vp->v_mount == NULL) {
2840		/* printf("vn_setlabel: null v_mount\n"); */
2841		if (vp->v_type != VNON)
2842			printf("vn_setlabel: null v_mount with non-VNON\n");
2843		return (EBADF);
2844	}
2845
2846	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2847		return (EOPNOTSUPP);
2848
2849	/*
2850	 * Multi-phase commit.  First check the policies to confirm the
2851	 * change is OK.  Then commit via the filesystem.  Finally,
2852	 * update the actual vnode label.  Question: maybe the filesystem
2853	 * should update the vnode at the end as part of VOP_SETLABEL()?
2854	 */
2855	error = mac_check_vnode_relabel(cred, vp, intlabel);
2856	if (error)
2857		return (error);
2858
2859	/*
2860	 * VADMIN provides the opportunity for the filesystem to make
2861	 * decisions about who is and is not able to modify labels
2862	 * and protections on files.  This might not be right.  We can't
2863	 * assume VOP_SETLABEL() will do it, because we might implement
2864	 * that as part of vop_stdsetlabel_ea().
2865	 */
2866	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
2867	if (error)
2868		return (error);
2869
2870	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
2871	if (error)
2872		return (error);
2873
2874	return (0);
2875}
2876
2877int
2878__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
2879{
2880	char *elements, *buffer;
2881	struct mac mac;
2882	struct proc *tproc;
2883	struct ucred *tcred;
2884	int error;
2885
2886	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
2887	if (error)
2888		return (error);
2889
2890	error = mac_check_structmac_consistent(&mac);
2891	if (error)
2892		return (error);
2893
2894	tproc = pfind(uap->pid);
2895	if (tproc == NULL)
2896		return (ESRCH);
2897
2898	tcred = NULL;				/* Satisfy gcc. */
2899	error = p_cansee(td, tproc);
2900	if (error == 0)
2901		tcred = crhold(tproc->p_ucred);
2902	PROC_UNLOCK(tproc);
2903	if (error)
2904		return (error);
2905
2906	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2907	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2908	if (error) {
2909		free(elements, M_MACTEMP);
2910		crfree(tcred);
2911		return (error);
2912	}
2913
2914	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2915	error = mac_externalize_cred_label(&tcred->cr_label, elements,
2916	    buffer, mac.m_buflen, M_WAITOK);
2917	if (error == 0)
2918		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2919
2920	free(buffer, M_MACTEMP);
2921	free(elements, M_MACTEMP);
2922	crfree(tcred);
2923	return (error);
2924}
2925
2926/*
2927 * MPSAFE
2928 */
2929int
2930__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
2931{
2932	char *elements, *buffer;
2933	struct mac mac;
2934	int error;
2935
2936	error = copyin(uap->mac_p, &mac, sizeof(mac));
2937	if (error)
2938		return (error);
2939
2940	error = mac_check_structmac_consistent(&mac);
2941	if (error)
2942		return (error);
2943
2944	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2945	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2946	if (error) {
2947		free(elements, M_MACTEMP);
2948		return (error);
2949	}
2950
2951	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2952	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
2953	    elements, buffer, mac.m_buflen, M_WAITOK);
2954	if (error == 0)
2955		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2956
2957	free(buffer, M_MACTEMP);
2958	free(elements, M_MACTEMP);
2959	return (error);
2960}
2961
2962/*
2963 * MPSAFE
2964 */
2965int
2966__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
2967{
2968	struct ucred *newcred, *oldcred;
2969	struct label intlabel;
2970	struct proc *p;
2971	struct mac mac;
2972	char *buffer;
2973	int error;
2974
2975	error = copyin(uap->mac_p, &mac, sizeof(mac));
2976	if (error)
2977		return (error);
2978
2979	error = mac_check_structmac_consistent(&mac);
2980	if (error)
2981		return (error);
2982
2983	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2984	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2985	if (error) {
2986		free(buffer, M_MACTEMP);
2987		return (error);
2988	}
2989
2990	mac_init_cred_label(&intlabel);
2991	error = mac_internalize_cred_label(&intlabel, buffer);
2992	free(buffer, M_MACTEMP);
2993	if (error) {
2994		mac_destroy_cred_label(&intlabel);
2995		return (error);
2996	}
2997
2998	newcred = crget();
2999
3000	p = td->td_proc;
3001	PROC_LOCK(p);
3002	oldcred = p->p_ucred;
3003
3004	error = mac_check_cred_relabel(oldcred, &intlabel);
3005	if (error) {
3006		PROC_UNLOCK(p);
3007		crfree(newcred);
3008		goto out;
3009	}
3010
3011	setsugid(p);
3012	crcopy(newcred, oldcred);
3013	mac_relabel_cred(newcred, &intlabel);
3014	p->p_ucred = newcred;
3015
3016	/*
3017	 * Grab additional reference for use while revoking mmaps, prior
3018	 * to releasing the proc lock and sharing the cred.
3019	 */
3020	crhold(newcred);
3021	PROC_UNLOCK(p);
3022
3023	if (mac_enforce_vm) {
3024		mtx_lock(&Giant);
3025		mac_cred_mmapped_drop_perms(td, newcred);
3026		mtx_unlock(&Giant);
3027	}
3028
3029	crfree(newcred);	/* Free revocation reference. */
3030	crfree(oldcred);
3031
3032out:
3033	mac_destroy_cred_label(&intlabel);
3034	return (error);
3035}
3036
3037/*
3038 * MPSAFE
3039 */
3040int
3041__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3042{
3043	char *elements, *buffer;
3044	struct label intlabel;
3045	struct file *fp;
3046	struct mac mac;
3047	struct vnode *vp;
3048	struct pipe *pipe;
3049	short label_type;
3050	int error;
3051
3052	error = copyin(uap->mac_p, &mac, sizeof(mac));
3053	if (error)
3054		return (error);
3055
3056	error = mac_check_structmac_consistent(&mac);
3057	if (error)
3058		return (error);
3059
3060	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3061	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3062	if (error) {
3063		free(elements, M_MACTEMP);
3064		return (error);
3065	}
3066
3067	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3068	mtx_lock(&Giant);				/* VFS */
3069	error = fget(td, SCARG(uap, fd), &fp);
3070	if (error)
3071		goto out;
3072
3073	label_type = fp->f_type;
3074	switch (fp->f_type) {
3075	case DTYPE_FIFO:
3076	case DTYPE_VNODE:
3077		vp = (struct vnode *)fp->f_data;
3078
3079		mac_init_vnode_label(&intlabel);
3080
3081		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3082		mac_copy_vnode_label(&vp->v_label, &intlabel);
3083		VOP_UNLOCK(vp, 0, td);
3084
3085		break;
3086	case DTYPE_PIPE:
3087		pipe = (struct pipe *)fp->f_data;
3088
3089		mac_init_pipe_label(&intlabel);
3090
3091		PIPE_LOCK(pipe);
3092		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3093		PIPE_UNLOCK(pipe);
3094		break;
3095	default:
3096		error = EINVAL;
3097		fdrop(fp, td);
3098		goto out;
3099	}
3100	fdrop(fp, td);
3101
3102	switch (label_type) {
3103	case DTYPE_FIFO:
3104	case DTYPE_VNODE:
3105		if (error == 0)
3106			error = mac_externalize_vnode_label(&intlabel,
3107			    elements, buffer, mac.m_buflen, M_WAITOK);
3108		mac_destroy_vnode_label(&intlabel);
3109		break;
3110	case DTYPE_PIPE:
3111		error = mac_externalize_pipe_label(&intlabel, elements,
3112		    buffer, mac.m_buflen, M_WAITOK);
3113		mac_destroy_pipe_label(&intlabel);
3114		break;
3115	default:
3116		panic("__mac_get_fd: corrupted label_type");
3117	}
3118
3119	if (error == 0)
3120		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3121
3122out:
3123	mtx_unlock(&Giant);				/* VFS */
3124	free(buffer, M_MACTEMP);
3125	free(elements, M_MACTEMP);
3126
3127	return (error);
3128}
3129
3130/*
3131 * MPSAFE
3132 */
3133int
3134__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3135{
3136	char *elements, *buffer;
3137	struct nameidata nd;
3138	struct label intlabel;
3139	struct mac mac;
3140	int error;
3141
3142	error = copyin(uap->mac_p, &mac, sizeof(mac));
3143	if (error)
3144		return (error);
3145
3146	error = mac_check_structmac_consistent(&mac);
3147	if (error)
3148		return (error);
3149
3150	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3151	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3152	if (error) {
3153		free(elements, M_MACTEMP);
3154		return (error);
3155	}
3156
3157	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3158	mtx_lock(&Giant);				/* VFS */
3159	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3160	    td);
3161	error = namei(&nd);
3162	if (error)
3163		goto out;
3164
3165	mac_init_vnode_label(&intlabel);
3166	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3167	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3168	    mac.m_buflen, M_WAITOK);
3169
3170	NDFREE(&nd, 0);
3171	mac_destroy_vnode_label(&intlabel);
3172
3173	if (error == 0)
3174		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3175
3176out:
3177	mtx_unlock(&Giant);				/* VFS */
3178
3179	free(buffer, M_MACTEMP);
3180	free(elements, M_MACTEMP);
3181
3182	return (error);
3183}
3184
3185/*
3186 * MPSAFE
3187 */
3188int
3189__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3190{
3191	char *elements, *buffer;
3192	struct nameidata nd;
3193	struct label intlabel;
3194	struct mac mac;
3195	int error;
3196
3197	error = copyin(uap->mac_p, &mac, sizeof(mac));
3198	if (error)
3199		return (error);
3200
3201	error = mac_check_structmac_consistent(&mac);
3202	if (error)
3203		return (error);
3204
3205	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3206	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3207	if (error) {
3208		free(elements, M_MACTEMP);
3209		return (error);
3210	}
3211
3212	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3213	mtx_lock(&Giant);				/* VFS */
3214	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3215	    td);
3216	error = namei(&nd);
3217	if (error)
3218		goto out;
3219
3220	mac_init_vnode_label(&intlabel);
3221	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3222	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3223	    mac.m_buflen, M_WAITOK);
3224	NDFREE(&nd, 0);
3225	mac_destroy_vnode_label(&intlabel);
3226
3227	if (error == 0)
3228		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3229
3230out:
3231	mtx_unlock(&Giant);				/* VFS */
3232
3233	free(buffer, M_MACTEMP);
3234	free(elements, M_MACTEMP);
3235
3236	return (error);
3237}
3238
3239/*
3240 * MPSAFE
3241 */
3242int
3243__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3244{
3245	struct label intlabel;
3246	struct pipe *pipe;
3247	struct file *fp;
3248	struct mount *mp;
3249	struct vnode *vp;
3250	struct mac mac;
3251	char *buffer;
3252	int error;
3253
3254	error = copyin(uap->mac_p, &mac, sizeof(mac));
3255	if (error)
3256		return (error);
3257
3258	error = mac_check_structmac_consistent(&mac);
3259	if (error)
3260		return (error);
3261
3262	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3263	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3264	if (error) {
3265		free(buffer, M_MACTEMP);
3266		return (error);
3267	}
3268
3269	mtx_lock(&Giant);				/* VFS */
3270
3271	error = fget(td, SCARG(uap, fd), &fp);
3272	if (error)
3273		goto out;
3274
3275	switch (fp->f_type) {
3276	case DTYPE_FIFO:
3277	case DTYPE_VNODE:
3278		mac_init_vnode_label(&intlabel);
3279		error = mac_internalize_vnode_label(&intlabel, buffer);
3280		if (error) {
3281			mac_destroy_vnode_label(&intlabel);
3282			break;
3283		}
3284
3285		vp = (struct vnode *)fp->f_data;
3286		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3287		if (error != 0) {
3288			mac_destroy_vnode_label(&intlabel);
3289			break;
3290		}
3291
3292		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3293		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3294		VOP_UNLOCK(vp, 0, td);
3295		vn_finished_write(mp);
3296
3297		mac_destroy_vnode_label(&intlabel);
3298		break;
3299
3300	case DTYPE_PIPE:
3301		mac_init_pipe_label(&intlabel);
3302		error = mac_internalize_pipe_label(&intlabel, buffer);
3303		if (error == 0) {
3304			pipe = (struct pipe *)fp->f_data;
3305			PIPE_LOCK(pipe);
3306			error = mac_pipe_label_set(td->td_ucred, pipe,
3307			    &intlabel);
3308			PIPE_UNLOCK(pipe);
3309		}
3310
3311		mac_destroy_pipe_label(&intlabel);
3312		break;
3313
3314	default:
3315		error = EINVAL;
3316	}
3317
3318	fdrop(fp, td);
3319out:
3320	mtx_unlock(&Giant);				/* VFS */
3321
3322	free(buffer, M_MACTEMP);
3323
3324	return (error);
3325}
3326
3327/*
3328 * MPSAFE
3329 */
3330int
3331__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3332{
3333	struct label intlabel;
3334	struct nameidata nd;
3335	struct mount *mp;
3336	struct mac mac;
3337	char *buffer;
3338	int error;
3339
3340	error = copyin(uap->mac_p, &mac, sizeof(mac));
3341	if (error)
3342		return (error);
3343
3344	error = mac_check_structmac_consistent(&mac);
3345	if (error)
3346		return (error);
3347
3348	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3349	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3350	if (error) {
3351		free(buffer, M_MACTEMP);
3352		return (error);
3353	}
3354
3355	mac_init_vnode_label(&intlabel);
3356	error = mac_internalize_vnode_label(&intlabel, buffer);
3357	free(buffer, M_MACTEMP);
3358	if (error) {
3359		mac_destroy_vnode_label(&intlabel);
3360		return (error);
3361	}
3362
3363	mtx_lock(&Giant);				/* VFS */
3364
3365	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3366	    td);
3367	error = namei(&nd);
3368	if (error == 0) {
3369		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3370		if (error == 0)
3371			error = vn_setlabel(nd.ni_vp, &intlabel,
3372			    td->td_ucred);
3373		vn_finished_write(mp);
3374	}
3375
3376	NDFREE(&nd, 0);
3377	mtx_unlock(&Giant);				/* VFS */
3378	mac_destroy_vnode_label(&intlabel);
3379
3380	return (error);
3381}
3382
3383/*
3384 * MPSAFE
3385 */
3386int
3387__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3388{
3389	struct label intlabel;
3390	struct nameidata nd;
3391	struct mount *mp;
3392	struct mac mac;
3393	char *buffer;
3394	int error;
3395
3396	error = copyin(uap->mac_p, &mac, sizeof(mac));
3397	if (error)
3398		return (error);
3399
3400	error = mac_check_structmac_consistent(&mac);
3401	if (error)
3402		return (error);
3403
3404	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3405	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3406	if (error) {
3407		free(buffer, M_MACTEMP);
3408		return (error);
3409	}
3410
3411	mac_init_vnode_label(&intlabel);
3412	error = mac_internalize_vnode_label(&intlabel, buffer);
3413	free(buffer, M_MACTEMP);
3414	if (error) {
3415		mac_destroy_vnode_label(&intlabel);
3416		return (error);
3417	}
3418
3419	mtx_lock(&Giant);				/* VFS */
3420
3421	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3422	    td);
3423	error = namei(&nd);
3424	if (error == 0) {
3425		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3426		if (error == 0)
3427			error = vn_setlabel(nd.ni_vp, &intlabel,
3428			    td->td_ucred);
3429		vn_finished_write(mp);
3430	}
3431
3432	NDFREE(&nd, 0);
3433	mtx_unlock(&Giant);				/* VFS */
3434	mac_destroy_vnode_label(&intlabel);
3435
3436	return (error);
3437}
3438
3439/*
3440 * MPSAFE
3441 */
3442int
3443mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3444{
3445	struct mac_policy_conf *mpc;
3446	char target[MAC_MAX_POLICY_NAME];
3447	int error;
3448
3449	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3450	if (error)
3451		return (error);
3452
3453	error = ENOSYS;
3454	MAC_POLICY_LIST_BUSY();
3455	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3456		if (strcmp(mpc->mpc_name, target) == 0 &&
3457		    mpc->mpc_ops->mpo_syscall != NULL) {
3458			error = mpc->mpc_ops->mpo_syscall(td,
3459			    SCARG(uap, call), SCARG(uap, arg));
3460			goto out;
3461		}
3462	}
3463
3464out:
3465	MAC_POLICY_LIST_UNBUSY();
3466	return (error);
3467}
3468
3469SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3470SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3471
3472#else /* !MAC */
3473
3474int
3475__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3476{
3477
3478	return (ENOSYS);
3479}
3480
3481int
3482__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3483{
3484
3485	return (ENOSYS);
3486}
3487
3488int
3489__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3490{
3491
3492	return (ENOSYS);
3493}
3494
3495int
3496__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3497{
3498
3499	return (ENOSYS);
3500}
3501
3502int
3503__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3504{
3505
3506	return (ENOSYS);
3507}
3508
3509int
3510__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3511{
3512
3513	return (ENOSYS);
3514}
3515
3516int
3517__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3518{
3519
3520	return (ENOSYS);
3521}
3522
3523int
3524__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3525{
3526
3527	return (ENOSYS);
3528}
3529
3530int
3531__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3532{
3533
3534	return (ENOSYS);
3535}
3536
3537int
3538mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3539{
3540
3541	return (ENOSYS);
3542}
3543
3544#endif
3545