mac_cred.c revision 106045
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson and Ilmar Habibulin for the
8 * TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by NAI Labs,
11 * the Security Research Division of Network Associates, Inc. under
12 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
13 * CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 * 3. The names of the authors may not be used to endorse or promote
24 *    products derived from this software without specific prior written
25 *    permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * $FreeBSD: head/sys/security/mac/mac_process.c 106045 2002-10-27 15:50:49Z 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 flags)
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, flags);
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, mode_t 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	ASSERT_VOP_LOCKED(vp, "mac_check_system_reboot");
3018
3019	if (!mac_enforce_system)
3020		return (0);
3021
3022	MAC_CHECK(check_system_reboot, cred, howto);
3023
3024	return (error);
3025}
3026
3027int
3028mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
3029{
3030	int error;
3031
3032	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
3033
3034	if (!mac_enforce_system)
3035		return (0);
3036
3037	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
3038	return (error);
3039}
3040
3041int
3042mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
3043    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
3044{
3045	int error;
3046
3047	/*
3048	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
3049	 * but since it's not exported from kern_sysctl.c, we can't.
3050	 */
3051	if (!mac_enforce_system)
3052		return (0);
3053
3054	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
3055	    inkernel, new, newlen);
3056
3057	return (error);
3058}
3059
3060int
3061mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
3062    struct ifnet *ifnet)
3063{
3064	char *elements, *buffer;
3065	struct mac mac;
3066	int error;
3067
3068	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3069	if (error)
3070		return (error);
3071
3072	error = mac_check_structmac_consistent(&mac);
3073	if (error)
3074		return (error);
3075
3076	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3077	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3078	if (error) {
3079		free(elements, M_MACTEMP);
3080		return (error);
3081	}
3082
3083	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3084	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3085	    buffer, mac.m_buflen, M_WAITOK);
3086	if (error == 0)
3087		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3088
3089	free(buffer, M_MACTEMP);
3090	free(elements, M_MACTEMP);
3091
3092	return (error);
3093}
3094
3095int
3096mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3097    struct ifnet *ifnet)
3098{
3099	struct label intlabel;
3100	struct mac mac;
3101	char *buffer;
3102	int error;
3103
3104	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3105	if (error)
3106		return (error);
3107
3108	error = mac_check_structmac_consistent(&mac);
3109	if (error)
3110		return (error);
3111
3112	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3113	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3114	if (error) {
3115		free(buffer, M_MACTEMP);
3116		return (error);
3117	}
3118
3119	mac_init_ifnet_label(&intlabel);
3120	error = mac_internalize_ifnet_label(&intlabel, buffer);
3121	free(buffer, M_MACTEMP);
3122	if (error) {
3123		mac_destroy_ifnet_label(&intlabel);
3124		return (error);
3125	}
3126
3127	/*
3128	 * XXX: Note that this is a redundant privilege check, since
3129	 * policies impose this check themselves if required by the
3130	 * policy.  Eventually, this should go away.
3131	 */
3132	error = suser_cred(cred, 0);
3133	if (error) {
3134		mac_destroy_ifnet_label(&intlabel);
3135		return (error);
3136	}
3137
3138	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3139	    &intlabel);
3140	if (error) {
3141		mac_destroy_ifnet_label(&intlabel);
3142		return (error);
3143	}
3144
3145	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3146
3147	mac_destroy_ifnet_label(&intlabel);
3148	return (0);
3149}
3150
3151void
3152mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
3153{
3154
3155	MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
3156}
3157
3158void
3159mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
3160{
3161
3162	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
3163}
3164
3165void
3166mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
3167    struct devfs_dirent *de)
3168{
3169
3170	MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
3171	    &de->de_label);
3172}
3173
3174void
3175mac_create_devfs_directory(char *dirname, int dirnamelen,
3176    struct devfs_dirent *de)
3177{
3178
3179	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
3180	    &de->de_label);
3181}
3182
3183int
3184mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3185    struct mac *mac)
3186{
3187	struct label intlabel;
3188	char *buffer;
3189	int error;
3190
3191	error = mac_check_structmac_consistent(mac);
3192	if (error)
3193		return (error);
3194
3195	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3196	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3197	if (error) {
3198		free(buffer, M_MACTEMP);
3199		return (error);
3200	}
3201
3202	mac_init_socket_label(&intlabel, M_WAITOK);
3203	error = mac_internalize_socket_label(&intlabel, buffer);
3204	free(buffer, M_MACTEMP);
3205	if (error) {
3206		mac_destroy_socket_label(&intlabel);
3207		return (error);
3208	}
3209
3210	mac_check_socket_relabel(cred, so, &intlabel);
3211	if (error) {
3212		mac_destroy_socket_label(&intlabel);
3213		return (error);
3214	}
3215
3216	mac_relabel_socket(cred, so, &intlabel);
3217
3218	mac_destroy_socket_label(&intlabel);
3219	return (0);
3220}
3221
3222int
3223mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3224{
3225	int error;
3226
3227	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3228
3229	error = mac_check_pipe_relabel(cred, pipe, label);
3230	if (error)
3231		return (error);
3232
3233	mac_relabel_pipe(cred, pipe, label);
3234
3235	return (0);
3236}
3237
3238int
3239mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3240    struct mac *mac)
3241{
3242	char *buffer, *elements;
3243	int error;
3244
3245	error = mac_check_structmac_consistent(mac);
3246	if (error)
3247		return (error);
3248
3249	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3250	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3251	if (error) {
3252		free(elements, M_MACTEMP);
3253		return (error);
3254	}
3255
3256	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3257	error = mac_externalize_socket_label(&so->so_label, elements,
3258	    buffer, mac->m_buflen, M_WAITOK);
3259	if (error == 0)
3260		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3261
3262	free(buffer, M_MACTEMP);
3263	free(elements, M_MACTEMP);
3264
3265	return (error);
3266}
3267
3268int
3269mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3270    struct mac *mac)
3271{
3272	char *elements, *buffer;
3273	int error;
3274
3275	error = mac_check_structmac_consistent(mac);
3276	if (error)
3277		return (error);
3278
3279	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3280	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3281	if (error) {
3282		free(elements, M_MACTEMP);
3283		return (error);
3284	}
3285
3286	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3287	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3288	    elements, buffer, mac->m_buflen, M_WAITOK);
3289	if (error == 0)
3290		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3291
3292	free(buffer, M_MACTEMP);
3293	free(elements, M_MACTEMP);
3294
3295	return (error);
3296}
3297
3298/*
3299 * Implementation of VOP_SETLABEL() that relies on extended attributes
3300 * to store label data.  Can be referenced by filesystems supporting
3301 * extended attributes.
3302 */
3303int
3304vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3305{
3306	struct vnode *vp = ap->a_vp;
3307	struct label *intlabel = ap->a_label;
3308	int error;
3309
3310	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3311
3312	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3313		return (EOPNOTSUPP);
3314
3315	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3316	if (error)
3317		return (error);
3318
3319	mac_relabel_vnode(ap->a_cred, vp, intlabel);
3320
3321	return (0);
3322}
3323
3324static int
3325vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3326{
3327	int error;
3328
3329	if (vp->v_mount == NULL) {
3330		/* printf("vn_setlabel: null v_mount\n"); */
3331		if (vp->v_type != VNON)
3332			printf("vn_setlabel: null v_mount with non-VNON\n");
3333		return (EBADF);
3334	}
3335
3336	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3337		return (EOPNOTSUPP);
3338
3339	/*
3340	 * Multi-phase commit.  First check the policies to confirm the
3341	 * change is OK.  Then commit via the filesystem.  Finally,
3342	 * update the actual vnode label.  Question: maybe the filesystem
3343	 * should update the vnode at the end as part of VOP_SETLABEL()?
3344	 */
3345	error = mac_check_vnode_relabel(cred, vp, intlabel);
3346	if (error)
3347		return (error);
3348
3349	/*
3350	 * VADMIN provides the opportunity for the filesystem to make
3351	 * decisions about who is and is not able to modify labels
3352	 * and protections on files.  This might not be right.  We can't
3353	 * assume VOP_SETLABEL() will do it, because we might implement
3354	 * that as part of vop_stdsetlabel_ea().
3355	 */
3356	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3357	if (error)
3358		return (error);
3359
3360	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3361	if (error)
3362		return (error);
3363
3364	return (0);
3365}
3366
3367int
3368__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3369{
3370	char *elements, *buffer;
3371	struct mac mac;
3372	struct proc *tproc;
3373	struct ucred *tcred;
3374	int error;
3375
3376	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3377	if (error)
3378		return (error);
3379
3380	error = mac_check_structmac_consistent(&mac);
3381	if (error)
3382		return (error);
3383
3384	tproc = pfind(uap->pid);
3385	if (tproc == NULL)
3386		return (ESRCH);
3387
3388	tcred = NULL;				/* Satisfy gcc. */
3389	error = p_cansee(td, tproc);
3390	if (error == 0)
3391		tcred = crhold(tproc->p_ucred);
3392	PROC_UNLOCK(tproc);
3393	if (error)
3394		return (error);
3395
3396	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3397	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3398	if (error) {
3399		free(elements, M_MACTEMP);
3400		crfree(tcred);
3401		return (error);
3402	}
3403
3404	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3405	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3406	    buffer, mac.m_buflen, M_WAITOK);
3407	if (error == 0)
3408		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3409
3410	free(buffer, M_MACTEMP);
3411	free(elements, M_MACTEMP);
3412	crfree(tcred);
3413	return (error);
3414}
3415
3416/*
3417 * MPSAFE
3418 */
3419int
3420__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3421{
3422	char *elements, *buffer;
3423	struct mac mac;
3424	int error;
3425
3426	error = copyin(uap->mac_p, &mac, sizeof(mac));
3427	if (error)
3428		return (error);
3429
3430	error = mac_check_structmac_consistent(&mac);
3431	if (error)
3432		return (error);
3433
3434	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3435	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3436	if (error) {
3437		free(elements, M_MACTEMP);
3438		return (error);
3439	}
3440
3441	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3442	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3443	    elements, buffer, mac.m_buflen, M_WAITOK);
3444	if (error == 0)
3445		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3446
3447	free(buffer, M_MACTEMP);
3448	free(elements, M_MACTEMP);
3449	return (error);
3450}
3451
3452/*
3453 * MPSAFE
3454 */
3455int
3456__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3457{
3458	struct ucred *newcred, *oldcred;
3459	struct label intlabel;
3460	struct proc *p;
3461	struct mac mac;
3462	char *buffer;
3463	int error;
3464
3465	error = copyin(uap->mac_p, &mac, sizeof(mac));
3466	if (error)
3467		return (error);
3468
3469	error = mac_check_structmac_consistent(&mac);
3470	if (error)
3471		return (error);
3472
3473	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3474	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3475	if (error) {
3476		free(buffer, M_MACTEMP);
3477		return (error);
3478	}
3479
3480	mac_init_cred_label(&intlabel);
3481	error = mac_internalize_cred_label(&intlabel, buffer);
3482	free(buffer, M_MACTEMP);
3483	if (error) {
3484		mac_destroy_cred_label(&intlabel);
3485		return (error);
3486	}
3487
3488	newcred = crget();
3489
3490	p = td->td_proc;
3491	PROC_LOCK(p);
3492	oldcred = p->p_ucred;
3493
3494	error = mac_check_cred_relabel(oldcred, &intlabel);
3495	if (error) {
3496		PROC_UNLOCK(p);
3497		crfree(newcred);
3498		goto out;
3499	}
3500
3501	setsugid(p);
3502	crcopy(newcred, oldcred);
3503	mac_relabel_cred(newcred, &intlabel);
3504	p->p_ucred = newcred;
3505
3506	/*
3507	 * Grab additional reference for use while revoking mmaps, prior
3508	 * to releasing the proc lock and sharing the cred.
3509	 */
3510	crhold(newcred);
3511	PROC_UNLOCK(p);
3512
3513	if (mac_enforce_vm) {
3514		mtx_lock(&Giant);
3515		mac_cred_mmapped_drop_perms(td, newcred);
3516		mtx_unlock(&Giant);
3517	}
3518
3519	crfree(newcred);	/* Free revocation reference. */
3520	crfree(oldcred);
3521
3522out:
3523	mac_destroy_cred_label(&intlabel);
3524	return (error);
3525}
3526
3527/*
3528 * MPSAFE
3529 */
3530int
3531__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3532{
3533	char *elements, *buffer;
3534	struct label intlabel;
3535	struct file *fp;
3536	struct mac mac;
3537	struct vnode *vp;
3538	struct pipe *pipe;
3539	short label_type;
3540	int error;
3541
3542	error = copyin(uap->mac_p, &mac, sizeof(mac));
3543	if (error)
3544		return (error);
3545
3546	error = mac_check_structmac_consistent(&mac);
3547	if (error)
3548		return (error);
3549
3550	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3551	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3552	if (error) {
3553		free(elements, M_MACTEMP);
3554		return (error);
3555	}
3556
3557	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3558	mtx_lock(&Giant);				/* VFS */
3559	error = fget(td, SCARG(uap, fd), &fp);
3560	if (error)
3561		goto out;
3562
3563	label_type = fp->f_type;
3564	switch (fp->f_type) {
3565	case DTYPE_FIFO:
3566	case DTYPE_VNODE:
3567		vp = (struct vnode *)fp->f_data;
3568
3569		mac_init_vnode_label(&intlabel);
3570
3571		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3572		mac_copy_vnode_label(&vp->v_label, &intlabel);
3573		VOP_UNLOCK(vp, 0, td);
3574
3575		break;
3576	case DTYPE_PIPE:
3577		pipe = (struct pipe *)fp->f_data;
3578
3579		mac_init_pipe_label(&intlabel);
3580
3581		PIPE_LOCK(pipe);
3582		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3583		PIPE_UNLOCK(pipe);
3584		break;
3585	default:
3586		error = EINVAL;
3587		fdrop(fp, td);
3588		goto out;
3589	}
3590	fdrop(fp, td);
3591
3592	switch (label_type) {
3593	case DTYPE_FIFO:
3594	case DTYPE_VNODE:
3595		if (error == 0)
3596			error = mac_externalize_vnode_label(&intlabel,
3597			    elements, buffer, mac.m_buflen, M_WAITOK);
3598		mac_destroy_vnode_label(&intlabel);
3599		break;
3600	case DTYPE_PIPE:
3601		error = mac_externalize_pipe_label(&intlabel, elements,
3602		    buffer, mac.m_buflen, M_WAITOK);
3603		mac_destroy_pipe_label(&intlabel);
3604		break;
3605	default:
3606		panic("__mac_get_fd: corrupted label_type");
3607	}
3608
3609	if (error == 0)
3610		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3611
3612out:
3613	mtx_unlock(&Giant);				/* VFS */
3614	free(buffer, M_MACTEMP);
3615	free(elements, M_MACTEMP);
3616
3617	return (error);
3618}
3619
3620/*
3621 * MPSAFE
3622 */
3623int
3624__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3625{
3626	char *elements, *buffer;
3627	struct nameidata nd;
3628	struct label intlabel;
3629	struct mac mac;
3630	int error;
3631
3632	error = copyin(uap->mac_p, &mac, sizeof(mac));
3633	if (error)
3634		return (error);
3635
3636	error = mac_check_structmac_consistent(&mac);
3637	if (error)
3638		return (error);
3639
3640	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3641	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3642	if (error) {
3643		free(elements, M_MACTEMP);
3644		return (error);
3645	}
3646
3647	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3648	mtx_lock(&Giant);				/* VFS */
3649	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3650	    td);
3651	error = namei(&nd);
3652	if (error)
3653		goto out;
3654
3655	mac_init_vnode_label(&intlabel);
3656	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3657	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3658	    mac.m_buflen, M_WAITOK);
3659
3660	NDFREE(&nd, 0);
3661	mac_destroy_vnode_label(&intlabel);
3662
3663	if (error == 0)
3664		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3665
3666out:
3667	mtx_unlock(&Giant);				/* VFS */
3668
3669	free(buffer, M_MACTEMP);
3670	free(elements, M_MACTEMP);
3671
3672	return (error);
3673}
3674
3675/*
3676 * MPSAFE
3677 */
3678int
3679__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3680{
3681	char *elements, *buffer;
3682	struct nameidata nd;
3683	struct label intlabel;
3684	struct mac mac;
3685	int error;
3686
3687	error = copyin(uap->mac_p, &mac, sizeof(mac));
3688	if (error)
3689		return (error);
3690
3691	error = mac_check_structmac_consistent(&mac);
3692	if (error)
3693		return (error);
3694
3695	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3696	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3697	if (error) {
3698		free(elements, M_MACTEMP);
3699		return (error);
3700	}
3701
3702	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3703	mtx_lock(&Giant);				/* VFS */
3704	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3705	    td);
3706	error = namei(&nd);
3707	if (error)
3708		goto out;
3709
3710	mac_init_vnode_label(&intlabel);
3711	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3712	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3713	    mac.m_buflen, M_WAITOK);
3714	NDFREE(&nd, 0);
3715	mac_destroy_vnode_label(&intlabel);
3716
3717	if (error == 0)
3718		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3719
3720out:
3721	mtx_unlock(&Giant);				/* VFS */
3722
3723	free(buffer, M_MACTEMP);
3724	free(elements, M_MACTEMP);
3725
3726	return (error);
3727}
3728
3729/*
3730 * MPSAFE
3731 */
3732int
3733__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3734{
3735	struct label intlabel;
3736	struct pipe *pipe;
3737	struct file *fp;
3738	struct mount *mp;
3739	struct vnode *vp;
3740	struct mac mac;
3741	char *buffer;
3742	int error;
3743
3744	error = copyin(uap->mac_p, &mac, sizeof(mac));
3745	if (error)
3746		return (error);
3747
3748	error = mac_check_structmac_consistent(&mac);
3749	if (error)
3750		return (error);
3751
3752	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3753	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3754	if (error) {
3755		free(buffer, M_MACTEMP);
3756		return (error);
3757	}
3758
3759	mtx_lock(&Giant);				/* VFS */
3760
3761	error = fget(td, SCARG(uap, fd), &fp);
3762	if (error)
3763		goto out;
3764
3765	switch (fp->f_type) {
3766	case DTYPE_FIFO:
3767	case DTYPE_VNODE:
3768		mac_init_vnode_label(&intlabel);
3769		error = mac_internalize_vnode_label(&intlabel, buffer);
3770		if (error) {
3771			mac_destroy_vnode_label(&intlabel);
3772			break;
3773		}
3774
3775		vp = (struct vnode *)fp->f_data;
3776		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3777		if (error != 0) {
3778			mac_destroy_vnode_label(&intlabel);
3779			break;
3780		}
3781
3782		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3783		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3784		VOP_UNLOCK(vp, 0, td);
3785		vn_finished_write(mp);
3786
3787		mac_destroy_vnode_label(&intlabel);
3788		break;
3789
3790	case DTYPE_PIPE:
3791		mac_init_pipe_label(&intlabel);
3792		error = mac_internalize_pipe_label(&intlabel, buffer);
3793		if (error == 0) {
3794			pipe = (struct pipe *)fp->f_data;
3795			PIPE_LOCK(pipe);
3796			error = mac_pipe_label_set(td->td_ucred, pipe,
3797			    &intlabel);
3798			PIPE_UNLOCK(pipe);
3799		}
3800
3801		mac_destroy_pipe_label(&intlabel);
3802		break;
3803
3804	default:
3805		error = EINVAL;
3806	}
3807
3808	fdrop(fp, td);
3809out:
3810	mtx_unlock(&Giant);				/* VFS */
3811
3812	free(buffer, M_MACTEMP);
3813
3814	return (error);
3815}
3816
3817/*
3818 * MPSAFE
3819 */
3820int
3821__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3822{
3823	struct label intlabel;
3824	struct nameidata nd;
3825	struct mount *mp;
3826	struct mac mac;
3827	char *buffer;
3828	int error;
3829
3830	error = copyin(uap->mac_p, &mac, sizeof(mac));
3831	if (error)
3832		return (error);
3833
3834	error = mac_check_structmac_consistent(&mac);
3835	if (error)
3836		return (error);
3837
3838	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3839	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3840	if (error) {
3841		free(buffer, M_MACTEMP);
3842		return (error);
3843	}
3844
3845	mac_init_vnode_label(&intlabel);
3846	error = mac_internalize_vnode_label(&intlabel, buffer);
3847	free(buffer, M_MACTEMP);
3848	if (error) {
3849		mac_destroy_vnode_label(&intlabel);
3850		return (error);
3851	}
3852
3853	mtx_lock(&Giant);				/* VFS */
3854
3855	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3856	    td);
3857	error = namei(&nd);
3858	if (error == 0) {
3859		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3860		if (error == 0)
3861			error = vn_setlabel(nd.ni_vp, &intlabel,
3862			    td->td_ucred);
3863		vn_finished_write(mp);
3864	}
3865
3866	NDFREE(&nd, 0);
3867	mtx_unlock(&Giant);				/* VFS */
3868	mac_destroy_vnode_label(&intlabel);
3869
3870	return (error);
3871}
3872
3873/*
3874 * MPSAFE
3875 */
3876int
3877__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3878{
3879	struct label intlabel;
3880	struct nameidata nd;
3881	struct mount *mp;
3882	struct mac mac;
3883	char *buffer;
3884	int error;
3885
3886	error = copyin(uap->mac_p, &mac, sizeof(mac));
3887	if (error)
3888		return (error);
3889
3890	error = mac_check_structmac_consistent(&mac);
3891	if (error)
3892		return (error);
3893
3894	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3895	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3896	if (error) {
3897		free(buffer, M_MACTEMP);
3898		return (error);
3899	}
3900
3901	mac_init_vnode_label(&intlabel);
3902	error = mac_internalize_vnode_label(&intlabel, buffer);
3903	free(buffer, M_MACTEMP);
3904	if (error) {
3905		mac_destroy_vnode_label(&intlabel);
3906		return (error);
3907	}
3908
3909	mtx_lock(&Giant);				/* VFS */
3910
3911	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3912	    td);
3913	error = namei(&nd);
3914	if (error == 0) {
3915		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3916		if (error == 0)
3917			error = vn_setlabel(nd.ni_vp, &intlabel,
3918			    td->td_ucred);
3919		vn_finished_write(mp);
3920	}
3921
3922	NDFREE(&nd, 0);
3923	mtx_unlock(&Giant);				/* VFS */
3924	mac_destroy_vnode_label(&intlabel);
3925
3926	return (error);
3927}
3928
3929/*
3930 * MPSAFE
3931 */
3932int
3933mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3934{
3935	struct mac_policy_conf *mpc;
3936	char target[MAC_MAX_POLICY_NAME];
3937	int error;
3938
3939	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3940	if (error)
3941		return (error);
3942
3943	error = ENOSYS;
3944	MAC_POLICY_LIST_BUSY();
3945	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3946		if (strcmp(mpc->mpc_name, target) == 0 &&
3947		    mpc->mpc_ops->mpo_syscall != NULL) {
3948			error = mpc->mpc_ops->mpo_syscall(td,
3949			    SCARG(uap, call), SCARG(uap, arg));
3950			goto out;
3951		}
3952	}
3953
3954out:
3955	MAC_POLICY_LIST_UNBUSY();
3956	return (error);
3957}
3958
3959SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3960SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3961
3962#else /* !MAC */
3963
3964int
3965__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3966{
3967
3968	return (ENOSYS);
3969}
3970
3971int
3972__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3973{
3974
3975	return (ENOSYS);
3976}
3977
3978int
3979__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3980{
3981
3982	return (ENOSYS);
3983}
3984
3985int
3986__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3987{
3988
3989	return (ENOSYS);
3990}
3991
3992int
3993__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3994{
3995
3996	return (ENOSYS);
3997}
3998
3999int
4000__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4001{
4002
4003	return (ENOSYS);
4004}
4005
4006int
4007__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4008{
4009
4010	return (ENOSYS);
4011}
4012
4013int
4014__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4015{
4016
4017	return (ENOSYS);
4018}
4019
4020int
4021__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4022{
4023
4024	return (ENOSYS);
4025}
4026
4027int
4028mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4029{
4030
4031	return (ENOSYS);
4032}
4033
4034#endif
4035