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