mac_internal.h revision 106410
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson and Ilmar Habibulin for the
8 * TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: head/sys/security/mac/mac_internal.h 106410 2002-11-04 14:55:14Z 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_reboot(struct ucred *cred, int howto)
2474{
2475	int error;
2476
2477	if (!mac_enforce_system)
2478		return (0);
2479
2480	MAC_CHECK(check_system_reboot, cred, howto);
2481
2482	return (error);
2483}
2484
2485int
2486mac_check_system_settime(struct ucred *cred)
2487{
2488	int error;
2489
2490	if (!mac_enforce_system)
2491		return (0);
2492
2493	MAC_CHECK(check_system_settime, cred);
2494
2495	return (error);
2496}
2497
2498int
2499mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2500{
2501	int error;
2502
2503	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2504
2505	if (!mac_enforce_system)
2506		return (0);
2507
2508	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2509	return (error);
2510}
2511
2512int
2513mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2514    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2515{
2516	int error;
2517
2518	/*
2519	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2520	 * but since it's not exported from kern_sysctl.c, we can't.
2521	 */
2522	if (!mac_enforce_system)
2523		return (0);
2524
2525	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2526	    inkernel, new, newlen);
2527
2528	return (error);
2529}
2530
2531int
2532mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2533    struct ifnet *ifnet)
2534{
2535	char *elements, *buffer;
2536	struct mac mac;
2537	int error;
2538
2539	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2540	if (error)
2541		return (error);
2542
2543	error = mac_check_structmac_consistent(&mac);
2544	if (error)
2545		return (error);
2546
2547	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2548	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2549	if (error) {
2550		free(elements, M_MACTEMP);
2551		return (error);
2552	}
2553
2554	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2555	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2556	    buffer, mac.m_buflen, M_WAITOK);
2557	if (error == 0)
2558		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2559
2560	free(buffer, M_MACTEMP);
2561	free(elements, M_MACTEMP);
2562
2563	return (error);
2564}
2565
2566int
2567mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2568    struct ifnet *ifnet)
2569{
2570	struct label intlabel;
2571	struct mac mac;
2572	char *buffer;
2573	int error;
2574
2575	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2576	if (error)
2577		return (error);
2578
2579	error = mac_check_structmac_consistent(&mac);
2580	if (error)
2581		return (error);
2582
2583	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2584	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2585	if (error) {
2586		free(buffer, M_MACTEMP);
2587		return (error);
2588	}
2589
2590	mac_init_ifnet_label(&intlabel);
2591	error = mac_internalize_ifnet_label(&intlabel, buffer);
2592	free(buffer, M_MACTEMP);
2593	if (error) {
2594		mac_destroy_ifnet_label(&intlabel);
2595		return (error);
2596	}
2597
2598	/*
2599	 * XXX: Note that this is a redundant privilege check, since
2600	 * policies impose this check themselves if required by the
2601	 * policy.  Eventually, this should go away.
2602	 */
2603	error = suser_cred(cred, 0);
2604	if (error) {
2605		mac_destroy_ifnet_label(&intlabel);
2606		return (error);
2607	}
2608
2609	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2610	    &intlabel);
2611	if (error) {
2612		mac_destroy_ifnet_label(&intlabel);
2613		return (error);
2614	}
2615
2616	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2617
2618	mac_destroy_ifnet_label(&intlabel);
2619	return (0);
2620}
2621
2622void
2623mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2624{
2625
2626	MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2627}
2628
2629void
2630mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2631{
2632
2633	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2634}
2635
2636void
2637mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
2638    struct devfs_dirent *de)
2639{
2640
2641	MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
2642	    &de->de_label);
2643}
2644
2645void
2646mac_create_devfs_directory(char *dirname, int dirnamelen,
2647    struct devfs_dirent *de)
2648{
2649
2650	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2651	    &de->de_label);
2652}
2653
2654int
2655mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2656    struct mac *mac)
2657{
2658	struct label intlabel;
2659	char *buffer;
2660	int error;
2661
2662	error = mac_check_structmac_consistent(mac);
2663	if (error)
2664		return (error);
2665
2666	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2667	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2668	if (error) {
2669		free(buffer, M_MACTEMP);
2670		return (error);
2671	}
2672
2673	mac_init_socket_label(&intlabel, M_WAITOK);
2674	error = mac_internalize_socket_label(&intlabel, buffer);
2675	free(buffer, M_MACTEMP);
2676	if (error) {
2677		mac_destroy_socket_label(&intlabel);
2678		return (error);
2679	}
2680
2681	mac_check_socket_relabel(cred, so, &intlabel);
2682	if (error) {
2683		mac_destroy_socket_label(&intlabel);
2684		return (error);
2685	}
2686
2687	mac_relabel_socket(cred, so, &intlabel);
2688
2689	mac_destroy_socket_label(&intlabel);
2690	return (0);
2691}
2692
2693int
2694mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2695{
2696	int error;
2697
2698	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2699
2700	error = mac_check_pipe_relabel(cred, pipe, label);
2701	if (error)
2702		return (error);
2703
2704	mac_relabel_pipe(cred, pipe, label);
2705
2706	return (0);
2707}
2708
2709int
2710mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2711    struct mac *mac)
2712{
2713	char *buffer, *elements;
2714	int error;
2715
2716	error = mac_check_structmac_consistent(mac);
2717	if (error)
2718		return (error);
2719
2720	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2721	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2722	if (error) {
2723		free(elements, M_MACTEMP);
2724		return (error);
2725	}
2726
2727	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2728	error = mac_externalize_socket_label(&so->so_label, elements,
2729	    buffer, mac->m_buflen, M_WAITOK);
2730	if (error == 0)
2731		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2732
2733	free(buffer, M_MACTEMP);
2734	free(elements, M_MACTEMP);
2735
2736	return (error);
2737}
2738
2739int
2740mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2741    struct mac *mac)
2742{
2743	char *elements, *buffer;
2744	int error;
2745
2746	error = mac_check_structmac_consistent(mac);
2747	if (error)
2748		return (error);
2749
2750	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2751	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2752	if (error) {
2753		free(elements, M_MACTEMP);
2754		return (error);
2755	}
2756
2757	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2758	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2759	    elements, buffer, mac->m_buflen, M_WAITOK);
2760	if (error == 0)
2761		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2762
2763	free(buffer, M_MACTEMP);
2764	free(elements, M_MACTEMP);
2765
2766	return (error);
2767}
2768
2769/*
2770 * Implementation of VOP_SETLABEL() that relies on extended attributes
2771 * to store label data.  Can be referenced by filesystems supporting
2772 * extended attributes.
2773 */
2774int
2775vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2776{
2777	struct vnode *vp = ap->a_vp;
2778	struct label *intlabel = ap->a_label;
2779	int error;
2780
2781	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2782
2783	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2784		return (EOPNOTSUPP);
2785
2786	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2787	if (error)
2788		return (error);
2789
2790	mac_relabel_vnode(ap->a_cred, vp, intlabel);
2791
2792	return (0);
2793}
2794
2795static int
2796vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
2797{
2798	int error;
2799
2800	if (vp->v_mount == NULL) {
2801		/* printf("vn_setlabel: null v_mount\n"); */
2802		if (vp->v_type != VNON)
2803			printf("vn_setlabel: null v_mount with non-VNON\n");
2804		return (EBADF);
2805	}
2806
2807	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2808		return (EOPNOTSUPP);
2809
2810	/*
2811	 * Multi-phase commit.  First check the policies to confirm the
2812	 * change is OK.  Then commit via the filesystem.  Finally,
2813	 * update the actual vnode label.  Question: maybe the filesystem
2814	 * should update the vnode at the end as part of VOP_SETLABEL()?
2815	 */
2816	error = mac_check_vnode_relabel(cred, vp, intlabel);
2817	if (error)
2818		return (error);
2819
2820	/*
2821	 * VADMIN provides the opportunity for the filesystem to make
2822	 * decisions about who is and is not able to modify labels
2823	 * and protections on files.  This might not be right.  We can't
2824	 * assume VOP_SETLABEL() will do it, because we might implement
2825	 * that as part of vop_stdsetlabel_ea().
2826	 */
2827	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
2828	if (error)
2829		return (error);
2830
2831	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
2832	if (error)
2833		return (error);
2834
2835	return (0);
2836}
2837
2838int
2839__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
2840{
2841	char *elements, *buffer;
2842	struct mac mac;
2843	struct proc *tproc;
2844	struct ucred *tcred;
2845	int error;
2846
2847	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
2848	if (error)
2849		return (error);
2850
2851	error = mac_check_structmac_consistent(&mac);
2852	if (error)
2853		return (error);
2854
2855	tproc = pfind(uap->pid);
2856	if (tproc == NULL)
2857		return (ESRCH);
2858
2859	tcred = NULL;				/* Satisfy gcc. */
2860	error = p_cansee(td, tproc);
2861	if (error == 0)
2862		tcred = crhold(tproc->p_ucred);
2863	PROC_UNLOCK(tproc);
2864	if (error)
2865		return (error);
2866
2867	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2868	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2869	if (error) {
2870		free(elements, M_MACTEMP);
2871		crfree(tcred);
2872		return (error);
2873	}
2874
2875	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2876	error = mac_externalize_cred_label(&tcred->cr_label, elements,
2877	    buffer, mac.m_buflen, M_WAITOK);
2878	if (error == 0)
2879		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2880
2881	free(buffer, M_MACTEMP);
2882	free(elements, M_MACTEMP);
2883	crfree(tcred);
2884	return (error);
2885}
2886
2887/*
2888 * MPSAFE
2889 */
2890int
2891__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
2892{
2893	char *elements, *buffer;
2894	struct mac mac;
2895	int error;
2896
2897	error = copyin(uap->mac_p, &mac, sizeof(mac));
2898	if (error)
2899		return (error);
2900
2901	error = mac_check_structmac_consistent(&mac);
2902	if (error)
2903		return (error);
2904
2905	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2906	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2907	if (error) {
2908		free(elements, M_MACTEMP);
2909		return (error);
2910	}
2911
2912	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2913	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
2914	    elements, buffer, mac.m_buflen, M_WAITOK);
2915	if (error == 0)
2916		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2917
2918	free(buffer, M_MACTEMP);
2919	free(elements, M_MACTEMP);
2920	return (error);
2921}
2922
2923/*
2924 * MPSAFE
2925 */
2926int
2927__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
2928{
2929	struct ucred *newcred, *oldcred;
2930	struct label intlabel;
2931	struct proc *p;
2932	struct mac mac;
2933	char *buffer;
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	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2945	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2946	if (error) {
2947		free(buffer, M_MACTEMP);
2948		return (error);
2949	}
2950
2951	mac_init_cred_label(&intlabel);
2952	error = mac_internalize_cred_label(&intlabel, buffer);
2953	free(buffer, M_MACTEMP);
2954	if (error) {
2955		mac_destroy_cred_label(&intlabel);
2956		return (error);
2957	}
2958
2959	newcred = crget();
2960
2961	p = td->td_proc;
2962	PROC_LOCK(p);
2963	oldcred = p->p_ucred;
2964
2965	error = mac_check_cred_relabel(oldcred, &intlabel);
2966	if (error) {
2967		PROC_UNLOCK(p);
2968		crfree(newcred);
2969		goto out;
2970	}
2971
2972	setsugid(p);
2973	crcopy(newcred, oldcred);
2974	mac_relabel_cred(newcred, &intlabel);
2975	p->p_ucred = newcred;
2976
2977	/*
2978	 * Grab additional reference for use while revoking mmaps, prior
2979	 * to releasing the proc lock and sharing the cred.
2980	 */
2981	crhold(newcred);
2982	PROC_UNLOCK(p);
2983
2984	if (mac_enforce_vm) {
2985		mtx_lock(&Giant);
2986		mac_cred_mmapped_drop_perms(td, newcred);
2987		mtx_unlock(&Giant);
2988	}
2989
2990	crfree(newcred);	/* Free revocation reference. */
2991	crfree(oldcred);
2992
2993out:
2994	mac_destroy_cred_label(&intlabel);
2995	return (error);
2996}
2997
2998/*
2999 * MPSAFE
3000 */
3001int
3002__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3003{
3004	char *elements, *buffer;
3005	struct label intlabel;
3006	struct file *fp;
3007	struct mac mac;
3008	struct vnode *vp;
3009	struct pipe *pipe;
3010	short label_type;
3011	int error;
3012
3013	error = copyin(uap->mac_p, &mac, sizeof(mac));
3014	if (error)
3015		return (error);
3016
3017	error = mac_check_structmac_consistent(&mac);
3018	if (error)
3019		return (error);
3020
3021	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3022	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3023	if (error) {
3024		free(elements, M_MACTEMP);
3025		return (error);
3026	}
3027
3028	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3029	mtx_lock(&Giant);				/* VFS */
3030	error = fget(td, SCARG(uap, fd), &fp);
3031	if (error)
3032		goto out;
3033
3034	label_type = fp->f_type;
3035	switch (fp->f_type) {
3036	case DTYPE_FIFO:
3037	case DTYPE_VNODE:
3038		vp = (struct vnode *)fp->f_data;
3039
3040		mac_init_vnode_label(&intlabel);
3041
3042		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3043		mac_copy_vnode_label(&vp->v_label, &intlabel);
3044		VOP_UNLOCK(vp, 0, td);
3045
3046		break;
3047	case DTYPE_PIPE:
3048		pipe = (struct pipe *)fp->f_data;
3049
3050		mac_init_pipe_label(&intlabel);
3051
3052		PIPE_LOCK(pipe);
3053		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3054		PIPE_UNLOCK(pipe);
3055		break;
3056	default:
3057		error = EINVAL;
3058		fdrop(fp, td);
3059		goto out;
3060	}
3061	fdrop(fp, td);
3062
3063	switch (label_type) {
3064	case DTYPE_FIFO:
3065	case DTYPE_VNODE:
3066		if (error == 0)
3067			error = mac_externalize_vnode_label(&intlabel,
3068			    elements, buffer, mac.m_buflen, M_WAITOK);
3069		mac_destroy_vnode_label(&intlabel);
3070		break;
3071	case DTYPE_PIPE:
3072		error = mac_externalize_pipe_label(&intlabel, elements,
3073		    buffer, mac.m_buflen, M_WAITOK);
3074		mac_destroy_pipe_label(&intlabel);
3075		break;
3076	default:
3077		panic("__mac_get_fd: corrupted label_type");
3078	}
3079
3080	if (error == 0)
3081		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3082
3083out:
3084	mtx_unlock(&Giant);				/* VFS */
3085	free(buffer, M_MACTEMP);
3086	free(elements, M_MACTEMP);
3087
3088	return (error);
3089}
3090
3091/*
3092 * MPSAFE
3093 */
3094int
3095__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3096{
3097	char *elements, *buffer;
3098	struct nameidata nd;
3099	struct label intlabel;
3100	struct mac mac;
3101	int error;
3102
3103	error = copyin(uap->mac_p, &mac, sizeof(mac));
3104	if (error)
3105		return (error);
3106
3107	error = mac_check_structmac_consistent(&mac);
3108	if (error)
3109		return (error);
3110
3111	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3112	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3113	if (error) {
3114		free(elements, M_MACTEMP);
3115		return (error);
3116	}
3117
3118	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3119	mtx_lock(&Giant);				/* VFS */
3120	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3121	    td);
3122	error = namei(&nd);
3123	if (error)
3124		goto out;
3125
3126	mac_init_vnode_label(&intlabel);
3127	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3128	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3129	    mac.m_buflen, M_WAITOK);
3130
3131	NDFREE(&nd, 0);
3132	mac_destroy_vnode_label(&intlabel);
3133
3134	if (error == 0)
3135		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3136
3137out:
3138	mtx_unlock(&Giant);				/* VFS */
3139
3140	free(buffer, M_MACTEMP);
3141	free(elements, M_MACTEMP);
3142
3143	return (error);
3144}
3145
3146/*
3147 * MPSAFE
3148 */
3149int
3150__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3151{
3152	char *elements, *buffer;
3153	struct nameidata nd;
3154	struct label intlabel;
3155	struct mac mac;
3156	int error;
3157
3158	error = copyin(uap->mac_p, &mac, sizeof(mac));
3159	if (error)
3160		return (error);
3161
3162	error = mac_check_structmac_consistent(&mac);
3163	if (error)
3164		return (error);
3165
3166	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3167	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3168	if (error) {
3169		free(elements, M_MACTEMP);
3170		return (error);
3171	}
3172
3173	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3174	mtx_lock(&Giant);				/* VFS */
3175	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3176	    td);
3177	error = namei(&nd);
3178	if (error)
3179		goto out;
3180
3181	mac_init_vnode_label(&intlabel);
3182	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3183	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3184	    mac.m_buflen, M_WAITOK);
3185	NDFREE(&nd, 0);
3186	mac_destroy_vnode_label(&intlabel);
3187
3188	if (error == 0)
3189		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3190
3191out:
3192	mtx_unlock(&Giant);				/* VFS */
3193
3194	free(buffer, M_MACTEMP);
3195	free(elements, M_MACTEMP);
3196
3197	return (error);
3198}
3199
3200/*
3201 * MPSAFE
3202 */
3203int
3204__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3205{
3206	struct label intlabel;
3207	struct pipe *pipe;
3208	struct file *fp;
3209	struct mount *mp;
3210	struct vnode *vp;
3211	struct mac mac;
3212	char *buffer;
3213	int error;
3214
3215	error = copyin(uap->mac_p, &mac, sizeof(mac));
3216	if (error)
3217		return (error);
3218
3219	error = mac_check_structmac_consistent(&mac);
3220	if (error)
3221		return (error);
3222
3223	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3224	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3225	if (error) {
3226		free(buffer, M_MACTEMP);
3227		return (error);
3228	}
3229
3230	mtx_lock(&Giant);				/* VFS */
3231
3232	error = fget(td, SCARG(uap, fd), &fp);
3233	if (error)
3234		goto out;
3235
3236	switch (fp->f_type) {
3237	case DTYPE_FIFO:
3238	case DTYPE_VNODE:
3239		mac_init_vnode_label(&intlabel);
3240		error = mac_internalize_vnode_label(&intlabel, buffer);
3241		if (error) {
3242			mac_destroy_vnode_label(&intlabel);
3243			break;
3244		}
3245
3246		vp = (struct vnode *)fp->f_data;
3247		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3248		if (error != 0) {
3249			mac_destroy_vnode_label(&intlabel);
3250			break;
3251		}
3252
3253		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3254		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3255		VOP_UNLOCK(vp, 0, td);
3256		vn_finished_write(mp);
3257
3258		mac_destroy_vnode_label(&intlabel);
3259		break;
3260
3261	case DTYPE_PIPE:
3262		mac_init_pipe_label(&intlabel);
3263		error = mac_internalize_pipe_label(&intlabel, buffer);
3264		if (error == 0) {
3265			pipe = (struct pipe *)fp->f_data;
3266			PIPE_LOCK(pipe);
3267			error = mac_pipe_label_set(td->td_ucred, pipe,
3268			    &intlabel);
3269			PIPE_UNLOCK(pipe);
3270		}
3271
3272		mac_destroy_pipe_label(&intlabel);
3273		break;
3274
3275	default:
3276		error = EINVAL;
3277	}
3278
3279	fdrop(fp, td);
3280out:
3281	mtx_unlock(&Giant);				/* VFS */
3282
3283	free(buffer, M_MACTEMP);
3284
3285	return (error);
3286}
3287
3288/*
3289 * MPSAFE
3290 */
3291int
3292__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3293{
3294	struct label intlabel;
3295	struct nameidata nd;
3296	struct mount *mp;
3297	struct mac mac;
3298	char *buffer;
3299	int error;
3300
3301	error = copyin(uap->mac_p, &mac, sizeof(mac));
3302	if (error)
3303		return (error);
3304
3305	error = mac_check_structmac_consistent(&mac);
3306	if (error)
3307		return (error);
3308
3309	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3310	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3311	if (error) {
3312		free(buffer, M_MACTEMP);
3313		return (error);
3314	}
3315
3316	mac_init_vnode_label(&intlabel);
3317	error = mac_internalize_vnode_label(&intlabel, buffer);
3318	free(buffer, M_MACTEMP);
3319	if (error) {
3320		mac_destroy_vnode_label(&intlabel);
3321		return (error);
3322	}
3323
3324	mtx_lock(&Giant);				/* VFS */
3325
3326	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3327	    td);
3328	error = namei(&nd);
3329	if (error == 0) {
3330		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3331		if (error == 0)
3332			error = vn_setlabel(nd.ni_vp, &intlabel,
3333			    td->td_ucred);
3334		vn_finished_write(mp);
3335	}
3336
3337	NDFREE(&nd, 0);
3338	mtx_unlock(&Giant);				/* VFS */
3339	mac_destroy_vnode_label(&intlabel);
3340
3341	return (error);
3342}
3343
3344/*
3345 * MPSAFE
3346 */
3347int
3348__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3349{
3350	struct label intlabel;
3351	struct nameidata nd;
3352	struct mount *mp;
3353	struct mac mac;
3354	char *buffer;
3355	int error;
3356
3357	error = copyin(uap->mac_p, &mac, sizeof(mac));
3358	if (error)
3359		return (error);
3360
3361	error = mac_check_structmac_consistent(&mac);
3362	if (error)
3363		return (error);
3364
3365	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3366	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3367	if (error) {
3368		free(buffer, M_MACTEMP);
3369		return (error);
3370	}
3371
3372	mac_init_vnode_label(&intlabel);
3373	error = mac_internalize_vnode_label(&intlabel, buffer);
3374	free(buffer, M_MACTEMP);
3375	if (error) {
3376		mac_destroy_vnode_label(&intlabel);
3377		return (error);
3378	}
3379
3380	mtx_lock(&Giant);				/* VFS */
3381
3382	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3383	    td);
3384	error = namei(&nd);
3385	if (error == 0) {
3386		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3387		if (error == 0)
3388			error = vn_setlabel(nd.ni_vp, &intlabel,
3389			    td->td_ucred);
3390		vn_finished_write(mp);
3391	}
3392
3393	NDFREE(&nd, 0);
3394	mtx_unlock(&Giant);				/* VFS */
3395	mac_destroy_vnode_label(&intlabel);
3396
3397	return (error);
3398}
3399
3400/*
3401 * MPSAFE
3402 */
3403int
3404mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3405{
3406	struct mac_policy_conf *mpc;
3407	char target[MAC_MAX_POLICY_NAME];
3408	int error;
3409
3410	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3411	if (error)
3412		return (error);
3413
3414	error = ENOSYS;
3415	MAC_POLICY_LIST_BUSY();
3416	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3417		if (strcmp(mpc->mpc_name, target) == 0 &&
3418		    mpc->mpc_ops->mpo_syscall != NULL) {
3419			error = mpc->mpc_ops->mpo_syscall(td,
3420			    SCARG(uap, call), SCARG(uap, arg));
3421			goto out;
3422		}
3423	}
3424
3425out:
3426	MAC_POLICY_LIST_UNBUSY();
3427	return (error);
3428}
3429
3430SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3431SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3432
3433#else /* !MAC */
3434
3435int
3436__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3437{
3438
3439	return (ENOSYS);
3440}
3441
3442int
3443__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3444{
3445
3446	return (ENOSYS);
3447}
3448
3449int
3450__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3451{
3452
3453	return (ENOSYS);
3454}
3455
3456int
3457__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3458{
3459
3460	return (ENOSYS);
3461}
3462
3463int
3464__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3465{
3466
3467	return (ENOSYS);
3468}
3469
3470int
3471__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3472{
3473
3474	return (ENOSYS);
3475}
3476
3477int
3478__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3479{
3480
3481	return (ENOSYS);
3482}
3483
3484int
3485__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3486{
3487
3488	return (ENOSYS);
3489}
3490
3491int
3492__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3493{
3494
3495	return (ENOSYS);
3496}
3497
3498int
3499mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3500{
3501
3502	return (ENOSYS);
3503}
3504
3505#endif
3506