mac_internal.h revision 116701
1105196Swollman/*-
22742Swollman * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
386464Swollman * Copyright (c) 2001 Ilmar S. Habibulin
42742Swollman * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
52742Swollman * All rights reserved.
62742Swollman *
72742Swollman * This software was developed by Robert Watson and Ilmar Habibulin for the
82742Swollman * TrustedBSD Project.
92742Swollman *
1086222Swollman * This software was developed for the FreeBSD Project in part by Network
1186222Swollman * Associates Laboratories, the Security Research Division of Network
122742Swollman * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
1358787Sru * as part of the DARPA CHATS research program.
142742Swollman *
152742Swollman * Redistribution and use in source and binary forms, with or without
162742Swollman * modification, are permitted provided that the following conditions
172742Swollman * are met:
182742Swollman * 1. Redistributions of source code must retain the above copyright
192742Swollman *    notice, this list of conditions and the following disclaimer.
2058787Sru * 2. Redistributions in binary form must reproduce the above copyright
2158787Sru *    notice, this list of conditions and the following disclaimer in the
2258787Sru *    documentation and/or other materials provided with the distribution.
232742Swollman *
242742Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
259908Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
262742Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2730711Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
282742Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
299908Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
302742Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3158787Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3258787Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3314343Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3414343Swollman * SUCH DAMAGE.
3514343Swollman */
3614343Swollman
3714343Swollman/*
382742Swollman * Framework for extensible kernel access control.  Kernel and userland
399908Swollman * interface to the framework, policy registration and composition.
4020094Swollman */
4120094Swollman
4220094Swollman#include <sys/cdefs.h>
4320094Swollman__FBSDID("$FreeBSD: head/sys/security/mac/mac_internal.h 116701 2003-06-23 01:26:34Z rwatson $");
4420094Swollman
4520094Swollman#include "opt_mac.h"
4620094Swollman#include "opt_devfs.h"
4720094Swollman
4820094Swollman#include <sys/param.h>
4920094Swollman#include <sys/condvar.h>
5020094Swollman#include <sys/extattr.h>
5120094Swollman#include <sys/imgact.h>
5220094Swollman#include <sys/kernel.h>
5358787Sru#include <sys/lock.h>
5458787Sru#include <sys/malloc.h>
5521217Swollman#include <sys/mutex.h>
5621217Swollman#include <sys/mac.h>
5758787Sru#include <sys/module.h>
5858787Sru#include <sys/proc.h>
592742Swollman#include <sys/sbuf.h>
6058787Sru#include <sys/systm.h>
6121217Swollman#include <sys/sysproto.h>
6220094Swollman#include <sys/sysent.h>
6358787Sru#include <sys/vnode.h>
6458787Sru#include <sys/mount.h>
6520094Swollman#include <sys/file.h>
662742Swollman#include <sys/namei.h>
679908Swollman#include <sys/socket.h>
682742Swollman#include <sys/pipe.h>
6914343Swollman#include <sys/socketvar.h>
7014343Swollman#include <sys/sysctl.h>
7114343Swollman
7214343Swollman#include <vm/vm.h>
7314343Swollman#include <vm/pmap.h>
7414343Swollman#include <vm/vm_map.h>
7564499Swollman#include <vm/vm_object.h>
7664499Swollman
7764499Swollman#include <sys/mac_policy.h>
7864499Swollman
7964499Swollman#include <fs/devfs/devfs.h>
8014343Swollman
812742Swollman#include <net/bpfdesc.h>
822742Swollman#include <net/if.h>
832742Swollman#include <net/if_var.h>
8458787Sru
852742Swollman#include <netinet/in.h>
862742Swollman#include <netinet/ip_var.h>
879908Swollman
882742Swollman#ifdef MAC
8958787Sru
9058787Sru/*
9114343Swollman * Declare that the kernel provides MAC support, version 1.  This permits
9214343Swollman * modules to refuse to be loaded if the necessary support isn't present,
9358787Sru * even if it's pre-boot.
9414343Swollman */
9514343SwollmanMODULE_VERSION(kernel_mac_support, 1);
9614343Swollman
9758787SruSYSCTL_DECL(_security);
9814343Swollman
9958787SruSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
10058787Sru    "TrustedBSD MAC policy controls");
10158787Sru
10214343Swollman#if MAC_MAX_SLOTS > 32
10358787Sru#error "MAC_MAX_SLOTS too large"
10458787Sru#endif
1052742Swollman
1062742Swollmanstatic unsigned int mac_max_slots = MAC_MAX_SLOTS;
10758787Srustatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
10858787SruSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
10958787Sru    &mac_max_slots, 0, "");
1102742Swollman
1112742Swollman/*
1129908Swollman * Has the kernel started generating labeled objects yet?  All read/write
1132742Swollman * access to this variable is serialized during the boot process.  Following
11414343Swollman * the end of serialization, we don't update this flag; no locking.
11558787Sru */
11614343Swollmanstatic int	mac_late = 0;
11714343Swollman
11858787Sru/*
11958787Sru * Warn about EA transactions only the first time they happen.
12014343Swollman * Weak coherency, no locking.
12114343Swollman */
12258787Srustatic int	ea_warn_once = 0;
12343543Swollman
1242742Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
1252742Swollman/*
12658787Sru * Flag to indicate whether or not we should allocate label storage for
1272742Swollman * new mbufs.  Since most dynamic policies we currently work with don't
1282742Swollman * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
1299908Swollman * unless specifically notified of interest.  One result of this is
1302742Swollman * that if a dynamically loaded policy requests mbuf labels, it must
13114343Swollman * be able to deal with a NULL label being returned on any mbufs that
13214343Swollman * were already in flight when the policy was loaded.  Since the policy
13314343Swollman * already has to deal with uninitialized labels, this probably won't
13414343Swollman * be a problem.  Note: currently no locking.  Will this be a problem?
13514343Swollman */
13614343Swollmanstatic int	mac_labelmbufs = 0;
13714343Swollman#endif
13843543Swollman
13914343Swollmanstatic int	mac_enforce_fs = 1;
14014343SwollmanSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
14158787Sru    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
14243543SwollmanTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
1432742Swollman
1442742Swollmanstatic int	mac_enforce_kld = 1;
14558787SruSYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
1462742Swollman    &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
1472742SwollmanTUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
1482742Swollman
1492742Swollmanstatic int	mac_enforce_network = 1;
15058787SruSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
15158787Sru    &mac_enforce_network, 0, "Enforce MAC policy on network packets");
15258787SruTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
1538029Swollman
15414343Swollmanstatic int	mac_enforce_pipe = 1;
15514343SwollmanSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
15675267Swollman    &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
15775267SwollmanTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
15875267Swollman
15975267Swollmanstatic int	mac_enforce_process = 1;
16075267SwollmanSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
16175267Swollman    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
16275267SwollmanTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
16375267Swollman
16475267Swollmanstatic int	mac_enforce_socket = 1;
16575267SwollmanSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
1662742Swollman    &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
1672742SwollmanTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
16814343Swollman
1698029Swollmanstatic int	mac_enforce_system = 1;
17014343SwollmanSYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
1712742Swollman    &mac_enforce_system, 0, "Enforce MAC policy on system operations");
1722742SwollmanTUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
17314343Swollman
17458787Srustatic int	mac_enforce_vm = 1;
1752742SwollmanSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
17614343Swollman    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
17714343SwollmanTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
17814343Swollman
17914343Swollmanstatic int	mac_mmap_revocation = 1;
18030711SwollmanSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
18130711Swollman    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
18258787Sru    "relabel");
18358787Srustatic int	mac_mmap_revocation_via_cow = 0;
1842742SwollmanSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
18543014Swollman    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
18643014Swollman    "copy-on-write semantics, or by removing all write access");
18743014Swollman
18843014Swollman#ifdef MAC_DEBUG
1892742SwollmanSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
1902742Swollman    "TrustedBSD MAC debug info");
19158787Sru
1922742Swollmanstatic int	mac_debug_label_fallback = 0;
19319878SwollmanSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
19443014Swollman    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
19543014Swollman    "when label is corrupted.");
1962742SwollmanTUNABLE_INT("security.mac.debug_label_fallback",
1972742Swollman    &mac_debug_label_fallback);
19819878Swollman
19919878SwollmanSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
2002742Swollman    "TrustedBSD MAC object counters");
2012742Swollman
2022742Swollmanstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
2032742Swollman    nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
20419878Swollman    nmacipqs, nmacpipes, nmacprocs;
2052742Swollman
2062742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
20743543Swollman    &nmacmbufs, 0, "number of mbufs in use");
20875267SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
20975267Swollman    &nmaccreds, 0, "number of ucreds in use");
2102742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
2112742Swollman    &nmacifnets, 0, "number of ifnets in use");
21243543SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
2132742Swollman    &nmacipqs, 0, "number of ipqs in use");
2142742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
2152742Swollman    &nmacbpfdescs, 0, "number of bpfdescs in use");
2162742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
21719878Swollman    &nmacsockets, 0, "number of sockets in use");
2182742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
21919878Swollman    &nmacpipes, 0, "number of pipes in use");
2202742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
22119878Swollman    &nmacprocs, 0, "number of procs in use");
22243014SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
22343014Swollman    &nmacmounts, 0, "number of mounts in use");
2242742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
2252742Swollman    &nmactemp, 0, "number of temporary labels in use");
2262742SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
22775267Swollman    &nmacvnodes, 0, "number of vnodes in use");
22875267SwollmanSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
22975267Swollman    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
23075267Swollman#endif
2312742Swollman
2322742Swollmanstatic int	error_select(int error1, int error2);
2332742Swollmanstatic int	mac_policy_register(struct mac_policy_conf *mpc);
2342742Swollmanstatic int	mac_policy_unregister(struct mac_policy_conf *mpc);
23519878Swollman
2362742Swollmanstatic void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
23719878Swollman		    struct vnode *vp, int *prot);
23819878Swollmanstatic void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
23919878Swollman		    struct ucred *cred, struct vm_map *map);
2402742Swollman
24119878Swollmanstatic void	mac_destroy_socket_label(struct label *label);
24219878Swollman
24319878Swollmanstatic int	mac_setlabel_vnode_extattr(struct ucred *cred,
2442742Swollman		    struct vnode *vp, struct label *intlabel);
24514343Swollman
24614343SwollmanMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
24775267SwollmanMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
24875267Swollman
24919878Swollman/*
25075267Swollman * mac_static_policy_list holds a list of policy modules that are not
25175267Swollman * loaded while the system is "live", and cannot be unloaded.  These
25214343Swollman * policies can be invoked without holding the busy count.
25314343Swollman *
25414343Swollman * mac_policy_list stores the list of dynamic policies.  A busy count is
25514343Swollman * maintained for the list, stored in mac_policy_busy.  The busy count
25619878Swollman * is protected by mac_policy_mtx; the list may be modified only
25719878Swollman * while the busy count is 0, requiring that the lock be held to
25814343Swollman * prevent new references to the list from being acquired.  For almost
25919878Swollman * all operations, incrementing the busy count is sufficient to
26019878Swollman * guarantee consistency, as the list cannot be modified while the
26119878Swollman * busy count is elevated.  For a few special operations involving a
26214343Swollman * change to the list of active policies, the mtx itself must be held.
26314343Swollman * A condition variable, mac_policy_cv, is used to signal potential
26414343Swollman * exclusive consumers that they should try to acquire the lock if a
26514343Swollman * first attempt at exclusive access fails.
26619878Swollman */
26719878Swollmanstatic struct mtx mac_policy_mtx;
26814343Swollmanstatic struct cv mac_policy_cv;
26919878Swollmanstatic int mac_policy_count;
27014343Swollmanstatic LIST_HEAD(, mac_policy_conf) mac_policy_list;
27119878Swollmanstatic LIST_HEAD(, mac_policy_conf) mac_static_policy_list;
27214343Swollman
27358787Sru/*
27458787Sru * We manually invoke WITNESS_WARN() to allow Witness to generate
27558787Sru * warnings even if we don't end up ever triggering the wait at
27614343Swollman * run-time.  The consumer of the exclusive interface must not hold
2772742Swollman * any locks (other than potentially Giant) since we may sleep for
2782742Swollman * long (potentially indefinite) periods of time waiting for the
2792742Swollman * framework to become quiescent so that a policy list change may
28019878Swollman * be made.
2812742Swollman */
28219878Swollmanstatic __inline void
28319878Swollmanmac_policy_grab_exclusive(void)
2842742Swollman{
2852742Swollman	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
2862742Swollman 	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
28719878Swollman	mtx_lock(&mac_policy_mtx);
28819878Swollman	while (mac_policy_count != 0)
28943014Swollman		cv_wait(&mac_policy_cv, &mac_policy_mtx);
29058787Sru}
29143014Swollman
2922742Swollmanstatic __inline void
2932742Swollmanmac_policy_assert_exclusive(void)
2942742Swollman{
2952742Swollman	mtx_assert(&mac_policy_mtx, MA_OWNED);
2962742Swollman	KASSERT(mac_policy_count == 0,
2972742Swollman	    ("mac_policy_assert_exclusive(): not exclusive"));
2982742Swollman}
2992742Swollman
3002742Swollmanstatic __inline void
3012742Swollmanmac_policy_release_exclusive(void)
3022742Swollman{
3032742Swollman
30414343Swollman	KASSERT(mac_policy_count == 0,
3052742Swollman	    ("mac_policy_release_exclusive(): not exclusive"));
30614343Swollman	mtx_unlock(&mac_policy_mtx);
30714343Swollman	cv_signal(&mac_policy_cv);
3082742Swollman}
30914343Swollman
31043014Swollmanstatic __inline void
31114343Swollmanmac_policy_list_busy(void)
31214343Swollman{
31314343Swollman	mtx_lock(&mac_policy_mtx);
3149908Swollman	mac_policy_count++;
3159908Swollman	mtx_unlock(&mac_policy_mtx);
3169908Swollman}
3179908Swollman
3189908Swollmanstatic __inline int
3199908Swollmanmac_policy_list_conditional_busy(void)
3209908Swollman{
32120094Swollman	int ret;
32220094Swollman
3232742Swollman	mtx_lock(&mac_policy_mtx);
3242742Swollman	if (!LIST_EMPTY(&mac_policy_list)) {
32514343Swollman		mac_policy_count++;
3262742Swollman		ret = 1;
32720094Swollman	} else
3282742Swollman		ret = 0;
3298029Swollman	mtx_unlock(&mac_policy_mtx);
33030711Swollman	return (ret);
33158787Sru}
33258787Sru
3332742Swollmanstatic __inline void
33430711Swollmanmac_policy_list_unbusy(void)
33558787Sru{
33658787Sru	mtx_lock(&mac_policy_mtx);
33758787Sru	mac_policy_count--;
33830711Swollman	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
33930711Swollman	if (mac_policy_count == 0)
3402742Swollman		cv_signal(&mac_policy_cv);
3412742Swollman	mtx_unlock(&mac_policy_mtx);
3422742Swollman}
3432742Swollman
3442742Swollman/*
3452742Swollman * MAC_CHECK performs the designated check by walking the policy
34619878Swollman * module list and checking with each as to how it feels about the
34719878Swollman * request.  Note that it returns its value via 'error' in the scope
34819878Swollman * of the caller.
3492742Swollman */
3502742Swollman#define	MAC_CHECK(check, args...) do {					\
3512742Swollman	struct mac_policy_conf *mpc;					\
3522742Swollman	int entrycount;							\
35319878Swollman									\
35419878Swollman	error = 0;							\
3552742Swollman	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
35658787Sru		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
3579908Swollman			error = error_select(				\
3589908Swollman			    mpc->mpc_ops->mpo_ ## check (args),		\
35919878Swollman			    error);					\
3609908Swollman	}								\
3612742Swollman	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
3622742Swollman		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
3632742Swollman			if (mpc->mpc_ops->mpo_ ## check != NULL)	\
36486222Swollman				error = error_select(			\
36519878Swollman				    mpc->mpc_ops->mpo_ ## check (args),	\
3662742Swollman				    error);				\
3672742Swollman		}							\
3682742Swollman		mac_policy_list_unbusy();				\
3692742Swollman	}								\
37058787Sru} while (0)
37158787Sru
3722742Swollman/*
37314343Swollman * MAC_BOOLEAN performs the designated boolean composition by walking
37414343Swollman * the module list, invoking each instance of the operation, and
37514343Swollman * combining the results using the passed C operator.  Note that it
37619878Swollman * returns its value via 'result' in the scope of the caller, which
37714343Swollman * should be initialized by the caller in a meaningful way to get
37814343Swollman * a meaningful result.
37914343Swollman */
38014343Swollman#define	MAC_BOOLEAN(operation, composition, args...) do {		\
38114343Swollman	struct mac_policy_conf *mpc;					\
38214343Swollman	int entrycount;							\
38314343Swollman									\
38419878Swollman	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
38519878Swollman		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
38614343Swollman			result = result composition			\
3872742Swollman			    mpc->mpc_ops->mpo_ ## operation (args);	\
3882742Swollman	}								\
3892742Swollman	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
3902742Swollman		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
39119878Swollman			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
3922742Swollman				result = result composition		\
3932742Swollman				    mpc->mpc_ops->mpo_ ## operation	\
3942742Swollman				    (args);				\
3952742Swollman		}							\
39619878Swollman		mac_policy_list_unbusy();				\
3972742Swollman	}								\
3982742Swollman} while (0)
39958787Sru
40075267Swollman#define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
40175267Swollman    outbuflen) do {							\
40293799Swollman	int claimed, first, ignorenotfound, savedlen;			\
40393799Swollman	char *element_name, *element_temp;				\
4042742Swollman	struct sbuf sb;							\
4052742Swollman									\
40658787Sru	error = 0;							\
40758787Sru	first = 1;							\
40858787Sru	sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN);		\
4092742Swollman	element_temp = elementlist;					\
4102742Swollman	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
4112742Swollman		if (element_name[0] == '?') {				\
4122742Swollman			element_name++;					\
41319878Swollman			ignorenotfound = 1;				\
4142742Swollman		 } else							\
41543014Swollman			ignorenotfound = 0;				\
41643014Swollman		savedlen = sbuf_len(&sb);				\
41743014Swollman		if (first) {						\
41843014Swollman			error = sbuf_printf(&sb, "%s/", element_name);	\
41943014Swollman			first = 0;					\
42043014Swollman		} else							\
42143014Swollman			error = sbuf_printf(&sb, ",%s/", element_name);	\
42243014Swollman		if (error == -1) {					\
42343014Swollman			error = EINVAL;	/* XXX: E2BIG? */		\
42443014Swollman			break;						\
42543014Swollman		}							\
42643014Swollman		claimed = 0;						\
42743014Swollman		MAC_CHECK(externalize_ ## type, label, element_name,	\
42843014Swollman		    &sb, &claimed);					\
42943014Swollman		if (error)						\
43043014Swollman			break;						\
43143014Swollman		if (claimed == 0 && ignorenotfound) {			\
43243014Swollman			/* Revert last label name. */			\
43343014Swollman			sbuf_setpos(&sb, savedlen);			\
43443014Swollman		} else if (claimed != 1) {				\
43543014Swollman			error = EINVAL;	/* XXX: ENOLABEL? */		\
43643014Swollman			break;						\
43743014Swollman		}							\
43843014Swollman	}								\
43943014Swollman	sbuf_finish(&sb);						\
44043014Swollman} while (0)
44143014Swollman
44243014Swollman#define	MAC_INTERNALIZE(type, label, instring) do {			\
44343014Swollman	char *element, *element_name, *element_data;			\
44443014Swollman	int claimed;							\
44543014Swollman									\
44643014Swollman	error = 0;							\
44743014Swollman	element = instring;						\
4482742Swollman	while ((element_name = strsep(&element, ",")) != NULL) {	\
4492742Swollman		element_data = element_name;				\
45019878Swollman		element_name = strsep(&element_data, "/");		\
45119878Swollman		if (element_data == NULL) {				\
45219878Swollman			error = EINVAL;					\
45320094Swollman			break;						\
45420094Swollman		}							\
45520094Swollman		claimed = 0;						\
4562742Swollman		MAC_CHECK(internalize_ ## type, label, element_name,	\
4572742Swollman		    element_data, &claimed);				\
45819878Swollman		if (error)						\
4592742Swollman			break;						\
4602742Swollman		if (claimed != 1) {					\
4612742Swollman			/* XXXMAC: Another error here? */		\
4622742Swollman			error = EINVAL;					\
46319878Swollman			break;						\
4642742Swollman		}							\
4652742Swollman	}								\
4662742Swollman} while (0)
4672742Swollman
4682742Swollman/*
4692742Swollman * MAC_PERFORM performs the designated operation by walking the policy
4702742Swollman * module list and invoking that operation for each policy.
4712742Swollman */
4722742Swollman#define	MAC_PERFORM(operation, args...) do {				\
47358787Sru	struct mac_policy_conf *mpc;					\
4742742Swollman	int entrycount;							\
47558787Sru									\
47658787Sru	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
4772742Swollman		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
47886222Swollman			mpc->mpc_ops->mpo_ ## operation (args);		\
47920094Swollman	}								\
48020094Swollman	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
48120094Swollman		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
48220094Swollman			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
48320094Swollman				mpc->mpc_ops->mpo_ ## operation (args);	\
48420094Swollman		}							\
48520094Swollman		mac_policy_list_unbusy();				\
48620094Swollman	}								\
4872742Swollman} while (0)
4882742Swollman
4892742Swollman/*
4902742Swollman * Initialize the MAC subsystem, including appropriate SMP locks.
4912742Swollman */
49258787Srustatic void
4932742Swollmanmac_init(void)
4942742Swollman{
4952742Swollman
4962742Swollman	LIST_INIT(&mac_static_policy_list);
4972742Swollman	LIST_INIT(&mac_policy_list);
4982742Swollman
4992742Swollman	mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
5002742Swollman	cv_init(&mac_policy_cv, "mac_policy_cv");
5012742Swollman}
5022742Swollman
50375267Swollman/*
5042742Swollman * For the purposes of modules that want to know if they were loaded
5052742Swollman * "early", set the mac_late flag once we've processed modules either
50619878Swollman * linked into the kernel, or loaded before the kernel startup.
5072742Swollman */
50814343Swollmanstatic void
50958787Srumac_late_init(void)
5102742Swollman{
51114343Swollman
5129908Swollman	mac_late = 1;
5132742Swollman}
5142742Swollman
5152742Swollman/*
5162742Swollman * After the policy list has changed, walk the list to update any global
5172742Swollman * flags.
51858787Sru */
51958787Srustatic void
52058787Srumac_policy_updateflags(void)
52158787Sru{
52219878Swollman	struct mac_policy_conf *tmpc;
5232742Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
5242742Swollman	int labelmbufs;
5252742Swollman#endif
5262742Swollman
5272742Swollman	mac_policy_assert_exclusive();
5282742Swollman
5292742Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
5302742Swollman	labelmbufs = 0;
5312742Swollman#endif
5322742Swollman
5332742Swollman	LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
5342742Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
5352742Swollman		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
5362742Swollman			labelmbufs++;
5372742Swollman#endif
5382742Swollman	}
5392742Swollman	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
54086222Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
5412742Swollman		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
5422742Swollman			labelmbufs++;
5432742Swollman#endif
5442742Swollman	}
5452742Swollman
54686222Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
54786222Swollman	mac_labelmbufs = (labelmbufs != 0);
54886222Swollman#endif
54986222Swollman}
55086222Swollman
55186222Swollman/*
55286222Swollman * Allow MAC policy modules to register during boot, etc.
55386222Swollman */
55486222Swollmanint
55586222Swollmanmac_policy_modevent(module_t mod, int type, void *data)
55686222Swollman{
55786222Swollman	struct mac_policy_conf *mpc;
55886222Swollman	int error;
55986222Swollman
56086222Swollman	error = 0;
56186222Swollman	mpc = (struct mac_policy_conf *) data;
56286222Swollman
56386222Swollman	switch (type) {
56486222Swollman	case MOD_LOAD:
56586222Swollman		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
56686222Swollman		    mac_late) {
56786222Swollman			printf("mac_policy_modevent: can't load %s policy "
56886222Swollman			    "after booting\n", mpc->mpc_name);
56986222Swollman			error = EBUSY;
57086222Swollman			break;
57186222Swollman		}
57286222Swollman		error = mac_policy_register(mpc);
57386222Swollman		break;
57486222Swollman	case MOD_UNLOAD:
57586222Swollman		/* Don't unregister the module if it was never registered. */
57686222Swollman		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
57786222Swollman		    != 0)
57886222Swollman			error = mac_policy_unregister(mpc);
57986222Swollman		else
58086222Swollman			error = 0;
58186222Swollman		break;
58286222Swollman	default:
58386222Swollman		break;
58486222Swollman	}
58586222Swollman
58686222Swollman	return (error);
58786222Swollman}
58886222Swollman
58986222Swollmanstatic int
59086222Swollmanmac_policy_register(struct mac_policy_conf *mpc)
59186222Swollman{
59286222Swollman	struct mac_policy_conf *tmpc;
59386222Swollman	int error, slot, static_entry;
59486222Swollman
59586222Swollman	error = 0;
59686222Swollman
59786222Swollman	/*
59886222Swollman	 * We don't technically need exclusive access while !mac_late,
59986222Swollman	 * but hold it for assertion consistency.
60086222Swollman	 */
60186222Swollman	mac_policy_grab_exclusive();
60286222Swollman
60386222Swollman	/*
60486222Swollman	 * If the module can potentially be unloaded, or we're loading
60586222Swollman	 * late, we have to stick it in the non-static list and pay
60686222Swollman	 * an extra performance overhead.  Otherwise, we can pay a
60786222Swollman	 * light locking cost and stick it in the static list.
60886222Swollman	 */
60986222Swollman	static_entry = (!mac_late &&
61086222Swollman	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
61186222Swollman
61286222Swollman	if (static_entry) {
61386222Swollman		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
61486222Swollman			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
61586222Swollman				error = EEXIST;
61686222Swollman				goto out;
61786222Swollman			}
61886222Swollman		}
61986222Swollman	} else {
62086222Swollman		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
62186222Swollman			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
62286222Swollman				error = EEXIST;
62386222Swollman				goto out;
62486222Swollman			}
62586222Swollman		}
62686222Swollman	}
62714343Swollman	if (mpc->mpc_field_off != NULL) {
6289908Swollman		slot = ffs(mac_slot_offsets_free);
6299908Swollman		if (slot == 0) {
6309908Swollman			error = ENOMEM;
6319908Swollman			goto out;
6329908Swollman		}
63314343Swollman		slot--;
6342742Swollman		mac_slot_offsets_free &= ~(1 << slot);
63543014Swollman		*mpc->mpc_field_off = slot;
63675267Swollman	}
63743014Swollman	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
63843014Swollman
63943014Swollman	/*
64075267Swollman	 * If we're loading a MAC module after the framework has
64143014Swollman	 * initialized, it has to go into the dynamic list.  If
64243014Swollman	 * we're loading it before we've finished initializing,
64343014Swollman	 * it can go into the static list with weaker locker
64443014Swollman	 * requirements.
64543014Swollman	 */
64658787Sru	if (static_entry)
64743014Swollman		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
64843014Swollman	else
64943014Swollman		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
65043014Swollman
65143014Swollman	/* Per-policy initialization. */
65243014Swollman	if (mpc->mpc_ops->mpo_init != NULL)
65343014Swollman		(*(mpc->mpc_ops->mpo_init))(mpc);
6549908Swollman	mac_policy_updateflags();
6559908Swollman
65619878Swollman	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
6572742Swollman	    mpc->mpc_name);
6582742Swollman
6592742Swollmanout:
6602742Swollman	mac_policy_release_exclusive();
6619908Swollman	return (error);
6622742Swollman}
66319878Swollman
6642742Swollmanstatic int
6652742Swollmanmac_policy_unregister(struct mac_policy_conf *mpc)
6662742Swollman{
6679908Swollman
6682742Swollman	/*
66919878Swollman	 * If we fail the load, we may get a request to unload.  Check
6702742Swollman	 * to see if we did the run-time registration, and if not,
6712742Swollman	 * silently succeed.
6722742Swollman	 */
6732742Swollman	mac_policy_grab_exclusive();
6742742Swollman	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
6752742Swollman		mac_policy_release_exclusive();
6762742Swollman		return (0);
6772742Swollman	}
6782742Swollman#if 0
6792742Swollman	/*
6802742Swollman	 * Don't allow unloading modules with private data.
6812742Swollman	 */
6822742Swollman	if (mpc->mpc_field_off != NULL) {
6832742Swollman		MAC_POLICY_LIST_UNLOCK();
68419878Swollman		return (EBUSY);
6852742Swollman	}
6862742Swollman#endif
6872742Swollman	/*
68819878Swollman	 * Only allow the unload to proceed if the module is unloadable
6892742Swollman	 * by its own definition.
6902742Swollman	 */
6912742Swollman	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
6922742Swollman		mac_policy_release_exclusive();
6932742Swollman		return (EBUSY);
6942742Swollman	}
69519878Swollman	if (mpc->mpc_ops->mpo_destroy != NULL)
6962742Swollman		(*(mpc->mpc_ops->mpo_destroy))(mpc);
6972742Swollman
6982742Swollman	LIST_REMOVE(mpc, mpc_list);
69958787Sru	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
70058787Sru	mac_policy_updateflags();
70158787Sru
70258787Sru	mac_policy_release_exclusive();
70358787Sru
7049908Swollman	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
70519878Swollman	    mpc->mpc_name);
7062742Swollman
7072742Swollman	return (0);
7082742Swollman}
7092742Swollman
7102742Swollman/*
7112742Swollman * Define an error value precedence, and given two arguments, selects the
7122742Swollman * value with the higher precedence.
7132742Swollman */
7142742Swollmanstatic int
7152742Swollmanerror_select(int error1, int error2)
71619878Swollman{
7172742Swollman
7182742Swollman	/* Certain decision-making errors take top priority. */
7192742Swollman	if (error1 == EDEADLK || error2 == EDEADLK)
72019878Swollman		return (EDEADLK);
7212742Swollman
7222742Swollman	/* Invalid arguments should be reported where possible. */
7232742Swollman	if (error1 == EINVAL || error2 == EINVAL)
7242742Swollman		return (EINVAL);
72519878Swollman
7262742Swollman	/* Precedence goes to "visibility", with both process and file. */
7272742Swollman	if (error1 == ESRCH || error2 == ESRCH)
7282742Swollman		return (ESRCH);
7292742Swollman
73019878Swollman	if (error1 == ENOENT || error2 == ENOENT)
7312742Swollman		return (ENOENT);
7322742Swollman
7332742Swollman	/* Precedence goes to DAC/MAC protections. */
7342742Swollman	if (error1 == EACCES || error2 == EACCES)
7352742Swollman		return (EACCES);
7362742Swollman
7372742Swollman	/* Precedence goes to privilege. */
73819878Swollman	if (error1 == EPERM || error2 == EPERM)
7392742Swollman		return (EPERM);
7402742Swollman
741105196Swollman	/* Precedence goes to error over success; otherwise, arbitrary. */
742105196Swollman	if (error1 != 0)
743105196Swollman		return (error1);
744105196Swollman	return (error2);
745105196Swollman}
746105196Swollman
747105196Swollmanstatic struct label *
748105196Swollmanmbuf_to_label(struct mbuf *mbuf)
749105196Swollman{
750105196Swollman	struct m_tag *tag;
751105196Swollman	struct label *label;
752105196Swollman
753105196Swollman	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
754105196Swollman	label = (struct label *)(tag+1);
755105196Swollman
756105196Swollman	return (label);
757105196Swollman}
758105196Swollman
759105196Swollmanstatic void
760105196Swollmanmac_init_label(struct label *label)
761105196Swollman{
762105196Swollman
763105196Swollman	bzero(label, sizeof(*label));
764105196Swollman	label->l_flags = MAC_FLAG_INITIALIZED;
765105196Swollman}
766105196Swollman
767105196Swollmanstatic void
768105196Swollmanmac_destroy_label(struct label *label)
769105196Swollman{
770105196Swollman
771105196Swollman	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
772105196Swollman	    ("destroying uninitialized label"));
7739908Swollman
7742742Swollman	bzero(label, sizeof(*label));
77519878Swollman	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
7762742Swollman}
7772742Swollman
7782742Swollmanvoid
7792742Swollmanmac_init_bpfdesc(struct bpf_d *bpf_d)
7802742Swollman{
7812742Swollman
7822742Swollman	mac_init_label(&bpf_d->bd_label);
7832742Swollman	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
7842742Swollman#ifdef MAC_DEBUG
7852742Swollman	atomic_add_int(&nmacbpfdescs, 1);
7862742Swollman#endif
7872742Swollman}
7882742Swollman
7892742Swollmanstatic void
7902742Swollmanmac_init_cred_label(struct label *label)
7912742Swollman{
7922742Swollman
79319878Swollman	mac_init_label(label);
7942742Swollman	MAC_PERFORM(init_cred_label, label);
7952742Swollman#ifdef MAC_DEBUG
7962742Swollman	atomic_add_int(&nmaccreds, 1);
7972742Swollman#endif
7982742Swollman}
7992742Swollman
8002742Swollmanvoid
8019908Swollmanmac_init_cred(struct ucred *cred)
8022742Swollman{
80319878Swollman
8042742Swollman	mac_init_cred_label(&cred->cr_label);
8052742Swollman}
8062742Swollman
8072742Swollmanvoid
80819878Swollmanmac_init_devfsdirent(struct devfs_dirent *de)
8092742Swollman{
8102742Swollman
8112742Swollman	mac_init_label(&de->de_label);
8122742Swollman	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
8132742Swollman#ifdef MAC_DEBUG
8142742Swollman	atomic_add_int(&nmacdevfsdirents, 1);
8152742Swollman#endif
8162742Swollman}
8172742Swollman
8182742Swollmanstatic void
81919878Swollmanmac_init_ifnet_label(struct label *label)
8202742Swollman{
8212742Swollman
8222742Swollman	mac_init_label(label);
8232742Swollman	MAC_PERFORM(init_ifnet_label, label);
82419878Swollman#ifdef MAC_DEBUG
8252742Swollman	atomic_add_int(&nmacifnets, 1);
8262742Swollman#endif
8272742Swollman}
8282742Swollman
8292742Swollmanvoid
83019878Swollmanmac_init_ifnet(struct ifnet *ifp)
8312742Swollman{
8322742Swollman
8332742Swollman	mac_init_ifnet_label(&ifp->if_label);
8342742Swollman}
83519878Swollman
8362742Swollmanint
8372742Swollmanmac_init_ipq(struct ipq *ipq, int flag)
8382742Swollman{
8392742Swollman	int error;
8409908Swollman
8419908Swollman	mac_init_label(&ipq->ipq_label);
8429908Swollman
8439908Swollman	MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag);
8442742Swollman	if (error) {
8459908Swollman		MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
8469908Swollman		mac_destroy_label(&ipq->ipq_label);
84758787Sru	}
84858787Sru#ifdef MAC_DEBUG
8492742Swollman	if (error == 0)
8502742Swollman		atomic_add_int(&nmacipqs, 1);
8512742Swollman#endif
85219878Swollman	return (error);
8532742Swollman}
8542742Swollman
8552742Swollmanint
8562742Swollmanmac_init_mbuf_tag(struct m_tag *tag, int flag)
85758787Sru{
85858787Sru	struct label *label;
85958787Sru	int error;
86058787Sru
86158787Sru	label = (struct label *) (tag + 1);
86258787Sru	mac_init_label(label);
86358787Sru
86464499Swollman	MAC_CHECK(init_mbuf_label, label, flag);
86564499Swollman	if (error) {
86664499Swollman		MAC_PERFORM(destroy_mbuf_label, label);
8679908Swollman		mac_destroy_label(label);
8682742Swollman	}
86958787Sru#ifdef MAC_DEBUG
87058787Sru	if (error == 0)
8712742Swollman		atomic_add_int(&nmacmbufs, 1);
8722742Swollman#endif
8732742Swollman	return (error);
87486222Swollman}
87586222Swollman
87686222Swollmanint
87786222Swollmanmac_init_mbuf(struct mbuf *m, int flag)
87886222Swollman{
87986222Swollman	struct m_tag *tag;
88086222Swollman	int error;
88186222Swollman
88286222Swollman	M_ASSERTPKTHDR(m);
88386222Swollman
88486222Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
88586222Swollman	/*
88686222Swollman	 * Don't reserve space for labels on mbufs unless we have a policy
88786222Swollman	 * that uses the labels.
88886222Swollman	 */
88986222Swollman	if (mac_labelmbufs) {
89086222Swollman#endif
89186222Swollman		tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
89286222Swollman		    flag);
89386222Swollman		if (tag == NULL)
89486222Swollman			return (ENOMEM);
89586222Swollman		error = mac_init_mbuf_tag(tag, flag);
8969908Swollman		if (error) {
8972742Swollman			m_tag_free(tag);
8982742Swollman			return (error);
8992742Swollman		}
9002742Swollman		m_tag_prepend(m, tag);
9012742Swollman#ifndef MAC_ALWAYS_LABEL_MBUF
9022742Swollman	}
9032742Swollman#endif
9042742Swollman	return (0);
9052742Swollman}
9062742Swollman
9072742Swollmanvoid
9082742Swollmanmac_init_mount(struct mount *mp)
90958787Sru{
91058787Sru
91158787Sru	mac_init_label(&mp->mnt_mntlabel);
91258787Sru	mac_init_label(&mp->mnt_fslabel);
91358787Sru	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
91458787Sru	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
91558787Sru#ifdef MAC_DEBUG
91658787Sru	atomic_add_int(&nmacmounts, 1);
91758787Sru#endif
91858787Sru}
9192742Swollman
92058787Srustatic void
92158787Srumac_init_pipe_label(struct label *label)
92258787Sru{
92358787Sru
92458787Sru	mac_init_label(label);
92558787Sru	MAC_PERFORM(init_pipe_label, label);
92658787Sru#ifdef MAC_DEBUG
9272742Swollman	atomic_add_int(&nmacpipes, 1);
92858787Sru#endif
92958787Sru}
93058787Sru
93158787Sruvoid
93258787Srumac_init_pipe(struct pipe *pipe)
93358787Sru{
93458787Sru	struct label *label;
93558787Sru
93658787Sru	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
93758787Sru	pipe->pipe_label = label;
93858787Sru	pipe->pipe_peer->pipe_label = label;
93958787Sru	mac_init_pipe_label(label);
94058787Sru}
94158787Sru
94258787Sruvoid
94358787Srumac_init_proc(struct proc *p)
94458787Sru{
94558787Sru
94658787Sru	mac_init_label(&p->p_label);
94758787Sru	MAC_PERFORM(init_proc_label, &p->p_label);
94858787Sru#ifdef MAC_DEBUG
94958787Sru	atomic_add_int(&nmacprocs, 1);
95058787Sru#endif
95158787Sru}
95258787Sru
95358787Srustatic int
95458787Srumac_init_socket_label(struct label *label, int flag)
95558787Sru{
95658787Sru	int error;
95775267Swollman
95858787Sru	mac_init_label(label);
95958787Sru
96058787Sru	MAC_CHECK(init_socket_label, label, flag);
96158787Sru	if (error) {
96258787Sru		MAC_PERFORM(destroy_socket_label, label);
96358787Sru		mac_destroy_label(label);
9642742Swollman	}
96543543Swollman
96643543Swollman#ifdef MAC_DEBUG
96758787Sru	if (error == 0)
96843543Swollman		atomic_add_int(&nmacsockets, 1);
96967578Swollman#endif
97075267Swollman
97175267Swollman	return (error);
97267578Swollman}
9739908Swollman
9742742Swollmanstatic int
97567578Swollmanmac_init_socket_peer_label(struct label *label, int flag)
9762742Swollman{
9772742Swollman	int error;
97819878Swollman
9792742Swollman	mac_init_label(label);
9802742Swollman
9812742Swollman	MAC_CHECK(init_socket_peer_label, label, flag);
98243014Swollman	if (error) {
9832742Swollman		MAC_PERFORM(destroy_socket_label, label);
9842742Swollman		mac_destroy_label(label);
9852742Swollman	}
9862742Swollman
9872742Swollman	return (error);
9882742Swollman}
9892742Swollman
9902742Swollmanint
9912742Swollmanmac_init_socket(struct socket *socket, int flag)
9922742Swollman{
9932742Swollman	int error;
9949908Swollman
9952742Swollman	error = mac_init_socket_label(&socket->so_label, flag);
99619878Swollman	if (error)
9972742Swollman		return (error);
9982742Swollman
9992742Swollman	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
10002742Swollman	if (error)
10012742Swollman		mac_destroy_socket_label(&socket->so_label);
100258787Sru
100358787Sru	return (error);
100458787Sru}
100558787Sru
100658787Sruvoid
100758787Srumac_init_vnode_label(struct label *label)
100886464Swollman{
100958787Sru
101058787Sru	mac_init_label(label);
101158787Sru	MAC_PERFORM(init_vnode_label, label);
101214343Swollman#ifdef MAC_DEBUG
101375267Swollman	atomic_add_int(&nmacvnodes, 1);
101475267Swollman#endif
101575267Swollman}
101675267Swollman
101775267Swollmanvoid
101875267Swollmanmac_init_vnode(struct vnode *vp)
101958787Sru{
102075267Swollman
102175267Swollman	mac_init_vnode_label(&vp->v_label);
102275267Swollman}
102367578Swollman
10242742Swollmanvoid
10252742Swollmanmac_destroy_bpfdesc(struct bpf_d *bpf_d)
102658787Sru{
10272742Swollman
102819878Swollman	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
10292742Swollman	mac_destroy_label(&bpf_d->bd_label);
10302742Swollman#ifdef MAC_DEBUG
10312742Swollman	atomic_subtract_int(&nmacbpfdescs, 1);
10322742Swollman#endif
10332742Swollman}
103419878Swollman
10352742Swollmanstatic void
10362742Swollmanmac_destroy_cred_label(struct label *label)
10372742Swollman{
10382742Swollman
10392742Swollman	MAC_PERFORM(destroy_cred_label, label);
10402742Swollman	mac_destroy_label(label);
10412742Swollman#ifdef MAC_DEBUG
10422742Swollman	atomic_subtract_int(&nmaccreds, 1);
10432742Swollman#endif
10442742Swollman}
10452742Swollman
10462742Swollmanvoid
10472742Swollmanmac_destroy_cred(struct ucred *cred)
104819878Swollman{
10492742Swollman
10502742Swollman	mac_destroy_cred_label(&cred->cr_label);
10512742Swollman}
105214343Swollman
105314343Swollmanvoid
105414343Swollmanmac_destroy_devfsdirent(struct devfs_dirent *de)
105514343Swollman{
105614343Swollman
105714343Swollman	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
105814343Swollman	mac_destroy_label(&de->de_label);
105958787Sru#ifdef MAC_DEBUG
106058787Sru	atomic_subtract_int(&nmacdevfsdirents, 1);
106158787Sru#endif
106220094Swollman}
106358787Sru
106414343Swollmanstatic void
10652742Swollmanmac_destroy_ifnet_label(struct label *label)
10662742Swollman{
106758787Sru
10682742Swollman	MAC_PERFORM(destroy_ifnet_label, label);
10692742Swollman	mac_destroy_label(label);
107058787Sru#ifdef MAC_DEBUG
107158787Sru	atomic_subtract_int(&nmacifnets, 1);
107258787Sru#endif
10732742Swollman}
107443543Swollman
107543543Swollmanvoid
107675267Swollmanmac_destroy_ifnet(struct ifnet *ifp)
107743543Swollman{
107843543Swollman
107958787Sru	mac_destroy_ifnet_label(&ifp->if_label);
108058787Sru}
108158787Sru
108243543Swollmanvoid
108343543Swollmanmac_destroy_ipq(struct ipq *ipq)
108443543Swollman{
108543543Swollman
108643543Swollman	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
108743543Swollman	mac_destroy_label(&ipq->ipq_label);
108843543Swollman#ifdef MAC_DEBUG
108975267Swollman	atomic_subtract_int(&nmacipqs, 1);
109075267Swollman#endif
109158787Sru}
109214343Swollman
109314343Swollmanvoid
109414343Swollmanmac_destroy_mbuf_tag(struct m_tag *tag)
109514343Swollman{
109658787Sru	struct label *label;
109717200Swollman
109817200Swollman	label = (struct label *)(tag+1);
109917200Swollman
110017200Swollman	MAC_PERFORM(destroy_mbuf_label, label);
110117200Swollman	mac_destroy_label(label);
110217200Swollman#ifdef MAC_DEBUG
110317200Swollman	atomic_subtract_int(&nmacmbufs, 1);
110458787Sru#endif
11052742Swollman}
11062742Swollman
11072742Swollmanvoid
11082742Swollmanmac_destroy_mount(struct mount *mp)
110919878Swollman{
11102742Swollman
11112742Swollman	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
11122742Swollman	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
111358787Sru	mac_destroy_label(&mp->mnt_fslabel);
111414343Swollman	mac_destroy_label(&mp->mnt_mntlabel);
11152742Swollman#ifdef MAC_DEBUG
111658787Sru	atomic_subtract_int(&nmacmounts, 1);
11172742Swollman#endif
11182742Swollman}
111975267Swollman
112075267Swollmanstatic void
112114343Swollmanmac_destroy_pipe_label(struct label *label)
112275267Swollman{
112375267Swollman
112475267Swollman	MAC_PERFORM(destroy_pipe_label, label);
112575267Swollman	mac_destroy_label(label);
112658787Sru#ifdef MAC_DEBUG
112775267Swollman	atomic_subtract_int(&nmacpipes, 1);
112817200Swollman#endif
112917200Swollman}
113017200Swollman
113117200Swollmanvoid
113217200Swollmanmac_destroy_pipe(struct pipe *pipe)
113317200Swollman{
113458787Sru
113517200Swollman	mac_destroy_pipe_label(pipe->pipe_label);
113617200Swollman	free(pipe->pipe_label, M_MACPIPELABEL);
113758787Sru}
113858787Sru
113958787Sruvoid
114058787Srumac_destroy_proc(struct proc *p)
114158787Sru{
114258787Sru
114358787Sru	MAC_PERFORM(destroy_proc_label, &p->p_label);
114458787Sru	mac_destroy_label(&p->p_label);
114558787Sru#ifdef MAC_DEBUG
114658787Sru	atomic_subtract_int(&nmacprocs, 1);
114758787Sru#endif
114858787Sru}
114958787Sru
115058787Srustatic void
115158787Srumac_destroy_socket_label(struct label *label)
115258787Sru{
115358787Sru
115458787Sru	MAC_PERFORM(destroy_socket_label, label);
115558787Sru	mac_destroy_label(label);
115658787Sru#ifdef MAC_DEBUG
115758787Sru	atomic_subtract_int(&nmacsockets, 1);
115858787Sru#endif
115958787Sru}
116058787Sru
116158787Srustatic void
116258787Srumac_destroy_socket_peer_label(struct label *label)
116358787Sru{
116458787Sru
116558787Sru	MAC_PERFORM(destroy_socket_peer_label, label);
116658787Sru	mac_destroy_label(label);
116758787Sru}
116858787Sru
116958787Sruvoid
117014343Swollmanmac_destroy_socket(struct socket *socket)
117114343Swollman{
117258787Sru
117358787Sru	mac_destroy_socket_label(&socket->so_label);
117414343Swollman	mac_destroy_socket_peer_label(&socket->so_peerlabel);
117514343Swollman}
117614343Swollman
117717200Swollmanvoid
117858787Srumac_destroy_vnode_label(struct label *label)
117917200Swollman{
118017200Swollman
118117200Swollman	MAC_PERFORM(destroy_vnode_label, label);
118217200Swollman	mac_destroy_label(label);
118317200Swollman#ifdef MAC_DEBUG
118417200Swollman	atomic_subtract_int(&nmacvnodes, 1);
118558787Sru#endif
118658787Sru}
118758787Sru
118858787Sruvoid
118958787Srumac_destroy_vnode(struct vnode *vp)
119058787Sru{
119158787Sru
119258787Sru	mac_destroy_vnode_label(&vp->v_label);
119358787Sru}
119458787Sru
119558787Sruvoid
119658787Srumac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
119758787Sru{
119858787Sru	struct label *src_label, *dest_label;
119958787Sru
120058787Sru	src_label = (struct label *)(src+1);
120158787Sru	dest_label = (struct label *)(dest+1);
120258787Sru
120358787Sru	/*
120458787Sru	 * mac_init_mbuf_tag() is called on the target tag in
120558787Sru	 * m_tag_copy(), so we don't need to call it here.
120658787Sru	 */
120758787Sru	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
120858787Sru}
120958787Sru
121058787Srustatic void
121158787Srumac_copy_pipe_label(struct label *src, struct label *dest)
121258787Sru{
121358787Sru
121458787Sru	MAC_PERFORM(copy_pipe_label, src, dest);
121558787Sru}
121658787Sru
121758787Sruvoid
121858787Srumac_copy_vnode_label(struct label *src, struct label *dest)
121958787Sru{
122058787Sru
122158787Sru	MAC_PERFORM(copy_vnode_label, src, dest);
122258787Sru}
122375267Swollman
122458787Srustatic int
122558787Srumac_check_structmac_consistent(struct mac *mac)
122658787Sru{
122758787Sru
122875267Swollman	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
122958787Sru		return (EINVAL);
123058787Sru
123158787Sru	return (0);
123258787Sru}
123358787Sru
123458787Srustatic int
123558787Srumac_externalize_cred_label(struct label *label, char *elements,
123658787Sru    char *outbuf, size_t outbuflen, int flags)
123758787Sru{
123875267Swollman	int error;
123975267Swollman
124075267Swollman	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
124175267Swollman
124258787Sru	return (error);
124358787Sru}
124458787Sru
124558787Srustatic int
124658787Srumac_externalize_ifnet_label(struct label *label, char *elements,
124758787Sru    char *outbuf, size_t outbuflen, int flags)
124858787Sru{
124975267Swollman	int error;
125075267Swollman
125175267Swollman	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
125275267Swollman
125375267Swollman	return (error);
125475267Swollman}
125575267Swollman
125658787Srustatic int
125775267Swollmanmac_externalize_pipe_label(struct label *label, char *elements,
125875267Swollman    char *outbuf, size_t outbuflen, int flags)
125975267Swollman{
126093799Swollman	int error;
126193799Swollman
126293799Swollman	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
126393799Swollman
126493799Swollman	return (error);
126586222Swollman}
126686222Swollman
126758787Srustatic int
126858787Srumac_externalize_socket_label(struct label *label, char *elements,
126958787Sru    char *outbuf, size_t outbuflen, int flags)
127058787Sru{
127158787Sru	int error;
127275267Swollman
127358787Sru	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
127458787Sru
127558787Sru	return (error);
127658787Sru}
127758787Sru
127858787Srustatic int
127958787Srumac_externalize_socket_peer_label(struct label *label, char *elements,
128058787Sru    char *outbuf, size_t outbuflen, int flags)
128158787Sru{
128258787Sru	int error;
128358787Sru
128458787Sru	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
128558787Sru
128658787Sru	return (error);
128758787Sru}
128858787Sru
128958787Srustatic int
129058787Srumac_externalize_vnode_label(struct label *label, char *elements,
129158787Sru    char *outbuf, size_t outbuflen, int flags)
129258787Sru{
1293	int error;
1294
1295	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1296
1297	return (error);
1298}
1299
1300static int
1301mac_internalize_cred_label(struct label *label, char *string)
1302{
1303	int error;
1304
1305	MAC_INTERNALIZE(cred_label, label, string);
1306
1307	return (error);
1308}
1309
1310static int
1311mac_internalize_ifnet_label(struct label *label, char *string)
1312{
1313	int error;
1314
1315	MAC_INTERNALIZE(ifnet_label, label, string);
1316
1317	return (error);
1318}
1319
1320static int
1321mac_internalize_pipe_label(struct label *label, char *string)
1322{
1323	int error;
1324
1325	MAC_INTERNALIZE(pipe_label, label, string);
1326
1327	return (error);
1328}
1329
1330static int
1331mac_internalize_socket_label(struct label *label, char *string)
1332{
1333	int error;
1334
1335	MAC_INTERNALIZE(socket_label, label, string);
1336
1337	return (error);
1338}
1339
1340static int
1341mac_internalize_vnode_label(struct label *label, char *string)
1342{
1343	int error;
1344
1345	MAC_INTERNALIZE(vnode_label, label, string);
1346
1347	return (error);
1348}
1349
1350/*
1351 * Initialize MAC label for the first kernel process, from which other
1352 * kernel processes and threads are spawned.
1353 */
1354void
1355mac_create_proc0(struct ucred *cred)
1356{
1357
1358	MAC_PERFORM(create_proc0, cred);
1359}
1360
1361/*
1362 * Initialize MAC label for the first userland process, from which other
1363 * userland processes and threads are spawned.
1364 */
1365void
1366mac_create_proc1(struct ucred *cred)
1367{
1368
1369	MAC_PERFORM(create_proc1, cred);
1370}
1371
1372void
1373mac_thread_userret(struct thread *td)
1374{
1375
1376	MAC_PERFORM(thread_userret, td);
1377}
1378
1379/*
1380 * When a new process is created, its label must be initialized.  Generally,
1381 * this involves inheritence from the parent process, modulo possible
1382 * deltas.  This function allows that processing to take place.
1383 */
1384void
1385mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1386{
1387
1388	MAC_PERFORM(create_cred, parent_cred, child_cred);
1389}
1390
1391void
1392mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1393    struct vnode *vp)
1394{
1395
1396	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1397	    &vp->v_label);
1398}
1399
1400void
1401mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1402    struct vnode *vp)
1403{
1404
1405	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1406	    &de->de_label, vp, &vp->v_label);
1407}
1408
1409int
1410mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1411{
1412	int error;
1413
1414	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1415
1416	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1417	    &vp->v_label);
1418
1419	return (error);
1420}
1421
1422void
1423mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1424{
1425
1426	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1427	    &vp->v_label);
1428}
1429
1430int
1431mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1432    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1433{
1434	int error;
1435
1436	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1437	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1438
1439	error = VOP_OPENEXTATTR(vp, cred, curthread);
1440	if (error == EOPNOTSUPP) {
1441		/* XXX: Optionally abort if transactions not supported. */
1442		if (ea_warn_once == 0) {
1443			printf("Warning: transactions not supported "
1444			    "in EA write.\n");
1445			ea_warn_once = 1;
1446		}
1447	} else if (error)
1448		return (error);
1449
1450	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1451	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1452
1453	if (error) {
1454		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1455		return (error);
1456	}
1457
1458	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1459
1460	if (error == EOPNOTSUPP)
1461		error = 0;				/* XXX */
1462
1463	return (error);
1464}
1465
1466static int
1467mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1468    struct label *intlabel)
1469{
1470	int error;
1471
1472	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1473
1474	error = VOP_OPENEXTATTR(vp, cred, curthread);
1475	if (error == EOPNOTSUPP) {
1476		/* XXX: Optionally abort if transactions not supported. */
1477		if (ea_warn_once == 0) {
1478			printf("Warning: transactions not supported "
1479			    "in EA write.\n");
1480			ea_warn_once = 1;
1481		}
1482	} else if (error)
1483		return (error);
1484
1485	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1486
1487	if (error) {
1488		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1489		return (error);
1490	}
1491
1492	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1493
1494	if (error == EOPNOTSUPP)
1495		error = 0;				/* XXX */
1496
1497	return (error);
1498}
1499
1500int
1501mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1502    struct label *execlabelstorage)
1503{
1504	struct mac mac;
1505	char *buffer;
1506	int error;
1507
1508	if (mac_p == NULL)
1509		return (0);
1510
1511	error = copyin(mac_p, &mac, sizeof(mac));
1512	if (error)
1513		return (error);
1514
1515	error = mac_check_structmac_consistent(&mac);
1516	if (error)
1517		return (error);
1518
1519	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1520	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1521	if (error) {
1522		free(buffer, M_MACTEMP);
1523		return (error);
1524	}
1525
1526	mac_init_cred_label(execlabelstorage);
1527	error = mac_internalize_cred_label(execlabelstorage, buffer);
1528	free(buffer, M_MACTEMP);
1529	if (error) {
1530		mac_destroy_cred_label(execlabelstorage);
1531		return (error);
1532	}
1533	imgp->execlabel = execlabelstorage;
1534	return (0);
1535}
1536
1537void
1538mac_execve_exit(struct image_params *imgp)
1539{
1540	if (imgp->execlabel != NULL)
1541		mac_destroy_cred_label(imgp->execlabel);
1542}
1543
1544void
1545mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1546    struct label *interpvnodelabel, struct image_params *imgp)
1547{
1548
1549	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1550
1551	if (!mac_enforce_process && !mac_enforce_fs)
1552		return;
1553
1554	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1555	    interpvnodelabel, imgp, imgp->execlabel);
1556}
1557
1558int
1559mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1560    struct label *interpvnodelabel, struct image_params *imgp)
1561{
1562	int result;
1563
1564	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1565
1566	if (!mac_enforce_process && !mac_enforce_fs)
1567		return (0);
1568
1569	result = 0;
1570	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1571	    interpvnodelabel, imgp, imgp->execlabel);
1572
1573	return (result);
1574}
1575
1576int
1577mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1578{
1579	int error;
1580
1581	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1582
1583	if (!mac_enforce_fs)
1584		return (0);
1585
1586	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1587	return (error);
1588}
1589
1590int
1591mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1592{
1593	int error;
1594
1595	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1596
1597	if (!mac_enforce_fs)
1598		return (0);
1599
1600	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1601	return (error);
1602}
1603
1604int
1605mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1606{
1607	int error;
1608
1609	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1610
1611	if (!mac_enforce_fs)
1612		return (0);
1613
1614	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1615	return (error);
1616}
1617
1618int
1619mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1620    struct componentname *cnp, struct vattr *vap)
1621{
1622	int error;
1623
1624	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1625
1626	if (!mac_enforce_fs)
1627		return (0);
1628
1629	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1630	return (error);
1631}
1632
1633int
1634mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1635    struct componentname *cnp)
1636{
1637	int error;
1638
1639	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1640	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1641
1642	if (!mac_enforce_fs)
1643		return (0);
1644
1645	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1646	    &vp->v_label, cnp);
1647	return (error);
1648}
1649
1650int
1651mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1652    acl_type_t type)
1653{
1654	int error;
1655
1656	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1657
1658	if (!mac_enforce_fs)
1659		return (0);
1660
1661	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1662	return (error);
1663}
1664
1665int
1666mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1667    struct image_params *imgp)
1668{
1669	int error;
1670
1671	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1672
1673	if (!mac_enforce_process && !mac_enforce_fs)
1674		return (0);
1675
1676	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1677	    imgp->execlabel);
1678
1679	return (error);
1680}
1681
1682int
1683mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1684{
1685	int error;
1686
1687	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1688
1689	if (!mac_enforce_fs)
1690		return (0);
1691
1692	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1693	return (error);
1694}
1695
1696int
1697mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1698    int attrnamespace, const char *name, struct uio *uio)
1699{
1700	int error;
1701
1702	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1703
1704	if (!mac_enforce_fs)
1705		return (0);
1706
1707	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1708	    attrnamespace, name, uio);
1709	return (error);
1710}
1711
1712int
1713mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1714    struct vnode *vp, struct componentname *cnp)
1715{
1716	int error;
1717
1718	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1719	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1720
1721	if (!mac_enforce_fs)
1722		return (0);
1723
1724	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1725	    &vp->v_label, cnp);
1726	return (error);
1727}
1728
1729int
1730mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1731    struct componentname *cnp)
1732{
1733	int error;
1734
1735	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1736
1737	if (!mac_enforce_fs)
1738		return (0);
1739
1740	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1741	return (error);
1742}
1743
1744int
1745mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1746{
1747	int error;
1748
1749	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1750
1751	if (!mac_enforce_fs || !mac_enforce_vm)
1752		return (0);
1753
1754	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1755	return (error);
1756}
1757
1758void
1759mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1760{
1761	int result = *prot;
1762
1763	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1764
1765	if (!mac_enforce_fs || !mac_enforce_vm)
1766		return;
1767
1768	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1769	    &result);
1770
1771	*prot = result;
1772}
1773
1774int
1775mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1776{
1777	int error;
1778
1779	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1780
1781	if (!mac_enforce_fs || !mac_enforce_vm)
1782		return (0);
1783
1784	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1785	return (error);
1786}
1787
1788int
1789mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1790{
1791	int error;
1792
1793	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1794
1795	if (!mac_enforce_fs)
1796		return (0);
1797
1798	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1799	return (error);
1800}
1801
1802int
1803mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1804    struct vnode *vp)
1805{
1806	int error;
1807
1808	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1809
1810	if (!mac_enforce_fs)
1811		return (0);
1812
1813	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1814	    &vp->v_label);
1815
1816	return (error);
1817}
1818
1819int
1820mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1821    struct vnode *vp)
1822{
1823	int error;
1824
1825	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1826
1827	if (!mac_enforce_fs)
1828		return (0);
1829
1830	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1831	    &vp->v_label);
1832
1833	return (error);
1834}
1835
1836int
1837mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1838{
1839	int error;
1840
1841	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1842
1843	if (!mac_enforce_fs)
1844		return (0);
1845
1846	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1847	return (error);
1848}
1849
1850int
1851mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1852{
1853	int error;
1854
1855	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1856
1857	if (!mac_enforce_fs)
1858		return (0);
1859
1860	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1861	return (error);
1862}
1863
1864static int
1865mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1866    struct label *newlabel)
1867{
1868	int error;
1869
1870	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1871
1872	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1873
1874	return (error);
1875}
1876
1877int
1878mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1879    struct vnode *vp, struct componentname *cnp)
1880{
1881	int error;
1882
1883	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1884	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1885
1886	if (!mac_enforce_fs)
1887		return (0);
1888
1889	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1890	    &vp->v_label, cnp);
1891	return (error);
1892}
1893
1894int
1895mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1896    struct vnode *vp, int samedir, struct componentname *cnp)
1897{
1898	int error;
1899
1900	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1901	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1902
1903	if (!mac_enforce_fs)
1904		return (0);
1905
1906	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1907	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1908	return (error);
1909}
1910
1911int
1912mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1913{
1914	int error;
1915
1916	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1917
1918	if (!mac_enforce_fs)
1919		return (0);
1920
1921	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1922	return (error);
1923}
1924
1925int
1926mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1927    struct acl *acl)
1928{
1929	int error;
1930
1931	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1932
1933	if (!mac_enforce_fs)
1934		return (0);
1935
1936	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1937	return (error);
1938}
1939
1940int
1941mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1942    int attrnamespace, const char *name, struct uio *uio)
1943{
1944	int error;
1945
1946	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1947
1948	if (!mac_enforce_fs)
1949		return (0);
1950
1951	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1952	    attrnamespace, name, uio);
1953	return (error);
1954}
1955
1956int
1957mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1958{
1959	int error;
1960
1961	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1962
1963	if (!mac_enforce_fs)
1964		return (0);
1965
1966	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1967	return (error);
1968}
1969
1970int
1971mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1972{
1973	int error;
1974
1975	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1976
1977	if (!mac_enforce_fs)
1978		return (0);
1979
1980	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1981	return (error);
1982}
1983
1984int
1985mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1986    gid_t gid)
1987{
1988	int error;
1989
1990	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1991
1992	if (!mac_enforce_fs)
1993		return (0);
1994
1995	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1996	return (error);
1997}
1998
1999int
2000mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2001    struct timespec atime, struct timespec mtime)
2002{
2003	int error;
2004
2005	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2006
2007	if (!mac_enforce_fs)
2008		return (0);
2009
2010	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2011	    mtime);
2012	return (error);
2013}
2014
2015int
2016mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2017    struct vnode *vp)
2018{
2019	int error;
2020
2021	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2022
2023	if (!mac_enforce_fs)
2024		return (0);
2025
2026	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2027	    &vp->v_label);
2028	return (error);
2029}
2030
2031int
2032mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2033    struct vnode *vp)
2034{
2035	int error;
2036
2037	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2038
2039	if (!mac_enforce_fs)
2040		return (0);
2041
2042	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2043	    &vp->v_label);
2044
2045	return (error);
2046}
2047
2048/*
2049 * When relabeling a process, call out to the policies for the maximum
2050 * permission allowed for each object type we know about in its
2051 * memory space, and revoke access (in the least surprising ways we
2052 * know) when necessary.  The process lock is not held here.
2053 */
2054void
2055mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2056{
2057
2058	/* XXX freeze all other threads */
2059	mac_cred_mmapped_drop_perms_recurse(td, cred,
2060	    &td->td_proc->p_vmspace->vm_map);
2061	/* XXX allow other threads to continue */
2062}
2063
2064static __inline const char *
2065prot2str(vm_prot_t prot)
2066{
2067
2068	switch (prot & VM_PROT_ALL) {
2069	case VM_PROT_READ:
2070		return ("r--");
2071	case VM_PROT_READ | VM_PROT_WRITE:
2072		return ("rw-");
2073	case VM_PROT_READ | VM_PROT_EXECUTE:
2074		return ("r-x");
2075	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2076		return ("rwx");
2077	case VM_PROT_WRITE:
2078		return ("-w-");
2079	case VM_PROT_EXECUTE:
2080		return ("--x");
2081	case VM_PROT_WRITE | VM_PROT_EXECUTE:
2082		return ("-wx");
2083	default:
2084		return ("---");
2085	}
2086}
2087
2088static void
2089mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2090    struct vm_map *map)
2091{
2092	struct vm_map_entry *vme;
2093	int result;
2094	vm_prot_t revokeperms;
2095	vm_object_t object;
2096	vm_ooffset_t offset;
2097	struct vnode *vp;
2098
2099	if (!mac_mmap_revocation)
2100		return;
2101
2102	vm_map_lock_read(map);
2103	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2104		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2105			mac_cred_mmapped_drop_perms_recurse(td, cred,
2106			    vme->object.sub_map);
2107			continue;
2108		}
2109		/*
2110		 * Skip over entries that obviously are not shared.
2111		 */
2112		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2113		    !vme->max_protection)
2114			continue;
2115		/*
2116		 * Drill down to the deepest backing object.
2117		 */
2118		offset = vme->offset;
2119		object = vme->object.vm_object;
2120		if (object == NULL)
2121			continue;
2122		while (object->backing_object != NULL) {
2123			object = object->backing_object;
2124			offset += object->backing_object_offset;
2125		}
2126		/*
2127		 * At the moment, vm_maps and objects aren't considered
2128		 * by the MAC system, so only things with backing by a
2129		 * normal object (read: vnodes) are checked.
2130		 */
2131		if (object->type != OBJT_VNODE)
2132			continue;
2133		vp = (struct vnode *)object->handle;
2134		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2135		result = vme->max_protection;
2136		mac_check_vnode_mmap_downgrade(cred, vp, &result);
2137		VOP_UNLOCK(vp, 0, td);
2138		/*
2139		 * Find out what maximum protection we may be allowing
2140		 * now but a policy needs to get removed.
2141		 */
2142		revokeperms = vme->max_protection & ~result;
2143		if (!revokeperms)
2144			continue;
2145		printf("pid %ld: revoking %s perms from %#lx:%ld "
2146		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2147		    prot2str(revokeperms), (u_long)vme->start,
2148		    (long)(vme->end - vme->start),
2149		    prot2str(vme->max_protection), prot2str(vme->protection));
2150		vm_map_lock_upgrade(map);
2151		/*
2152		 * This is the really simple case: if a map has more
2153		 * max_protection than is allowed, but it's not being
2154		 * actually used (that is, the current protection is
2155		 * still allowed), we can just wipe it out and do
2156		 * nothing more.
2157		 */
2158		if ((vme->protection & revokeperms) == 0) {
2159			vme->max_protection -= revokeperms;
2160		} else {
2161			if (revokeperms & VM_PROT_WRITE) {
2162				/*
2163				 * In the more complicated case, flush out all
2164				 * pending changes to the object then turn it
2165				 * copy-on-write.
2166				 */
2167				vm_object_reference(object);
2168				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2169				VM_OBJECT_LOCK(object);
2170				vm_object_page_clean(object,
2171				    OFF_TO_IDX(offset),
2172				    OFF_TO_IDX(offset + vme->end - vme->start +
2173					PAGE_MASK),
2174				    OBJPC_SYNC);
2175				VM_OBJECT_UNLOCK(object);
2176				VOP_UNLOCK(vp, 0, td);
2177				vm_object_deallocate(object);
2178				/*
2179				 * Why bother if there's no read permissions
2180				 * anymore?  For the rest, we need to leave
2181				 * the write permissions on for COW, or
2182				 * remove them entirely if configured to.
2183				 */
2184				if (!mac_mmap_revocation_via_cow) {
2185					vme->max_protection &= ~VM_PROT_WRITE;
2186					vme->protection &= ~VM_PROT_WRITE;
2187				} if ((revokeperms & VM_PROT_READ) == 0)
2188					vme->eflags |= MAP_ENTRY_COW |
2189					    MAP_ENTRY_NEEDS_COPY;
2190			}
2191			if (revokeperms & VM_PROT_EXECUTE) {
2192				vme->max_protection &= ~VM_PROT_EXECUTE;
2193				vme->protection &= ~VM_PROT_EXECUTE;
2194			}
2195			if (revokeperms & VM_PROT_READ) {
2196				vme->max_protection = 0;
2197				vme->protection = 0;
2198			}
2199			pmap_protect(map->pmap, vme->start, vme->end,
2200			    vme->protection & ~revokeperms);
2201			vm_map_simplify_entry(map, vme);
2202		}
2203		vm_map_lock_downgrade(map);
2204	}
2205	vm_map_unlock_read(map);
2206}
2207
2208/*
2209 * When the subject's label changes, it may require revocation of privilege
2210 * to mapped objects.  This can't be done on-the-fly later with a unified
2211 * buffer cache.
2212 */
2213static void
2214mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2215{
2216
2217	MAC_PERFORM(relabel_cred, cred, newlabel);
2218}
2219
2220void
2221mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2222{
2223
2224	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2225}
2226
2227void
2228mac_create_ifnet(struct ifnet *ifnet)
2229{
2230
2231	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2232}
2233
2234void
2235mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2236{
2237
2238	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2239}
2240
2241void
2242mac_create_socket(struct ucred *cred, struct socket *socket)
2243{
2244
2245	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2246}
2247
2248void
2249mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2250{
2251
2252	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2253}
2254
2255void
2256mac_create_socket_from_socket(struct socket *oldsocket,
2257    struct socket *newsocket)
2258{
2259
2260	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2261	    newsocket, &newsocket->so_label);
2262}
2263
2264static void
2265mac_relabel_socket(struct ucred *cred, struct socket *socket,
2266    struct label *newlabel)
2267{
2268
2269	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2270}
2271
2272static void
2273mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2274{
2275
2276	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2277}
2278
2279void
2280mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2281{
2282	struct label *label;
2283
2284	label = mbuf_to_label(mbuf);
2285
2286	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
2287	    &socket->so_peerlabel);
2288}
2289
2290void
2291mac_set_socket_peer_from_socket(struct socket *oldsocket,
2292    struct socket *newsocket)
2293{
2294
2295	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2296	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2297}
2298
2299void
2300mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2301{
2302	struct label *label;
2303
2304	label = mbuf_to_label(datagram);
2305
2306	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2307	    datagram, label);
2308}
2309
2310void
2311mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2312{
2313	struct label *datagramlabel, *fragmentlabel;
2314
2315	datagramlabel = mbuf_to_label(datagram);
2316	fragmentlabel = mbuf_to_label(fragment);
2317
2318	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
2319	    fragmentlabel);
2320}
2321
2322void
2323mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2324{
2325	struct label *label;
2326
2327	label = mbuf_to_label(fragment);
2328
2329	MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
2330}
2331
2332void
2333mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2334{
2335	struct label *oldmbuflabel, *newmbuflabel;
2336
2337	oldmbuflabel = mbuf_to_label(oldmbuf);
2338	newmbuflabel = mbuf_to_label(newmbuf);
2339
2340	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
2341	    newmbuflabel);
2342}
2343
2344void
2345mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2346{
2347	struct label *label;
2348
2349	label = mbuf_to_label(mbuf);
2350
2351	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2352	    label);
2353}
2354
2355void
2356mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2357{
2358	struct label *label;
2359
2360	label = mbuf_to_label(mbuf);
2361
2362	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2363	    label);
2364}
2365
2366void
2367mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2368{
2369	struct label *label;
2370
2371	label = mbuf_to_label(mbuf);
2372
2373	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2374	    label);
2375}
2376
2377void
2378mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2379    struct mbuf *newmbuf)
2380{
2381	struct label *oldmbuflabel, *newmbuflabel;
2382
2383	oldmbuflabel = mbuf_to_label(oldmbuf);
2384	newmbuflabel = mbuf_to_label(newmbuf);
2385
2386	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
2387	    ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
2388}
2389
2390void
2391mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2392{
2393	struct label *oldmbuflabel, *newmbuflabel;
2394
2395	oldmbuflabel = mbuf_to_label(oldmbuf);
2396	newmbuflabel = mbuf_to_label(newmbuf);
2397
2398	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
2399	    newmbuflabel);
2400}
2401
2402int
2403mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2404{
2405	struct label *label;
2406	int result;
2407
2408	label = mbuf_to_label(fragment);
2409
2410	result = 1;
2411	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
2412	    &ipq->ipq_label);
2413
2414	return (result);
2415}
2416
2417void
2418mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2419{
2420	struct label *label;
2421
2422	label = mbuf_to_label(fragment);
2423
2424	MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
2425}
2426
2427void
2428mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2429{
2430	struct label *label;
2431
2432	label = mbuf_to_label(mbuf);
2433
2434	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2435	    label);
2436}
2437
2438void
2439mac_create_mount(struct ucred *cred, struct mount *mp)
2440{
2441
2442	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2443	    &mp->mnt_fslabel);
2444}
2445
2446void
2447mac_create_root_mount(struct ucred *cred, struct mount *mp)
2448{
2449
2450	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2451	    &mp->mnt_fslabel);
2452}
2453
2454int
2455mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2456{
2457	int error;
2458
2459	if (!mac_enforce_network)
2460		return (0);
2461
2462	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2463	    &ifnet->if_label);
2464
2465	return (error);
2466}
2467
2468static int
2469mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2470{
2471	int error;
2472
2473	MAC_CHECK(check_cred_relabel, cred, newlabel);
2474
2475	return (error);
2476}
2477
2478int
2479mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2480{
2481	int error;
2482
2483	if (!mac_enforce_process)
2484		return (0);
2485
2486	MAC_CHECK(check_cred_visible, u1, u2);
2487
2488	return (error);
2489}
2490
2491int
2492mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2493{
2494	struct label *label;
2495	int error;
2496
2497	M_ASSERTPKTHDR(mbuf);
2498
2499	if (!mac_enforce_network)
2500		return (0);
2501
2502	label = mbuf_to_label(mbuf);
2503
2504	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2505	    label);
2506
2507	return (error);
2508}
2509
2510int
2511mac_check_kenv_dump(struct ucred *cred)
2512{
2513	int error;
2514
2515	if (!mac_enforce_system)
2516		return (0);
2517
2518	MAC_CHECK(check_kenv_dump, cred);
2519
2520	return (error);
2521}
2522
2523int
2524mac_check_kenv_get(struct ucred *cred, char *name)
2525{
2526	int error;
2527
2528	if (!mac_enforce_system)
2529		return (0);
2530
2531	MAC_CHECK(check_kenv_get, cred, name);
2532
2533	return (error);
2534}
2535
2536int
2537mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2538{
2539	int error;
2540
2541	if (!mac_enforce_system)
2542		return (0);
2543
2544	MAC_CHECK(check_kenv_set, cred, name, value);
2545
2546	return (error);
2547}
2548
2549int
2550mac_check_kenv_unset(struct ucred *cred, char *name)
2551{
2552	int error;
2553
2554	if (!mac_enforce_system)
2555		return (0);
2556
2557	MAC_CHECK(check_kenv_unset, cred, name);
2558
2559	return (error);
2560}
2561
2562int
2563mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2564{
2565	int error;
2566
2567	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2568
2569	if (!mac_enforce_kld)
2570		return (0);
2571
2572	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2573
2574	return (error);
2575}
2576
2577int
2578mac_check_kld_stat(struct ucred *cred)
2579{
2580	int error;
2581
2582	if (!mac_enforce_kld)
2583		return (0);
2584
2585	MAC_CHECK(check_kld_stat, cred);
2586
2587	return (error);
2588}
2589
2590int
2591mac_check_kld_unload(struct ucred *cred)
2592{
2593	int error;
2594
2595	if (!mac_enforce_kld)
2596		return (0);
2597
2598	MAC_CHECK(check_kld_unload, cred);
2599
2600	return (error);
2601}
2602
2603int
2604mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2605{
2606	int error;
2607
2608	if (!mac_enforce_fs)
2609		return (0);
2610
2611	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2612
2613	return (error);
2614}
2615
2616int
2617mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2618    void *data)
2619{
2620	int error;
2621
2622	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2623
2624	if (!mac_enforce_pipe)
2625		return (0);
2626
2627	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2628
2629	return (error);
2630}
2631
2632int
2633mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2634{
2635	int error;
2636
2637	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2638
2639	if (!mac_enforce_pipe)
2640		return (0);
2641
2642	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2643
2644	return (error);
2645}
2646
2647int
2648mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2649{
2650	int error;
2651
2652	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2653
2654	if (!mac_enforce_pipe)
2655		return (0);
2656
2657	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2658
2659	return (error);
2660}
2661
2662static int
2663mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2664    struct label *newlabel)
2665{
2666	int error;
2667
2668	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2669
2670	if (!mac_enforce_pipe)
2671		return (0);
2672
2673	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2674
2675	return (error);
2676}
2677
2678int
2679mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2680{
2681	int error;
2682
2683	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2684
2685	if (!mac_enforce_pipe)
2686		return (0);
2687
2688	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2689
2690	return (error);
2691}
2692
2693int
2694mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2695{
2696	int error;
2697
2698	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2699
2700	if (!mac_enforce_pipe)
2701		return (0);
2702
2703	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2704
2705	return (error);
2706}
2707
2708int
2709mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2710{
2711	int error;
2712
2713	PROC_LOCK_ASSERT(proc, MA_OWNED);
2714
2715	if (!mac_enforce_process)
2716		return (0);
2717
2718	MAC_CHECK(check_proc_debug, cred, proc);
2719
2720	return (error);
2721}
2722
2723int
2724mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2725{
2726	int error;
2727
2728	PROC_LOCK_ASSERT(proc, MA_OWNED);
2729
2730	if (!mac_enforce_process)
2731		return (0);
2732
2733	MAC_CHECK(check_proc_sched, cred, proc);
2734
2735	return (error);
2736}
2737
2738int
2739mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2740{
2741	int error;
2742
2743	PROC_LOCK_ASSERT(proc, MA_OWNED);
2744
2745	if (!mac_enforce_process)
2746		return (0);
2747
2748	MAC_CHECK(check_proc_signal, cred, proc, signum);
2749
2750	return (error);
2751}
2752
2753int
2754mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2755    struct sockaddr *sockaddr)
2756{
2757	int error;
2758
2759	if (!mac_enforce_socket)
2760		return (0);
2761
2762	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2763	    sockaddr);
2764
2765	return (error);
2766}
2767
2768int
2769mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2770    struct sockaddr *sockaddr)
2771{
2772	int error;
2773
2774	if (!mac_enforce_socket)
2775		return (0);
2776
2777	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2778	    sockaddr);
2779
2780	return (error);
2781}
2782
2783int
2784mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2785{
2786	struct label *label;
2787	int error;
2788
2789	if (!mac_enforce_socket)
2790		return (0);
2791
2792	label = mbuf_to_label(mbuf);
2793
2794	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2795	    label);
2796
2797	return (error);
2798}
2799
2800int
2801mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2802{
2803	int error;
2804
2805	if (!mac_enforce_socket)
2806		return (0);
2807
2808	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2809	return (error);
2810}
2811
2812int
2813mac_check_socket_receive(struct ucred *cred, struct socket *so)
2814{
2815	int error;
2816
2817	if (!mac_enforce_socket)
2818		return (0);
2819
2820	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2821
2822	return (error);
2823}
2824
2825static int
2826mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2827    struct label *newlabel)
2828{
2829	int error;
2830
2831	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2832	    newlabel);
2833
2834	return (error);
2835}
2836
2837int
2838mac_check_socket_send(struct ucred *cred, struct socket *so)
2839{
2840	int error;
2841
2842	if (!mac_enforce_socket)
2843		return (0);
2844
2845	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2846
2847	return (error);
2848}
2849
2850int
2851mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2852{
2853	int error;
2854
2855	if (!mac_enforce_socket)
2856		return (0);
2857
2858	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2859
2860	return (error);
2861}
2862
2863int
2864mac_check_sysarch_ioperm(struct ucred *cred)
2865{
2866	int error;
2867
2868	if (!mac_enforce_system)
2869		return (0);
2870
2871	MAC_CHECK(check_sysarch_ioperm, cred);
2872	return (error);
2873}
2874
2875int
2876mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2877{
2878	int error;
2879
2880	if (vp != NULL) {
2881		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2882	}
2883
2884	if (!mac_enforce_system)
2885		return (0);
2886
2887	MAC_CHECK(check_system_acct, cred, vp,
2888	    vp != NULL ? &vp->v_label : NULL);
2889
2890	return (error);
2891}
2892
2893int
2894mac_check_system_nfsd(struct ucred *cred)
2895{
2896	int error;
2897
2898	if (!mac_enforce_system)
2899		return (0);
2900
2901	MAC_CHECK(check_system_nfsd, cred);
2902
2903	return (error);
2904}
2905
2906int
2907mac_check_system_reboot(struct ucred *cred, int howto)
2908{
2909	int error;
2910
2911	if (!mac_enforce_system)
2912		return (0);
2913
2914	MAC_CHECK(check_system_reboot, cred, howto);
2915
2916	return (error);
2917}
2918
2919int
2920mac_check_system_settime(struct ucred *cred)
2921{
2922	int error;
2923
2924	if (!mac_enforce_system)
2925		return (0);
2926
2927	MAC_CHECK(check_system_settime, cred);
2928
2929	return (error);
2930}
2931
2932int
2933mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2934{
2935	int error;
2936
2937	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2938
2939	if (!mac_enforce_system)
2940		return (0);
2941
2942	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2943	return (error);
2944}
2945
2946int
2947mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2948{
2949	int error;
2950
2951	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2952
2953	if (!mac_enforce_system)
2954		return (0);
2955
2956	MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2957	return (error);
2958}
2959
2960int
2961mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2962    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2963{
2964	int error;
2965
2966	/*
2967	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2968	 * but since it's not exported from kern_sysctl.c, we can't.
2969	 */
2970	if (!mac_enforce_system)
2971		return (0);
2972
2973	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2974	    inkernel, new, newlen);
2975
2976	return (error);
2977}
2978
2979int
2980mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2981    struct ifnet *ifnet)
2982{
2983	char *elements, *buffer;
2984	struct mac mac;
2985	int error;
2986
2987	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2988	if (error)
2989		return (error);
2990
2991	error = mac_check_structmac_consistent(&mac);
2992	if (error)
2993		return (error);
2994
2995	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2996	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2997	if (error) {
2998		free(elements, M_MACTEMP);
2999		return (error);
3000	}
3001
3002	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3003	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3004	    buffer, mac.m_buflen, M_WAITOK);
3005	if (error == 0)
3006		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3007
3008	free(buffer, M_MACTEMP);
3009	free(elements, M_MACTEMP);
3010
3011	return (error);
3012}
3013
3014int
3015mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3016    struct ifnet *ifnet)
3017{
3018	struct label intlabel;
3019	struct mac mac;
3020	char *buffer;
3021	int error;
3022
3023	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3024	if (error)
3025		return (error);
3026
3027	error = mac_check_structmac_consistent(&mac);
3028	if (error)
3029		return (error);
3030
3031	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3032	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3033	if (error) {
3034		free(buffer, M_MACTEMP);
3035		return (error);
3036	}
3037
3038	mac_init_ifnet_label(&intlabel);
3039	error = mac_internalize_ifnet_label(&intlabel, buffer);
3040	free(buffer, M_MACTEMP);
3041	if (error) {
3042		mac_destroy_ifnet_label(&intlabel);
3043		return (error);
3044	}
3045
3046	/*
3047	 * XXX: Note that this is a redundant privilege check, since
3048	 * policies impose this check themselves if required by the
3049	 * policy.  Eventually, this should go away.
3050	 */
3051	error = suser_cred(cred, 0);
3052	if (error) {
3053		mac_destroy_ifnet_label(&intlabel);
3054		return (error);
3055	}
3056
3057	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3058	    &intlabel);
3059	if (error) {
3060		mac_destroy_ifnet_label(&intlabel);
3061		return (error);
3062	}
3063
3064	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3065
3066	mac_destroy_ifnet_label(&intlabel);
3067	return (0);
3068}
3069
3070void
3071mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
3072{
3073
3074	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
3075}
3076
3077void
3078mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3079    struct devfs_dirent *dd, struct devfs_dirent *de)
3080{
3081
3082	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
3083	    &de->de_label);
3084}
3085
3086void
3087mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
3088    struct devfs_dirent *de)
3089{
3090
3091	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
3092	    &de->de_label);
3093}
3094
3095int
3096mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3097    struct mac *mac)
3098{
3099	struct label intlabel;
3100	char *buffer;
3101	int error;
3102
3103	error = mac_check_structmac_consistent(mac);
3104	if (error)
3105		return (error);
3106
3107	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3108	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3109	if (error) {
3110		free(buffer, M_MACTEMP);
3111		return (error);
3112	}
3113
3114	mac_init_socket_label(&intlabel, M_WAITOK);
3115	error = mac_internalize_socket_label(&intlabel, buffer);
3116	free(buffer, M_MACTEMP);
3117	if (error) {
3118		mac_destroy_socket_label(&intlabel);
3119		return (error);
3120	}
3121
3122	mac_check_socket_relabel(cred, so, &intlabel);
3123	if (error) {
3124		mac_destroy_socket_label(&intlabel);
3125		return (error);
3126	}
3127
3128	mac_relabel_socket(cred, so, &intlabel);
3129
3130	mac_destroy_socket_label(&intlabel);
3131	return (0);
3132}
3133
3134int
3135mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3136{
3137	int error;
3138
3139	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3140
3141	error = mac_check_pipe_relabel(cred, pipe, label);
3142	if (error)
3143		return (error);
3144
3145	mac_relabel_pipe(cred, pipe, label);
3146
3147	return (0);
3148}
3149
3150int
3151mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3152    struct mac *mac)
3153{
3154	char *buffer, *elements;
3155	int error;
3156
3157	error = mac_check_structmac_consistent(mac);
3158	if (error)
3159		return (error);
3160
3161	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3162	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3163	if (error) {
3164		free(elements, M_MACTEMP);
3165		return (error);
3166	}
3167
3168	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3169	error = mac_externalize_socket_label(&so->so_label, elements,
3170	    buffer, mac->m_buflen, M_WAITOK);
3171	if (error == 0)
3172		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3173
3174	free(buffer, M_MACTEMP);
3175	free(elements, M_MACTEMP);
3176
3177	return (error);
3178}
3179
3180int
3181mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3182    struct mac *mac)
3183{
3184	char *elements, *buffer;
3185	int error;
3186
3187	error = mac_check_structmac_consistent(mac);
3188	if (error)
3189		return (error);
3190
3191	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3192	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3193	if (error) {
3194		free(elements, M_MACTEMP);
3195		return (error);
3196	}
3197
3198	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3199	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3200	    elements, buffer, mac->m_buflen, M_WAITOK);
3201	if (error == 0)
3202		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3203
3204	free(buffer, M_MACTEMP);
3205	free(elements, M_MACTEMP);
3206
3207	return (error);
3208}
3209
3210/*
3211 * Implementation of VOP_SETLABEL() that relies on extended attributes
3212 * to store label data.  Can be referenced by filesystems supporting
3213 * extended attributes.
3214 */
3215int
3216vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3217{
3218	struct vnode *vp = ap->a_vp;
3219	struct label *intlabel = ap->a_label;
3220	int error;
3221
3222	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3223
3224	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3225		return (EOPNOTSUPP);
3226
3227	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3228	if (error)
3229		return (error);
3230
3231	mac_relabel_vnode(ap->a_cred, vp, intlabel);
3232
3233	return (0);
3234}
3235
3236static int
3237vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3238{
3239	int error;
3240
3241	if (vp->v_mount == NULL) {
3242		/* printf("vn_setlabel: null v_mount\n"); */
3243		if (vp->v_type != VNON)
3244			printf("vn_setlabel: null v_mount with non-VNON\n");
3245		return (EBADF);
3246	}
3247
3248	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3249		return (EOPNOTSUPP);
3250
3251	/*
3252	 * Multi-phase commit.  First check the policies to confirm the
3253	 * change is OK.  Then commit via the filesystem.  Finally,
3254	 * update the actual vnode label.  Question: maybe the filesystem
3255	 * should update the vnode at the end as part of VOP_SETLABEL()?
3256	 */
3257	error = mac_check_vnode_relabel(cred, vp, intlabel);
3258	if (error)
3259		return (error);
3260
3261	/*
3262	 * VADMIN provides the opportunity for the filesystem to make
3263	 * decisions about who is and is not able to modify labels
3264	 * and protections on files.  This might not be right.  We can't
3265	 * assume VOP_SETLABEL() will do it, because we might implement
3266	 * that as part of vop_stdsetlabel_ea().
3267	 */
3268	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3269	if (error)
3270		return (error);
3271
3272	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3273	if (error)
3274		return (error);
3275
3276	return (0);
3277}
3278
3279int
3280__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3281{
3282	char *elements, *buffer;
3283	struct mac mac;
3284	struct proc *tproc;
3285	struct ucred *tcred;
3286	int error;
3287
3288	error = copyin(uap->mac_p, &mac, sizeof(mac));
3289	if (error)
3290		return (error);
3291
3292	error = mac_check_structmac_consistent(&mac);
3293	if (error)
3294		return (error);
3295
3296	tproc = pfind(uap->pid);
3297	if (tproc == NULL)
3298		return (ESRCH);
3299
3300	tcred = NULL;				/* Satisfy gcc. */
3301	error = p_cansee(td, tproc);
3302	if (error == 0)
3303		tcred = crhold(tproc->p_ucred);
3304	PROC_UNLOCK(tproc);
3305	if (error)
3306		return (error);
3307
3308	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3309	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3310	if (error) {
3311		free(elements, M_MACTEMP);
3312		crfree(tcred);
3313		return (error);
3314	}
3315
3316	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3317	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3318	    buffer, mac.m_buflen, M_WAITOK);
3319	if (error == 0)
3320		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3321
3322	free(buffer, M_MACTEMP);
3323	free(elements, M_MACTEMP);
3324	crfree(tcred);
3325	return (error);
3326}
3327
3328/*
3329 * MPSAFE
3330 */
3331int
3332__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3333{
3334	char *elements, *buffer;
3335	struct mac mac;
3336	int error;
3337
3338	error = copyin(uap->mac_p, &mac, sizeof(mac));
3339	if (error)
3340		return (error);
3341
3342	error = mac_check_structmac_consistent(&mac);
3343	if (error)
3344		return (error);
3345
3346	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3347	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3348	if (error) {
3349		free(elements, M_MACTEMP);
3350		return (error);
3351	}
3352
3353	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3354	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3355	    elements, buffer, mac.m_buflen, M_WAITOK);
3356	if (error == 0)
3357		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3358
3359	free(buffer, M_MACTEMP);
3360	free(elements, M_MACTEMP);
3361	return (error);
3362}
3363
3364/*
3365 * MPSAFE
3366 */
3367int
3368__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3369{
3370	struct ucred *newcred, *oldcred;
3371	struct label intlabel;
3372	struct proc *p;
3373	struct mac mac;
3374	char *buffer;
3375	int error;
3376
3377	error = copyin(uap->mac_p, &mac, sizeof(mac));
3378	if (error)
3379		return (error);
3380
3381	error = mac_check_structmac_consistent(&mac);
3382	if (error)
3383		return (error);
3384
3385	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3386	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3387	if (error) {
3388		free(buffer, M_MACTEMP);
3389		return (error);
3390	}
3391
3392	mac_init_cred_label(&intlabel);
3393	error = mac_internalize_cred_label(&intlabel, buffer);
3394	free(buffer, M_MACTEMP);
3395	if (error) {
3396		mac_destroy_cred_label(&intlabel);
3397		return (error);
3398	}
3399
3400	newcred = crget();
3401
3402	p = td->td_proc;
3403	PROC_LOCK(p);
3404	oldcred = p->p_ucred;
3405
3406	error = mac_check_cred_relabel(oldcred, &intlabel);
3407	if (error) {
3408		PROC_UNLOCK(p);
3409		crfree(newcred);
3410		goto out;
3411	}
3412
3413	setsugid(p);
3414	crcopy(newcred, oldcred);
3415	mac_relabel_cred(newcred, &intlabel);
3416	p->p_ucred = newcred;
3417
3418	/*
3419	 * Grab additional reference for use while revoking mmaps, prior
3420	 * to releasing the proc lock and sharing the cred.
3421	 */
3422	crhold(newcred);
3423	PROC_UNLOCK(p);
3424
3425	if (mac_enforce_vm) {
3426		mtx_lock(&Giant);
3427		mac_cred_mmapped_drop_perms(td, newcred);
3428		mtx_unlock(&Giant);
3429	}
3430
3431	crfree(newcred);	/* Free revocation reference. */
3432	crfree(oldcred);
3433
3434out:
3435	mac_destroy_cred_label(&intlabel);
3436	return (error);
3437}
3438
3439/*
3440 * MPSAFE
3441 */
3442int
3443__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3444{
3445	char *elements, *buffer;
3446	struct label intlabel;
3447	struct file *fp;
3448	struct mac mac;
3449	struct vnode *vp;
3450	struct pipe *pipe;
3451	short label_type;
3452	int error;
3453
3454	error = copyin(uap->mac_p, &mac, sizeof(mac));
3455	if (error)
3456		return (error);
3457
3458	error = mac_check_structmac_consistent(&mac);
3459	if (error)
3460		return (error);
3461
3462	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3463	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3464	if (error) {
3465		free(elements, M_MACTEMP);
3466		return (error);
3467	}
3468
3469	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3470	mtx_lock(&Giant);				/* VFS */
3471	error = fget(td, uap->fd, &fp);
3472	if (error)
3473		goto out;
3474
3475	label_type = fp->f_type;
3476	switch (fp->f_type) {
3477	case DTYPE_FIFO:
3478	case DTYPE_VNODE:
3479		vp = fp->f_vnode;
3480
3481		mac_init_vnode_label(&intlabel);
3482
3483		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3484		mac_copy_vnode_label(&vp->v_label, &intlabel);
3485		VOP_UNLOCK(vp, 0, td);
3486
3487		break;
3488	case DTYPE_PIPE:
3489		pipe = fp->f_data;
3490
3491		mac_init_pipe_label(&intlabel);
3492
3493		PIPE_LOCK(pipe);
3494		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3495		PIPE_UNLOCK(pipe);
3496		break;
3497	default:
3498		error = EINVAL;
3499		fdrop(fp, td);
3500		goto out;
3501	}
3502	fdrop(fp, td);
3503
3504	switch (label_type) {
3505	case DTYPE_FIFO:
3506	case DTYPE_VNODE:
3507		if (error == 0)
3508			error = mac_externalize_vnode_label(&intlabel,
3509			    elements, buffer, mac.m_buflen, M_WAITOK);
3510		mac_destroy_vnode_label(&intlabel);
3511		break;
3512	case DTYPE_PIPE:
3513		error = mac_externalize_pipe_label(&intlabel, elements,
3514		    buffer, mac.m_buflen, M_WAITOK);
3515		mac_destroy_pipe_label(&intlabel);
3516		break;
3517	default:
3518		panic("__mac_get_fd: corrupted label_type");
3519	}
3520
3521	if (error == 0)
3522		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3523
3524out:
3525	mtx_unlock(&Giant);				/* VFS */
3526	free(buffer, M_MACTEMP);
3527	free(elements, M_MACTEMP);
3528
3529	return (error);
3530}
3531
3532/*
3533 * MPSAFE
3534 */
3535int
3536__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3537{
3538	char *elements, *buffer;
3539	struct nameidata nd;
3540	struct label intlabel;
3541	struct mac mac;
3542	int error;
3543
3544	error = copyin(uap->mac_p, &mac, sizeof(mac));
3545	if (error)
3546		return (error);
3547
3548	error = mac_check_structmac_consistent(&mac);
3549	if (error)
3550		return (error);
3551
3552	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3553	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3554	if (error) {
3555		free(elements, M_MACTEMP);
3556		return (error);
3557	}
3558
3559	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3560	mtx_lock(&Giant);				/* VFS */
3561	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3562	    td);
3563	error = namei(&nd);
3564	if (error)
3565		goto out;
3566
3567	mac_init_vnode_label(&intlabel);
3568	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3569	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3570	    mac.m_buflen, M_WAITOK);
3571
3572	NDFREE(&nd, 0);
3573	mac_destroy_vnode_label(&intlabel);
3574
3575	if (error == 0)
3576		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3577
3578out:
3579	mtx_unlock(&Giant);				/* VFS */
3580
3581	free(buffer, M_MACTEMP);
3582	free(elements, M_MACTEMP);
3583
3584	return (error);
3585}
3586
3587/*
3588 * MPSAFE
3589 */
3590int
3591__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3592{
3593	char *elements, *buffer;
3594	struct nameidata nd;
3595	struct label intlabel;
3596	struct mac mac;
3597	int error;
3598
3599	error = copyin(uap->mac_p, &mac, sizeof(mac));
3600	if (error)
3601		return (error);
3602
3603	error = mac_check_structmac_consistent(&mac);
3604	if (error)
3605		return (error);
3606
3607	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3608	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3609	if (error) {
3610		free(elements, M_MACTEMP);
3611		return (error);
3612	}
3613
3614	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3615	mtx_lock(&Giant);				/* VFS */
3616	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3617	    td);
3618	error = namei(&nd);
3619	if (error)
3620		goto out;
3621
3622	mac_init_vnode_label(&intlabel);
3623	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3624	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3625	    mac.m_buflen, M_WAITOK);
3626	NDFREE(&nd, 0);
3627	mac_destroy_vnode_label(&intlabel);
3628
3629	if (error == 0)
3630		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3631
3632out:
3633	mtx_unlock(&Giant);				/* VFS */
3634
3635	free(buffer, M_MACTEMP);
3636	free(elements, M_MACTEMP);
3637
3638	return (error);
3639}
3640
3641/*
3642 * MPSAFE
3643 */
3644int
3645__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3646{
3647	struct label intlabel;
3648	struct pipe *pipe;
3649	struct file *fp;
3650	struct mount *mp;
3651	struct vnode *vp;
3652	struct mac mac;
3653	char *buffer;
3654	int error;
3655
3656	error = copyin(uap->mac_p, &mac, sizeof(mac));
3657	if (error)
3658		return (error);
3659
3660	error = mac_check_structmac_consistent(&mac);
3661	if (error)
3662		return (error);
3663
3664	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3665	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3666	if (error) {
3667		free(buffer, M_MACTEMP);
3668		return (error);
3669	}
3670
3671	mtx_lock(&Giant);				/* VFS */
3672
3673	error = fget(td, uap->fd, &fp);
3674	if (error)
3675		goto out;
3676
3677	switch (fp->f_type) {
3678	case DTYPE_FIFO:
3679	case DTYPE_VNODE:
3680		mac_init_vnode_label(&intlabel);
3681		error = mac_internalize_vnode_label(&intlabel, buffer);
3682		if (error) {
3683			mac_destroy_vnode_label(&intlabel);
3684			break;
3685		}
3686
3687		vp = fp->f_vnode;
3688		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3689		if (error != 0) {
3690			mac_destroy_vnode_label(&intlabel);
3691			break;
3692		}
3693
3694		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3695		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3696		VOP_UNLOCK(vp, 0, td);
3697		vn_finished_write(mp);
3698
3699		mac_destroy_vnode_label(&intlabel);
3700		break;
3701
3702	case DTYPE_PIPE:
3703		mac_init_pipe_label(&intlabel);
3704		error = mac_internalize_pipe_label(&intlabel, buffer);
3705		if (error == 0) {
3706			pipe = fp->f_data;
3707			PIPE_LOCK(pipe);
3708			error = mac_pipe_label_set(td->td_ucred, pipe,
3709			    &intlabel);
3710			PIPE_UNLOCK(pipe);
3711		}
3712
3713		mac_destroy_pipe_label(&intlabel);
3714		break;
3715
3716	default:
3717		error = EINVAL;
3718	}
3719
3720	fdrop(fp, td);
3721out:
3722	mtx_unlock(&Giant);				/* VFS */
3723
3724	free(buffer, M_MACTEMP);
3725
3726	return (error);
3727}
3728
3729/*
3730 * MPSAFE
3731 */
3732int
3733__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3734{
3735	struct label intlabel;
3736	struct nameidata nd;
3737	struct mount *mp;
3738	struct mac mac;
3739	char *buffer;
3740	int error;
3741
3742	error = copyin(uap->mac_p, &mac, sizeof(mac));
3743	if (error)
3744		return (error);
3745
3746	error = mac_check_structmac_consistent(&mac);
3747	if (error)
3748		return (error);
3749
3750	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3751	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3752	if (error) {
3753		free(buffer, M_MACTEMP);
3754		return (error);
3755	}
3756
3757	mac_init_vnode_label(&intlabel);
3758	error = mac_internalize_vnode_label(&intlabel, buffer);
3759	free(buffer, M_MACTEMP);
3760	if (error) {
3761		mac_destroy_vnode_label(&intlabel);
3762		return (error);
3763	}
3764
3765	mtx_lock(&Giant);				/* VFS */
3766
3767	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3768	    td);
3769	error = namei(&nd);
3770	if (error == 0) {
3771		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3772		if (error == 0)
3773			error = vn_setlabel(nd.ni_vp, &intlabel,
3774			    td->td_ucred);
3775		vn_finished_write(mp);
3776	}
3777
3778	NDFREE(&nd, 0);
3779	mtx_unlock(&Giant);				/* VFS */
3780	mac_destroy_vnode_label(&intlabel);
3781
3782	return (error);
3783}
3784
3785/*
3786 * MPSAFE
3787 */
3788int
3789__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3790{
3791	struct label intlabel;
3792	struct nameidata nd;
3793	struct mount *mp;
3794	struct mac mac;
3795	char *buffer;
3796	int error;
3797
3798	error = copyin(uap->mac_p, &mac, sizeof(mac));
3799	if (error)
3800		return (error);
3801
3802	error = mac_check_structmac_consistent(&mac);
3803	if (error)
3804		return (error);
3805
3806	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3807	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3808	if (error) {
3809		free(buffer, M_MACTEMP);
3810		return (error);
3811	}
3812
3813	mac_init_vnode_label(&intlabel);
3814	error = mac_internalize_vnode_label(&intlabel, buffer);
3815	free(buffer, M_MACTEMP);
3816	if (error) {
3817		mac_destroy_vnode_label(&intlabel);
3818		return (error);
3819	}
3820
3821	mtx_lock(&Giant);				/* VFS */
3822
3823	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3824	    td);
3825	error = namei(&nd);
3826	if (error == 0) {
3827		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3828		if (error == 0)
3829			error = vn_setlabel(nd.ni_vp, &intlabel,
3830			    td->td_ucred);
3831		vn_finished_write(mp);
3832	}
3833
3834	NDFREE(&nd, 0);
3835	mtx_unlock(&Giant);				/* VFS */
3836	mac_destroy_vnode_label(&intlabel);
3837
3838	return (error);
3839}
3840
3841/*
3842 * MPSAFE
3843 */
3844int
3845mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3846{
3847	struct mac_policy_conf *mpc;
3848	char target[MAC_MAX_POLICY_NAME];
3849	int entrycount, error;
3850
3851	error = copyinstr(uap->policy, target, sizeof(target), NULL);
3852	if (error)
3853		return (error);
3854
3855	error = ENOSYS;
3856	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3857		if (strcmp(mpc->mpc_name, target) == 0 &&
3858		    mpc->mpc_ops->mpo_syscall != NULL) {
3859			error = mpc->mpc_ops->mpo_syscall(td,
3860			    uap->call, uap->arg);
3861			goto out;
3862		}
3863	}
3864
3865	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
3866		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3867			if (strcmp(mpc->mpc_name, target) == 0 &&
3868			    mpc->mpc_ops->mpo_syscall != NULL) {
3869				error = mpc->mpc_ops->mpo_syscall(td,
3870				    uap->call, uap->arg);
3871				break;
3872			}
3873		}
3874		mac_policy_list_unbusy();
3875	}
3876out:
3877	return (error);
3878}
3879
3880SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3881SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3882
3883#else /* !MAC */
3884
3885int
3886__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3887{
3888
3889	return (ENOSYS);
3890}
3891
3892int
3893__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3894{
3895
3896	return (ENOSYS);
3897}
3898
3899int
3900__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3901{
3902
3903	return (ENOSYS);
3904}
3905
3906int
3907__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3908{
3909
3910	return (ENOSYS);
3911}
3912
3913int
3914__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3915{
3916
3917	return (ENOSYS);
3918}
3919
3920int
3921__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3922{
3923
3924	return (ENOSYS);
3925}
3926
3927int
3928__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3929{
3930
3931	return (ENOSYS);
3932}
3933
3934int
3935__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3936{
3937
3938	return (ENOSYS);
3939}
3940
3941int
3942__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3943{
3944
3945	return (ENOSYS);
3946}
3947
3948int
3949mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3950{
3951
3952	return (ENOSYS);
3953}
3954
3955#endif
3956