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