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