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