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