mac_vfs.c revision 106024
118334Speter/*-
218334Speter * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
318334Speter * Copyright (c) 2001 Ilmar S. Habibulin
418334Speter * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
518334Speter * All rights reserved.
618334Speter *
718334Speter * This software was developed by Robert Watson and Ilmar Habibulin for the
818334Speter * TrustedBSD Project.
918334Speter *
1018334Speter * This software was developed for the FreeBSD Project in part by NAI Labs,
1118334Speter * the Security Research Division of Network Associates, Inc. under
1218334Speter * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
1318334Speter * CHATS research program.
1418334Speter *
1518334Speter * Redistribution and use in source and binary forms, with or without
1618334Speter * modification, are permitted provided that the following conditions
1718334Speter * are met:
1818334Speter * 1. Redistributions of source code must retain the above copyright
1918334Speter *    notice, this list of conditions and the following disclaimer.
2018334Speter * 2. Redistributions in binary form must reproduce the above copyright
2118334Speter *    notice, this list of conditions and the following disclaimer in the
2218334Speter *    documentation and/or other materials provided with the distribution.
2318334Speter * 3. The names of the authors may not be used to endorse or promote
2418334Speter *    products derived from this software without specific prior written
2518334Speter *    permission.
2618334Speter *
2718334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2818334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2918334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3018334Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
3118334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3218334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3318334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3418334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3518334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3618334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3718334Speter * SUCH DAMAGE.
3818334Speter *
3918334Speter * $FreeBSD: head/sys/security/mac/mac_vfs.c 106024 2002-10-27 07:03:29Z rwatson $
4018334Speter */
4118334Speter/*
4218334Speter * Developed by the TrustedBSD Project.
4318334Speter *
4418334Speter * Framework for extensible kernel access control.  Kernel and userland
4518334Speter * interface to the framework, policy registration and composition.
4618334Speter */
4718334Speter
4818334Speter#include "opt_mac.h"
4918334Speter#include "opt_devfs.h"
5018334Speter
5118334Speter#include <sys/param.h>
5218334Speter#include <sys/extattr.h>
5318334Speter#include <sys/kernel.h>
5418334Speter#include <sys/lock.h>
5518334Speter#include <sys/malloc.h>
5618334Speter#include <sys/mutex.h>
5718334Speter#include <sys/mac.h>
5818334Speter#include <sys/module.h>
5918334Speter#include <sys/proc.h>
6018334Speter#include <sys/systm.h>
6118334Speter#include <sys/sysproto.h>
6218334Speter#include <sys/sysent.h>
6318334Speter#include <sys/vnode.h>
6418334Speter#include <sys/mount.h>
6518334Speter#include <sys/file.h>
6618334Speter#include <sys/namei.h>
6718334Speter#include <sys/socket.h>
6818334Speter#include <sys/pipe.h>
6918334Speter#include <sys/socketvar.h>
7018334Speter#include <sys/sysctl.h>
7118334Speter
7218334Speter#include <vm/vm.h>
7318334Speter#include <vm/pmap.h>
7418334Speter#include <vm/vm_map.h>
7518334Speter#include <vm/vm_object.h>
7618334Speter
7718334Speter#include <sys/mac_policy.h>
7818334Speter
7918334Speter#include <fs/devfs/devfs.h>
8018334Speter
8118334Speter#include <net/bpfdesc.h>
8218334Speter#include <net/if.h>
8318334Speter#include <net/if_var.h>
8418334Speter
8518334Speter#include <netinet/in.h>
8618334Speter#include <netinet/ip_var.h>
8718334Speter
8818334Speter#ifdef MAC
8918334Speter
9018334Speter/*
9118334Speter * Declare that the kernel provides MAC support, version 1.  This permits
9218334Speter * modules to refuse to be loaded if the necessary support isn't present,
9318334Speter * even if it's pre-boot.
9418334Speter */
9518334SpeterMODULE_VERSION(kernel_mac_support, 1);
9618334Speter
9718334SpeterSYSCTL_DECL(_security);
9818334Speter
9918334SpeterSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
10018334Speter    "TrustedBSD MAC policy controls");
10118334Speter
10218334Speter#if MAC_MAX_POLICIES > 32
10318334Speter#error "MAC_MAX_POLICIES too large"
10418334Speter#endif
10518334Speter
10618334Speterstatic unsigned int mac_max_policies = MAC_MAX_POLICIES;
10718334Speterstatic unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
10818334SpeterSYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
10918334Speter    &mac_max_policies, 0, "");
11018334Speter
11118334Speter/*
11218334Speter * Has the kernel started generating labeled objects yet?  All read/write
11318334Speter * access to this variable is serialized during the boot process.  Following
11418334Speter * the end of serialization, we don't update this flag; no locking.
11518334Speter */
11618334Speterstatic int	mac_late = 0;
11718334Speter
11818334Speter/*
11918334Speter * Warn about EA transactions only the first time they happen.
12018334Speter * Weak coherency, no locking.
12118334Speter */
12218334Speterstatic int	ea_warn_once = 0;
12318334Speter
12418334Speterstatic int	mac_enforce_fs = 1;
12518334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
12618334Speter    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
12718334SpeterTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
12818334Speter
12918334Speterstatic int	mac_enforce_network = 1;
13018334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
13118334Speter    &mac_enforce_network, 0, "Enforce MAC policy on network packets");
13218334SpeterTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
13318334Speter
13418334Speterstatic int	mac_enforce_pipe = 1;
13518334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
13618334Speter    &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
13718334SpeterTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
13818334Speter
13918334Speterstatic int	mac_enforce_process = 1;
14018334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
14118334Speter    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
14218334SpeterTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
14318334Speter
14418334Speterstatic int	mac_enforce_reboot = 1;
14518334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_reboot, CTLFLAG_RW,
14618334Speter    &mac_enforce_reboot, 0, "Enforce MAC policy for reboot operations");
14718334SpeterTUNABLE_INT("security.mac.enforce_reboot", &mac_enforce_reboot);
14818334Speter
14918334Speterstatic int	mac_enforce_socket = 1;
15018334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
15118334Speter    &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
15218334SpeterTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
15318334Speter
15418334Speterstatic int     mac_enforce_vm = 1;
15518334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
15618334Speter    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
15718334SpeterTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
15818334Speter
15918334Speterstatic int	mac_cache_fslabel_in_vnode = 1;
16018334SpeterSYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW,
16118334Speter    &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode");
16218334SpeterTUNABLE_INT("security.mac.cache_fslabel_in_vnode",
16318334Speter    &mac_cache_fslabel_in_vnode);
16418334Speter
16518334Speterstatic int	mac_mmap_revocation = 1;
16618334SpeterSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
16718334Speter    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
16818334Speter    "relabel");
16918334Speterstatic int	mac_mmap_revocation_via_cow = 0;
17018334SpeterSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
17118334Speter    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
17218334Speter    "copy-on-write semantics, or by removing all write access");
17318334Speter
17418334Speter#ifdef MAC_DEBUG
17518334SpeterSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
17618334Speter    "TrustedBSD MAC debug info");
17718334Speter
17818334Speterstatic int	mac_debug_label_fallback = 0;
17918334SpeterSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
18018334Speter    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
18118334Speter    "when label is corrupted.");
18218334SpeterTUNABLE_INT("security.mac.debug_label_fallback",
18318334Speter    &mac_debug_label_fallback);
18418334Speter
18518334SpeterSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
18618334Speter    "TrustedBSD MAC object counters");
18718334Speter
18818334Speterstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
18918334Speter    nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
19018334Speter    nmacipqs, nmacpipes;
19118334Speter
19218334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
19318334Speter    &nmacmbufs, 0, "number of mbufs in use");
19418334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
19518334Speter    &nmaccreds, 0, "number of ucreds in use");
19618334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
19718334Speter    &nmacifnets, 0, "number of ifnets in use");
19818334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
19918334Speter    &nmacipqs, 0, "number of ipqs in use");
20018334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
20118334Speter    &nmacbpfdescs, 0, "number of bpfdescs in use");
20218334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
20318334Speter    &nmacsockets, 0, "number of sockets in use");
20418334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
20518334Speter    &nmacpipes, 0, "number of pipes in use");
20618334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
20718334Speter    &nmacmounts, 0, "number of mounts in use");
20818334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
20918334Speter    &nmactemp, 0, "number of temporary labels in use");
21018334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
21118334Speter    &nmacvnodes, 0, "number of vnodes in use");
21218334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
21318334Speter    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
21418334Speter#endif
21518334Speter
21618334Speterstatic int	error_select(int error1, int error2);
21718334Speterstatic int	mac_policy_register(struct mac_policy_conf *mpc);
21818334Speterstatic int	mac_policy_unregister(struct mac_policy_conf *mpc);
21918334Speter
22018334Speterstatic void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
22118334Speter		    struct vnode *vp, int *prot);
22218334Speterstatic void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
22318334Speter		    struct ucred *cred, struct vm_map *map);
22418334Speter
22518334Speterstatic void	mac_destroy_socket_label(struct label *label);
22618334Speter
22718334Speterstatic int	mac_setlabel_vnode_extattr(struct ucred *cred,
22818334Speter		    struct vnode *vp, struct label *intlabel);
22918334Speter
23018334Speter
23118334SpeterMALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector");
23218334SpeterMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
23318334SpeterMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
23418334Speter
23518334Speter/*
23618334Speter * mac_policy_list_lock protects the consistency of 'mac_policy_list',
23718334Speter * the linked list of attached policy modules.  Read-only consumers of
23818334Speter * the list must acquire a shared lock for the duration of their use;
23918334Speter * writers must acquire an exclusive lock.  Note that for compound
24018334Speter * operations, locks should be held for the entire compound operation,
24118334Speter * and that this is not yet done for relabel requests.
24218334Speter */
24318334Speterstatic struct mtx mac_policy_list_lock;
24418334Speterstatic LIST_HEAD(, mac_policy_conf) mac_policy_list;
24518334Speterstatic int mac_policy_list_busy;
24618334Speter#define	MAC_POLICY_LIST_LOCKINIT()	mtx_init(&mac_policy_list_lock,	\
24718334Speter	"mac_policy_list_lock", NULL, MTX_DEF);
24818334Speter#define	MAC_POLICY_LIST_LOCK()	mtx_lock(&mac_policy_list_lock);
24918334Speter#define	MAC_POLICY_LIST_UNLOCK()	mtx_unlock(&mac_policy_list_lock);
25018334Speter
25118334Speter#define	MAC_POLICY_LIST_BUSY() do {					\
25218334Speter	MAC_POLICY_LIST_LOCK();						\
25318334Speter	mac_policy_list_busy++;						\
25418334Speter	MAC_POLICY_LIST_UNLOCK();					\
25518334Speter} while (0)
25618334Speter
25718334Speter#define	MAC_POLICY_LIST_UNBUSY() do {					\
25818334Speter	MAC_POLICY_LIST_LOCK();						\
25918334Speter	mac_policy_list_busy--;						\
26018334Speter	if (mac_policy_list_busy < 0)					\
26118334Speter		panic("Extra mac_policy_list_busy--");			\
26218334Speter	MAC_POLICY_LIST_UNLOCK();					\
26318334Speter} while (0)
26418334Speter
26518334Speter/*
26618334Speter * MAC_CHECK performs the designated check by walking the policy
26718334Speter * module list and checking with each as to how it feels about the
26818334Speter * request.  Note that it returns its value via 'error' in the scope
26918334Speter * of the caller.
27018334Speter */
27118334Speter#define	MAC_CHECK(check, args...) do {					\
27218334Speter	struct mac_policy_conf *mpc;					\
27318334Speter									\
27418334Speter	error = 0;							\
27518334Speter	MAC_POLICY_LIST_BUSY();						\
27618334Speter	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
27718334Speter		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
27818334Speter			error = error_select(				\
27918334Speter			    mpc->mpc_ops->mpo_ ## check (args),		\
28018334Speter			    error);					\
28118334Speter	}								\
28218334Speter	MAC_POLICY_LIST_UNBUSY();					\
28318334Speter} while (0)
28418334Speter
28518334Speter/*
28618334Speter * MAC_BOOLEAN performs the designated boolean composition by walking
28718334Speter * the module list, invoking each instance of the operation, and
28818334Speter * combining the results using the passed C operator.  Note that it
28918334Speter * returns its value via 'result' in the scope of the caller, which
29018334Speter * should be initialized by the caller in a meaningful way to get
29118334Speter * a meaningful result.
29218334Speter */
29318334Speter#define	MAC_BOOLEAN(operation, composition, args...) do {		\
29418334Speter	struct mac_policy_conf *mpc;					\
29518334Speter									\
29618334Speter	MAC_POLICY_LIST_BUSY();						\
29718334Speter	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
29818334Speter		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
29918334Speter			result = result composition			\
30018334Speter			    mpc->mpc_ops->mpo_ ## operation (args);	\
30118334Speter	}								\
30218334Speter	MAC_POLICY_LIST_UNBUSY();					\
30318334Speter} while (0)
30418334Speter
30518334Speter#define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
30618334Speter    outbuflen) do {							\
30718334Speter	char *curptr, *curptr_start, *element_name, *element_temp;	\
30818334Speter	size_t left, left_start, len;					\
30918334Speter	int claimed, first, first_start, ignorenotfound;		\
31018334Speter									\
31118334Speter	error = 0;							\
31218334Speter	element_temp = elementlist;					\
31318334Speter	curptr = outbuf;						\
31418334Speter	curptr[0] = '\0';						\
31518334Speter	left = outbuflen;						\
31618334Speter	first = 1;							\
31718334Speter	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
31818334Speter		curptr_start = curptr;					\
31918334Speter		left_start = left;					\
32018334Speter		first_start = first;					\
32118334Speter		if (element_name[0] == '?') {				\
32218334Speter			element_name++;					\
32318334Speter			ignorenotfound = 1;				\
32418334Speter		} else							\
32518334Speter			ignorenotfound = 0;				\
32618334Speter		claimed = 0;						\
32718334Speter		if (first) {						\
32818334Speter			len = snprintf(curptr, left, "%s/",		\
32918334Speter			    element_name);				\
33018334Speter			first = 0;					\
33118334Speter		} else							\
33218334Speter			len = snprintf(curptr, left, ",%s/",		\
33318334Speter			    element_name);				\
33418334Speter		if (len >= left) {					\
33518334Speter			error = EINVAL;		/* XXXMAC: E2BIG */	\
33618334Speter			break;						\
33718334Speter		}							\
33818334Speter		curptr += len;						\
33918334Speter		left -= len;						\
34018334Speter									\
34118334Speter		MAC_CHECK(externalize_ ## type, label, element_name,	\
34218334Speter		    curptr, left, &len, &claimed);			\
34318334Speter		if (error)						\
34418334Speter			break;						\
34518334Speter		if (claimed == 1) {					\
34618334Speter			if (len >= outbuflen) {				\
34718334Speter				error = EINVAL;	/* XXXMAC: E2BIG */	\
34818334Speter				break;					\
34918334Speter			}						\
35018334Speter			curptr += len;					\
35118334Speter			left -= len;					\
35218334Speter		} else if (claimed == 0 && ignorenotfound) {		\
35318334Speter			/*						\
35418334Speter			 * Revert addition of the label element		\
35518334Speter			 * name.					\
35618334Speter			 */						\
35718334Speter			curptr = curptr_start;				\
35818334Speter			*curptr = '\0';					\
35918334Speter			left = left_start;				\
36018334Speter			first = first_start;				\
36118334Speter		} else {						\
36218334Speter			error = EINVAL;		/* XXXMAC: ENOLABEL */	\
36318334Speter			break;						\
36418334Speter		}							\
36518334Speter	}								\
36618334Speter} while (0)
36718334Speter
36818334Speter#define	MAC_INTERNALIZE(type, label, instring) do {			\
36918334Speter	char *element, *element_name, *element_data;			\
37018334Speter	int claimed;							\
37118334Speter									\
37218334Speter	error = 0;							\
37318334Speter	element = instring;						\
37418334Speter	while ((element_name = strsep(&element, ",")) != NULL) {	\
37518334Speter		element_data = element_name;				\
37618334Speter		element_name = strsep(&element_data, "/");		\
37718334Speter		if (element_data == NULL) {				\
37818334Speter			error = EINVAL;					\
37918334Speter			break;						\
38018334Speter		}							\
38118334Speter		claimed = 0;						\
38218334Speter		MAC_CHECK(internalize_ ## type, label, element_name,	\
38318334Speter		    element_data, &claimed);				\
38418334Speter		if (error)						\
38518334Speter			break;						\
38618334Speter		if (claimed != 1) {					\
38718334Speter			/* XXXMAC: Another error here? */		\
38818334Speter			error = EINVAL;					\
38918334Speter			break;						\
39018334Speter		}							\
39118334Speter	}								\
39218334Speter} while (0)
39318334Speter
39418334Speter/*
39518334Speter * MAC_PERFORM performs the designated operation by walking the policy
39618334Speter * module list and invoking that operation for each policy.
39718334Speter */
39818334Speter#define	MAC_PERFORM(operation, args...) do {				\
39918334Speter	struct mac_policy_conf *mpc;					\
40018334Speter									\
40118334Speter	MAC_POLICY_LIST_BUSY();						\
40218334Speter	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
40318334Speter		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
40418334Speter			mpc->mpc_ops->mpo_ ## operation (args);		\
40518334Speter	}								\
40618334Speter	MAC_POLICY_LIST_UNBUSY();					\
40718334Speter} while (0)
40818334Speter
40918334Speter/*
41018334Speter * Initialize the MAC subsystem, including appropriate SMP locks.
41118334Speter */
41218334Speterstatic void
41318334Spetermac_init(void)
41418334Speter{
41518334Speter
41618334Speter	LIST_INIT(&mac_policy_list);
41718334Speter	MAC_POLICY_LIST_LOCKINIT();
41818334Speter}
41918334Speter
42018334Speter/*
42118334Speter * For the purposes of modules that want to know if they were loaded
42218334Speter * "early", set the mac_late flag once we've processed modules either
42318334Speter * linked into the kernel, or loaded before the kernel startup.
42418334Speter */
42518334Speterstatic void
42618334Spetermac_late_init(void)
42718334Speter{
42818334Speter
42918334Speter	mac_late = 1;
43018334Speter}
43118334Speter
43218334Speter/*
43318334Speter * Allow MAC policy modules to register during boot, etc.
43418334Speter */
43518334Speterint
43618334Spetermac_policy_modevent(module_t mod, int type, void *data)
43718334Speter{
43818334Speter	struct mac_policy_conf *mpc;
43918334Speter	int error;
44018334Speter
44118334Speter	error = 0;
44218334Speter	mpc = (struct mac_policy_conf *) data;
44318334Speter
44418334Speter	switch (type) {
44518334Speter	case MOD_LOAD:
44618334Speter		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
44718334Speter		    mac_late) {
44818334Speter			printf("mac_policy_modevent: can't load %s policy "
44918334Speter			    "after booting\n", mpc->mpc_name);
45018334Speter			error = EBUSY;
45118334Speter			break;
45218334Speter		}
45318334Speter		error = mac_policy_register(mpc);
45418334Speter		break;
45518334Speter	case MOD_UNLOAD:
45618334Speter		/* Don't unregister the module if it was never registered. */
45718334Speter		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
45818334Speter		    != 0)
45918334Speter			error = mac_policy_unregister(mpc);
46018334Speter		else
46118334Speter			error = 0;
46218334Speter		break;
46318334Speter	default:
46418334Speter		break;
46518334Speter	}
46618334Speter
46718334Speter	return (error);
46818334Speter}
46918334Speter
47018334Speterstatic int
47118334Spetermac_policy_register(struct mac_policy_conf *mpc)
47218334Speter{
47318334Speter	struct mac_policy_conf *tmpc;
47418334Speter	struct mac_policy_op_entry *mpe;
47518334Speter	int slot;
47618334Speter
47718334Speter	MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops),
47818334Speter	    M_MACOPVEC, M_WAITOK | M_ZERO);
47918334Speter	for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) {
48018334Speter		switch (mpe->mpe_constant) {
48118334Speter		case MAC_OP_LAST:
48218334Speter			/*
48318334Speter			 * Doesn't actually happen, but this allows checking
48418334Speter			 * that all enumerated values are handled.
48518334Speter			 */
48618334Speter			break;
48718334Speter		case MAC_DESTROY:
48818334Speter			mpc->mpc_ops->mpo_destroy =
48918334Speter			    mpe->mpe_function;
49018334Speter			break;
49118334Speter		case MAC_INIT:
49218334Speter			mpc->mpc_ops->mpo_init =
49318334Speter			    mpe->mpe_function;
49418334Speter			break;
49518334Speter		case MAC_SYSCALL:
49618334Speter			mpc->mpc_ops->mpo_syscall =
49718334Speter			    mpe->mpe_function;
49818334Speter			break;
49918334Speter		case MAC_INIT_BPFDESC_LABEL:
50018334Speter			mpc->mpc_ops->mpo_init_bpfdesc_label =
50118334Speter			    mpe->mpe_function;
50218334Speter			break;
50318334Speter		case MAC_INIT_CRED_LABEL:
50418334Speter			mpc->mpc_ops->mpo_init_cred_label =
50518334Speter			    mpe->mpe_function;
50618334Speter			break;
50718334Speter		case MAC_INIT_DEVFSDIRENT_LABEL:
50818334Speter			mpc->mpc_ops->mpo_init_devfsdirent_label =
50918334Speter			    mpe->mpe_function;
51018334Speter			break;
51118334Speter		case MAC_INIT_IFNET_LABEL:
51218334Speter			mpc->mpc_ops->mpo_init_ifnet_label =
51318334Speter			    mpe->mpe_function;
51418334Speter			break;
51518334Speter		case MAC_INIT_IPQ_LABEL:
51618334Speter			mpc->mpc_ops->mpo_init_ipq_label =
51718334Speter			    mpe->mpe_function;
51818334Speter			break;
51918334Speter		case MAC_INIT_MBUF_LABEL:
52018334Speter			mpc->mpc_ops->mpo_init_mbuf_label =
52118334Speter			    mpe->mpe_function;
52218334Speter			break;
52318334Speter		case MAC_INIT_MOUNT_LABEL:
52418334Speter			mpc->mpc_ops->mpo_init_mount_label =
52518334Speter			    mpe->mpe_function;
52618334Speter			break;
52718334Speter		case MAC_INIT_MOUNT_FS_LABEL:
52818334Speter			mpc->mpc_ops->mpo_init_mount_fs_label =
52918334Speter			    mpe->mpe_function;
53018334Speter			break;
53118334Speter		case MAC_INIT_PIPE_LABEL:
53218334Speter			mpc->mpc_ops->mpo_init_pipe_label =
53318334Speter			    mpe->mpe_function;
53418334Speter			break;
53518334Speter		case MAC_INIT_SOCKET_LABEL:
53618334Speter			mpc->mpc_ops->mpo_init_socket_label =
53718334Speter			    mpe->mpe_function;
53818334Speter			break;
53918334Speter		case MAC_INIT_SOCKET_PEER_LABEL:
54018334Speter			mpc->mpc_ops->mpo_init_socket_peer_label =
54118334Speter			    mpe->mpe_function;
54218334Speter			break;
54318334Speter		case MAC_INIT_VNODE_LABEL:
54418334Speter			mpc->mpc_ops->mpo_init_vnode_label =
54518334Speter			    mpe->mpe_function;
54618334Speter			break;
54718334Speter		case MAC_DESTROY_BPFDESC_LABEL:
54818334Speter			mpc->mpc_ops->mpo_destroy_bpfdesc_label =
54918334Speter			    mpe->mpe_function;
55018334Speter			break;
55118334Speter		case MAC_DESTROY_CRED_LABEL:
55218334Speter			mpc->mpc_ops->mpo_destroy_cred_label =
55318334Speter			    mpe->mpe_function;
55418334Speter			break;
55518334Speter		case MAC_DESTROY_DEVFSDIRENT_LABEL:
55618334Speter			mpc->mpc_ops->mpo_destroy_devfsdirent_label =
55718334Speter			    mpe->mpe_function;
55818334Speter			break;
55918334Speter		case MAC_DESTROY_IFNET_LABEL:
56018334Speter			mpc->mpc_ops->mpo_destroy_ifnet_label =
56118334Speter			    mpe->mpe_function;
56218334Speter			break;
56318334Speter		case MAC_DESTROY_IPQ_LABEL:
56418334Speter			mpc->mpc_ops->mpo_destroy_ipq_label =
56518334Speter			    mpe->mpe_function;
56618334Speter			break;
56718334Speter		case MAC_DESTROY_MBUF_LABEL:
56818334Speter			mpc->mpc_ops->mpo_destroy_mbuf_label =
56918334Speter			    mpe->mpe_function;
57018334Speter			break;
57118334Speter		case MAC_DESTROY_MOUNT_LABEL:
57218334Speter			mpc->mpc_ops->mpo_destroy_mount_label =
57318334Speter			    mpe->mpe_function;
57418334Speter			break;
57518334Speter		case MAC_DESTROY_MOUNT_FS_LABEL:
57618334Speter			mpc->mpc_ops->mpo_destroy_mount_fs_label =
57718334Speter			    mpe->mpe_function;
57818334Speter			break;
57918334Speter		case MAC_DESTROY_PIPE_LABEL:
58018334Speter			mpc->mpc_ops->mpo_destroy_pipe_label =
58118334Speter			    mpe->mpe_function;
58218334Speter			break;
58318334Speter		case MAC_DESTROY_SOCKET_LABEL:
58418334Speter			mpc->mpc_ops->mpo_destroy_socket_label =
58518334Speter			    mpe->mpe_function;
58618334Speter			break;
58718334Speter		case MAC_DESTROY_SOCKET_PEER_LABEL:
58818334Speter			mpc->mpc_ops->mpo_destroy_socket_peer_label =
58918334Speter			    mpe->mpe_function;
59018334Speter			break;
59118334Speter		case MAC_DESTROY_VNODE_LABEL:
59218334Speter			mpc->mpc_ops->mpo_destroy_vnode_label =
59318334Speter			    mpe->mpe_function;
59418334Speter			break;
59518334Speter		case MAC_COPY_PIPE_LABEL:
59618334Speter			mpc->mpc_ops->mpo_copy_pipe_label =
59718334Speter			    mpe->mpe_function;
59818334Speter			break;
59918334Speter		case MAC_COPY_VNODE_LABEL:
60018334Speter			mpc->mpc_ops->mpo_copy_vnode_label =
60118334Speter			    mpe->mpe_function;
60218334Speter			break;
60318334Speter		case MAC_EXTERNALIZE_CRED_LABEL:
60418334Speter			mpc->mpc_ops->mpo_externalize_cred_label =
60518334Speter			    mpe->mpe_function;
60618334Speter			break;
60718334Speter		case MAC_EXTERNALIZE_IFNET_LABEL:
60818334Speter			mpc->mpc_ops->mpo_externalize_ifnet_label =
60918334Speter			    mpe->mpe_function;
61018334Speter			break;
61118334Speter		case MAC_EXTERNALIZE_PIPE_LABEL:
61218334Speter			mpc->mpc_ops->mpo_externalize_pipe_label =
61318334Speter			    mpe->mpe_function;
61418334Speter			break;
61518334Speter		case MAC_EXTERNALIZE_SOCKET_LABEL:
61618334Speter			mpc->mpc_ops->mpo_externalize_socket_label =
61718334Speter			    mpe->mpe_function;
61818334Speter			break;
61918334Speter		case MAC_EXTERNALIZE_SOCKET_PEER_LABEL:
62018334Speter			mpc->mpc_ops->mpo_externalize_socket_peer_label =
62118334Speter			    mpe->mpe_function;
62218334Speter			break;
62318334Speter		case MAC_EXTERNALIZE_VNODE_LABEL:
62418334Speter			mpc->mpc_ops->mpo_externalize_vnode_label =
62518334Speter			    mpe->mpe_function;
62618334Speter			break;
62718334Speter		case MAC_INTERNALIZE_CRED_LABEL:
62818334Speter			mpc->mpc_ops->mpo_internalize_cred_label =
62918334Speter			    mpe->mpe_function;
63018334Speter			break;
63118334Speter		case MAC_INTERNALIZE_IFNET_LABEL:
63218334Speter			mpc->mpc_ops->mpo_internalize_ifnet_label =
63318334Speter			    mpe->mpe_function;
63418334Speter			break;
63518334Speter		case MAC_INTERNALIZE_PIPE_LABEL:
63618334Speter			mpc->mpc_ops->mpo_internalize_pipe_label =
63718334Speter			    mpe->mpe_function;
63818334Speter			break;
63918334Speter		case MAC_INTERNALIZE_SOCKET_LABEL:
64018334Speter			mpc->mpc_ops->mpo_internalize_socket_label =
64118334Speter			    mpe->mpe_function;
64218334Speter			break;
64318334Speter		case MAC_INTERNALIZE_VNODE_LABEL:
64418334Speter			mpc->mpc_ops->mpo_internalize_vnode_label =
64518334Speter			    mpe->mpe_function;
64618334Speter			break;
64718334Speter		case MAC_CREATE_DEVFS_DEVICE:
64818334Speter			mpc->mpc_ops->mpo_create_devfs_device =
64918334Speter			    mpe->mpe_function;
65018334Speter			break;
65118334Speter		case MAC_CREATE_DEVFS_DIRECTORY:
65218334Speter			mpc->mpc_ops->mpo_create_devfs_directory =
65318334Speter			    mpe->mpe_function;
65418334Speter			break;
65518334Speter		case MAC_CREATE_DEVFS_SYMLINK:
65618334Speter			mpc->mpc_ops->mpo_create_devfs_symlink =
65718334Speter			    mpe->mpe_function;
65818334Speter			break;
65918334Speter		case MAC_CREATE_DEVFS_VNODE:
66018334Speter			mpc->mpc_ops->mpo_create_devfs_vnode =
66118334Speter			    mpe->mpe_function;
66218334Speter			break;
66318334Speter		case MAC_CREATE_MOUNT:
66418334Speter			mpc->mpc_ops->mpo_create_mount =
66518334Speter			    mpe->mpe_function;
66618334Speter			break;
66718334Speter		case MAC_CREATE_ROOT_MOUNT:
66818334Speter			mpc->mpc_ops->mpo_create_root_mount =
66918334Speter			    mpe->mpe_function;
67018334Speter			break;
67118334Speter		case MAC_RELABEL_VNODE:
67218334Speter			mpc->mpc_ops->mpo_relabel_vnode =
67318334Speter			    mpe->mpe_function;
67418334Speter			break;
67518334Speter		case MAC_UPDATE_DEVFSDIRENT:
67618334Speter			mpc->mpc_ops->mpo_update_devfsdirent =
67718334Speter			    mpe->mpe_function;
67818334Speter			break;
67918334Speter		case MAC_ASSOCIATE_VNODE_DEVFS:
68018334Speter			mpc->mpc_ops->mpo_associate_vnode_devfs =
68118334Speter			    mpe->mpe_function;
68218334Speter			break;
68318334Speter		case MAC_ASSOCIATE_VNODE_EXTATTR:
68418334Speter			mpc->mpc_ops->mpo_associate_vnode_extattr =
68518334Speter			    mpe->mpe_function;
68618334Speter			break;
68718334Speter		case MAC_ASSOCIATE_VNODE_SINGLELABEL:
68818334Speter			mpc->mpc_ops->mpo_associate_vnode_singlelabel =
68918334Speter			    mpe->mpe_function;
69018334Speter			break;
69118334Speter		case MAC_CREATE_VNODE_EXTATTR:
69218334Speter			mpc->mpc_ops->mpo_create_vnode_extattr =
69318334Speter			    mpe->mpe_function;
69418334Speter			break;
69518334Speter		case MAC_SETLABEL_VNODE_EXTATTR:
69618334Speter			mpc->mpc_ops->mpo_setlabel_vnode_extattr =
69718334Speter			    mpe->mpe_function;
69818334Speter			break;
69918334Speter		case MAC_CREATE_MBUF_FROM_SOCKET:
70018334Speter			mpc->mpc_ops->mpo_create_mbuf_from_socket =
70118334Speter			    mpe->mpe_function;
70218334Speter			break;
70318334Speter		case MAC_CREATE_PIPE:
70418334Speter			mpc->mpc_ops->mpo_create_pipe =
70518334Speter			    mpe->mpe_function;
70618334Speter			break;
70718334Speter		case MAC_CREATE_SOCKET:
70818334Speter			mpc->mpc_ops->mpo_create_socket =
70918334Speter			    mpe->mpe_function;
71018334Speter			break;
71118334Speter		case MAC_CREATE_SOCKET_FROM_SOCKET:
71218334Speter			mpc->mpc_ops->mpo_create_socket_from_socket =
71318334Speter			    mpe->mpe_function;
71418334Speter			break;
71518334Speter		case MAC_RELABEL_PIPE:
71618334Speter			mpc->mpc_ops->mpo_relabel_pipe =
71718334Speter			    mpe->mpe_function;
71818334Speter			break;
71918334Speter		case MAC_RELABEL_SOCKET:
72018334Speter			mpc->mpc_ops->mpo_relabel_socket =
72118334Speter			    mpe->mpe_function;
72218334Speter			break;
72318334Speter		case MAC_SET_SOCKET_PEER_FROM_MBUF:
72418334Speter			mpc->mpc_ops->mpo_set_socket_peer_from_mbuf =
72518334Speter			    mpe->mpe_function;
72618334Speter			break;
72718334Speter		case MAC_SET_SOCKET_PEER_FROM_SOCKET:
72818334Speter			mpc->mpc_ops->mpo_set_socket_peer_from_socket =
72918334Speter			    mpe->mpe_function;
73018334Speter			break;
73118334Speter		case MAC_CREATE_BPFDESC:
73218334Speter			mpc->mpc_ops->mpo_create_bpfdesc =
73318334Speter			    mpe->mpe_function;
73418334Speter			break;
73518334Speter		case MAC_CREATE_DATAGRAM_FROM_IPQ:
73618334Speter			mpc->mpc_ops->mpo_create_datagram_from_ipq =
73718334Speter			    mpe->mpe_function;
73818334Speter			break;
73918334Speter		case MAC_CREATE_FRAGMENT:
74018334Speter			mpc->mpc_ops->mpo_create_fragment =
74118334Speter			    mpe->mpe_function;
74218334Speter			break;
74318334Speter		case MAC_CREATE_IFNET:
74418334Speter			mpc->mpc_ops->mpo_create_ifnet =
74518334Speter			    mpe->mpe_function;
74618334Speter			break;
74718334Speter		case MAC_CREATE_IPQ:
74818334Speter			mpc->mpc_ops->mpo_create_ipq =
74918334Speter			    mpe->mpe_function;
75018334Speter			break;
75118334Speter		case MAC_CREATE_MBUF_FROM_MBUF:
75218334Speter			mpc->mpc_ops->mpo_create_mbuf_from_mbuf =
75318334Speter			    mpe->mpe_function;
75418334Speter			break;
75518334Speter		case MAC_CREATE_MBUF_LINKLAYER:
75618334Speter			mpc->mpc_ops->mpo_create_mbuf_linklayer =
75718334Speter			    mpe->mpe_function;
75818334Speter			break;
75918334Speter		case MAC_CREATE_MBUF_FROM_BPFDESC:
76018334Speter			mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc =
76118334Speter			    mpe->mpe_function;
76218334Speter			break;
76318334Speter		case MAC_CREATE_MBUF_FROM_IFNET:
76418334Speter			mpc->mpc_ops->mpo_create_mbuf_from_ifnet =
76518334Speter			    mpe->mpe_function;
76618334Speter			break;
76718334Speter		case MAC_CREATE_MBUF_MULTICAST_ENCAP:
76818334Speter			mpc->mpc_ops->mpo_create_mbuf_multicast_encap =
76918334Speter			    mpe->mpe_function;
77018334Speter			break;
77118334Speter		case MAC_CREATE_MBUF_NETLAYER:
77218334Speter			mpc->mpc_ops->mpo_create_mbuf_netlayer =
77318334Speter			    mpe->mpe_function;
77418334Speter			break;
77518334Speter		case MAC_FRAGMENT_MATCH:
77618334Speter			mpc->mpc_ops->mpo_fragment_match =
77718334Speter			    mpe->mpe_function;
77818334Speter			break;
77918334Speter		case MAC_RELABEL_IFNET:
78018334Speter			mpc->mpc_ops->mpo_relabel_ifnet =
78118334Speter			    mpe->mpe_function;
78218334Speter			break;
78318334Speter		case MAC_UPDATE_IPQ:
78418334Speter			mpc->mpc_ops->mpo_update_ipq =
78518334Speter			    mpe->mpe_function;
78618334Speter			break;
78718334Speter		case MAC_CREATE_CRED:
78818334Speter			mpc->mpc_ops->mpo_create_cred =
78918334Speter			    mpe->mpe_function;
79018334Speter			break;
79118334Speter		case MAC_EXECVE_TRANSITION:
79218334Speter			mpc->mpc_ops->mpo_execve_transition =
79318334Speter			    mpe->mpe_function;
79418334Speter			break;
79518334Speter		case MAC_EXECVE_WILL_TRANSITION:
79618334Speter			mpc->mpc_ops->mpo_execve_will_transition =
79718334Speter			    mpe->mpe_function;
79818334Speter			break;
79918334Speter		case MAC_CREATE_PROC0:
80018334Speter			mpc->mpc_ops->mpo_create_proc0 =
80118334Speter			    mpe->mpe_function;
80218334Speter			break;
80318334Speter		case MAC_CREATE_PROC1:
80418334Speter			mpc->mpc_ops->mpo_create_proc1 =
80518334Speter			    mpe->mpe_function;
80618334Speter			break;
80718334Speter		case MAC_RELABEL_CRED:
80818334Speter			mpc->mpc_ops->mpo_relabel_cred =
80918334Speter			    mpe->mpe_function;
81018334Speter			break;
81118334Speter		case MAC_THREAD_USERRET:
81218334Speter			mpc->mpc_ops->mpo_thread_userret =
81318334Speter			    mpe->mpe_function;
81418334Speter			break;
81518334Speter		case MAC_CHECK_BPFDESC_RECEIVE:
81618334Speter			mpc->mpc_ops->mpo_check_bpfdesc_receive =
81718334Speter			    mpe->mpe_function;
81818334Speter			break;
81918334Speter		case MAC_CHECK_CRED_RELABEL:
82018334Speter			mpc->mpc_ops->mpo_check_cred_relabel =
82118334Speter			    mpe->mpe_function;
82218334Speter			break;
82318334Speter		case MAC_CHECK_CRED_VISIBLE:
82418334Speter			mpc->mpc_ops->mpo_check_cred_visible =
82518334Speter			    mpe->mpe_function;
82618334Speter			break;
82718334Speter		case MAC_CHECK_IFNET_RELABEL:
82818334Speter			mpc->mpc_ops->mpo_check_ifnet_relabel =
82918334Speter			    mpe->mpe_function;
83018334Speter			break;
83118334Speter		case MAC_CHECK_IFNET_TRANSMIT:
83218334Speter			mpc->mpc_ops->mpo_check_ifnet_transmit =
83318334Speter			    mpe->mpe_function;
83418334Speter			break;
83518334Speter		case MAC_CHECK_MOUNT_STAT:
83618334Speter			mpc->mpc_ops->mpo_check_mount_stat =
83718334Speter			    mpe->mpe_function;
83818334Speter			break;
83918334Speter		case MAC_CHECK_PIPE_IOCTL:
84018334Speter			mpc->mpc_ops->mpo_check_pipe_ioctl =
84118334Speter			    mpe->mpe_function;
84218334Speter			break;
84318334Speter		case MAC_CHECK_PIPE_POLL:
84418334Speter			mpc->mpc_ops->mpo_check_pipe_poll =
84518334Speter			    mpe->mpe_function;
84618334Speter			break;
84718334Speter		case MAC_CHECK_PIPE_READ:
84818334Speter			mpc->mpc_ops->mpo_check_pipe_read =
84918334Speter			    mpe->mpe_function;
85018334Speter			break;
85118334Speter		case MAC_CHECK_PIPE_RELABEL:
85218334Speter			mpc->mpc_ops->mpo_check_pipe_relabel =
85318334Speter			    mpe->mpe_function;
85418334Speter			break;
85518334Speter		case MAC_CHECK_PIPE_STAT:
85618334Speter			mpc->mpc_ops->mpo_check_pipe_stat =
85718334Speter			    mpe->mpe_function;
85818334Speter			break;
85918334Speter		case MAC_CHECK_PIPE_WRITE:
86018334Speter			mpc->mpc_ops->mpo_check_pipe_write =
86118334Speter			    mpe->mpe_function;
86218334Speter			break;
86318334Speter		case MAC_CHECK_PROC_DEBUG:
86418334Speter			mpc->mpc_ops->mpo_check_proc_debug =
86518334Speter			    mpe->mpe_function;
86618334Speter			break;
86718334Speter		case MAC_CHECK_PROC_SCHED:
86818334Speter			mpc->mpc_ops->mpo_check_proc_sched =
86918334Speter			    mpe->mpe_function;
87018334Speter			break;
87118334Speter		case MAC_CHECK_PROC_SIGNAL:
87218334Speter			mpc->mpc_ops->mpo_check_proc_signal =
87318334Speter			    mpe->mpe_function;
87418334Speter			break;
87518334Speter		case MAC_CHECK_SOCKET_BIND:
87618334Speter			mpc->mpc_ops->mpo_check_socket_bind =
87718334Speter			    mpe->mpe_function;
87818334Speter			break;
87918334Speter		case MAC_CHECK_SOCKET_CONNECT:
88018334Speter			mpc->mpc_ops->mpo_check_socket_connect =
88118334Speter			    mpe->mpe_function;
88218334Speter			break;
88318334Speter		case MAC_CHECK_SOCKET_DELIVER:
88418334Speter			mpc->mpc_ops->mpo_check_socket_deliver =
88518334Speter			    mpe->mpe_function;
88618334Speter			break;
88718334Speter		case MAC_CHECK_SOCKET_LISTEN:
88818334Speter			mpc->mpc_ops->mpo_check_socket_listen =
88918334Speter			    mpe->mpe_function;
89018334Speter			break;
89118334Speter		case MAC_CHECK_SOCKET_RECEIVE:
89218334Speter			mpc->mpc_ops->mpo_check_socket_receive =
89318334Speter			    mpe->mpe_function;
89418334Speter			break;
89518334Speter		case MAC_CHECK_SOCKET_RELABEL:
89618334Speter			mpc->mpc_ops->mpo_check_socket_relabel =
89718334Speter			    mpe->mpe_function;
89818334Speter			break;
89918334Speter		case MAC_CHECK_SOCKET_SEND:
90018334Speter			mpc->mpc_ops->mpo_check_socket_send =
90118334Speter			    mpe->mpe_function;
90218334Speter			break;
90318334Speter		case MAC_CHECK_SOCKET_VISIBLE:
90418334Speter			mpc->mpc_ops->mpo_check_socket_visible =
90518334Speter			    mpe->mpe_function;
90618334Speter			break;
90718334Speter		case MAC_CHECK_SYSTEM_REBOOT:
90818334Speter			mpc->mpc_ops->mpo_check_system_reboot =
90918334Speter			    mpe->mpe_function;
91018334Speter			break;
91118334Speter		case MAC_CHECK_SYSTEM_SWAPON:
91218334Speter			mpc->mpc_ops->mpo_check_system_swapon =
91318334Speter			    mpe->mpe_function;
91418334Speter			break;
91518334Speter		case MAC_CHECK_VNODE_ACCESS:
91618334Speter			mpc->mpc_ops->mpo_check_vnode_access =
91718334Speter			    mpe->mpe_function;
91818334Speter			break;
91918334Speter		case MAC_CHECK_VNODE_CHDIR:
92018334Speter			mpc->mpc_ops->mpo_check_vnode_chdir =
92118334Speter			    mpe->mpe_function;
92218334Speter			break;
92318334Speter		case MAC_CHECK_VNODE_CHROOT:
92418334Speter			mpc->mpc_ops->mpo_check_vnode_chroot =
92518334Speter			    mpe->mpe_function;
92618334Speter			break;
92718334Speter		case MAC_CHECK_VNODE_CREATE:
92818334Speter			mpc->mpc_ops->mpo_check_vnode_create =
92918334Speter			    mpe->mpe_function;
93018334Speter			break;
93118334Speter		case MAC_CHECK_VNODE_DELETE:
93218334Speter			mpc->mpc_ops->mpo_check_vnode_delete =
93318334Speter			    mpe->mpe_function;
93418334Speter			break;
93518334Speter		case MAC_CHECK_VNODE_DELETEACL:
93618334Speter			mpc->mpc_ops->mpo_check_vnode_deleteacl =
93718334Speter			    mpe->mpe_function;
93818334Speter			break;
93918334Speter		case MAC_CHECK_VNODE_EXEC:
94018334Speter			mpc->mpc_ops->mpo_check_vnode_exec =
94118334Speter			    mpe->mpe_function;
94218334Speter			break;
94318334Speter		case MAC_CHECK_VNODE_GETACL:
94418334Speter			mpc->mpc_ops->mpo_check_vnode_getacl =
94518334Speter			    mpe->mpe_function;
94618334Speter			break;
94718334Speter		case MAC_CHECK_VNODE_GETEXTATTR:
94818334Speter			mpc->mpc_ops->mpo_check_vnode_getextattr =
94918334Speter			    mpe->mpe_function;
95018334Speter			break;
95118334Speter		case MAC_CHECK_VNODE_LINK:
95218334Speter			mpc->mpc_ops->mpo_check_vnode_link =
95318334Speter			    mpe->mpe_function;
95418334Speter			break;
95518334Speter		case MAC_CHECK_VNODE_LOOKUP:
95618334Speter			mpc->mpc_ops->mpo_check_vnode_lookup =
95718334Speter			    mpe->mpe_function;
95818334Speter			break;
95918334Speter		case MAC_CHECK_VNODE_MMAP:
96018334Speter			mpc->mpc_ops->mpo_check_vnode_mmap =
96118334Speter			    mpe->mpe_function;
96218334Speter			break;
96318334Speter		case MAC_CHECK_VNODE_MMAP_DOWNGRADE:
96418334Speter			mpc->mpc_ops->mpo_check_vnode_mmap_downgrade =
96518334Speter			    mpe->mpe_function;
96618334Speter			break;
96718334Speter		case MAC_CHECK_VNODE_MPROTECT:
96818334Speter			mpc->mpc_ops->mpo_check_vnode_mprotect =
96918334Speter			    mpe->mpe_function;
97018334Speter			break;
97118334Speter		case MAC_CHECK_VNODE_OPEN:
97218334Speter			mpc->mpc_ops->mpo_check_vnode_open =
97318334Speter			    mpe->mpe_function;
97418334Speter			break;
97518334Speter		case MAC_CHECK_VNODE_POLL:
97618334Speter			mpc->mpc_ops->mpo_check_vnode_poll =
97718334Speter			    mpe->mpe_function;
97818334Speter			break;
97918334Speter		case MAC_CHECK_VNODE_READ:
98018334Speter			mpc->mpc_ops->mpo_check_vnode_read =
98118334Speter			    mpe->mpe_function;
98218334Speter			break;
98318334Speter		case MAC_CHECK_VNODE_READDIR:
98418334Speter			mpc->mpc_ops->mpo_check_vnode_readdir =
98518334Speter			    mpe->mpe_function;
98618334Speter			break;
98718334Speter		case MAC_CHECK_VNODE_READLINK:
98818334Speter			mpc->mpc_ops->mpo_check_vnode_readlink =
98918334Speter			    mpe->mpe_function;
99018334Speter			break;
99118334Speter		case MAC_CHECK_VNODE_RELABEL:
99218334Speter			mpc->mpc_ops->mpo_check_vnode_relabel =
99318334Speter			    mpe->mpe_function;
99418334Speter			break;
99518334Speter		case MAC_CHECK_VNODE_RENAME_FROM:
99618334Speter			mpc->mpc_ops->mpo_check_vnode_rename_from =
99718334Speter			    mpe->mpe_function;
99818334Speter			break;
99918334Speter		case MAC_CHECK_VNODE_RENAME_TO:
100018334Speter			mpc->mpc_ops->mpo_check_vnode_rename_to =
100118334Speter			    mpe->mpe_function;
100218334Speter			break;
100318334Speter		case MAC_CHECK_VNODE_REVOKE:
100418334Speter			mpc->mpc_ops->mpo_check_vnode_revoke =
100518334Speter			    mpe->mpe_function;
100618334Speter			break;
100718334Speter		case MAC_CHECK_VNODE_SETACL:
100818334Speter			mpc->mpc_ops->mpo_check_vnode_setacl =
100918334Speter			    mpe->mpe_function;
101018334Speter			break;
101118334Speter		case MAC_CHECK_VNODE_SETEXTATTR:
101218334Speter			mpc->mpc_ops->mpo_check_vnode_setextattr =
101318334Speter			    mpe->mpe_function;
101418334Speter			break;
101518334Speter		case MAC_CHECK_VNODE_SETFLAGS:
101618334Speter			mpc->mpc_ops->mpo_check_vnode_setflags =
101718334Speter			    mpe->mpe_function;
101818334Speter			break;
101918334Speter		case MAC_CHECK_VNODE_SETMODE:
102018334Speter			mpc->mpc_ops->mpo_check_vnode_setmode =
102118334Speter			    mpe->mpe_function;
102218334Speter			break;
102318334Speter		case MAC_CHECK_VNODE_SETOWNER:
102418334Speter			mpc->mpc_ops->mpo_check_vnode_setowner =
102518334Speter			    mpe->mpe_function;
102618334Speter			break;
102718334Speter		case MAC_CHECK_VNODE_SETUTIMES:
102818334Speter			mpc->mpc_ops->mpo_check_vnode_setutimes =
102918334Speter			    mpe->mpe_function;
103018334Speter			break;
103118334Speter		case MAC_CHECK_VNODE_STAT:
103218334Speter			mpc->mpc_ops->mpo_check_vnode_stat =
103318334Speter			    mpe->mpe_function;
103418334Speter			break;
103518334Speter		case MAC_CHECK_VNODE_WRITE:
103618334Speter			mpc->mpc_ops->mpo_check_vnode_write =
103718334Speter			    mpe->mpe_function;
103818334Speter			break;
103918334Speter/*
104018334Speter		default:
104118334Speter			printf("MAC policy `%s': unknown operation %d\n",
104218334Speter			    mpc->mpc_name, mpe->mpe_constant);
104318334Speter			return (EINVAL);
104418334Speter*/
104518334Speter		}
104618334Speter	}
104718334Speter	MAC_POLICY_LIST_LOCK();
104818334Speter	if (mac_policy_list_busy > 0) {
104918334Speter		MAC_POLICY_LIST_UNLOCK();
105018334Speter		FREE(mpc->mpc_ops, M_MACOPVEC);
105118334Speter		mpc->mpc_ops = NULL;
105218334Speter		return (EBUSY);
105318334Speter	}
105418334Speter	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
105518334Speter		if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
105618334Speter			MAC_POLICY_LIST_UNLOCK();
105718334Speter			FREE(mpc->mpc_ops, M_MACOPVEC);
105818334Speter			mpc->mpc_ops = NULL;
105918334Speter			return (EEXIST);
106018334Speter		}
106118334Speter	}
106218334Speter	if (mpc->mpc_field_off != NULL) {
106318334Speter		slot = ffs(mac_policy_offsets_free);
106418334Speter		if (slot == 0) {
106518334Speter			MAC_POLICY_LIST_UNLOCK();
106618334Speter			FREE(mpc->mpc_ops, M_MACOPVEC);
106718334Speter			mpc->mpc_ops = NULL;
106818334Speter			return (ENOMEM);
106918334Speter		}
107018334Speter		slot--;
107118334Speter		mac_policy_offsets_free &= ~(1 << slot);
107218334Speter		*mpc->mpc_field_off = slot;
107318334Speter	}
107418334Speter	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
107518334Speter	LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
107618334Speter
107718334Speter	/* Per-policy initialization. */
107818334Speter	if (mpc->mpc_ops->mpo_init != NULL)
107918334Speter		(*(mpc->mpc_ops->mpo_init))(mpc);
108018334Speter	MAC_POLICY_LIST_UNLOCK();
108118334Speter
108218334Speter	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
108318334Speter	    mpc->mpc_name);
108418334Speter
108518334Speter	return (0);
108618334Speter}
108718334Speter
108818334Speterstatic int
108918334Spetermac_policy_unregister(struct mac_policy_conf *mpc)
109018334Speter{
109118334Speter
109218334Speter	/*
109318334Speter	 * If we fail the load, we may get a request to unload.  Check
109418334Speter	 * to see if we did the run-time registration, and if not,
109518334Speter	 * silently succeed.
109618334Speter	 */
109718334Speter	MAC_POLICY_LIST_LOCK();
109818334Speter	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
109918334Speter		MAC_POLICY_LIST_UNLOCK();
110018334Speter		return (0);
110118334Speter	}
110218334Speter#if 0
110318334Speter	/*
110418334Speter	 * Don't allow unloading modules with private data.
110518334Speter	 */
110618334Speter	if (mpc->mpc_field_off != NULL) {
110718334Speter		MAC_POLICY_LIST_UNLOCK();
110818334Speter		return (EBUSY);
110918334Speter	}
111018334Speter#endif
111118334Speter	/*
111218334Speter	 * Only allow the unload to proceed if the module is unloadable
111318334Speter	 * by its own definition.
111418334Speter	 */
111518334Speter	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
111618334Speter		MAC_POLICY_LIST_UNLOCK();
111718334Speter		return (EBUSY);
111818334Speter	}
111918334Speter	/*
112018334Speter	 * Right now, we EBUSY if the list is in use.  In the future,
112118334Speter	 * for reliability reasons, we might want to sleep and wakeup
112218334Speter	 * later to try again.
112318334Speter	 */
112418334Speter	if (mac_policy_list_busy > 0) {
112518334Speter		MAC_POLICY_LIST_UNLOCK();
112618334Speter		return (EBUSY);
112718334Speter	}
112818334Speter	if (mpc->mpc_ops->mpo_destroy != NULL)
112918334Speter		(*(mpc->mpc_ops->mpo_destroy))(mpc);
113018334Speter
113118334Speter	LIST_REMOVE(mpc, mpc_list);
113218334Speter	MAC_POLICY_LIST_UNLOCK();
113318334Speter
113418334Speter	FREE(mpc->mpc_ops, M_MACOPVEC);
113518334Speter	mpc->mpc_ops = NULL;
113618334Speter	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
113718334Speter
113818334Speter	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
113918334Speter	    mpc->mpc_name);
114018334Speter
114118334Speter	return (0);
114218334Speter}
114318334Speter
114418334Speter/*
114518334Speter * Define an error value precedence, and given two arguments, selects the
114618334Speter * value with the higher precedence.
114718334Speter */
114818334Speterstatic int
114918334Spetererror_select(int error1, int error2)
115018334Speter{
115118334Speter
115218334Speter	/* Certain decision-making errors take top priority. */
115318334Speter	if (error1 == EDEADLK || error2 == EDEADLK)
115418334Speter		return (EDEADLK);
115518334Speter
115618334Speter	/* Invalid arguments should be reported where possible. */
115718334Speter	if (error1 == EINVAL || error2 == EINVAL)
115818334Speter		return (EINVAL);
115918334Speter
116018334Speter	/* Precedence goes to "visibility", with both process and file. */
116118334Speter	if (error1 == ESRCH || error2 == ESRCH)
116218334Speter		return (ESRCH);
116318334Speter
116418334Speter	if (error1 == ENOENT || error2 == ENOENT)
116518334Speter		return (ENOENT);
116618334Speter
116718334Speter	/* Precedence goes to DAC/MAC protections. */
116818334Speter	if (error1 == EACCES || error2 == EACCES)
116918334Speter		return (EACCES);
117018334Speter
117118334Speter	/* Precedence goes to privilege. */
117218334Speter	if (error1 == EPERM || error2 == EPERM)
117318334Speter		return (EPERM);
117418334Speter
117518334Speter	/* Precedence goes to error over success; otherwise, arbitrary. */
117618334Speter	if (error1 != 0)
117718334Speter		return (error1);
117818334Speter	return (error2);
117918334Speter}
118018334Speter
118118334Speterstatic void
118218334Spetermac_init_label(struct label *label)
118318334Speter{
118418334Speter
118518334Speter	bzero(label, sizeof(*label));
118618334Speter	label->l_flags = MAC_FLAG_INITIALIZED;
118718334Speter}
118818334Speter
118918334Speterstatic void
119018334Spetermac_destroy_label(struct label *label)
119118334Speter{
119218334Speter
119318334Speter	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
119418334Speter	    ("destroying uninitialized label"));
119518334Speter
119618334Speter	bzero(label, sizeof(*label));
119718334Speter	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
119818334Speter}
119918334Speter
120018334Spetervoid
120118334Spetermac_init_bpfdesc(struct bpf_d *bpf_d)
120218334Speter{
120318334Speter
120418334Speter	mac_init_label(&bpf_d->bd_label);
120518334Speter	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
120618334Speter#ifdef MAC_DEBUG
120718334Speter	atomic_add_int(&nmacbpfdescs, 1);
120818334Speter#endif
120918334Speter}
121018334Speter
121118334Speterstatic void
121218334Spetermac_init_cred_label(struct label *label)
121318334Speter{
121418334Speter
121518334Speter	mac_init_label(label);
121618334Speter	MAC_PERFORM(init_cred_label, label);
121718334Speter#ifdef MAC_DEBUG
121818334Speter	atomic_add_int(&nmaccreds, 1);
121918334Speter#endif
122018334Speter}
122118334Speter
122218334Spetervoid
122318334Spetermac_init_cred(struct ucred *cred)
122418334Speter{
122518334Speter
122618334Speter	mac_init_cred_label(&cred->cr_label);
122718334Speter}
122818334Speter
122918334Spetervoid
123018334Spetermac_init_devfsdirent(struct devfs_dirent *de)
123118334Speter{
123218334Speter
123318334Speter	mac_init_label(&de->de_label);
123418334Speter	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
123518334Speter#ifdef MAC_DEBUG
123618334Speter	atomic_add_int(&nmacdevfsdirents, 1);
123718334Speter#endif
123818334Speter}
123918334Speter
124018334Speterstatic void
124118334Spetermac_init_ifnet_label(struct label *label)
124218334Speter{
124318334Speter
124418334Speter	mac_init_label(label);
124518334Speter	MAC_PERFORM(init_ifnet_label, label);
124618334Speter#ifdef MAC_DEBUG
124718334Speter	atomic_add_int(&nmacifnets, 1);
124818334Speter#endif
124918334Speter}
125018334Speter
125118334Spetervoid
125218334Spetermac_init_ifnet(struct ifnet *ifp)
125318334Speter{
125418334Speter
125518334Speter	mac_init_ifnet_label(&ifp->if_label);
125618334Speter}
125718334Speter
125818334Spetervoid
125918334Spetermac_init_ipq(struct ipq *ipq)
126018334Speter{
126118334Speter
126218334Speter	mac_init_label(&ipq->ipq_label);
126318334Speter	MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
126418334Speter#ifdef MAC_DEBUG
126518334Speter	atomic_add_int(&nmacipqs, 1);
126618334Speter#endif
126718334Speter}
126818334Speter
126918334Speterint
127018334Spetermac_init_mbuf(struct mbuf *m, int flag)
127118334Speter{
127218334Speter	int error;
127318334Speter
127418334Speter	KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
127518334Speter
127618334Speter	mac_init_label(&m->m_pkthdr.label);
127718334Speter
127818334Speter	MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
127918334Speter	if (error) {
128018334Speter		MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
128118334Speter		mac_destroy_label(&m->m_pkthdr.label);
128218334Speter	}
128318334Speter
128418334Speter#ifdef MAC_DEBUG
128518334Speter	if (error == 0)
128618334Speter		atomic_add_int(&nmacmbufs, 1);
128718334Speter#endif
128818334Speter	return (error);
128918334Speter}
129018334Speter
129118334Spetervoid
129218334Spetermac_init_mount(struct mount *mp)
129318334Speter{
129418334Speter
129518334Speter	mac_init_label(&mp->mnt_mntlabel);
129618334Speter	mac_init_label(&mp->mnt_fslabel);
129718334Speter	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
129818334Speter	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
129918334Speter#ifdef MAC_DEBUG
130018334Speter	atomic_add_int(&nmacmounts, 1);
130118334Speter#endif
130218334Speter}
130318334Speter
130418334Speterstatic void
130518334Spetermac_init_pipe_label(struct label *label)
130618334Speter{
130718334Speter
130818334Speter	mac_init_label(label);
130918334Speter	MAC_PERFORM(init_pipe_label, label);
131018334Speter#ifdef MAC_DEBUG
131118334Speter	atomic_add_int(&nmacpipes, 1);
131218334Speter#endif
131318334Speter}
131418334Speter
131518334Spetervoid
131618334Spetermac_init_pipe(struct pipe *pipe)
131718334Speter{
131818334Speter	struct label *label;
131918334Speter
132018334Speter	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
132118334Speter	pipe->pipe_label = label;
132218334Speter	pipe->pipe_peer->pipe_label = label;
132318334Speter	mac_init_pipe_label(label);
132418334Speter}
132518334Speter
132618334Speterstatic int
132718334Spetermac_init_socket_label(struct label *label, int flag)
132818334Speter{
132918334Speter	int error;
133018334Speter
133118334Speter	mac_init_label(label);
133218334Speter
133318334Speter	MAC_CHECK(init_socket_label, label, flag);
133418334Speter	if (error) {
133518334Speter		MAC_PERFORM(destroy_socket_label, label);
133618334Speter		mac_destroy_label(label);
133718334Speter	}
133818334Speter
133918334Speter#ifdef MAC_DEBUG
134018334Speter	if (error == 0)
134118334Speter		atomic_add_int(&nmacsockets, 1);
134218334Speter#endif
134318334Speter
134418334Speter	return (error);
134518334Speter}
134618334Speter
134718334Speterstatic int
134818334Spetermac_init_socket_peer_label(struct label *label, int flag)
134918334Speter{
135018334Speter	int error;
135118334Speter
135218334Speter	mac_init_label(label);
135318334Speter
135418334Speter	MAC_CHECK(init_socket_peer_label, label, flag);
135518334Speter	if (error) {
135618334Speter		MAC_PERFORM(destroy_socket_label, label);
135718334Speter		mac_destroy_label(label);
135818334Speter	}
135918334Speter
136018334Speter	return (error);
136118334Speter}
136218334Speter
136318334Speterint
136418334Spetermac_init_socket(struct socket *socket, int flag)
136518334Speter{
136618334Speter	int error;
136718334Speter
136818334Speter	error = mac_init_socket_label(&socket->so_label, flag);
136918334Speter	if (error)
137018334Speter		return (error);
137118334Speter
137218334Speter	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
137318334Speter	if (error)
137418334Speter		mac_destroy_socket_label(&socket->so_label);
137518334Speter
137618334Speter	return (error);
137718334Speter}
137818334Speter
137918334Spetervoid
138018334Spetermac_init_vnode_label(struct label *label)
138118334Speter{
138218334Speter
138318334Speter	mac_init_label(label);
138418334Speter	MAC_PERFORM(init_vnode_label, label);
138518334Speter#ifdef MAC_DEBUG
138618334Speter	atomic_add_int(&nmacvnodes, 1);
138718334Speter#endif
138818334Speter}
138918334Speter
139018334Spetervoid
139118334Spetermac_init_vnode(struct vnode *vp)
139218334Speter{
139318334Speter
139418334Speter	mac_init_vnode_label(&vp->v_label);
139518334Speter}
139618334Speter
139718334Spetervoid
139818334Spetermac_destroy_bpfdesc(struct bpf_d *bpf_d)
139918334Speter{
140018334Speter
140118334Speter	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
140218334Speter	mac_destroy_label(&bpf_d->bd_label);
140318334Speter#ifdef MAC_DEBUG
140418334Speter	atomic_subtract_int(&nmacbpfdescs, 1);
140518334Speter#endif
140618334Speter}
140718334Speter
140818334Speterstatic void
140918334Spetermac_destroy_cred_label(struct label *label)
141018334Speter{
141118334Speter
141218334Speter	MAC_PERFORM(destroy_cred_label, label);
141318334Speter	mac_destroy_label(label);
141418334Speter#ifdef MAC_DEBUG
141518334Speter	atomic_subtract_int(&nmaccreds, 1);
141618334Speter#endif
141718334Speter}
141818334Speter
141918334Spetervoid
142018334Spetermac_destroy_cred(struct ucred *cred)
142118334Speter{
142218334Speter
142318334Speter	mac_destroy_cred_label(&cred->cr_label);
142418334Speter}
142518334Speter
142618334Spetervoid
142718334Spetermac_destroy_devfsdirent(struct devfs_dirent *de)
142818334Speter{
142918334Speter
143018334Speter	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
143118334Speter	mac_destroy_label(&de->de_label);
143218334Speter#ifdef MAC_DEBUG
143318334Speter	atomic_subtract_int(&nmacdevfsdirents, 1);
143418334Speter#endif
143518334Speter}
143618334Speter
143718334Speterstatic void
143818334Spetermac_destroy_ifnet_label(struct label *label)
143918334Speter{
144018334Speter
144118334Speter	MAC_PERFORM(destroy_ifnet_label, label);
144218334Speter	mac_destroy_label(label);
144318334Speter#ifdef MAC_DEBUG
144418334Speter	atomic_subtract_int(&nmacifnets, 1);
144518334Speter#endif
144618334Speter}
144718334Speter
144818334Spetervoid
144918334Spetermac_destroy_ifnet(struct ifnet *ifp)
145018334Speter{
145118334Speter
145218334Speter	mac_destroy_ifnet_label(&ifp->if_label);
145318334Speter}
145418334Speter
145518334Spetervoid
145618334Spetermac_destroy_ipq(struct ipq *ipq)
145718334Speter{
145818334Speter
145918334Speter	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
146018334Speter	mac_destroy_label(&ipq->ipq_label);
146118334Speter#ifdef MAC_DEBUG
146218334Speter	atomic_subtract_int(&nmacipqs, 1);
146318334Speter#endif
146418334Speter}
146518334Speter
146618334Spetervoid
146718334Spetermac_destroy_mbuf(struct mbuf *m)
146818334Speter{
146918334Speter
147018334Speter	MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
147118334Speter	mac_destroy_label(&m->m_pkthdr.label);
147218334Speter#ifdef MAC_DEBUG
147318334Speter	atomic_subtract_int(&nmacmbufs, 1);
147418334Speter#endif
147518334Speter}
147618334Speter
147718334Spetervoid
147818334Spetermac_destroy_mount(struct mount *mp)
147918334Speter{
148018334Speter
148118334Speter	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
148218334Speter	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
148318334Speter	mac_destroy_label(&mp->mnt_fslabel);
148418334Speter	mac_destroy_label(&mp->mnt_mntlabel);
148518334Speter#ifdef MAC_DEBUG
148618334Speter	atomic_subtract_int(&nmacmounts, 1);
148718334Speter#endif
148818334Speter}
148918334Speter
149018334Speterstatic void
149118334Spetermac_destroy_pipe_label(struct label *label)
149218334Speter{
149318334Speter
149418334Speter	MAC_PERFORM(destroy_pipe_label, label);
149518334Speter	mac_destroy_label(label);
149618334Speter#ifdef MAC_DEBUG
149718334Speter	atomic_subtract_int(&nmacpipes, 1);
149818334Speter#endif
149918334Speter}
150018334Speter
150118334Spetervoid
150218334Spetermac_destroy_pipe(struct pipe *pipe)
150318334Speter{
150418334Speter
150518334Speter	mac_destroy_pipe_label(pipe->pipe_label);
150618334Speter	free(pipe->pipe_label, M_MACPIPELABEL);
150718334Speter}
150818334Speter
150918334Speterstatic void
151018334Spetermac_destroy_socket_label(struct label *label)
151118334Speter{
151218334Speter
151318334Speter	MAC_PERFORM(destroy_socket_label, label);
151418334Speter	mac_destroy_label(label);
151518334Speter#ifdef MAC_DEBUG
151618334Speter	atomic_subtract_int(&nmacsockets, 1);
151718334Speter#endif
151818334Speter}
151918334Speter
152018334Speterstatic void
152118334Spetermac_destroy_socket_peer_label(struct label *label)
152218334Speter{
152318334Speter
152418334Speter	MAC_PERFORM(destroy_socket_peer_label, label);
152518334Speter	mac_destroy_label(label);
152618334Speter}
152718334Speter
152818334Spetervoid
152918334Spetermac_destroy_socket(struct socket *socket)
153018334Speter{
153118334Speter
153218334Speter	mac_destroy_socket_label(&socket->so_label);
153318334Speter	mac_destroy_socket_peer_label(&socket->so_peerlabel);
153418334Speter}
153518334Speter
153618334Spetervoid
153718334Spetermac_destroy_vnode_label(struct label *label)
153818334Speter{
153918334Speter
154018334Speter	MAC_PERFORM(destroy_vnode_label, label);
154118334Speter	mac_destroy_label(label);
154218334Speter#ifdef MAC_DEBUG
154318334Speter	atomic_subtract_int(&nmacvnodes, 1);
154418334Speter#endif
154518334Speter}
154618334Speter
154718334Spetervoid
154818334Spetermac_destroy_vnode(struct vnode *vp)
154918334Speter{
155018334Speter
155118334Speter	mac_destroy_vnode_label(&vp->v_label);
155218334Speter}
155318334Speter
155418334Speterstatic void
155518334Spetermac_copy_pipe_label(struct label *src, struct label *dest)
155618334Speter{
155718334Speter
155818334Speter	MAC_PERFORM(copy_pipe_label, src, dest);
155918334Speter}
156018334Speter
156118334Spetervoid
156218334Spetermac_copy_vnode_label(struct label *src, struct label *dest)
156318334Speter{
156418334Speter
156518334Speter	MAC_PERFORM(copy_vnode_label, src, dest);
156618334Speter}
156718334Speter
156818334Speterstatic int
156918334Spetermac_check_structmac_consistent(struct mac *mac)
157018334Speter{
157118334Speter
157218334Speter	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
157318334Speter		return (EINVAL);
157418334Speter
157518334Speter	return (0);
157618334Speter}
157718334Speter
157818334Speterstatic int
157918334Spetermac_externalize_cred_label(struct label *label, char *elements,
158018334Speter    char *outbuf, size_t outbuflen, int flags)
158118334Speter{
158218334Speter	int error;
158318334Speter
158418334Speter	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
158518334Speter
158618334Speter	return (error);
158718334Speter}
158818334Speter
158918334Speterstatic int
159018334Spetermac_externalize_ifnet_label(struct label *label, char *elements,
159118334Speter    char *outbuf, size_t outbuflen, int flags)
159218334Speter{
159318334Speter	int error;
159418334Speter
159518334Speter	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
159618334Speter
159718334Speter	return (error);
159818334Speter}
159918334Speter
160018334Speterstatic int
160118334Spetermac_externalize_pipe_label(struct label *label, char *elements,
160218334Speter    char *outbuf, size_t outbuflen, int flags)
160318334Speter{
160418334Speter	int error;
160518334Speter
160618334Speter	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
160718334Speter
160818334Speter	return (error);
160918334Speter}
161018334Speter
161118334Speterstatic int
161218334Spetermac_externalize_socket_label(struct label *label, char *elements,
161318334Speter    char *outbuf, size_t outbuflen, int flags)
161418334Speter{
161518334Speter	int error;
161618334Speter
161718334Speter	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
161818334Speter
161918334Speter	return (error);
162018334Speter}
162118334Speter
162218334Speterstatic int
162318334Spetermac_externalize_socket_peer_label(struct label *label, char *elements,
162418334Speter    char *outbuf, size_t outbuflen, int flags)
162518334Speter{
162618334Speter	int error;
162718334Speter
162818334Speter	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
162918334Speter
163018334Speter	return (error);
163118334Speter}
163218334Speter
163318334Speterstatic int
163418334Spetermac_externalize_vnode_label(struct label *label, char *elements,
163518334Speter    char *outbuf, size_t outbuflen, int flags)
163618334Speter{
163718334Speter	int error;
163818334Speter
163918334Speter	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
164018334Speter
164118334Speter	return (error);
164218334Speter}
164318334Speter
164418334Speterstatic int
164518334Spetermac_internalize_cred_label(struct label *label, char *string)
164618334Speter{
164718334Speter	int error;
164818334Speter
164918334Speter	MAC_INTERNALIZE(cred_label, label, string);
165018334Speter
165118334Speter	return (error);
165218334Speter}
165318334Speter
165418334Speterstatic int
165518334Spetermac_internalize_ifnet_label(struct label *label, char *string)
165618334Speter{
165718334Speter	int error;
165818334Speter
165918334Speter	MAC_INTERNALIZE(ifnet_label, label, string);
166018334Speter
166118334Speter	return (error);
166218334Speter}
166318334Speter
166418334Speterstatic int
166518334Spetermac_internalize_pipe_label(struct label *label, char *string)
166618334Speter{
166718334Speter	int error;
166818334Speter
166918334Speter	MAC_INTERNALIZE(pipe_label, label, string);
167018334Speter
167118334Speter	return (error);
167218334Speter}
167318334Speter
167418334Speterstatic int
167518334Spetermac_internalize_socket_label(struct label *label, char *string)
167618334Speter{
167718334Speter	int error;
167818334Speter
167918334Speter	MAC_INTERNALIZE(socket_label, label, string);
168018334Speter
168118334Speter	return (error);
168218334Speter}
168318334Speter
168418334Speterstatic int
168518334Spetermac_internalize_vnode_label(struct label *label, char *string)
168618334Speter{
168718334Speter	int error;
168818334Speter
168918334Speter	MAC_INTERNALIZE(vnode_label, label, string);
169018334Speter
169118334Speter	return (error);
169218334Speter}
169318334Speter
169418334Speter/*
169518334Speter * Initialize MAC label for the first kernel process, from which other
169618334Speter * kernel processes and threads are spawned.
169718334Speter */
169818334Spetervoid
169918334Spetermac_create_proc0(struct ucred *cred)
170018334Speter{
170118334Speter
170218334Speter	MAC_PERFORM(create_proc0, cred);
170318334Speter}
170418334Speter
170518334Speter/*
170618334Speter * Initialize MAC label for the first userland process, from which other
170718334Speter * userland processes and threads are spawned.
170818334Speter */
170918334Spetervoid
171018334Spetermac_create_proc1(struct ucred *cred)
171118334Speter{
171218334Speter
171318334Speter	MAC_PERFORM(create_proc1, cred);
171418334Speter}
171518334Speter
171618334Spetervoid
171718334Spetermac_thread_userret(struct thread *td)
171818334Speter{
171918334Speter
172018334Speter	MAC_PERFORM(thread_userret, td);
172118334Speter}
172218334Speter
172318334Speter/*
172418334Speter * When a new process is created, its label must be initialized.  Generally,
172518334Speter * this involves inheritence from the parent process, modulo possible
172618334Speter * deltas.  This function allows that processing to take place.
172718334Speter */
172818334Spetervoid
172918334Spetermac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
173018334Speter{
173118334Speter
173218334Speter	MAC_PERFORM(create_cred, parent_cred, child_cred);
173318334Speter}
173418334Speter
173518334Spetervoid
173618334Spetermac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
173718334Speter{
173818334Speter
173918334Speter	MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
174018334Speter}
174118334Speter
174218334Spetervoid
174318334Spetermac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
174418334Speter    struct vnode *vp)
174518334Speter{
174618334Speter
174718334Speter	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
174818334Speter	    &de->de_label, vp, &vp->v_label);
174918334Speter}
175018334Speter
175118334Speterint
175218334Spetermac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
175318334Speter{
175418334Speter	int error;
175518334Speter
175618334Speter	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
175718334Speter
175818334Speter	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
175918334Speter	    &vp->v_label);
176018334Speter
176118334Speter	return (error);
176218334Speter}
176318334Speter
176418334Spetervoid
176518334Spetermac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
176618334Speter{
176718334Speter
176818334Speter	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
176918334Speter	    &vp->v_label);
177018334Speter}
177118334Speter
177218334Speterint
177318334Spetermac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
177418334Speter    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
177518334Speter{
177618334Speter	int error;
177718334Speter
177818334Speter	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
177918334Speter	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
178018334Speter
178118334Speter	error = VOP_OPENEXTATTR(vp, cred, curthread);
178218334Speter	if (error == EOPNOTSUPP) {
178318334Speter		/* XXX: Optionally abort if transactions not supported. */
178418334Speter		if (ea_warn_once == 0) {
178518334Speter			printf("Warning: transactions not supported "
178618334Speter			    "in EA write.\n");
178718334Speter			ea_warn_once = 1;
178818334Speter		}
178918334Speter	} else if (error)
179018334Speter		return (error);
179118334Speter
179218334Speter	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
179318334Speter	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
179418334Speter
179518334Speter	if (error) {
179618334Speter		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
179718334Speter		return (error);
179818334Speter	}
179918334Speter
180018334Speter	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
180118334Speter
180218334Speter	if (error == EOPNOTSUPP)
180318334Speter		error = 0;				/* XXX */
180418334Speter
180518334Speter	return (error);
180618334Speter}
180718334Speter
180818334Speterstatic int
180918334Spetermac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
181018334Speter    struct label *intlabel)
181118334Speter{
181218334Speter	int error;
181318334Speter
181418334Speter	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
181518334Speter
181618334Speter	error = VOP_OPENEXTATTR(vp, cred, curthread);
181718334Speter	if (error == EOPNOTSUPP) {
181818334Speter		/* XXX: Optionally abort if transactions not supported. */
181918334Speter		if (ea_warn_once == 0) {
182018334Speter			printf("Warning: transactions not supported "
182118334Speter			    "in EA write.\n");
182218334Speter			ea_warn_once = 1;
182318334Speter		}
182418334Speter	} else if (error)
182518334Speter		return (error);
182618334Speter
182718334Speter	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
182818334Speter
182918334Speter	if (error) {
183018334Speter		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
183118334Speter		return (error);
183218334Speter	}
183318334Speter
183418334Speter	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
183518334Speter
183618334Speter	if (error == EOPNOTSUPP)
183718334Speter		error = 0;				/* XXX */
183818334Speter
183918334Speter	return (error);
184018334Speter}
184118334Speter
184218334Spetervoid
184318334Spetermac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
184418334Speter{
184518334Speter
184618334Speter	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
184718334Speter
184818334Speter	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
184918334Speter}
185018334Speter
185118334Speterint
185218334Spetermac_execve_will_transition(struct ucred *old, struct vnode *vp)
185318334Speter{
185418334Speter	int result;
185518334Speter
185618334Speter	result = 0;
185718334Speter	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
185818334Speter
185918334Speter	return (result);
186018334Speter}
186118334Speter
186218334Speterint
186318334Spetermac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
186418334Speter{
186518334Speter	int error;
186618334Speter
186718334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
186818334Speter
186918334Speter	if (!mac_enforce_fs)
187018334Speter		return (0);
187118334Speter
187218334Speter	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
187318334Speter	return (error);
187418334Speter}
187518334Speter
187618334Speterint
187718334Spetermac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
187818334Speter{
187918334Speter	int error;
188018334Speter
188118334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
188218334Speter
188318334Speter	if (!mac_enforce_fs)
188418334Speter		return (0);
188518334Speter
188618334Speter	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
188718334Speter	return (error);
188818334Speter}
188918334Speter
189018334Speterint
189118334Spetermac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
189218334Speter{
189318334Speter	int error;
189418334Speter
189518334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
189618334Speter
189718334Speter	if (!mac_enforce_fs)
189818334Speter		return (0);
189918334Speter
190018334Speter	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
190118334Speter	return (error);
190218334Speter}
190318334Speter
190418334Speterint
190518334Spetermac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
190618334Speter    struct componentname *cnp, struct vattr *vap)
190718334Speter{
190818334Speter	int error;
190918334Speter
191018334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
191118334Speter
191218334Speter	if (!mac_enforce_fs)
191318334Speter		return (0);
191418334Speter
191518334Speter	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
191618334Speter	return (error);
191718334Speter}
191818334Speter
191918334Speterint
192018334Spetermac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
192118334Speter    struct componentname *cnp)
192218334Speter{
192318334Speter	int error;
192418334Speter
192518334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
192618334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
192718334Speter
192818334Speter	if (!mac_enforce_fs)
192918334Speter		return (0);
193018334Speter
193118334Speter	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
193218334Speter	    &vp->v_label, cnp);
193318334Speter	return (error);
193418334Speter}
193518334Speter
193618334Speterint
193718334Spetermac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
193818334Speter    acl_type_t type)
193918334Speter{
194018334Speter	int error;
194118334Speter
194218334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
194318334Speter
194418334Speter	if (!mac_enforce_fs)
194518334Speter		return (0);
194618334Speter
194718334Speter	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
194818334Speter	return (error);
194918334Speter}
195018334Speter
195118334Speterint
195218334Spetermac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
195318334Speter{
195418334Speter	int error;
195518334Speter
195618334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
195718334Speter
195818334Speter	if (!mac_enforce_process && !mac_enforce_fs)
195918334Speter		return (0);
196018334Speter
196118334Speter	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
196218334Speter
196318334Speter	return (error);
196418334Speter}
196518334Speter
196618334Speterint
196718334Spetermac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
196818334Speter{
196918334Speter	int error;
197018334Speter
197118334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
197218334Speter
197318334Speter	if (!mac_enforce_fs)
197418334Speter		return (0);
197518334Speter
197618334Speter	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
197718334Speter	return (error);
197818334Speter}
197918334Speter
198018334Speterint
198118334Spetermac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
198218334Speter    int attrnamespace, const char *name, struct uio *uio)
198318334Speter{
198418334Speter	int error;
198518334Speter
198618334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
198718334Speter
198818334Speter	if (!mac_enforce_fs)
198918334Speter		return (0);
199018334Speter
199118334Speter	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
199218334Speter	    attrnamespace, name, uio);
199318334Speter	return (error);
199418334Speter}
199518334Speter
199618334Speterint
199718334Spetermac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
199818334Speter    struct vnode *vp, struct componentname *cnp)
199918334Speter{
200018334Speter	int error;
200118334Speter
200218334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
200318334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
200418334Speter
200518334Speter	if (!mac_enforce_fs)
200618334Speter		return (0);
200718334Speter
200818334Speter	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
200918334Speter	    &vp->v_label, cnp);
201018334Speter	return (error);
201118334Speter}
201218334Speter
201318334Speterint
201418334Spetermac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
201518334Speter    struct componentname *cnp)
201618334Speter{
201718334Speter	int error;
201818334Speter
201918334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
202018334Speter
202118334Speter	if (!mac_enforce_fs)
202218334Speter		return (0);
202318334Speter
202418334Speter	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
202518334Speter	return (error);
202618334Speter}
202718334Speter
202818334Speterint
202918334Spetermac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
203018334Speter{
203118334Speter	int error;
203218334Speter
203318334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
203418334Speter
203518334Speter	if (!mac_enforce_fs || !mac_enforce_vm)
203618334Speter		return (0);
203718334Speter
203818334Speter	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
203918334Speter	return (error);
204018334Speter}
204118334Speter
204218334Spetervoid
204318334Spetermac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
204418334Speter{
204518334Speter	int result = *prot;
204618334Speter
204718334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
204818334Speter
204918334Speter	if (!mac_enforce_fs || !mac_enforce_vm)
205018334Speter		return;
205118334Speter
205218334Speter	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
205318334Speter	    &result);
205418334Speter
205518334Speter	*prot = result;
205618334Speter}
205718334Speter
205818334Speterint
205918334Spetermac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
206018334Speter{
206118334Speter	int error;
206218334Speter
206318334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
206418334Speter
206518334Speter	if (!mac_enforce_fs || !mac_enforce_vm)
206618334Speter		return (0);
206718334Speter
206818334Speter	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
206918334Speter	return (error);
207018334Speter}
207118334Speter
207218334Speterint
207318334Spetermac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
207418334Speter{
207518334Speter	int error;
207618334Speter
207718334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
207818334Speter
207918334Speter	if (!mac_enforce_fs)
208018334Speter		return (0);
208118334Speter
208218334Speter	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
208318334Speter	return (error);
208418334Speter}
208518334Speter
208618334Speterint
208718334Spetermac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
208818334Speter    struct vnode *vp)
208918334Speter{
209018334Speter	int error;
209118334Speter
209218334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
209318334Speter
209418334Speter	if (!mac_enforce_fs)
209518334Speter		return (0);
209618334Speter
209718334Speter	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
209818334Speter	    &vp->v_label);
209918334Speter
210018334Speter	return (error);
210118334Speter}
210218334Speter
210318334Speterint
210418334Spetermac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
210518334Speter    struct vnode *vp)
210618334Speter{
210718334Speter	int error;
210818334Speter
210918334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
211018334Speter
211118334Speter	if (!mac_enforce_fs)
211218334Speter		return (0);
211318334Speter
211418334Speter	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
211518334Speter	    &vp->v_label);
211618334Speter
211718334Speter	return (error);
211818334Speter}
211918334Speter
212018334Speterint
212118334Spetermac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
212218334Speter{
212318334Speter	int error;
212418334Speter
212518334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
212618334Speter
212718334Speter	if (!mac_enforce_fs)
212818334Speter		return (0);
212918334Speter
213018334Speter	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
213118334Speter	return (error);
213218334Speter}
213318334Speter
213418334Speterint
213518334Spetermac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
213618334Speter{
213718334Speter	int error;
213818334Speter
213918334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
214018334Speter
214118334Speter	if (!mac_enforce_fs)
214218334Speter		return (0);
214318334Speter
214418334Speter	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
214518334Speter	return (error);
214618334Speter}
214718334Speter
214818334Speterstatic int
214918334Spetermac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
215018334Speter    struct label *newlabel)
215118334Speter{
215218334Speter	int error;
215318334Speter
215418334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
215518334Speter
215618334Speter	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
215718334Speter
215818334Speter	return (error);
215918334Speter}
216018334Speter
216118334Speterint
216218334Spetermac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
216318334Speter    struct vnode *vp, struct componentname *cnp)
216418334Speter{
216518334Speter	int error;
216618334Speter
216718334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
216818334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
216918334Speter
217018334Speter	if (!mac_enforce_fs)
217118334Speter		return (0);
217218334Speter
217318334Speter	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
217418334Speter	    &vp->v_label, cnp);
217518334Speter	return (error);
217618334Speter}
217718334Speter
217818334Speterint
217918334Spetermac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
218018334Speter    struct vnode *vp, int samedir, struct componentname *cnp)
218118334Speter{
218218334Speter	int error;
218318334Speter
218418334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
218518334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
218618334Speter
218718334Speter	if (!mac_enforce_fs)
218818334Speter		return (0);
218918334Speter
219018334Speter	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
219118334Speter	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
219218334Speter	return (error);
219318334Speter}
219418334Speter
219518334Speterint
219618334Spetermac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
219718334Speter{
219818334Speter	int error;
219918334Speter
220018334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
220118334Speter
220218334Speter	if (!mac_enforce_fs)
220318334Speter		return (0);
220418334Speter
220518334Speter	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
220618334Speter	return (error);
220718334Speter}
220818334Speter
220918334Speterint
221018334Spetermac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
221118334Speter    struct acl *acl)
221218334Speter{
221318334Speter	int error;
221418334Speter
221518334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
221618334Speter
221718334Speter	if (!mac_enforce_fs)
221818334Speter		return (0);
221918334Speter
222018334Speter	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
222118334Speter	return (error);
222218334Speter}
222318334Speter
222418334Speterint
222518334Spetermac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
222618334Speter    int attrnamespace, const char *name, struct uio *uio)
222718334Speter{
222818334Speter	int error;
222918334Speter
223018334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
223118334Speter
223218334Speter	if (!mac_enforce_fs)
223318334Speter		return (0);
223418334Speter
223518334Speter	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
223618334Speter	    attrnamespace, name, uio);
223718334Speter	return (error);
223818334Speter}
223918334Speter
224018334Speterint
224118334Spetermac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
224218334Speter{
224318334Speter	int error;
224418334Speter
224518334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
224618334Speter
224718334Speter	if (!mac_enforce_fs)
224818334Speter		return (0);
224918334Speter
225018334Speter	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
225118334Speter	return (error);
225218334Speter}
225318334Speter
225418334Speterint
225518334Spetermac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
225618334Speter{
225718334Speter	int error;
225818334Speter
225918334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
226018334Speter
226118334Speter	if (!mac_enforce_fs)
226218334Speter		return (0);
226318334Speter
226418334Speter	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
226518334Speter	return (error);
226618334Speter}
226718334Speter
226818334Speterint
226918334Spetermac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
227018334Speter    gid_t gid)
227118334Speter{
227218334Speter	int error;
227318334Speter
227418334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
227518334Speter
227618334Speter	if (!mac_enforce_fs)
227718334Speter		return (0);
227818334Speter
227918334Speter	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
228018334Speter	return (error);
228118334Speter}
228218334Speter
228318334Speterint
228418334Spetermac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
228518334Speter    struct timespec atime, struct timespec mtime)
228618334Speter{
228718334Speter	int error;
228818334Speter
228918334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
229018334Speter
229118334Speter	if (!mac_enforce_fs)
229218334Speter		return (0);
229318334Speter
229418334Speter	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
229518334Speter	    mtime);
229618334Speter	return (error);
229718334Speter}
229818334Speter
229918334Speterint
230018334Spetermac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
230118334Speter    struct vnode *vp)
230218334Speter{
230318334Speter	int error;
230418334Speter
230518334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
230618334Speter
230718334Speter	if (!mac_enforce_fs)
230818334Speter		return (0);
230918334Speter
231018334Speter	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
231118334Speter	    &vp->v_label);
231218334Speter	return (error);
231318334Speter}
231418334Speter
231518334Speterint
231618334Spetermac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
231718334Speter    struct vnode *vp)
231818334Speter{
231918334Speter	int error;
232018334Speter
232118334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
232218334Speter
232318334Speter	if (!mac_enforce_fs)
232418334Speter		return (0);
232518334Speter
232618334Speter	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
232718334Speter	    &vp->v_label);
232818334Speter
232918334Speter	return (error);
233018334Speter}
233118334Speter
233218334Speter/*
233318334Speter * When relabeling a process, call out to the policies for the maximum
233418334Speter * permission allowed for each object type we know about in its
233518334Speter * memory space, and revoke access (in the least surprising ways we
233618334Speter * know) when necessary.  The process lock is not held here.
233718334Speter */
233818334Speterstatic void
233918334Spetermac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
234018334Speter{
234118334Speter
234218334Speter	/* XXX freeze all other threads */
234318334Speter	mac_cred_mmapped_drop_perms_recurse(td, cred,
234418334Speter	    &td->td_proc->p_vmspace->vm_map);
234518334Speter	/* XXX allow other threads to continue */
234618334Speter}
234718334Speter
234818334Speterstatic __inline const char *
234918334Speterprot2str(vm_prot_t prot)
235018334Speter{
235118334Speter
235218334Speter	switch (prot & VM_PROT_ALL) {
235318334Speter	case VM_PROT_READ:
235418334Speter		return ("r--");
235518334Speter	case VM_PROT_READ | VM_PROT_WRITE:
235618334Speter		return ("rw-");
235718334Speter	case VM_PROT_READ | VM_PROT_EXECUTE:
235818334Speter		return ("r-x");
235918334Speter	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
236018334Speter		return ("rwx");
236118334Speter	case VM_PROT_WRITE:
236218334Speter		return ("-w-");
236318334Speter	case VM_PROT_EXECUTE:
236418334Speter		return ("--x");
236518334Speter	case VM_PROT_WRITE | VM_PROT_EXECUTE:
236618334Speter		return ("-wx");
236718334Speter	default:
236818334Speter		return ("---");
236918334Speter	}
237018334Speter}
237118334Speter
237218334Speterstatic void
237318334Spetermac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
237418334Speter    struct vm_map *map)
237518334Speter{
237618334Speter	struct vm_map_entry *vme;
237718334Speter	int result;
237818334Speter	vm_prot_t revokeperms;
237918334Speter	vm_object_t object;
238018334Speter	vm_ooffset_t offset;
238118334Speter	struct vnode *vp;
238218334Speter
238318334Speter	if (!mac_mmap_revocation)
238418334Speter		return;
238518334Speter
238618334Speter	vm_map_lock_read(map);
238718334Speter	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
238818334Speter		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
238918334Speter			mac_cred_mmapped_drop_perms_recurse(td, cred,
239018334Speter			    vme->object.sub_map);
239118334Speter			continue;
239218334Speter		}
239318334Speter		/*
239418334Speter		 * Skip over entries that obviously are not shared.
239518334Speter		 */
239618334Speter		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
239718334Speter		    !vme->max_protection)
239818334Speter			continue;
239918334Speter		/*
240018334Speter		 * Drill down to the deepest backing object.
240118334Speter		 */
240218334Speter		offset = vme->offset;
240318334Speter		object = vme->object.vm_object;
240418334Speter		if (object == NULL)
240518334Speter			continue;
240618334Speter		while (object->backing_object != NULL) {
240718334Speter			object = object->backing_object;
240818334Speter			offset += object->backing_object_offset;
240918334Speter		}
241018334Speter		/*
241118334Speter		 * At the moment, vm_maps and objects aren't considered
241218334Speter		 * by the MAC system, so only things with backing by a
241318334Speter		 * normal object (read: vnodes) are checked.
241418334Speter		 */
241518334Speter		if (object->type != OBJT_VNODE)
241618334Speter			continue;
241718334Speter		vp = (struct vnode *)object->handle;
241818334Speter		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
241918334Speter		result = vme->max_protection;
242018334Speter		mac_check_vnode_mmap_downgrade(cred, vp, &result);
242118334Speter		VOP_UNLOCK(vp, 0, td);
242218334Speter		/*
242318334Speter		 * Find out what maximum protection we may be allowing
242418334Speter		 * now but a policy needs to get removed.
242518334Speter		 */
242618334Speter		revokeperms = vme->max_protection & ~result;
242718334Speter		if (!revokeperms)
242818334Speter			continue;
242918334Speter		printf("pid %ld: revoking %s perms from %#lx:%ld "
243018334Speter		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
243118334Speter		    prot2str(revokeperms), (u_long)vme->start,
243218334Speter		    (long)(vme->end - vme->start),
243318334Speter		    prot2str(vme->max_protection), prot2str(vme->protection));
243418334Speter		vm_map_lock_upgrade(map);
243518334Speter		/*
243618334Speter		 * This is the really simple case: if a map has more
243718334Speter		 * max_protection than is allowed, but it's not being
243818334Speter		 * actually used (that is, the current protection is
243918334Speter		 * still allowed), we can just wipe it out and do
244018334Speter		 * nothing more.
244118334Speter		 */
244218334Speter		if ((vme->protection & revokeperms) == 0) {
244318334Speter			vme->max_protection -= revokeperms;
244418334Speter		} else {
244518334Speter			if (revokeperms & VM_PROT_WRITE) {
244618334Speter				/*
244718334Speter				 * In the more complicated case, flush out all
244818334Speter				 * pending changes to the object then turn it
244918334Speter				 * copy-on-write.
245018334Speter				 */
245118334Speter				vm_object_reference(object);
245218334Speter				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
245318334Speter				vm_object_page_clean(object,
245418334Speter				    OFF_TO_IDX(offset),
245518334Speter				    OFF_TO_IDX(offset + vme->end - vme->start +
245618334Speter					PAGE_MASK),
245718334Speter				    OBJPC_SYNC);
245818334Speter				VOP_UNLOCK(vp, 0, td);
245918334Speter				vm_object_deallocate(object);
246018334Speter				/*
246118334Speter				 * Why bother if there's no read permissions
246218334Speter				 * anymore?  For the rest, we need to leave
246318334Speter				 * the write permissions on for COW, or
246418334Speter				 * remove them entirely if configured to.
246518334Speter				 */
246618334Speter				if (!mac_mmap_revocation_via_cow) {
246718334Speter					vme->max_protection &= ~VM_PROT_WRITE;
246818334Speter					vme->protection &= ~VM_PROT_WRITE;
246918334Speter				} if ((revokeperms & VM_PROT_READ) == 0)
247018334Speter					vme->eflags |= MAP_ENTRY_COW |
247118334Speter					    MAP_ENTRY_NEEDS_COPY;
247218334Speter			}
247318334Speter			if (revokeperms & VM_PROT_EXECUTE) {
247418334Speter				vme->max_protection &= ~VM_PROT_EXECUTE;
247518334Speter				vme->protection &= ~VM_PROT_EXECUTE;
247618334Speter			}
247718334Speter			if (revokeperms & VM_PROT_READ) {
247818334Speter				vme->max_protection = 0;
247918334Speter				vme->protection = 0;
248018334Speter			}
248118334Speter			pmap_protect(map->pmap, vme->start, vme->end,
248218334Speter			    vme->protection & ~revokeperms);
248318334Speter			vm_map_simplify_entry(map, vme);
248418334Speter		}
248518334Speter		vm_map_lock_downgrade(map);
248618334Speter	}
248718334Speter	vm_map_unlock_read(map);
248818334Speter}
248918334Speter
249018334Speter/*
249118334Speter * When the subject's label changes, it may require revocation of privilege
249218334Speter * to mapped objects.  This can't be done on-the-fly later with a unified
249318334Speter * buffer cache.
249418334Speter */
249518334Speterstatic void
249618334Spetermac_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