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