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