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