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