mac_vfs.c revision 107271
118334Speter/*-
290075Sobrien * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
390075Sobrien * Copyright (c) 2001 Ilmar S. Habibulin
418334Speter * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
590075Sobrien * All rights reserved.
618334Speter *
790075Sobrien * This software was developed by Robert Watson and Ilmar Habibulin for the
890075Sobrien * TrustedBSD Project.
990075Sobrien *
1090075Sobrien * This software was developed for the FreeBSD Project in part by Network
1118334Speter * Associates Laboratories, the Security Research Division of Network
1290075Sobrien * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
1390075Sobrien * as part of the DARPA CHATS research program.
1490075Sobrien *
1590075Sobrien * Redistribution and use in source and binary forms, with or without
1618334Speter * modification, are permitted provided that the following conditions
1718334Speter * are met:
1890075Sobrien * 1. Redistributions of source code must retain the above copyright
1990075Sobrien *    notice, this list of conditions and the following disclaimer.
2090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
2118334Speter *    notice, this list of conditions and the following disclaimer in the
2218334Speter *    documentation and/or other materials provided with the distribution.
2318334Speter *
2450397Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2552284Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2652284Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2752284Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2890075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2952284Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3018334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3118334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3318334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3490075Sobrien * SUCH DAMAGE.
3590075Sobrien *
3618334Speter * $FreeBSD: head/sys/security/mac/mac_vfs.c 107271 2002-11-26 17:11:57Z rwatson $
3790075Sobrien */
3890075Sobrien/*
3918334Speter * Developed by the TrustedBSD Project.
4018334Speter *
4190075Sobrien * Framework for extensible kernel access control.  Kernel and userland
4290075Sobrien * interface to the framework, policy registration and composition.
4318334Speter */
4418334Speter
4518334Speter#include "opt_mac.h"
4618334Speter#include "opt_devfs.h"
4718334Speter
4818334Speter#include <sys/param.h>
4918334Speter#include <sys/condvar.h>
5018334Speter#include <sys/extattr.h>
5118334Speter#include <sys/imgact.h>
5218334Speter#include <sys/kernel.h>
5390075Sobrien#include <sys/lock.h>
5418334Speter#include <sys/malloc.h>
5590075Sobrien#include <sys/mutex.h>
5618334Speter#include <sys/mac.h>
5718334Speter#include <sys/module.h>
5818334Speter#include <sys/proc.h>
5918334Speter#include <sys/systm.h>
6050397Sobrien#include <sys/sysproto.h>
6118334Speter#include <sys/sysent.h>
6218334Speter#include <sys/vnode.h>
6318334Speter#include <sys/mount.h>
6418334Speter#include <sys/file.h>
6518334Speter#include <sys/namei.h>
6618334Speter#include <sys/socket.h>
6718334Speter#include <sys/pipe.h>
6818334Speter#include <sys/socketvar.h>
6918334Speter#include <sys/sysctl.h>
7018334Speter
7118334Speter#include <vm/vm.h>
7218334Speter#include <vm/pmap.h>
7318334Speter#include <vm/vm_map.h>
7418334Speter#include <vm/vm_object.h>
7518334Speter
7618334Speter#include <sys/mac_policy.h>
7718334Speter
7818334Speter#include <fs/devfs/devfs.h>
7918334Speter
8018334Speter#include <net/bpfdesc.h>
8118334Speter#include <net/if.h>
8218334Speter#include <net/if_var.h>
8318334Speter
8418334Speter#include <netinet/in.h>
8518334Speter#include <netinet/ip_var.h>
8618334Speter
8718334Speter#ifdef MAC
8890075Sobrien
8990075Sobrien/*
9018334Speter * Declare that the kernel provides MAC support, version 1.  This permits
9190075Sobrien * modules to refuse to be loaded if the necessary support isn't present,
9252284Sobrien * even if it's pre-boot.
9352284Sobrien */
9452284SobrienMODULE_VERSION(kernel_mac_support, 1);
9590075Sobrien
9652284SobrienSYSCTL_DECL(_security);
9752284Sobrien
9852284SobrienSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
9990075Sobrien    "TrustedBSD MAC policy controls");
10090075Sobrien
10190075Sobrien#if MAC_MAX_POLICIES > 32
10290075Sobrien#error "MAC_MAX_POLICIES too large"
10318334Speter#endif
10490075Sobrien
10590075Sobrienstatic unsigned int mac_max_policies = MAC_MAX_POLICIES;
10690075Sobrienstatic unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
10790075SobrienSYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
10890075Sobrien    &mac_max_policies, 0, "");
10990075Sobrien
11090075Sobrien/*
11190075Sobrien * Has the kernel started generating labeled objects yet?  All read/write
11290075Sobrien * access to this variable is serialized during the boot process.  Following
11390075Sobrien * the end of serialization, we don't update this flag; no locking.
11450397Sobrien */
11590075Sobrienstatic int	mac_late = 0;
11650397Sobrien
11790075Sobrien/*
11890075Sobrien * Warn about EA transactions only the first time they happen.
11990075Sobrien * Weak coherency, no locking.
12090075Sobrien */
12118334Speterstatic int	ea_warn_once = 0;
12218334Speter
12318334Speterstatic int	mac_enforce_fs = 1;
12418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
12518334Speter    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
12618334SpeterTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
12718334Speter
12818334Speterstatic int	mac_enforce_kld = 1;
12918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
13018334Speter    &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
13118334SpeterTUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
13218334Speter
13318334Speterstatic int	mac_enforce_network = 1;
13418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
13518334Speter    &mac_enforce_network, 0, "Enforce MAC policy on network packets");
13618334SpeterTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
13718334Speter
13818334Speterstatic int	mac_enforce_pipe = 1;
13918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
14018334Speter    &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
14118334SpeterTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
14218334Speter
14318334Speterstatic int	mac_enforce_process = 1;
14418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
14518334Speter    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
14618334SpeterTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
14718334Speter
14818334Speterstatic int	mac_enforce_socket = 1;
14918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
15018334Speter    &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
15118334SpeterTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
15218334Speter
15318334Speterstatic int	mac_enforce_system = 1;
15418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
15518334Speter    &mac_enforce_system, 0, "Enforce MAC policy on system operations");
15618334SpeterTUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
15718334Speter
15818334Speterstatic int	mac_enforce_vm = 1;
15918334SpeterSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
16018334Speter    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
16118334SpeterTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
16218334Speter
16318334Speterstatic int	mac_mmap_revocation = 1;
16418334SpeterSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
16550397Sobrien    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
16618334Speter    "relabel");
16750397Sobrienstatic int	mac_mmap_revocation_via_cow = 0;
16818334SpeterSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
16952284Sobrien    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
17018334Speter    "copy-on-write semantics, or by removing all write access");
17118334Speter
17218334Speter#ifdef MAC_DEBUG
17318334SpeterSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
17418334Speter    "TrustedBSD MAC debug info");
17518334Speter
17618334Speterstatic int	mac_debug_label_fallback = 0;
17718334SpeterSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
17818334Speter    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
17918334Speter    "when label is corrupted.");
18018334SpeterTUNABLE_INT("security.mac.debug_label_fallback",
18118334Speter    &mac_debug_label_fallback);
18218334Speter
18318334SpeterSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
18418334Speter    "TrustedBSD MAC object counters");
18518334Speter
18618334Speterstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
18718334Speter    nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
18818334Speter    nmacipqs, nmacpipes, nmacprocs;
18996263Sobrien
19096263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
19196263Sobrien    &nmacmbufs, 0, "number of mbufs in use");
19296263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
19396263Sobrien    &nmaccreds, 0, "number of ucreds in use");
19496263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
19596263Sobrien    &nmacifnets, 0, "number of ifnets in use");
19618334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
19796263Sobrien    &nmacipqs, 0, "number of ipqs in use");
19896263SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
19918334Speter    &nmacbpfdescs, 0, "number of bpfdescs in use");
20018334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
20118334Speter    &nmacsockets, 0, "number of sockets in use");
20218334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
20318334Speter    &nmacpipes, 0, "number of pipes in use");
20450397SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
20518334Speter    &nmacprocs, 0, "number of procs in use");
20618334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
20718334Speter    &nmacmounts, 0, "number of mounts in use");
20818334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
20918334Speter    &nmactemp, 0, "number of temporary labels in use");
21050397SobrienSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
21118334Speter    &nmacvnodes, 0, "number of vnodes in use");
21218334SpeterSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
21318334Speter    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
21418334Speter#endif
21552284Sobrien
21652284Sobrienstatic int	error_select(int error1, int error2);
21752284Sobrienstatic int	mac_policy_register(struct mac_policy_conf *mpc);
21852284Sobrienstatic int	mac_policy_unregister(struct mac_policy_conf *mpc);
21952284Sobrien
22052284Sobrienstatic void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
22152284Sobrien		    struct vnode *vp, int *prot);
22252284Sobrienstatic void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
22352284Sobrien		    struct ucred *cred, struct vm_map *map);
22452284Sobrien
22552284Sobrienstatic void	mac_destroy_socket_label(struct label *label);
22652284Sobrien
22752284Sobrienstatic int	mac_setlabel_vnode_extattr(struct ucred *cred,
22852284Sobrien		    struct vnode *vp, struct label *intlabel);
22952284Sobrien
23052284SobrienMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
23190075SobrienMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
23290075Sobrien
23390075Sobrien/*
23490075Sobrien * mac_policy_list stores the list of active policies.  A busy count is
23552284Sobrien * maintained for the list, stored in mac_policy_busy.  The busy count
23690075Sobrien * is protected by mac_policy_list_lock; the list may be modified only
23790075Sobrien * while the busy count is 0, requiring that the lock be held to
23890075Sobrien * prevent new references to the list from being acquired.  For almost
23990075Sobrien * all operations, incrementing the busy count is sufficient to
24090075Sobrien * guarantee consistency, as the list cannot be modified while the
24190075Sobrien * busy count is elevated.  For a few special operations involving a
24290075Sobrien * change to the list of active policies, the lock itself must be held.
24390075Sobrien * A condition variable, mac_policy_list_not_busy, is used to signal
24452284Sobrien * potential exclusive consumers that they should try to acquire the
24552284Sobrien * lock if a first attempt at exclusive access fails.
24652284Sobrien */
24752284Sobrienstatic struct mtx mac_policy_list_lock;
24852284Sobrienstatic struct cv mac_policy_list_not_busy;
24952284Sobrienstatic LIST_HEAD(, mac_policy_conf) mac_policy_list;
25052284Sobrienstatic int mac_policy_list_busy;
25152284Sobrien
25252284Sobrien#define	MAC_POLICY_LIST_LOCKINIT() do {					\
25352284Sobrien	mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL,	\
25490075Sobrien	    MTX_DEF);							\
25552284Sobrien	cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy");	\
25652284Sobrien} while (0)
25790075Sobrien
25852284Sobrien#define	MAC_POLICY_LIST_LOCK() do {					\
25952284Sobrien	mtx_lock(&mac_policy_list_lock);				\
26052284Sobrien} while (0)
26152284Sobrien
26252284Sobrien#define	MAC_POLICY_LIST_UNLOCK() do {					\
26390075Sobrien	mtx_unlock(&mac_policy_list_lock);				\
26452284Sobrien} while (0)
26552284Sobrien
26652284Sobrien/*
26752284Sobrien * We manually invoke WITNESS_SLEEP() to allow Witness to generate
26852284Sobrien * warnings even if we don't end up ever triggering the wait at
26952284Sobrien * run-time.  The consumer of the exclusive interface must not hold
27052284Sobrien * any locks (other than potentially Giant) since we may sleep for
27152284Sobrien * long (potentially indefinite) periods of time waiting for the
27252284Sobrien * framework to become quiescent so that a policy list change may
27352284Sobrien * be made.
27490075Sobrien */
27552284Sobrien#define	MAC_POLICY_LIST_EXCLUSIVE() do {				\
27652284Sobrien	WITNESS_SLEEP(1, NULL);						\
27790075Sobrien	mtx_lock(&mac_policy_list_lock);				\
27852284Sobrien	while (mac_policy_list_busy != 0)				\
27952284Sobrien		cv_wait(&mac_policy_list_not_busy,			\
28052284Sobrien		    &mac_policy_list_lock);				\
28152284Sobrien} while (0)
28252284Sobrien
28390075Sobrien#define	MAC_POLICY_LIST_BUSY() do {					\
28452284Sobrien	MAC_POLICY_LIST_LOCK();						\
28552284Sobrien	mac_policy_list_busy++;						\
28652284Sobrien	MAC_POLICY_LIST_UNLOCK();					\
28752284Sobrien} while (0)
28852284Sobrien
28952284Sobrien#define	MAC_POLICY_LIST_UNBUSY() do {					\
29090075Sobrien	MAC_POLICY_LIST_LOCK();						\
29152284Sobrien	mac_policy_list_busy--;						\
29252284Sobrien	KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK"));	\
29390075Sobrien	if (mac_policy_list_busy == 0)					\
29452284Sobrien		cv_signal(&mac_policy_list_not_busy);			\
29552284Sobrien	MAC_POLICY_LIST_UNLOCK();					\
29652284Sobrien} while (0)
29752284Sobrien
29852284Sobrien/*
29990075Sobrien * MAC_CHECK performs the designated check by walking the policy
30052284Sobrien * module list and checking with each as to how it feels about the
30152284Sobrien * request.  Note that it returns its value via 'error' in the scope
30290075Sobrien * of the caller.
30352284Sobrien */
30452284Sobrien#define	MAC_CHECK(check, args...) do {					\
30590075Sobrien	struct mac_policy_conf *mpc;					\
30652284Sobrien									\
30752284Sobrien	error = 0;							\
30852284Sobrien	MAC_POLICY_LIST_BUSY();						\
30952284Sobrien	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
31052284Sobrien		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
31190075Sobrien			error = error_select(				\
31252284Sobrien			    mpc->mpc_ops->mpo_ ## check (args),		\
31352284Sobrien			    error);					\
31452284Sobrien	}								\
31552284Sobrien	MAC_POLICY_LIST_UNBUSY();					\
31652284Sobrien} while (0)
31752284Sobrien
31852284Sobrien/*
31952284Sobrien * MAC_BOOLEAN performs the designated boolean composition by walking
32052284Sobrien * the module list, invoking each instance of the operation, and
32152284Sobrien * combining the results using the passed C operator.  Note that it
32252284Sobrien * returns its value via 'result' in the scope of the caller, which
32352284Sobrien * should be initialized by the caller in a meaningful way to get
32452284Sobrien * a meaningful result.
32552284Sobrien */
32652284Sobrien#define	MAC_BOOLEAN(operation, composition, args...) do {		\
32752284Sobrien	struct mac_policy_conf *mpc;					\
32852284Sobrien									\
32952284Sobrien	MAC_POLICY_LIST_BUSY();						\
33052284Sobrien	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
33152284Sobrien		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
33252284Sobrien			result = result composition			\
33352284Sobrien			    mpc->mpc_ops->mpo_ ## operation (args);	\
33452284Sobrien	}								\
33552284Sobrien	MAC_POLICY_LIST_UNBUSY();					\
33652284Sobrien} while (0)
33752284Sobrien
33852284Sobrien#define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
33952284Sobrien    outbuflen) do {							\
34052284Sobrien	char *curptr, *curptr_start, *element_name, *element_temp;	\
34152284Sobrien	size_t left, left_start, len;					\
34252284Sobrien	int claimed, first, first_start, ignorenotfound;		\
34352284Sobrien									\
34452284Sobrien	error = 0;							\
34552284Sobrien	element_temp = elementlist;					\
34652284Sobrien	curptr = outbuf;						\
34752284Sobrien	curptr[0] = '\0';						\
34852284Sobrien	left = outbuflen;						\
34952284Sobrien	first = 1;							\
35052284Sobrien	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
35152284Sobrien		curptr_start = curptr;					\
35252284Sobrien		left_start = left;					\
35352284Sobrien		first_start = first;					\
35452284Sobrien		if (element_name[0] == '?') {				\
35552284Sobrien			element_name++;					\
35652284Sobrien			ignorenotfound = 1;				\
35752284Sobrien		} else							\
35852284Sobrien			ignorenotfound = 0;				\
35952284Sobrien		claimed = 0;						\
36052284Sobrien		if (first) {						\
36152284Sobrien			len = snprintf(curptr, left, "%s/",		\
36252284Sobrien			    element_name);				\
36352284Sobrien			first = 0;					\
36490075Sobrien		} else							\
36590075Sobrien			len = snprintf(curptr, left, ",%s/",		\
36690075Sobrien			    element_name);				\
36790075Sobrien		if (len >= left) {					\
36890075Sobrien			error = EINVAL;		/* XXXMAC: E2BIG */	\
36990075Sobrien			break;						\
37090075Sobrien		}							\
37190075Sobrien		curptr += len;						\
37290075Sobrien		left -= len;						\
37390075Sobrien									\
37490075Sobrien		MAC_CHECK(externalize_ ## type, label, element_name,	\
37590075Sobrien		    curptr, left, &len, &claimed);			\
37652284Sobrien		if (error)						\
37752284Sobrien			break;						\
37852284Sobrien		if (claimed == 1) {					\
37952284Sobrien			if (len >= outbuflen) {				\
38052284Sobrien				error = EINVAL;	/* XXXMAC: E2BIG */	\
38152284Sobrien				break;					\
38252284Sobrien			}						\
38352284Sobrien			curptr += len;					\
38452284Sobrien			left -= len;					\
38552284Sobrien		} else if (claimed == 0 && ignorenotfound) {		\
38652284Sobrien			/*						\
38752284Sobrien			 * Revert addition of the label element		\
38852284Sobrien			 * name.					\
38952284Sobrien			 */						\
39052284Sobrien			curptr = curptr_start;				\
39152284Sobrien			*curptr = '\0';					\
39252284Sobrien			left = left_start;				\
39352284Sobrien			first = first_start;				\
39490075Sobrien		} else {						\
39590075Sobrien			error = EINVAL;		/* XXXMAC: ENOLABEL */	\
39652284Sobrien			break;						\
39752284Sobrien		}							\
39852284Sobrien	}								\
39952284Sobrien} while (0)
40052284Sobrien
40152284Sobrien#define	MAC_INTERNALIZE(type, label, instring) do {			\
40252284Sobrien	char *element, *element_name, *element_data;			\
40352284Sobrien	int claimed;							\
40490075Sobrien									\
40552284Sobrien	error = 0;							\
40652284Sobrien	element = instring;						\
40752284Sobrien	while ((element_name = strsep(&element, ",")) != NULL) {	\
40852284Sobrien		element_data = element_name;				\
40952284Sobrien		element_name = strsep(&element_data, "/");		\
41052284Sobrien		if (element_data == NULL) {				\
41152284Sobrien			error = EINVAL;					\
41252284Sobrien			break;						\
41352284Sobrien		}							\
41452284Sobrien		claimed = 0;						\
41552284Sobrien		MAC_CHECK(internalize_ ## type, label, element_name,	\
41652284Sobrien		    element_data, &claimed);				\
41752284Sobrien		if (error)						\
41852284Sobrien			break;						\
41952284Sobrien		if (claimed != 1) {					\
42090075Sobrien			/* XXXMAC: Another error here? */		\
42152284Sobrien			error = EINVAL;					\
42252284Sobrien			break;						\
42352284Sobrien		}							\
42452284Sobrien	}								\
42552284Sobrien} while (0)
42690075Sobrien
42752284Sobrien/*
42852284Sobrien * MAC_PERFORM performs the designated operation by walking the policy
42952284Sobrien * module list and invoking that operation for each policy.
43052284Sobrien */
43152284Sobrien#define	MAC_PERFORM(operation, args...) do {				\
43252284Sobrien	struct mac_policy_conf *mpc;					\
43352284Sobrien									\
43452284Sobrien	MAC_POLICY_LIST_BUSY();						\
43552284Sobrien	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
43652284Sobrien		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
43752284Sobrien			mpc->mpc_ops->mpo_ ## operation (args);		\
43852284Sobrien	}								\
43952284Sobrien	MAC_POLICY_LIST_UNBUSY();					\
44090075Sobrien} while (0)
44152284Sobrien
44252284Sobrien/*
44352284Sobrien * Initialize the MAC subsystem, including appropriate SMP locks.
44452284Sobrien */
44552284Sobrienstatic void
44690075Sobrienmac_init(void)
44752284Sobrien{
44852284Sobrien
44952284Sobrien	LIST_INIT(&mac_policy_list);
45052284Sobrien	MAC_POLICY_LIST_LOCKINIT();
45152284Sobrien}
45252284Sobrien
45352284Sobrien/*
45452284Sobrien * For the purposes of modules that want to know if they were loaded
45552284Sobrien * "early", set the mac_late flag once we've processed modules either
45652284Sobrien * linked into the kernel, or loaded before the kernel startup.
45790075Sobrien */
45852284Sobrienstatic void
45952284Sobrienmac_late_init(void)
46052284Sobrien{
46152284Sobrien
46252284Sobrien	mac_late = 1;
46390075Sobrien}
46452284Sobrien
46552284Sobrien/*
46690075Sobrien * Allow MAC policy modules to register during boot, etc.
46752284Sobrien */
46852284Sobrienint
46952284Sobrienmac_policy_modevent(module_t mod, int type, void *data)
47052284Sobrien{
47152284Sobrien	struct mac_policy_conf *mpc;
47290075Sobrien	int error;
47352284Sobrien
47452284Sobrien	error = 0;
47552284Sobrien	mpc = (struct mac_policy_conf *) data;
47652284Sobrien
47752284Sobrien	switch (type) {
47852284Sobrien	case MOD_LOAD:
47952284Sobrien		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
48052284Sobrien		    mac_late) {
48152284Sobrien			printf("mac_policy_modevent: can't load %s policy "
48252284Sobrien			    "after booting\n", mpc->mpc_name);
48352284Sobrien			error = EBUSY;
48452284Sobrien			break;
48552284Sobrien		}
48652284Sobrien		error = mac_policy_register(mpc);
48752284Sobrien		break;
48852284Sobrien	case MOD_UNLOAD:
48952284Sobrien		/* Don't unregister the module if it was never registered. */
49052284Sobrien		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
49152284Sobrien		    != 0)
49252284Sobrien			error = mac_policy_unregister(mpc);
49352284Sobrien		else
49452284Sobrien			error = 0;
49552284Sobrien		break;
49652284Sobrien	default:
49752284Sobrien		break;
49852284Sobrien	}
49952284Sobrien
50052284Sobrien	return (error);
50152284Sobrien}
50252284Sobrien
50352284Sobrienstatic int
50452284Sobrienmac_policy_register(struct mac_policy_conf *mpc)
50552284Sobrien{
50652284Sobrien	struct mac_policy_conf *tmpc;
50752284Sobrien	int slot;
50852284Sobrien
50952284Sobrien	MAC_POLICY_LIST_EXCLUSIVE();
51052284Sobrien	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
51152284Sobrien		if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
51252284Sobrien			MAC_POLICY_LIST_UNLOCK();
51352284Sobrien			return (EEXIST);
51452284Sobrien		}
51552284Sobrien	}
51652284Sobrien	if (mpc->mpc_field_off != NULL) {
51752284Sobrien		slot = ffs(mac_policy_offsets_free);
51852284Sobrien		if (slot == 0) {
51952284Sobrien			MAC_POLICY_LIST_UNLOCK();
52052284Sobrien			return (ENOMEM);
52152284Sobrien		}
52252284Sobrien		slot--;
52352284Sobrien		mac_policy_offsets_free &= ~(1 << slot);
52452284Sobrien		*mpc->mpc_field_off = slot;
52590075Sobrien	}
52652284Sobrien	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
52752284Sobrien	LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
52852284Sobrien
52952284Sobrien	/* Per-policy initialization. */
53052284Sobrien	if (mpc->mpc_ops->mpo_init != NULL)
53190075Sobrien		(*(mpc->mpc_ops->mpo_init))(mpc);
53252284Sobrien	MAC_POLICY_LIST_UNLOCK();
53352284Sobrien
53452284Sobrien	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
53552284Sobrien	    mpc->mpc_name);
53652284Sobrien
53752284Sobrien	return (0);
53852284Sobrien}
53952284Sobrien
54052284Sobrienstatic int
54152284Sobrienmac_policy_unregister(struct mac_policy_conf *mpc)
54252284Sobrien{
54390075Sobrien
54452284Sobrien	/*
54552284Sobrien	 * If we fail the load, we may get a request to unload.  Check
54690075Sobrien	 * to see if we did the run-time registration, and if not,
54752284Sobrien	 * silently succeed.
54852284Sobrien	 */
54952284Sobrien	MAC_POLICY_LIST_EXCLUSIVE();
55052284Sobrien	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
55152284Sobrien		MAC_POLICY_LIST_UNLOCK();
55252284Sobrien		return (0);
55352284Sobrien	}
55452284Sobrien#if 0
55552284Sobrien	/*
55652284Sobrien	 * Don't allow unloading modules with private data.
55790075Sobrien	 */
55852284Sobrien	if (mpc->mpc_field_off != NULL) {
55952284Sobrien		MAC_POLICY_LIST_UNLOCK();
56052284Sobrien		return (EBUSY);
56152284Sobrien	}
56252284Sobrien#endif
56390075Sobrien	/*
56452284Sobrien	 * Only allow the unload to proceed if the module is unloadable
56552284Sobrien	 * by its own definition.
56690075Sobrien	 */
56752284Sobrien	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
56852284Sobrien		MAC_POLICY_LIST_UNLOCK();
56952284Sobrien		return (EBUSY);
57052284Sobrien	}
57152284Sobrien	if (mpc->mpc_ops->mpo_destroy != NULL)
57290075Sobrien		(*(mpc->mpc_ops->mpo_destroy))(mpc);
57352284Sobrien
57452284Sobrien	LIST_REMOVE(mpc, mpc_list);
57552284Sobrien	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
57652284Sobrien
57752284Sobrien	MAC_POLICY_LIST_UNLOCK();
57852284Sobrien
57952284Sobrien	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
58052284Sobrien	    mpc->mpc_name);
58152284Sobrien
58252284Sobrien	return (0);
58352284Sobrien}
58452284Sobrien
58552284Sobrien/*
58652284Sobrien * Define an error value precedence, and given two arguments, selects the
58752284Sobrien * value with the higher precedence.
58852284Sobrien */
58952284Sobrienstatic int
59052284Sobrienerror_select(int error1, int error2)
59152284Sobrien{
59252284Sobrien
59352284Sobrien	/* Certain decision-making errors take top priority. */
59452284Sobrien	if (error1 == EDEADLK || error2 == EDEADLK)
59552284Sobrien		return (EDEADLK);
59652284Sobrien
59752284Sobrien	/* Invalid arguments should be reported where possible. */
59852284Sobrien	if (error1 == EINVAL || error2 == EINVAL)
59952284Sobrien		return (EINVAL);
60052284Sobrien
60152284Sobrien	/* Precedence goes to "visibility", with both process and file. */
60252284Sobrien	if (error1 == ESRCH || error2 == ESRCH)
60352284Sobrien		return (ESRCH);
60452284Sobrien
60552284Sobrien	if (error1 == ENOENT || error2 == ENOENT)
60652284Sobrien		return (ENOENT);
60752284Sobrien
60852284Sobrien	/* Precedence goes to DAC/MAC protections. */
60952284Sobrien	if (error1 == EACCES || error2 == EACCES)
61090075Sobrien		return (EACCES);
61190075Sobrien
61290075Sobrien	/* Precedence goes to privilege. */
61390075Sobrien	if (error1 == EPERM || error2 == EPERM)
61490075Sobrien		return (EPERM);
61590075Sobrien
61690075Sobrien	/* Precedence goes to error over success; otherwise, arbitrary. */
61790075Sobrien	if (error1 != 0)
61890075Sobrien		return (error1);
61990075Sobrien	return (error2);
62090075Sobrien}
62190075Sobrien
62290075Sobrienstatic void
62390075Sobrienmac_init_label(struct label *label)
62490075Sobrien{
62590075Sobrien
62690075Sobrien	bzero(label, sizeof(*label));
62790075Sobrien	label->l_flags = MAC_FLAG_INITIALIZED;
62890075Sobrien}
62918334Speter
63018334Speterstatic void
63118334Spetermac_destroy_label(struct label *label)
63218334Speter{
63318334Speter
63418334Speter	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
63518334Speter	    ("destroying uninitialized label"));
63618334Speter
63718334Speter	bzero(label, sizeof(*label));
63818334Speter	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
63918334Speter}
64018334Speter
64118334Spetervoid
64218334Spetermac_init_bpfdesc(struct bpf_d *bpf_d)
64318334Speter{
64418334Speter
64518334Speter	mac_init_label(&bpf_d->bd_label);
64618334Speter	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
64718334Speter#ifdef MAC_DEBUG
64818334Speter	atomic_add_int(&nmacbpfdescs, 1);
64918334Speter#endif
65018334Speter}
65118334Speter
65218334Speterstatic void
65318334Spetermac_init_cred_label(struct label *label)
65490075Sobrien{
65518334Speter
65618334Speter	mac_init_label(label);
65718334Speter	MAC_PERFORM(init_cred_label, label);
65818334Speter#ifdef MAC_DEBUG
65918334Speter	atomic_add_int(&nmaccreds, 1);
66018334Speter#endif
66118334Speter}
66218334Speter
66318334Spetervoid
66418334Spetermac_init_cred(struct ucred *cred)
66518334Speter{
66618334Speter
66718334Speter	mac_init_cred_label(&cred->cr_label);
66818334Speter}
66918334Speter
67018334Spetervoid
67118334Spetermac_init_devfsdirent(struct devfs_dirent *de)
67218334Speter{
67318334Speter
67418334Speter	mac_init_label(&de->de_label);
67518334Speter	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
67618334Speter#ifdef MAC_DEBUG
67718334Speter	atomic_add_int(&nmacdevfsdirents, 1);
67818334Speter#endif
67918334Speter}
68018334Speter
68118334Speterstatic void
68218334Spetermac_init_ifnet_label(struct label *label)
68318334Speter{
68418334Speter
68518334Speter	mac_init_label(label);
68618334Speter	MAC_PERFORM(init_ifnet_label, label);
68718334Speter#ifdef MAC_DEBUG
68818334Speter	atomic_add_int(&nmacifnets, 1);
68990075Sobrien#endif
69018334Speter}
69118334Speter
69218334Spetervoid
69390075Sobrienmac_init_ifnet(struct ifnet *ifp)
69418334Speter{
69518334Speter
69618334Speter	mac_init_ifnet_label(&ifp->if_label);
69718334Speter}
69818334Speter
69918334Spetervoid
70018334Spetermac_init_ipq(struct ipq *ipq)
70118334Speter{
70218334Speter
70318334Speter	mac_init_label(&ipq->ipq_label);
70418334Speter	MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
70518334Speter#ifdef MAC_DEBUG
70618334Speter	atomic_add_int(&nmacipqs, 1);
70718334Speter#endif
70818334Speter}
70918334Speter
71018334Speterint
71118334Spetermac_init_mbuf(struct mbuf *m, int flag)
71218334Speter{
71318334Speter	int error;
71418334Speter
71518334Speter	KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
71618334Speter
71718334Speter	mac_init_label(&m->m_pkthdr.label);
71818334Speter
71918334Speter	MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
72018334Speter	if (error) {
72118334Speter		MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
72218334Speter		mac_destroy_label(&m->m_pkthdr.label);
72318334Speter	}
72418334Speter
72518334Speter#ifdef MAC_DEBUG
72618334Speter	if (error == 0)
72718334Speter		atomic_add_int(&nmacmbufs, 1);
72818334Speter#endif
72918334Speter	return (error);
73090075Sobrien}
73190075Sobrien
73218334Spetervoid
73318334Spetermac_init_mount(struct mount *mp)
73418334Speter{
73518334Speter
73618334Speter	mac_init_label(&mp->mnt_mntlabel);
73718334Speter	mac_init_label(&mp->mnt_fslabel);
73818334Speter	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
73918334Speter	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
74018334Speter#ifdef MAC_DEBUG
74150397Sobrien	atomic_add_int(&nmacmounts, 1);
74218334Speter#endif
74318334Speter}
74418334Speter
74518334Speterstatic void
74618334Spetermac_init_pipe_label(struct label *label)
74790075Sobrien{
74818334Speter
74918334Speter	mac_init_label(label);
75018334Speter	MAC_PERFORM(init_pipe_label, label);
75118334Speter#ifdef MAC_DEBUG
75218334Speter	atomic_add_int(&nmacpipes, 1);
75318334Speter#endif
75418334Speter}
75590075Sobrien
75690075Sobrienvoid
75790075Sobrienmac_init_pipe(struct pipe *pipe)
75890075Sobrien{
75990075Sobrien	struct label *label;
76090075Sobrien
76190075Sobrien	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
76290075Sobrien	pipe->pipe_label = label;
76318334Speter	pipe->pipe_peer->pipe_label = label;
76490075Sobrien	mac_init_pipe_label(label);
76518334Speter}
76690075Sobrien
76790075Sobrienvoid
76890075Sobrienmac_init_proc(struct proc *p)
76990075Sobrien{
77090075Sobrien
77190075Sobrien	mac_init_label(&p->p_label);
77290075Sobrien	MAC_PERFORM(init_proc_label, &p->p_label);
77318334Speter#ifdef MAC_DEBUG
77490075Sobrien	atomic_add_int(&nmacprocs, 1);
77518334Speter#endif
77690075Sobrien}
77790075Sobrien
77890075Sobrienstatic int
77990075Sobrienmac_init_socket_label(struct label *label, int flag)
78090075Sobrien{
78190075Sobrien	int error;
78290075Sobrien
78390075Sobrien	mac_init_label(label);
78418334Speter
78518334Speter	MAC_CHECK(init_socket_label, label, flag);
78618334Speter	if (error) {
78718334Speter		MAC_PERFORM(destroy_socket_label, label);
78890075Sobrien		mac_destroy_label(label);
78918334Speter	}
79018334Speter
79118334Speter#ifdef MAC_DEBUG
79290075Sobrien	if (error == 0)
79318334Speter		atomic_add_int(&nmacsockets, 1);
79418334Speter#endif
79518334Speter
79690075Sobrien	return (error);
79718334Speter}
79818334Speter
79918334Speterstatic int
80018334Spetermac_init_socket_peer_label(struct label *label, int flag)
80118334Speter{
80218334Speter	int error;
80318334Speter
80418334Speter	mac_init_label(label);
80518334Speter
80618334Speter	MAC_CHECK(init_socket_peer_label, label, flag);
80718334Speter	if (error) {
80818334Speter		MAC_PERFORM(destroy_socket_label, label);
80918334Speter		mac_destroy_label(label);
81018334Speter	}
81118334Speter
81218334Speter	return (error);
81318334Speter}
81418334Speter
81518334Speterint
81618334Spetermac_init_socket(struct socket *socket, int flag)
81718334Speter{
81818334Speter	int error;
81918334Speter
82018334Speter	error = mac_init_socket_label(&socket->so_label, flag);
82118334Speter	if (error)
82218334Speter		return (error);
82318334Speter
82418334Speter	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
82518334Speter	if (error)
82618334Speter		mac_destroy_socket_label(&socket->so_label);
82718334Speter
82818334Speter	return (error);
82918334Speter}
83018334Speter
83118334Spetervoid
83218334Spetermac_init_vnode_label(struct label *label)
83318334Speter{
83418334Speter
83518334Speter	mac_init_label(label);
83618334Speter	MAC_PERFORM(init_vnode_label, label);
83718334Speter#ifdef MAC_DEBUG
83818334Speter	atomic_add_int(&nmacvnodes, 1);
83918334Speter#endif
84018334Speter}
84118334Speter
84218334Spetervoid
84318334Spetermac_init_vnode(struct vnode *vp)
84418334Speter{
84518334Speter
84618334Speter	mac_init_vnode_label(&vp->v_label);
84718334Speter}
84818334Speter
84918334Spetervoid
85018334Spetermac_destroy_bpfdesc(struct bpf_d *bpf_d)
85118334Speter{
85218334Speter
85318334Speter	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
85418334Speter	mac_destroy_label(&bpf_d->bd_label);
85518334Speter#ifdef MAC_DEBUG
85618334Speter	atomic_subtract_int(&nmacbpfdescs, 1);
85718334Speter#endif
85818334Speter}
85918334Speter
86018334Speterstatic void
86118334Spetermac_destroy_cred_label(struct label *label)
86290075Sobrien{
86318334Speter
86418334Speter	MAC_PERFORM(destroy_cred_label, label);
86518334Speter	mac_destroy_label(label);
86618334Speter#ifdef MAC_DEBUG
86718334Speter	atomic_subtract_int(&nmaccreds, 1);
86818334Speter#endif
86918334Speter}
87018334Speter
87118334Spetervoid
87218334Spetermac_destroy_cred(struct ucred *cred)
87318334Speter{
87418334Speter
87518334Speter	mac_destroy_cred_label(&cred->cr_label);
87618334Speter}
87718334Speter
87818334Spetervoid
87918334Spetermac_destroy_devfsdirent(struct devfs_dirent *de)
88018334Speter{
88118334Speter
88218334Speter	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
88318334Speter	mac_destroy_label(&de->de_label);
88418334Speter#ifdef MAC_DEBUG
88518334Speter	atomic_subtract_int(&nmacdevfsdirents, 1);
88618334Speter#endif
88718334Speter}
88818334Speter
88918334Speterstatic void
89018334Spetermac_destroy_ifnet_label(struct label *label)
89118334Speter{
89218334Speter
89318334Speter	MAC_PERFORM(destroy_ifnet_label, label);
89418334Speter	mac_destroy_label(label);
89518334Speter#ifdef MAC_DEBUG
89618334Speter	atomic_subtract_int(&nmacifnets, 1);
89718334Speter#endif
89818334Speter}
89918334Speter
90018334Spetervoid
90118334Spetermac_destroy_ifnet(struct ifnet *ifp)
90218334Speter{
90318334Speter
90418334Speter	mac_destroy_ifnet_label(&ifp->if_label);
90518334Speter}
90618334Speter
90718334Spetervoid
90818334Spetermac_destroy_ipq(struct ipq *ipq)
90918334Speter{
91018334Speter
91118334Speter	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
91218334Speter	mac_destroy_label(&ipq->ipq_label);
91318334Speter#ifdef MAC_DEBUG
91418334Speter	atomic_subtract_int(&nmacipqs, 1);
91518334Speter#endif
91618334Speter}
91718334Speter
91818334Spetervoid
91918334Spetermac_destroy_mbuf(struct mbuf *m)
92018334Speter{
92118334Speter
92218334Speter	MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
92318334Speter	mac_destroy_label(&m->m_pkthdr.label);
92418334Speter#ifdef MAC_DEBUG
92518334Speter	atomic_subtract_int(&nmacmbufs, 1);
92618334Speter#endif
92718334Speter}
92818334Speter
92918334Spetervoid
93018334Spetermac_destroy_mount(struct mount *mp)
93118334Speter{
93218334Speter
93318334Speter	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
93418334Speter	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
93518334Speter	mac_destroy_label(&mp->mnt_fslabel);
93650397Sobrien	mac_destroy_label(&mp->mnt_mntlabel);
93750397Sobrien#ifdef MAC_DEBUG
93818334Speter	atomic_subtract_int(&nmacmounts, 1);
93918334Speter#endif
94018334Speter}
94118334Speter
94218334Speterstatic void
94318334Spetermac_destroy_pipe_label(struct label *label)
94418334Speter{
94518334Speter
94618334Speter	MAC_PERFORM(destroy_pipe_label, label);
94718334Speter	mac_destroy_label(label);
94818334Speter#ifdef MAC_DEBUG
94918334Speter	atomic_subtract_int(&nmacpipes, 1);
95018334Speter#endif
95118334Speter}
95218334Speter
95318334Spetervoid
95418334Spetermac_destroy_pipe(struct pipe *pipe)
95518334Speter{
95618334Speter
95718334Speter	mac_destroy_pipe_label(pipe->pipe_label);
95818334Speter	free(pipe->pipe_label, M_MACPIPELABEL);
95918334Speter}
96018334Speter
96118334Spetervoid
96218334Spetermac_destroy_proc(struct proc *p)
96318334Speter{
96418334Speter
96518334Speter	MAC_PERFORM(destroy_proc_label, &p->p_label);
96618334Speter	mac_destroy_label(&p->p_label);
96718334Speter#ifdef MAC_DEBUG
96818334Speter	atomic_subtract_int(&nmacprocs, 1);
96918334Speter#endif
97018334Speter}
97118334Speter
97218334Speterstatic void
97318334Spetermac_destroy_socket_label(struct label *label)
97418334Speter{
97518334Speter
97618334Speter	MAC_PERFORM(destroy_socket_label, label);
97718334Speter	mac_destroy_label(label);
97818334Speter#ifdef MAC_DEBUG
97918334Speter	atomic_subtract_int(&nmacsockets, 1);
98018334Speter#endif
98118334Speter}
98218334Speter
98318334Speterstatic void
98418334Spetermac_destroy_socket_peer_label(struct label *label)
98518334Speter{
98618334Speter
98718334Speter	MAC_PERFORM(destroy_socket_peer_label, label);
98818334Speter	mac_destroy_label(label);
98918334Speter}
99018334Speter
99118334Spetervoid
99218334Spetermac_destroy_socket(struct socket *socket)
99318334Speter{
99418334Speter
99518334Speter	mac_destroy_socket_label(&socket->so_label);
99618334Speter	mac_destroy_socket_peer_label(&socket->so_peerlabel);
99718334Speter}
99818334Speter
99918334Spetervoid
100018334Spetermac_destroy_vnode_label(struct label *label)
100118334Speter{
100218334Speter
100318334Speter	MAC_PERFORM(destroy_vnode_label, label);
100418334Speter	mac_destroy_label(label);
100518334Speter#ifdef MAC_DEBUG
100618334Speter	atomic_subtract_int(&nmacvnodes, 1);
100718334Speter#endif
100818334Speter}
100918334Speter
101018334Spetervoid
101118334Spetermac_destroy_vnode(struct vnode *vp)
101218334Speter{
101318334Speter
101418334Speter	mac_destroy_vnode_label(&vp->v_label);
101518334Speter}
101618334Speter
101718334Speterstatic void
101818334Spetermac_copy_pipe_label(struct label *src, struct label *dest)
101918334Speter{
102018334Speter
102118334Speter	MAC_PERFORM(copy_pipe_label, src, dest);
102218334Speter}
102318334Speter
102418334Spetervoid
102518334Spetermac_copy_vnode_label(struct label *src, struct label *dest)
102618334Speter{
102718334Speter
102818334Speter	MAC_PERFORM(copy_vnode_label, src, dest);
102918334Speter}
103018334Speter
103118334Speterstatic int
103218334Spetermac_check_structmac_consistent(struct mac *mac)
103318334Speter{
103418334Speter
103518334Speter	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
103618334Speter		return (EINVAL);
103718334Speter
103818334Speter	return (0);
103918334Speter}
104018334Speter
104118334Speterstatic int
104218334Spetermac_externalize_cred_label(struct label *label, char *elements,
104318334Speter    char *outbuf, size_t outbuflen, int flags)
104418334Speter{
104518334Speter	int error;
104618334Speter
104718334Speter	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
104818334Speter
104918334Speter	return (error);
105018334Speter}
105118334Speter
105218334Speterstatic int
105318334Spetermac_externalize_ifnet_label(struct label *label, char *elements,
105418334Speter    char *outbuf, size_t outbuflen, int flags)
105518334Speter{
105650397Sobrien	int error;
105718334Speter
105818334Speter	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
105918334Speter
106018334Speter	return (error);
106118334Speter}
106218334Speter
106318334Speterstatic int
106418334Spetermac_externalize_pipe_label(struct label *label, char *elements,
106518334Speter    char *outbuf, size_t outbuflen, int flags)
106618334Speter{
106718334Speter	int error;
106818334Speter
106918334Speter	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
107018334Speter
107118334Speter	return (error);
107218334Speter}
107318334Speter
107418334Speterstatic int
107518334Spetermac_externalize_socket_label(struct label *label, char *elements,
107618334Speter    char *outbuf, size_t outbuflen, int flags)
107718334Speter{
107818334Speter	int error;
107918334Speter
108018334Speter	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
108118334Speter
108218334Speter	return (error);
108318334Speter}
108418334Speter
108518334Speterstatic int
108618334Spetermac_externalize_socket_peer_label(struct label *label, char *elements,
108718334Speter    char *outbuf, size_t outbuflen, int flags)
108818334Speter{
108918334Speter	int error;
109018334Speter
109118334Speter	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
109218334Speter
109318334Speter	return (error);
109418334Speter}
109518334Speter
109618334Speterstatic int
109718334Spetermac_externalize_vnode_label(struct label *label, char *elements,
109818334Speter    char *outbuf, size_t outbuflen, int flags)
109918334Speter{
110018334Speter	int error;
110118334Speter
110218334Speter	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
110318334Speter
110418334Speter	return (error);
110518334Speter}
110618334Speter
110718334Speterstatic int
110818334Spetermac_internalize_cred_label(struct label *label, char *string)
110918334Speter{
111018334Speter	int error;
111118334Speter
111218334Speter	MAC_INTERNALIZE(cred_label, label, string);
111318334Speter
111418334Speter	return (error);
111518334Speter}
111618334Speter
111718334Speterstatic int
111818334Spetermac_internalize_ifnet_label(struct label *label, char *string)
111918334Speter{
112018334Speter	int error;
112118334Speter
112218334Speter	MAC_INTERNALIZE(ifnet_label, label, string);
112318334Speter
112418334Speter	return (error);
112518334Speter}
112618334Speter
112718334Speterstatic int
112818334Spetermac_internalize_pipe_label(struct label *label, char *string)
112918334Speter{
113018334Speter	int error;
113118334Speter
113218334Speter	MAC_INTERNALIZE(pipe_label, label, string);
113318334Speter
113418334Speter	return (error);
113518334Speter}
113618334Speter
113718334Speterstatic int
113818334Spetermac_internalize_socket_label(struct label *label, char *string)
113918334Speter{
114018334Speter	int error;
114118334Speter
114218334Speter	MAC_INTERNALIZE(socket_label, label, string);
114318334Speter
114418334Speter	return (error);
114518334Speter}
114618334Speter
114718334Speterstatic int
114818334Spetermac_internalize_vnode_label(struct label *label, char *string)
114918334Speter{
115018334Speter	int error;
115118334Speter
115218334Speter	MAC_INTERNALIZE(vnode_label, label, string);
115318334Speter
115418334Speter	return (error);
115518334Speter}
115618334Speter
115718334Speter/*
115818334Speter * Initialize MAC label for the first kernel process, from which other
115918334Speter * kernel processes and threads are spawned.
116018334Speter */
116118334Spetervoid
116218334Spetermac_create_proc0(struct ucred *cred)
116318334Speter{
116418334Speter
116518334Speter	MAC_PERFORM(create_proc0, cred);
116618334Speter}
116718334Speter
116818334Speter/*
116918334Speter * Initialize MAC label for the first userland process, from which other
117050397Sobrien * userland processes and threads are spawned.
117118334Speter */
117218334Spetervoid
117318334Spetermac_create_proc1(struct ucred *cred)
117418334Speter{
117518334Speter
117618334Speter	MAC_PERFORM(create_proc1, cred);
117718334Speter}
117818334Speter
117918334Spetervoid
118018334Spetermac_thread_userret(struct thread *td)
118118334Speter{
118218334Speter
118318334Speter	MAC_PERFORM(thread_userret, td);
118418334Speter}
118518334Speter
118618334Speter/*
118718334Speter * When a new process is created, its label must be initialized.  Generally,
118818334Speter * this involves inheritence from the parent process, modulo possible
118918334Speter * deltas.  This function allows that processing to take place.
119018334Speter */
119118334Spetervoid
119218334Spetermac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
119318334Speter{
119418334Speter
119590075Sobrien	MAC_PERFORM(create_cred, parent_cred, child_cred);
119652284Sobrien}
119718334Speter
119818334Spetervoid
119918334Spetermac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
120018334Speter{
120118334Speter
120218334Speter	MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
120318334Speter}
120418334Speter
120518334Spetervoid
120618334Spetermac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
120718334Speter    struct vnode *vp)
120818334Speter{
120918334Speter
121018334Speter	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
121118334Speter	    &de->de_label, vp, &vp->v_label);
121218334Speter}
121318334Speter
121418334Speterint
121518334Spetermac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
121618334Speter{
121718334Speter	int error;
121850397Sobrien
121918334Speter	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
122018334Speter
122118334Speter	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
122218334Speter	    &vp->v_label);
122318334Speter
122418334Speter	return (error);
122518334Speter}
122618334Speter
122718334Spetervoid
122818334Spetermac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
122918334Speter{
123018334Speter
123118334Speter	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
123218334Speter	    &vp->v_label);
123318334Speter}
123418334Speter
123518334Speterint
123618334Spetermac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
123718334Speter    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
123818334Speter{
123918334Speter	int error;
124050397Sobrien
124150397Sobrien	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
124290075Sobrien	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
124350397Sobrien
124450397Sobrien	error = VOP_OPENEXTATTR(vp, cred, curthread);
124518334Speter	if (error == EOPNOTSUPP) {
124618334Speter		/* XXX: Optionally abort if transactions not supported. */
124718334Speter		if (ea_warn_once == 0) {
124818334Speter			printf("Warning: transactions not supported "
124990075Sobrien			    "in EA write.\n");
125090075Sobrien			ea_warn_once = 1;
125118334Speter		}
125290075Sobrien	} else if (error)
125390075Sobrien		return (error);
125490075Sobrien
125590075Sobrien	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
125618334Speter	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
125718334Speter
125818334Speter	if (error) {
125918334Speter		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
126090075Sobrien		return (error);
126150397Sobrien	}
126290075Sobrien
126390075Sobrien	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
126490075Sobrien
126550397Sobrien	if (error == EOPNOTSUPP)
126618334Speter		error = 0;				/* XXX */
126718334Speter
126818334Speter	return (error);
126918334Speter}
127018334Speter
127118334Speterstatic int
127218334Spetermac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
127318334Speter    struct label *intlabel)
127490075Sobrien{
127518334Speter	int error;
127618334Speter
127718334Speter	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
127818334Speter
127918334Speter	error = VOP_OPENEXTATTR(vp, cred, curthread);
128018334Speter	if (error == EOPNOTSUPP) {
128118334Speter		/* XXX: Optionally abort if transactions not supported. */
128250397Sobrien		if (ea_warn_once == 0) {
128350397Sobrien			printf("Warning: transactions not supported "
128450397Sobrien			    "in EA write.\n");
128518334Speter			ea_warn_once = 1;
128652284Sobrien		}
128752284Sobrien	} else if (error)
128852284Sobrien		return (error);
128952284Sobrien
129052284Sobrien	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
129150397Sobrien
129290075Sobrien	if (error) {
129318334Speter		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
129418334Speter		return (error);
129590075Sobrien	}
129618334Speter
129718334Speter	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
129818334Speter
129918334Speter	if (error == EOPNOTSUPP)
130018334Speter		error = 0;				/* XXX */
130118334Speter
130218334Speter	return (error);
130318334Speter}
130418334Speter
130518334Speterint
130618334Spetermac_execve_enter(struct image_params *imgp, struct mac *mac_p,
130718334Speter    struct label *execlabelstorage)
130818334Speter{
130918334Speter	struct mac mac;
131018334Speter	char *buffer;
131118334Speter	int error;
131218334Speter
131318334Speter	if (mac_p == NULL)
131418334Speter		return (0);
131518334Speter
131618334Speter	error = copyin(mac_p, &mac, sizeof(mac));
131718334Speter	if (error)
131818334Speter		return (error);
131918334Speter
132018334Speter	error = mac_check_structmac_consistent(&mac);
132118334Speter	if (error)
132218334Speter		return (error);
132318334Speter
132418334Speter	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
132518334Speter	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
132618334Speter	if (error) {
132718334Speter		free(buffer, M_MACTEMP);
132818334Speter		return (error);
132918334Speter	}
133018334Speter
133118334Speter	mac_init_cred_label(execlabelstorage);
133218334Speter	error = mac_internalize_cred_label(execlabelstorage, buffer);
133318334Speter	free(buffer, M_MACTEMP);
133418334Speter	if (error) {
133518334Speter		mac_destroy_cred_label(execlabelstorage);
133618334Speter		return (error);
133718334Speter	}
133818334Speter	imgp->execlabel = execlabelstorage;
133918334Speter	return (0);
134018334Speter}
134118334Speter
134218334Spetervoid
134318334Spetermac_execve_exit(struct image_params *imgp)
134418334Speter{
134518334Speter	if (imgp->execlabel != NULL)
134618334Speter		mac_destroy_cred_label(imgp->execlabel);
134718334Speter}
134818334Speter
134918334Spetervoid
135018334Spetermac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
135118334Speter    struct label *interpvnodelabel, struct image_params *imgp)
135218334Speter{
135318334Speter
135418334Speter	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
135518334Speter
135618334Speter	if (!mac_enforce_process && !mac_enforce_fs)
135718334Speter		return;
135818334Speter
135918334Speter	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
136018334Speter	    interpvnodelabel, imgp, imgp->execlabel);
136118334Speter}
136218334Speter
136318334Speterint
136418334Spetermac_execve_will_transition(struct ucred *old, struct vnode *vp,
136518334Speter    struct label *interpvnodelabel, struct image_params *imgp)
136618334Speter{
136752284Sobrien	int result;
136852284Sobrien
136918334Speter	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
137018334Speter
137118334Speter	if (!mac_enforce_process && !mac_enforce_fs)
137218334Speter		return (0);
137318334Speter
137418334Speter	result = 0;
137518334Speter	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
137618334Speter	    interpvnodelabel, imgp, imgp->execlabel);
137718334Speter
137818334Speter	return (result);
137918334Speter}
138018334Speter
138118334Speterint
138218334Spetermac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
138318334Speter{
138418334Speter	int error;
138518334Speter
138618334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
138718334Speter
138818334Speter	if (!mac_enforce_fs)
138918334Speter		return (0);
139018334Speter
139118334Speter	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
139218334Speter	return (error);
139318334Speter}
139418334Speter
139518334Speterint
139618334Spetermac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
139718334Speter{
139818334Speter	int error;
139918334Speter
140018334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
140118334Speter
140218334Speter	if (!mac_enforce_fs)
140318334Speter		return (0);
140418334Speter
140518334Speter	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
140618334Speter	return (error);
140718334Speter}
140818334Speter
140918334Speterint
141018334Spetermac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
141118334Speter{
141218334Speter	int error;
141318334Speter
141418334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
141518334Speter
141618334Speter	if (!mac_enforce_fs)
141718334Speter		return (0);
141818334Speter
141918334Speter	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
142018334Speter	return (error);
142118334Speter}
142218334Speter
142318334Speterint
142418334Spetermac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
142518334Speter    struct componentname *cnp, struct vattr *vap)
142618334Speter{
142718334Speter	int error;
142818334Speter
142918334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
143018334Speter
143118334Speter	if (!mac_enforce_fs)
143218334Speter		return (0);
143318334Speter
143418334Speter	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
143518334Speter	return (error);
143618334Speter}
143718334Speter
143818334Speterint
143918334Spetermac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
144018334Speter    struct componentname *cnp)
144118334Speter{
144218334Speter	int error;
144318334Speter
144418334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
144518334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
144618334Speter
144718334Speter	if (!mac_enforce_fs)
144818334Speter		return (0);
144918334Speter
145018334Speter	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
145118334Speter	    &vp->v_label, cnp);
145218334Speter	return (error);
145318334Speter}
145418334Speter
145518334Speterint
145618334Spetermac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
145718334Speter    acl_type_t type)
145818334Speter{
145918334Speter	int error;
146018334Speter
146118334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
146218334Speter
146318334Speter	if (!mac_enforce_fs)
146418334Speter		return (0);
146518334Speter
146618334Speter	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
146750397Sobrien	return (error);
146850397Sobrien}
146950397Sobrien
147052284Sobrienint
147152284Sobrienmac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
147252284Sobrien    struct image_params *imgp)
147352284Sobrien{
147452284Sobrien	int error;
147550397Sobrien
147690075Sobrien	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
147718334Speter
147818334Speter	if (!mac_enforce_process && !mac_enforce_fs)
147918334Speter		return (0);
148018334Speter
148118334Speter	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
148218334Speter	    imgp->execlabel);
148318334Speter
148418334Speter	return (error);
148518334Speter}
148618334Speter
148718334Speterint
148818334Spetermac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
148918334Speter{
149018334Speter	int error;
149118334Speter
149218334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
149318334Speter
149418334Speter	if (!mac_enforce_fs)
149518334Speter		return (0);
149618334Speter
149718334Speter	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
149818334Speter	return (error);
149918334Speter}
150018334Speter
150118334Speterint
150218334Spetermac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
150318334Speter    int attrnamespace, const char *name, struct uio *uio)
150418334Speter{
150518334Speter	int error;
150618334Speter
150718334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
150818334Speter
150918334Speter	if (!mac_enforce_fs)
151018334Speter		return (0);
151118334Speter
151218334Speter	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
151318334Speter	    attrnamespace, name, uio);
151418334Speter	return (error);
151518334Speter}
151618334Speter
151718334Speterint
151818334Spetermac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
151952284Sobrien    struct vnode *vp, struct componentname *cnp)
152018334Speter{
152118334Speter	int error;
152218334Speter
152318334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
152452284Sobrien	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
152518334Speter
152618334Speter	if (!mac_enforce_fs)
152718334Speter		return (0);
152818334Speter
152918334Speter	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
153018334Speter	    &vp->v_label, cnp);
153118334Speter	return (error);
153252284Sobrien}
153318334Speter
153418334Speterint
153518334Spetermac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
153618334Speter    struct componentname *cnp)
153718334Speter{
153818334Speter	int error;
153918334Speter
154018334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
154118334Speter
154218334Speter	if (!mac_enforce_fs)
154318334Speter		return (0);
154418334Speter
154518334Speter	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
154618334Speter	return (error);
154718334Speter}
154818334Speter
154918334Speterint
155018334Spetermac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
155118334Speter{
155218334Speter	int error;
155318334Speter
155418334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
155518334Speter
155618334Speter	if (!mac_enforce_fs || !mac_enforce_vm)
155718334Speter		return (0);
155818334Speter
155918334Speter	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
156018334Speter	return (error);
156190075Sobrien}
156290075Sobrien
156390075Sobrienvoid
156418334Spetermac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
156518334Speter{
156618334Speter	int result = *prot;
156718334Speter
156818334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
156918334Speter
157018334Speter	if (!mac_enforce_fs || !mac_enforce_vm)
157118334Speter		return;
157218334Speter
157318334Speter	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
157418334Speter	    &result);
157518334Speter
157618334Speter	*prot = result;
157718334Speter}
157818334Speter
157918334Speterint
158018334Spetermac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
158118334Speter{
158218334Speter	int error;
158318334Speter
158418334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
158518334Speter
158618334Speter	if (!mac_enforce_fs || !mac_enforce_vm)
158718334Speter		return (0);
158818334Speter
158918334Speter	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
159018334Speter	return (error);
159118334Speter}
159218334Speter
159318334Speterint
159418334Spetermac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
159518334Speter{
159618334Speter	int error;
159790075Sobrien
159890075Sobrien	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
159990075Sobrien
160090075Sobrien	if (!mac_enforce_fs)
160118334Speter		return (0);
160218334Speter
160318334Speter	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
160418334Speter	return (error);
160518334Speter}
160618334Speter
160718334Speterint
160818334Spetermac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
160918334Speter    struct vnode *vp)
161018334Speter{
161118334Speter	int error;
161218334Speter
161318334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
161418334Speter
161518334Speter	if (!mac_enforce_fs)
161690075Sobrien		return (0);
161790075Sobrien
161890075Sobrien	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
161990075Sobrien	    &vp->v_label);
162018334Speter
162118334Speter	return (error);
162218334Speter}
162318334Speter
162418334Speterint
162518334Spetermac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
162618334Speter    struct vnode *vp)
162718334Speter{
162818334Speter	int error;
162918334Speter
163018334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
163118334Speter
163218334Speter	if (!mac_enforce_fs)
163318334Speter		return (0);
163418334Speter
163518334Speter	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
163618334Speter	    &vp->v_label);
163718334Speter
163818334Speter	return (error);
163918334Speter}
164018334Speter
164118334Speterint
164218334Spetermac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
164318334Speter{
164418334Speter	int error;
164518334Speter
164618334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
164718334Speter
164818334Speter	if (!mac_enforce_fs)
164918334Speter		return (0);
165018334Speter
165118334Speter	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
165218334Speter	return (error);
165318334Speter}
165418334Speter
165518334Speterint
165618334Spetermac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
165718334Speter{
165818334Speter	int error;
165918334Speter
166018334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
166118334Speter
166218334Speter	if (!mac_enforce_fs)
166318334Speter		return (0);
166418334Speter
166518334Speter	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
166618334Speter	return (error);
166718334Speter}
166818334Speter
166918334Speterstatic int
167018334Spetermac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
167118334Speter    struct label *newlabel)
167218334Speter{
167318334Speter	int error;
167418334Speter
167518334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
167618334Speter
167718334Speter	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
167818334Speter
167918334Speter	return (error);
168018334Speter}
168118334Speter
168218334Speterint
168318334Spetermac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
168418334Speter    struct vnode *vp, struct componentname *cnp)
168518334Speter{
168618334Speter	int error;
168718334Speter
168818334Speter	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
168918334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
169018334Speter
169118334Speter	if (!mac_enforce_fs)
169218334Speter		return (0);
169318334Speter
169418334Speter	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
169518334Speter	    &vp->v_label, cnp);
169652284Sobrien	return (error);
169718334Speter}
169852284Sobrien
169952284Sobrienint
170052284Sobrienmac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
170152284Sobrien    struct vnode *vp, int samedir, struct componentname *cnp)
170252284Sobrien{
170352284Sobrien	int error;
170418334Speter
170552284Sobrien	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
170652284Sobrien	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
170752284Sobrien
170852284Sobrien	if (!mac_enforce_fs)
170952284Sobrien		return (0);
171052284Sobrien
171118334Speter	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
171252284Sobrien	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
171352284Sobrien	return (error);
171418334Speter}
171518334Speter
171618334Speterint
171718334Spetermac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
171818334Speter{
171918334Speter	int error;
172018334Speter
172118334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
172218334Speter
172318334Speter	if (!mac_enforce_fs)
172418334Speter		return (0);
172518334Speter
172618334Speter	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
172718334Speter	return (error);
172818334Speter}
172950397Sobrien
173050397Sobrienint
173118334Spetermac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
173218334Speter    struct acl *acl)
173318334Speter{
173418334Speter	int error;
173518334Speter
173618334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
173718334Speter
173818334Speter	if (!mac_enforce_fs)
173918334Speter		return (0);
174018334Speter
174118334Speter	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
174218334Speter	return (error);
174318334Speter}
174418334Speter
174518334Speterint
174618334Spetermac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
174718334Speter    int attrnamespace, const char *name, struct uio *uio)
174818334Speter{
174918334Speter	int error;
175018334Speter
175118334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
175218334Speter
175318334Speter	if (!mac_enforce_fs)
175418334Speter		return (0);
175518334Speter
175618334Speter	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
175718334Speter	    attrnamespace, name, uio);
175818334Speter	return (error);
175918334Speter}
176018334Speter
176118334Speterint
176218334Spetermac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
176318334Speter{
176418334Speter	int error;
176518334Speter
176618334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
176718334Speter
176890075Sobrien	if (!mac_enforce_fs)
176918334Speter		return (0);
177018334Speter
177118334Speter	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
177218334Speter	return (error);
177318334Speter}
177418334Speter
177518334Speterint
177650397Sobrienmac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
177718334Speter{
177818334Speter	int error;
177918334Speter
178018334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
178118334Speter
178218334Speter	if (!mac_enforce_fs)
178318334Speter		return (0);
178418334Speter
178518334Speter	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
178618334Speter	return (error);
178718334Speter}
178818334Speter
178918334Speterint
179018334Spetermac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
179118334Speter    gid_t gid)
179218334Speter{
179318334Speter	int error;
179418334Speter
179518334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
179618334Speter
179718334Speter	if (!mac_enforce_fs)
179818334Speter		return (0);
179918334Speter
180018334Speter	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
180118334Speter	return (error);
180218334Speter}
180318334Speter
180418334Speterint
180518334Spetermac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
180618334Speter    struct timespec atime, struct timespec mtime)
180718334Speter{
180818334Speter	int error;
180918334Speter
181018334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
181118334Speter
181218334Speter	if (!mac_enforce_fs)
181318334Speter		return (0);
181418334Speter
181518334Speter	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
181618334Speter	    mtime);
181718334Speter	return (error);
181818334Speter}
181918334Speter
182018334Speterint
182118334Spetermac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
182218334Speter    struct vnode *vp)
182318334Speter{
182418334Speter	int error;
182518334Speter
182618334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
182718334Speter
182818334Speter	if (!mac_enforce_fs)
182918334Speter		return (0);
183018334Speter
183118334Speter	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
183218334Speter	    &vp->v_label);
183318334Speter	return (error);
183418334Speter}
183518334Speter
183618334Speterint
183718334Spetermac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
183818334Speter    struct vnode *vp)
183918334Speter{
184018334Speter	int error;
184118334Speter
184218334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
184318334Speter
184418334Speter	if (!mac_enforce_fs)
184518334Speter		return (0);
184618334Speter
184718334Speter	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
184818334Speter	    &vp->v_label);
184918334Speter
185018334Speter	return (error);
185118334Speter}
185218334Speter
185318334Speter/*
185418334Speter * When relabeling a process, call out to the policies for the maximum
185518334Speter * permission allowed for each object type we know about in its
185618334Speter * memory space, and revoke access (in the least surprising ways we
185718334Speter * know) when necessary.  The process lock is not held here.
185818334Speter */
185918334Spetervoid
186018334Spetermac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
186118334Speter{
186218334Speter
186318334Speter	/* XXX freeze all other threads */
186418334Speter	mac_cred_mmapped_drop_perms_recurse(td, cred,
186518334Speter	    &td->td_proc->p_vmspace->vm_map);
186618334Speter	/* XXX allow other threads to continue */
186718334Speter}
186818334Speter
186918334Speterstatic __inline const char *
187018334Speterprot2str(vm_prot_t prot)
187190075Sobrien{
187218334Speter
187318334Speter	switch (prot & VM_PROT_ALL) {
187418334Speter	case VM_PROT_READ:
187518334Speter		return ("r--");
187618334Speter	case VM_PROT_READ | VM_PROT_WRITE:
187718334Speter		return ("rw-");
187818334Speter	case VM_PROT_READ | VM_PROT_EXECUTE:
187918334Speter		return ("r-x");
188018334Speter	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
188118334Speter		return ("rwx");
188218334Speter	case VM_PROT_WRITE:
188318334Speter		return ("-w-");
188418334Speter	case VM_PROT_EXECUTE:
188518334Speter		return ("--x");
188618334Speter	case VM_PROT_WRITE | VM_PROT_EXECUTE:
188718334Speter		return ("-wx");
188818334Speter	default:
188918334Speter		return ("---");
189018334Speter	}
189118334Speter}
189218334Speter
189318334Speterstatic void
189418334Spetermac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
189518334Speter    struct vm_map *map)
189618334Speter{
189718334Speter	struct vm_map_entry *vme;
189818334Speter	int result;
189918334Speter	vm_prot_t revokeperms;
190018334Speter	vm_object_t object;
190118334Speter	vm_ooffset_t offset;
190218334Speter	struct vnode *vp;
190318334Speter
190418334Speter	if (!mac_mmap_revocation)
190518334Speter		return;
190618334Speter
190718334Speter	vm_map_lock_read(map);
190818334Speter	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
190918334Speter		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
191018334Speter			mac_cred_mmapped_drop_perms_recurse(td, cred,
191118334Speter			    vme->object.sub_map);
191218334Speter			continue;
191318334Speter		}
191418334Speter		/*
191518334Speter		 * Skip over entries that obviously are not shared.
191618334Speter		 */
191718334Speter		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
191818334Speter		    !vme->max_protection)
191918334Speter			continue;
192050397Sobrien		/*
192118334Speter		 * Drill down to the deepest backing object.
192218334Speter		 */
192318334Speter		offset = vme->offset;
192418334Speter		object = vme->object.vm_object;
192518334Speter		if (object == NULL)
192618334Speter			continue;
192718334Speter		while (object->backing_object != NULL) {
192818334Speter			object = object->backing_object;
192918334Speter			offset += object->backing_object_offset;
193018334Speter		}
193118334Speter		/*
193218334Speter		 * At the moment, vm_maps and objects aren't considered
193318334Speter		 * by the MAC system, so only things with backing by a
193418334Speter		 * normal object (read: vnodes) are checked.
193518334Speter		 */
193618334Speter		if (object->type != OBJT_VNODE)
193718334Speter			continue;
193818334Speter		vp = (struct vnode *)object->handle;
193918334Speter		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
194018334Speter		result = vme->max_protection;
194118334Speter		mac_check_vnode_mmap_downgrade(cred, vp, &result);
194218334Speter		VOP_UNLOCK(vp, 0, td);
194318334Speter		/*
194418334Speter		 * Find out what maximum protection we may be allowing
194518334Speter		 * now but a policy needs to get removed.
194618334Speter		 */
194718334Speter		revokeperms = vme->max_protection & ~result;
194818334Speter		if (!revokeperms)
194918334Speter			continue;
195018334Speter		printf("pid %ld: revoking %s perms from %#lx:%ld "
195118334Speter		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
195290075Sobrien		    prot2str(revokeperms), (u_long)vme->start,
195318334Speter		    (long)(vme->end - vme->start),
195418334Speter		    prot2str(vme->max_protection), prot2str(vme->protection));
195518334Speter		vm_map_lock_upgrade(map);
195690075Sobrien		/*
195718334Speter		 * This is the really simple case: if a map has more
195818334Speter		 * max_protection than is allowed, but it's not being
195918334Speter		 * actually used (that is, the current protection is
196018334Speter		 * still allowed), we can just wipe it out and do
196118334Speter		 * nothing more.
196218334Speter		 */
196318334Speter		if ((vme->protection & revokeperms) == 0) {
196418334Speter			vme->max_protection -= revokeperms;
196518334Speter		} else {
196618334Speter			if (revokeperms & VM_PROT_WRITE) {
196718334Speter				/*
196818334Speter				 * In the more complicated case, flush out all
196918334Speter				 * pending changes to the object then turn it
197018334Speter				 * copy-on-write.
197118334Speter				 */
197218334Speter				vm_object_reference(object);
197318334Speter				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
197490075Sobrien				vm_object_page_clean(object,
197590075Sobrien				    OFF_TO_IDX(offset),
197618334Speter				    OFF_TO_IDX(offset + vme->end - vme->start +
197718334Speter					PAGE_MASK),
197818334Speter				    OBJPC_SYNC);
197918334Speter				VOP_UNLOCK(vp, 0, td);
198018334Speter				vm_object_deallocate(object);
198118334Speter				/*
198218334Speter				 * Why bother if there's no read permissions
198318334Speter				 * anymore?  For the rest, we need to leave
198418334Speter				 * the write permissions on for COW, or
198518334Speter				 * remove them entirely if configured to.
198618334Speter				 */
198718334Speter				if (!mac_mmap_revocation_via_cow) {
198890075Sobrien					vme->max_protection &= ~VM_PROT_WRITE;
198918334Speter					vme->protection &= ~VM_PROT_WRITE;
199018334Speter				} if ((revokeperms & VM_PROT_READ) == 0)
199190075Sobrien					vme->eflags |= MAP_ENTRY_COW |
199218334Speter					    MAP_ENTRY_NEEDS_COPY;
199318334Speter			}
199418334Speter			if (revokeperms & VM_PROT_EXECUTE) {
199518334Speter				vme->max_protection &= ~VM_PROT_EXECUTE;
199690075Sobrien				vme->protection &= ~VM_PROT_EXECUTE;
199790075Sobrien			}
199818334Speter			if (revokeperms & VM_PROT_READ) {
199918334Speter				vme->max_protection = 0;
200018334Speter				vme->protection = 0;
200118334Speter			}
200218334Speter			pmap_protect(map->pmap, vme->start, vme->end,
200318334Speter			    vme->protection & ~revokeperms);
200418334Speter			vm_map_simplify_entry(map, vme);
200518334Speter		}
200618334Speter		vm_map_lock_downgrade(map);
200718334Speter	}
200818334Speter	vm_map_unlock_read(map);
200918334Speter}
201018334Speter
201118334Speter/*
201218334Speter * When the subject's label changes, it may require revocation of privilege
201318334Speter * to mapped objects.  This can't be done on-the-fly later with a unified
201418334Speter * buffer cache.
201518334Speter */
201618334Speterstatic void
201718334Spetermac_relabel_cred(struct ucred *cred, struct label *newlabel)
201818334Speter{
201918334Speter
202090075Sobrien	MAC_PERFORM(relabel_cred, cred, newlabel);
202190075Sobrien}
202290075Sobrien
202390075Sobrienvoid
202418334Spetermac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
202590075Sobrien{
202618334Speter
202718334Speter	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
202818334Speter}
202918334Speter
203018334Spetervoid
203118334Spetermac_create_ifnet(struct ifnet *ifnet)
203218334Speter{
203318334Speter
203418334Speter	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
203518334Speter}
203618334Speter
203718334Spetervoid
203818334Spetermac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
203918334Speter{
204018334Speter
204118334Speter	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
204290075Sobrien}
204390075Sobrien
204490075Sobrienvoid
204590075Sobrienmac_create_socket(struct ucred *cred, struct socket *socket)
204690075Sobrien{
204790075Sobrien
204890075Sobrien	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
204990075Sobrien}
205090075Sobrien
205190075Sobrienvoid
205290075Sobrienmac_create_pipe(struct ucred *cred, struct pipe *pipe)
205390075Sobrien{
205490075Sobrien
205590075Sobrien	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
205690075Sobrien}
205790075Sobrien
205890075Sobrienvoid
205990075Sobrienmac_create_socket_from_socket(struct socket *oldsocket,
206018334Speter    struct socket *newsocket)
206118334Speter{
206218334Speter
206318334Speter	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
206418334Speter	    newsocket, &newsocket->so_label);
206518334Speter}
206618334Speter
206718334Speterstatic void
206818334Spetermac_relabel_socket(struct ucred *cred, struct socket *socket,
206918334Speter    struct label *newlabel)
207018334Speter{
207118334Speter
207218334Speter	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
207318334Speter}
207418334Speter
207518334Speterstatic void
207618334Spetermac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
207718334Speter{
207818334Speter
207918334Speter	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
208018334Speter}
208190075Sobrien
208218334Spetervoid
208318334Spetermac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
208418334Speter{
208518334Speter
208618334Speter	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
208718334Speter	    socket, &socket->so_peerlabel);
208818334Speter}
208918334Speter
209018334Spetervoid
209118334Spetermac_set_socket_peer_from_socket(struct socket *oldsocket,
209218334Speter    struct socket *newsocket)
209318334Speter{
209418334Speter
209518334Speter	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
209618334Speter	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
209718334Speter}
209818334Speter
209918334Spetervoid
210090075Sobrienmac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
210118334Speter{
210218334Speter
210318334Speter	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
210418334Speter	    datagram, &datagram->m_pkthdr.label);
210518334Speter}
210618334Speter
210718334Spetervoid
210818334Spetermac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
210918334Speter{
211018334Speter
211118334Speter	MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
211218334Speter	    fragment, &fragment->m_pkthdr.label);
211318334Speter}
211490075Sobrien
211518334Spetervoid
211618334Spetermac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
211790075Sobrien{
211818334Speter
211918334Speter	MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
212018334Speter	    &ipq->ipq_label);
212118334Speter}
212218334Speter
212318334Spetervoid
212418334Spetermac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
212518334Speter{
212618334Speter
212718334Speter	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
212818334Speter	    newmbuf, &newmbuf->m_pkthdr.label);
212918334Speter}
213018334Speter
213118334Spetervoid
213218334Spetermac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
213318334Speter{
213418334Speter
213518334Speter	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
213618334Speter	    &mbuf->m_pkthdr.label);
213718334Speter}
213818334Speter
213918334Spetervoid
214018334Spetermac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
214118334Speter{
214218334Speter
214318334Speter	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
214418334Speter	    &mbuf->m_pkthdr.label);
214518334Speter}
214618334Speter
214718334Spetervoid
214818334Spetermac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
214918334Speter{
215018334Speter
215118334Speter	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
215218334Speter	    &mbuf->m_pkthdr.label);
215318334Speter}
215418334Speter
215518334Spetervoid
215618334Spetermac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
215718334Speter    struct mbuf *newmbuf)
215818334Speter{
215918334Speter
216018334Speter	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
216118334Speter	    &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
216218334Speter	    &newmbuf->m_pkthdr.label);
216318334Speter}
216418334Speter
216518334Spetervoid
216618334Spetermac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
216718334Speter{
216818334Speter
216918334Speter	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
217018334Speter	    newmbuf, &newmbuf->m_pkthdr.label);
217118334Speter}
217218334Speter
217318334Speterint
217418334Spetermac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
217518334Speter{
217618334Speter	int result;
217718334Speter
217818334Speter	result = 1;
217918334Speter	MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
218018334Speter	    ipq, &ipq->ipq_label);
218118334Speter
218218334Speter	return (result);
218318334Speter}
218418334Speter
218518334Spetervoid
218618334Spetermac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
218718334Speter{
218818334Speter
218918334Speter	MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
219018334Speter	    &ipq->ipq_label);
219118334Speter}
219218334Speter
219318334Spetervoid
219418334Spetermac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
219518334Speter{
219618334Speter
219718334Speter	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
219890075Sobrien	    &mbuf->m_pkthdr.label);
219918334Speter}
220018334Speter
220118334Spetervoid
220218334Spetermac_create_mount(struct ucred *cred, struct mount *mp)
220318334Speter{
220418334Speter
220518334Speter	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
220618334Speter	    &mp->mnt_fslabel);
220750397Sobrien}
220850397Sobrien
220918334Spetervoid
221018334Spetermac_create_root_mount(struct ucred *cred, struct mount *mp)
221118334Speter{
221218334Speter
221390075Sobrien	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
221418334Speter	    &mp->mnt_fslabel);
221518334Speter}
221618334Speter
221718334Speterint
221818334Spetermac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
221918334Speter{
222018334Speter	int error;
222118334Speter
222218334Speter	if (!mac_enforce_network)
222318334Speter		return (0);
222418334Speter
222518334Speter	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
222618334Speter	    &ifnet->if_label);
222718334Speter
222818334Speter	return (error);
222918334Speter}
223018334Speter
223118334Speterstatic int
223218334Spetermac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
223318334Speter{
223418334Speter	int error;
223518334Speter
223618334Speter	MAC_CHECK(check_cred_relabel, cred, newlabel);
223718334Speter
223818334Speter	return (error);
223918334Speter}
224018334Speter
224118334Speterint
224218334Spetermac_check_cred_visible(struct ucred *u1, struct ucred *u2)
224318334Speter{
224418334Speter	int error;
224518334Speter
224618334Speter	if (!mac_enforce_process)
224718334Speter		return (0);
224818334Speter
224918334Speter	MAC_CHECK(check_cred_visible, u1, u2);
225018334Speter
225118334Speter	return (error);
225250397Sobrien}
225350397Sobrien
225418334Speterint
225518334Spetermac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
225618334Speter{
225718334Speter	int error;
225818334Speter
225918334Speter	if (!mac_enforce_network)
226018334Speter		return (0);
226118334Speter
226218334Speter	KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
226318334Speter	if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
226418334Speter		if_printf(ifnet, "not initialized\n");
226518334Speter
226618334Speter	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
226718334Speter	    &mbuf->m_pkthdr.label);
226890075Sobrien
226918334Speter	return (error);
227018334Speter}
227118334Speter
227218334Speterint
227318334Spetermac_check_kenv_dump(struct ucred *cred)
227450397Sobrien{
227518334Speter	int error;
227618334Speter
227718334Speter	if (!mac_enforce_system)
227818334Speter		return (0);
227918334Speter
228018334Speter	MAC_CHECK(check_kenv_dump, cred);
228118334Speter
228218334Speter	return (error);
228318334Speter}
228418334Speter
228518334Speterint
228618334Spetermac_check_kenv_get(struct ucred *cred, char *name)
228718334Speter{
228818334Speter	int error;
228918334Speter
229018334Speter	if (!mac_enforce_system)
229118334Speter		return (0);
229218334Speter
229318334Speter	MAC_CHECK(check_kenv_get, cred, name);
229418334Speter
229518334Speter	return (error);
229618334Speter}
229718334Speter
229818334Speterint
229918334Spetermac_check_kenv_set(struct ucred *cred, char *name, char *value)
230018334Speter{
230118334Speter	int error;
230218334Speter
230318334Speter	if (!mac_enforce_system)
230418334Speter		return (0);
230518334Speter
230618334Speter	MAC_CHECK(check_kenv_set, cred, name, value);
230718334Speter
230818334Speter	return (error);
230918334Speter}
231018334Speter
231118334Speterint
231218334Spetermac_check_kenv_unset(struct ucred *cred, char *name)
231318334Speter{
231418334Speter	int error;
231518334Speter
231618334Speter	if (!mac_enforce_system)
231718334Speter		return (0);
231818334Speter
231918334Speter	MAC_CHECK(check_kenv_unset, cred, name);
232018334Speter
232118334Speter	return (error);
232218334Speter}
232318334Speter
232490075Sobrienint
232518334Spetermac_check_kld_load(struct ucred *cred, struct vnode *vp)
232618334Speter{
232790075Sobrien	int error;
232890075Sobrien
232990075Sobrien	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
233090075Sobrien
233118334Speter	if (!mac_enforce_kld)
233218334Speter		return (0);
233318334Speter
233418334Speter	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
233518334Speter
233618334Speter	return (error);
233718334Speter}
233818334Speter
233918334Speterint
234018334Spetermac_check_kld_stat(struct ucred *cred)
234118334Speter{
234218334Speter	int error;
234318334Speter
234418334Speter	if (!mac_enforce_kld)
234552284Sobrien		return (0);
234618334Speter
234718334Speter	MAC_CHECK(check_kld_stat, cred);
234890075Sobrien
234918334Speter	return (error);
235018334Speter}
235118334Speter
235290075Sobrienint
235318334Spetermac_check_kld_unload(struct ucred *cred)
235418334Speter{
235518334Speter	int error;
235618334Speter
235790075Sobrien	if (!mac_enforce_kld)
235890075Sobrien		return (0);
235990075Sobrien
236018334Speter	MAC_CHECK(check_kld_unload, cred);
236190075Sobrien
236290075Sobrien	return (error);
236318334Speter}
236418334Speter
236518334Speterint
236690075Sobrienmac_check_mount_stat(struct ucred *cred, struct mount *mount)
236790075Sobrien{
236890075Sobrien	int error;
236990075Sobrien
237090075Sobrien	if (!mac_enforce_fs)
237190075Sobrien		return (0);
237290075Sobrien
237390075Sobrien	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
237490075Sobrien
237590075Sobrien	return (error);
237690075Sobrien}
237790075Sobrien
237890075Sobrienint
237990075Sobrienmac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
238090075Sobrien    void *data)
238190075Sobrien{
238218334Speter	int error;
238318334Speter
238418334Speter	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
238518334Speter
238618334Speter	if (!mac_enforce_pipe)
238718334Speter		return (0);
238818334Speter
238918334Speter	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
239018334Speter
239118334Speter	return (error);
239218334Speter}
239318334Speter
239418334Speterint
239590075Sobrienmac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
239690075Sobrien{
239718334Speter	int error;
239818334Speter
239918334Speter	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
240018334Speter
240118334Speter	if (!mac_enforce_pipe)
240218334Speter		return (0);
240350397Sobrien
240450397Sobrien	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
240550397Sobrien
240650397Sobrien	return (error);
240750397Sobrien}
240850397Sobrien
240950397Sobrienint
241018334Spetermac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
241118334Speter{
241218334Speter	int error;
241318334Speter
241418334Speter	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
241518334Speter
241618334Speter	if (!mac_enforce_pipe)
241718334Speter		return (0);
241818334Speter
241918334Speter	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
242018334Speter
242118334Speter	return (error);
242218334Speter}
242390075Sobrien
242490075Sobrienstatic int
242518334Spetermac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
242618334Speter    struct label *newlabel)
242718334Speter{
242890075Sobrien	int error;
242990075Sobrien
243018334Speter	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
243190075Sobrien
243290075Sobrien	if (!mac_enforce_pipe)
243318334Speter		return (0);
243418334Speter
243518334Speter	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
243618334Speter
243718334Speter	return (error);
243818334Speter}
243918334Speter
244018334Speterint
244118334Spetermac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
244218334Speter{
244318334Speter	int error;
244418334Speter
244518334Speter	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
244618334Speter
244718334Speter	if (!mac_enforce_pipe)
244818334Speter		return (0);
244918334Speter
245018334Speter	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
245118334Speter
245218334Speter	return (error);
245318334Speter}
245418334Speter
245518334Speterint
245618334Spetermac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
245718334Speter{
245890075Sobrien	int error;
245918334Speter
246018334Speter	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
246118334Speter
246290075Sobrien	if (!mac_enforce_pipe)
246318334Speter		return (0);
246418334Speter
246518334Speter	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
246618334Speter
246718334Speter	return (error);
246818334Speter}
246918334Speter
247018334Speterint
247118334Spetermac_check_proc_debug(struct ucred *cred, struct proc *proc)
247218334Speter{
247318334Speter	int error;
247418334Speter
247518334Speter	PROC_LOCK_ASSERT(proc, MA_OWNED);
247618334Speter
247718334Speter	if (!mac_enforce_process)
247818334Speter		return (0);
247918334Speter
248018334Speter	MAC_CHECK(check_proc_debug, cred, proc);
248118334Speter
248218334Speter	return (error);
248318334Speter}
248418334Speter
248590075Sobrienint
248690075Sobrienmac_check_proc_sched(struct ucred *cred, struct proc *proc)
248790075Sobrien{
248890075Sobrien	int error;
248990075Sobrien
249018334Speter	PROC_LOCK_ASSERT(proc, MA_OWNED);
249190075Sobrien
249290075Sobrien	if (!mac_enforce_process)
249318334Speter		return (0);
249418334Speter
249518334Speter	MAC_CHECK(check_proc_sched, cred, proc);
249618334Speter
249718334Speter	return (error);
249818334Speter}
249918334Speter
250018334Speterint
250118334Spetermac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
250218334Speter{
250318334Speter	int error;
250418334Speter
250518334Speter	PROC_LOCK_ASSERT(proc, MA_OWNED);
250690075Sobrien
250718334Speter	if (!mac_enforce_process)
250818334Speter		return (0);
250990075Sobrien
251018334Speter	MAC_CHECK(check_proc_signal, cred, proc, signum);
251118334Speter
251218334Speter	return (error);
251318334Speter}
251418334Speter
251518334Speterint
251690075Sobrienmac_check_socket_bind(struct ucred *ucred, struct socket *socket,
251790075Sobrien    struct sockaddr *sockaddr)
251818334Speter{
251918334Speter	int error;
252090075Sobrien
252190075Sobrien	if (!mac_enforce_socket)
252218334Speter		return (0);
252318334Speter
252418334Speter	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
252518334Speter	    sockaddr);
252618334Speter
252718334Speter	return (error);
252818334Speter}
252918334Speter
253018334Speterint
253118334Spetermac_check_socket_connect(struct ucred *cred, struct socket *socket,
253218334Speter    struct sockaddr *sockaddr)
253318334Speter{
253418334Speter	int error;
253518334Speter
253618334Speter	if (!mac_enforce_socket)
253790075Sobrien		return (0);
253890075Sobrien
253918334Speter	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
254018334Speter	    sockaddr);
254118334Speter
254218334Speter	return (error);
254318334Speter}
254418334Speter
254518334Speterint
254618334Spetermac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
254718334Speter{
254818334Speter	int error;
254918334Speter
255018334Speter	if (!mac_enforce_socket)
255118334Speter		return (0);
255218334Speter
255318334Speter	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
255418334Speter	    &mbuf->m_pkthdr.label);
255518334Speter
255618334Speter	return (error);
255718334Speter}
255818334Speter
255918334Speterint
256018334Spetermac_check_socket_listen(struct ucred *cred, struct socket *socket)
256118334Speter{
256218334Speter	int error;
256318334Speter
256490075Sobrien	if (!mac_enforce_socket)
256590075Sobrien		return (0);
256618334Speter
256718334Speter	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
256818334Speter	return (error);
256918334Speter}
257018334Speter
257118334Speterint
257218334Spetermac_check_socket_receive(struct ucred *cred, struct socket *so)
257318334Speter{
257418334Speter	int error;
257518334Speter
257618334Speter	if (!mac_enforce_socket)
257718334Speter		return (0);
257818334Speter
257918334Speter	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
258018334Speter
258118334Speter	return (error);
258218334Speter}
258318334Speter
258418334Speterstatic int
258518334Spetermac_check_socket_relabel(struct ucred *cred, struct socket *socket,
258618334Speter    struct label *newlabel)
258718334Speter{
258818334Speter	int error;
258990075Sobrien
259018334Speter	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
259118334Speter	    newlabel);
259218334Speter
259318334Speter	return (error);
259418334Speter}
259518334Speter
259618334Speterint
259718334Spetermac_check_socket_send(struct ucred *cred, struct socket *so)
259818334Speter{
259990075Sobrien	int error;
260018334Speter
260118334Speter	if (!mac_enforce_socket)
260218334Speter		return (0);
260318334Speter
260418334Speter	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
260590075Sobrien
260618334Speter	return (error);
260718334Speter}
260818334Speter
260918334Speterint
261018334Spetermac_check_socket_visible(struct ucred *cred, struct socket *socket)
261118334Speter{
261218334Speter	int error;
261318334Speter
261418334Speter	if (!mac_enforce_socket)
261590075Sobrien		return (0);
261618334Speter
261790075Sobrien	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
261818334Speter
261918334Speter	return (error);
262018334Speter}
262118334Speter
262218334Speterint
262318334Spetermac_check_system_acct(struct ucred *cred, struct vnode *vp)
262418334Speter{
262518334Speter	int error;
262618334Speter
262718334Speter	if (vp != NULL) {
262818334Speter		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
262918334Speter	}
263018334Speter
263118334Speter	if (!mac_enforce_system)
263218334Speter		return (0);
263318334Speter
263418334Speter	MAC_CHECK(check_system_acct, cred, vp,
263518334Speter	    vp != NULL ? &vp->v_label : NULL);
263618334Speter
263718334Speter	return (error);
263818334Speter}
263918334Speter
264018334Speterint
264118334Spetermac_check_system_nfsd(struct ucred *cred)
264218334Speter{
264318334Speter	int error;
264418334Speter
264518334Speter	if (!mac_enforce_system)
264618334Speter		return (0);
264718334Speter
264818334Speter	MAC_CHECK(check_system_nfsd, cred);
264918334Speter
265018334Speter	return (error);
265118334Speter}
265218334Speter
265318334Speterint
265418334Spetermac_check_system_reboot(struct ucred *cred, int howto)
265518334Speter{
265618334Speter	int error;
265718334Speter
265818334Speter	if (!mac_enforce_system)
265990075Sobrien		return (0);
266090075Sobrien
266118334Speter	MAC_CHECK(check_system_reboot, cred, howto);
266218334Speter
266318334Speter	return (error);
266418334Speter}
266518334Speter
266618334Speterint
266750397Sobrienmac_check_system_settime(struct ucred *cred)
266850397Sobrien{
266950397Sobrien	int error;
267050397Sobrien
267118334Speter	if (!mac_enforce_system)
267218334Speter		return (0);
267318334Speter
267418334Speter	MAC_CHECK(check_system_settime, cred);
267590075Sobrien
267618334Speter	return (error);
267718334Speter}
267890075Sobrien
267918334Speterint
268018334Spetermac_check_system_swapon(struct ucred *cred, struct vnode *vp)
268118334Speter{
268218334Speter	int error;
268318334Speter
268418334Speter	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
268518334Speter
268618334Speter	if (!mac_enforce_system)
268718334Speter		return (0);
268818334Speter
268918334Speter	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
269018334Speter	return (error);
269118334Speter}
269218334Speter
269318334Speterint
269418334Spetermac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
269518334Speter    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
269618334Speter{
269718334Speter	int error;
269818334Speter
269918334Speter	/*
270018334Speter	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
270118334Speter	 * but since it's not exported from kern_sysctl.c, we can't.
270218334Speter	 */
270318334Speter	if (!mac_enforce_system)
270418334Speter		return (0);
270518334Speter
270618334Speter	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
270718334Speter	    inkernel, new, newlen);
270818334Speter
270918334Speter	return (error);
271018334Speter}
271118334Speter
271218334Speterint
271318334Spetermac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
271418334Speter    struct ifnet *ifnet)
271518334Speter{
271618334Speter	char *elements, *buffer;
271718334Speter	struct mac mac;
271818334Speter	int error;
271918334Speter
272018334Speter	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
272118334Speter	if (error)
272218334Speter		return (error);
272318334Speter
272418334Speter	error = mac_check_structmac_consistent(&mac);
272518334Speter	if (error)
272618334Speter		return (error);
272718334Speter
272818334Speter	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
272918334Speter	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
273018334Speter	if (error) {
273118334Speter		free(elements, M_MACTEMP);
273218334Speter		return (error);
273318334Speter	}
273418334Speter
273518334Speter	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
273618334Speter	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
273718334Speter	    buffer, mac.m_buflen, M_WAITOK);
273818334Speter	if (error == 0)
273918334Speter		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
274018334Speter
274118334Speter	free(buffer, M_MACTEMP);
274296263Sobrien	free(elements, M_MACTEMP);
274318334Speter
274418334Speter	return (error);
274518334Speter}
274618334Speter
274796263Sobrienint
274896263Sobrienmac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
274996263Sobrien    struct ifnet *ifnet)
275096263Sobrien{
275196263Sobrien	struct label intlabel;
275296263Sobrien	struct mac mac;
275396263Sobrien	char *buffer;
275490075Sobrien	int error;
275590075Sobrien
275618334Speter	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
275718334Speter	if (error)
275818334Speter		return (error);
275918334Speter
276018334Speter	error = mac_check_structmac_consistent(&mac);
276118334Speter	if (error)
276218334Speter		return (error);
276318334Speter
276418334Speter	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
276518334Speter	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
276618334Speter	if (error) {
276718334Speter		free(buffer, M_MACTEMP);
276818334Speter		return (error);
276918334Speter	}
277018334Speter
277118334Speter	mac_init_ifnet_label(&intlabel);
277218334Speter	error = mac_internalize_ifnet_label(&intlabel, buffer);
277318334Speter	free(buffer, M_MACTEMP);
277418334Speter	if (error) {
277518334Speter		mac_destroy_ifnet_label(&intlabel);
277618334Speter		return (error);
277718334Speter	}
277818334Speter
277918334Speter	/*
278018334Speter	 * XXX: Note that this is a redundant privilege check, since
278118334Speter	 * policies impose this check themselves if required by the
278218334Speter	 * policy.  Eventually, this should go away.
278318334Speter	 */
278418334Speter	error = suser_cred(cred, 0);
278518334Speter	if (error) {
278618334Speter		mac_destroy_ifnet_label(&intlabel);
278718334Speter		return (error);
278818334Speter	}
278950397Sobrien
279018334Speter	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
279118334Speter	    &intlabel);
279218334Speter	if (error) {
279318334Speter		mac_destroy_ifnet_label(&intlabel);
279418334Speter		return (error);
279518334Speter	}
279618334Speter
279750397Sobrien	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
279850397Sobrien
279918334Speter	mac_destroy_ifnet_label(&intlabel);
280018334Speter	return (0);
280150397Sobrien}
280250397Sobrien
280318334Spetervoid
280418334Spetermac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
280518334Speter{
280618334Speter
280718334Speter	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
280818334Speter}
280918334Speter
281052284Sobrienvoid
281118334Spetermac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
281218334Speter    struct devfs_dirent *de)
281390075Sobrien{
281490075Sobrien
281518334Speter	MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
281690075Sobrien	    &de->de_label);
281790075Sobrien}
281890075Sobrien
281990075Sobrienvoid
282090075Sobrienmac_create_devfs_directory(char *dirname, int dirnamelen,
282190075Sobrien    struct devfs_dirent *de)
282290075Sobrien{
282390075Sobrien
282418334Speter	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
282518334Speter	    &de->de_label);
282618334Speter}
282718334Speter
282818334Speterint
282918334Spetermac_setsockopt_label_set(struct ucred *cred, struct socket *so,
283050397Sobrien    struct mac *mac)
283150397Sobrien{
283250397Sobrien	struct label intlabel;
283318334Speter	char *buffer;
283418334Speter	int error;
283518334Speter
283618334Speter	error = mac_check_structmac_consistent(mac);
283718334Speter	if (error)
283818334Speter		return (error);
283918334Speter
284018334Speter	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
284118334Speter	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
284218334Speter	if (error) {
284318334Speter		free(buffer, M_MACTEMP);
284418334Speter		return (error);
284518334Speter	}
284618334Speter
284718334Speter	mac_init_socket_label(&intlabel, M_WAITOK);
284818334Speter	error = mac_internalize_socket_label(&intlabel, buffer);
284918334Speter	free(buffer, M_MACTEMP);
285018334Speter	if (error) {
285118334Speter		mac_destroy_socket_label(&intlabel);
285218334Speter		return (error);
285318334Speter	}
285418334Speter
285518334Speter	mac_check_socket_relabel(cred, so, &intlabel);
285618334Speter	if (error) {
285718334Speter		mac_destroy_socket_label(&intlabel);
285818334Speter		return (error);
285918334Speter	}
286018334Speter
286118334Speter	mac_relabel_socket(cred, so, &intlabel);
286218334Speter
286318334Speter	mac_destroy_socket_label(&intlabel);
286418334Speter	return (0);
286518334Speter}
286618334Speter
286718334Speterint
286818334Spetermac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
286970635Sobrien{
287018334Speter	int error;
287118334Speter
287270635Sobrien	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
287370635Sobrien
287470635Sobrien	error = mac_check_pipe_relabel(cred, pipe, label);
287570635Sobrien	if (error)
287690075Sobrien		return (error);
287790075Sobrien
287890075Sobrien	mac_relabel_pipe(cred, pipe, label);
287990075Sobrien
288090075Sobrien	return (0);
288190075Sobrien}
288290075Sobrien
288390075Sobrienint
288490075Sobrienmac_getsockopt_label_get(struct ucred *cred, struct socket *so,
288590075Sobrien    struct mac *mac)
288690075Sobrien{
288790075Sobrien	char *buffer, *elements;
288890075Sobrien	int error;
288990075Sobrien
289090075Sobrien	error = mac_check_structmac_consistent(mac);
289152284Sobrien	if (error)
289290075Sobrien		return (error);
289390075Sobrien
289490075Sobrien	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
289590075Sobrien	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
289652284Sobrien	if (error) {
289790075Sobrien		free(elements, M_MACTEMP);
289890075Sobrien		return (error);
289990075Sobrien	}
290090075Sobrien
290190075Sobrien	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
290290075Sobrien	error = mac_externalize_socket_label(&so->so_label, elements,
290390075Sobrien	    buffer, mac->m_buflen, M_WAITOK);
290490075Sobrien	if (error == 0)
290590075Sobrien		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
290652284Sobrien
290718334Speter	free(buffer, M_MACTEMP);
290818334Speter	free(elements, M_MACTEMP);
290918334Speter
291018334Speter	return (error);
291118334Speter}
291218334Speter
291318334Speterint
291418334Spetermac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
291518334Speter    struct mac *mac)
291696263Sobrien{
291718334Speter	char *elements, *buffer;
291896263Sobrien	int error;
291996263Sobrien
292096263Sobrien	error = mac_check_structmac_consistent(mac);
292196263Sobrien	if (error)
292296263Sobrien		return (error);
292396263Sobrien
292496263Sobrien	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
292518334Speter	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
292618334Speter	if (error) {
292718334Speter		free(elements, M_MACTEMP);
292818334Speter		return (error);
292918334Speter	}
293090075Sobrien
293190075Sobrien	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
293218334Speter	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
293318334Speter	    elements, buffer, mac->m_buflen, M_WAITOK);
293418334Speter	if (error == 0)
293518334Speter		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
293618334Speter
293718334Speter	free(buffer, M_MACTEMP);
293818334Speter	free(elements, M_MACTEMP);
293918334Speter
294018334Speter	return (error);
294118334Speter}
294218334Speter
294318334Speter/*
294418334Speter * Implementation of VOP_SETLABEL() that relies on extended attributes
294518334Speter * to store label data.  Can be referenced by filesystems supporting
294618334Speter * extended attributes.
294718334Speter */
294818334Speterint
294918334Spetervop_stdsetlabel_ea(struct vop_setlabel_args *ap)
295018334Speter{
295118334Speter	struct vnode *vp = ap->a_vp;
295218334Speter	struct label *intlabel = ap->a_label;
295318334Speter	int error;
295418334Speter
295518334Speter	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
295618334Speter
295718334Speter	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
295818334Speter		return (EOPNOTSUPP);
295918334Speter
296050397Sobrien	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
296150397Sobrien	if (error)
296252284Sobrien		return (error);
296390075Sobrien
296490075Sobrien	mac_relabel_vnode(ap->a_cred, vp, intlabel);
296590075Sobrien
296690075Sobrien	return (0);
296790075Sobrien}
296890075Sobrien
296990075Sobrienstatic int
297090075Sobrienvn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
297190075Sobrien{
297218334Speter	int error;
297370635Sobrien
297470635Sobrien	if (vp->v_mount == NULL) {
297570635Sobrien		/* printf("vn_setlabel: null v_mount\n"); */
297618334Speter		if (vp->v_type != VNON)
297718334Speter			printf("vn_setlabel: null v_mount with non-VNON\n");
297818334Speter		return (EBADF);
297918334Speter	}
298018334Speter
298118334Speter	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
298290075Sobrien		return (EOPNOTSUPP);
298390075Sobrien
298490075Sobrien	/*
298590075Sobrien	 * Multi-phase commit.  First check the policies to confirm the
298690075Sobrien	 * change is OK.  Then commit via the filesystem.  Finally,
298790075Sobrien	 * update the actual vnode label.  Question: maybe the filesystem
298890075Sobrien	 * should update the vnode at the end as part of VOP_SETLABEL()?
298918334Speter	 */
299018334Speter	error = mac_check_vnode_relabel(cred, vp, intlabel);
299118334Speter	if (error)
299218334Speter		return (error);
299318334Speter
299418334Speter	/*
299518334Speter	 * VADMIN provides the opportunity for the filesystem to make
299618334Speter	 * decisions about who is and is not able to modify labels
299718334Speter	 * and protections on files.  This might not be right.  We can't
299818334Speter	 * assume VOP_SETLABEL() will do it, because we might implement
299918334Speter	 * that as part of vop_stdsetlabel_ea().
300018334Speter	 */
300118334Speter	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
300218334Speter	if (error)
300318334Speter		return (error);
300418334Speter
300518334Speter	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
300618334Speter	if (error)
300718334Speter		return (error);
300818334Speter
300918334Speter	return (0);
301090075Sobrien}
301190075Sobrien
301290075Sobrienint
301318334Speter__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
301490075Sobrien{
301590075Sobrien	char *elements, *buffer;
301690075Sobrien	struct mac mac;
301790075Sobrien	struct proc *tproc;
301890075Sobrien	struct ucred *tcred;
301990075Sobrien	int error;
302090075Sobrien
302190075Sobrien	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
302290075Sobrien	if (error)
302390075Sobrien		return (error);
302490075Sobrien
302590075Sobrien	error = mac_check_structmac_consistent(&mac);
302690075Sobrien	if (error)
302790075Sobrien		return (error);
302890075Sobrien
302990075Sobrien	tproc = pfind(uap->pid);
303090075Sobrien	if (tproc == NULL)
303190075Sobrien		return (ESRCH);
303290075Sobrien
303390075Sobrien	tcred = NULL;				/* Satisfy gcc. */
303490075Sobrien	error = p_cansee(td, tproc);
303590075Sobrien	if (error == 0)
303690075Sobrien		tcred = crhold(tproc->p_ucred);
303790075Sobrien	PROC_UNLOCK(tproc);
303890075Sobrien	if (error)
303990075Sobrien		return (error);
304090075Sobrien
304190075Sobrien	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
304290075Sobrien	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
304390075Sobrien	if (error) {
304490075Sobrien		free(elements, M_MACTEMP);
304590075Sobrien		crfree(tcred);
304690075Sobrien		return (error);
304790075Sobrien	}
304890075Sobrien
304990075Sobrien	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
305090075Sobrien	error = mac_externalize_cred_label(&tcred->cr_label, elements,
305190075Sobrien	    buffer, mac.m_buflen, M_WAITOK);
305290075Sobrien	if (error == 0)
305390075Sobrien		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
305490075Sobrien
305590075Sobrien	free(buffer, M_MACTEMP);
305690075Sobrien	free(elements, M_MACTEMP);
305790075Sobrien	crfree(tcred);
305818334Speter	return (error);
305918334Speter}
306090075Sobrien
306118334Speter/*
306290075Sobrien * MPSAFE
306390075Sobrien */
306490075Sobrienint
306590075Sobrien__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
306690075Sobrien{
306790075Sobrien	char *elements, *buffer;
306818334Speter	struct mac mac;
306990075Sobrien	int error;
307090075Sobrien
307190075Sobrien	error = copyin(uap->mac_p, &mac, sizeof(mac));
307290075Sobrien	if (error)
307318334Speter		return (error);
307490075Sobrien
307590075Sobrien	error = mac_check_structmac_consistent(&mac);
307690075Sobrien	if (error)
307718334Speter		return (error);
307890075Sobrien
307990075Sobrien	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
308090075Sobrien	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
308118334Speter	if (error) {
308218334Speter		free(elements, M_MACTEMP);
308318334Speter		return (error);
308418334Speter	}
308518334Speter
308618334Speter	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
308718334Speter	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
308818334Speter	    elements, buffer, mac.m_buflen, M_WAITOK);
308918334Speter	if (error == 0)
309018334Speter		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
309118334Speter
309218334Speter	free(buffer, M_MACTEMP);
309318334Speter	free(elements, M_MACTEMP);
309418334Speter	return (error);
309518334Speter}
309618334Speter
309718334Speter/*
309890075Sobrien * MPSAFE
309990075Sobrien */
310018334Speterint
310118334Speter__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
310290075Sobrien{
310390075Sobrien	struct ucred *newcred, *oldcred;
310418334Speter	struct label intlabel;
310518334Speter	struct proc *p;
310652284Sobrien	struct mac mac;
310752284Sobrien	char *buffer;
310852284Sobrien	int error;
310952284Sobrien
311052284Sobrien	error = copyin(uap->mac_p, &mac, sizeof(mac));
311152284Sobrien	if (error)
311252284Sobrien		return (error);
311352284Sobrien
311418334Speter	error = mac_check_structmac_consistent(&mac);
311518334Speter	if (error)
311618334Speter		return (error);
311718334Speter
311818334Speter	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
311918334Speter	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
312018334Speter	if (error) {
312118334Speter		free(buffer, M_MACTEMP);
312290075Sobrien		return (error);
312390075Sobrien	}
312490075Sobrien
312590075Sobrien	mac_init_cred_label(&intlabel);
312690075Sobrien	error = mac_internalize_cred_label(&intlabel, buffer);
312718334Speter	free(buffer, M_MACTEMP);
312818334Speter	if (error) {
312918334Speter		mac_destroy_cred_label(&intlabel);
313018334Speter		return (error);
313118334Speter	}
313218334Speter
313318334Speter	newcred = crget();
313418334Speter
313518334Speter	p = td->td_proc;
313618334Speter	PROC_LOCK(p);
313718334Speter	oldcred = p->p_ucred;
313890075Sobrien
313990075Sobrien	error = mac_check_cred_relabel(oldcred, &intlabel);
314090075Sobrien	if (error) {
314118334Speter		PROC_UNLOCK(p);
314218334Speter		crfree(newcred);
314318334Speter		goto out;
314418334Speter	}
314518334Speter
314618334Speter	setsugid(p);
314718334Speter	crcopy(newcred, oldcred);
314818334Speter	mac_relabel_cred(newcred, &intlabel);
314990075Sobrien	p->p_ucred = newcred;
315090075Sobrien
315190075Sobrien	/*
315218334Speter	 * Grab additional reference for use while revoking mmaps, prior
315318334Speter	 * to releasing the proc lock and sharing the cred.
315418334Speter	 */
315518334Speter	crhold(newcred);
315618334Speter	PROC_UNLOCK(p);
315718334Speter
315890075Sobrien	if (mac_enforce_vm) {
315990075Sobrien		mtx_lock(&Giant);
316018334Speter		mac_cred_mmapped_drop_perms(td, newcred);
316118334Speter		mtx_unlock(&Giant);
316218334Speter	}
316390075Sobrien
316418334Speter	crfree(newcred);	/* Free revocation reference. */
316518334Speter	crfree(oldcred);
316618334Speter
316718334Speterout:
316818334Speter	mac_destroy_cred_label(&intlabel);
316990075Sobrien	return (error);
317018334Speter}
317118334Speter
317250397Sobrien/*
317350397Sobrien * MPSAFE
317450397Sobrien */
317518334Speterint
317690075Sobrien__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
317718334Speter{
317818334Speter	char *elements, *buffer;
317950397Sobrien	struct label intlabel;
318050397Sobrien	struct file *fp;
318150397Sobrien	struct mac mac;
318250397Sobrien	struct vnode *vp;
318318334Speter	struct pipe *pipe;
318450397Sobrien	short label_type;
318550397Sobrien	int error;
318650397Sobrien
318750397Sobrien	error = copyin(uap->mac_p, &mac, sizeof(mac));
318850397Sobrien	if (error)
318990075Sobrien		return (error);
319050397Sobrien
319190075Sobrien	error = mac_check_structmac_consistent(&mac);
319218334Speter	if (error)
319390075Sobrien		return (error);
319490075Sobrien
319590075Sobrien	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
319618334Speter	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
319718334Speter	if (error) {
319818334Speter		free(elements, M_MACTEMP);
319990075Sobrien		return (error);
320090075Sobrien	}
320190075Sobrien
320290075Sobrien	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
320318334Speter	mtx_lock(&Giant);				/* VFS */
320418334Speter	error = fget(td, SCARG(uap, fd), &fp);
320518334Speter	if (error)
320690075Sobrien		goto out;
320718334Speter
320818334Speter	label_type = fp->f_type;
320950397Sobrien	switch (fp->f_type) {
321050397Sobrien	case DTYPE_FIFO:
321118334Speter	case DTYPE_VNODE:
321218334Speter		vp = (struct vnode *)fp->f_data;
321318334Speter
321418334Speter		mac_init_vnode_label(&intlabel);
321518334Speter
321690075Sobrien		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
321790075Sobrien		mac_copy_vnode_label(&vp->v_label, &intlabel);
321818334Speter		VOP_UNLOCK(vp, 0, td);
321950397Sobrien
322050397Sobrien		break;
322150397Sobrien	case DTYPE_PIPE:
322250397Sobrien		pipe = (struct pipe *)fp->f_data;
322350397Sobrien
322450397Sobrien		mac_init_pipe_label(&intlabel);
322518334Speter
322618334Speter		PIPE_LOCK(pipe);
322718334Speter		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
322890075Sobrien		PIPE_UNLOCK(pipe);
322990075Sobrien		break;
323090075Sobrien	default:
323118334Speter		error = EINVAL;
323218334Speter		fdrop(fp, td);
323318334Speter		goto out;
323418334Speter	}
323590075Sobrien	fdrop(fp, td);
323618334Speter
323718334Speter	switch (label_type) {
323818334Speter	case DTYPE_FIFO:
323918334Speter	case DTYPE_VNODE:
324018334Speter		if (error == 0)
324190075Sobrien			error = mac_externalize_vnode_label(&intlabel,
324290075Sobrien			    elements, buffer, mac.m_buflen, M_WAITOK);
324390075Sobrien		mac_destroy_vnode_label(&intlabel);
324490075Sobrien		break;
324590075Sobrien	case DTYPE_PIPE:
324690075Sobrien		error = mac_externalize_pipe_label(&intlabel, elements,
324790075Sobrien		    buffer, mac.m_buflen, M_WAITOK);
324890075Sobrien		mac_destroy_pipe_label(&intlabel);
324990075Sobrien		break;
325090075Sobrien	default:
325190075Sobrien		panic("__mac_get_fd: corrupted label_type");
325290075Sobrien	}
325390075Sobrien
325490075Sobrien	if (error == 0)
325590075Sobrien		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
325690075Sobrien
325790075Sobrienout:
325890075Sobrien	mtx_unlock(&Giant);				/* VFS */
325990075Sobrien	free(buffer, M_MACTEMP);
326090075Sobrien	free(elements, M_MACTEMP);
326190075Sobrien
326290075Sobrien	return (error);
326390075Sobrien}
326490075Sobrien
326590075Sobrien/*
326690075Sobrien * MPSAFE
326790075Sobrien */
326890075Sobrienint
326990075Sobrien__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
327090075Sobrien{
327190075Sobrien	char *elements, *buffer;
327290075Sobrien	struct nameidata nd;
327390075Sobrien	struct label intlabel;
327490075Sobrien	struct mac mac;
327590075Sobrien	int error;
327690075Sobrien
327790075Sobrien	error = copyin(uap->mac_p, &mac, sizeof(mac));
327890075Sobrien	if (error)
327990075Sobrien		return (error);
328090075Sobrien
328190075Sobrien	error = mac_check_structmac_consistent(&mac);
328290075Sobrien	if (error)
328390075Sobrien		return (error);
328490075Sobrien
328590075Sobrien	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
328690075Sobrien	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
328790075Sobrien	if (error) {
328890075Sobrien		free(elements, M_MACTEMP);
328990075Sobrien		return (error);
329090075Sobrien	}
329190075Sobrien
329290075Sobrien	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
329390075Sobrien	mtx_lock(&Giant);				/* VFS */
329490075Sobrien	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
329590075Sobrien	    td);
329690075Sobrien	error = namei(&nd);
329790075Sobrien	if (error)
329890075Sobrien		goto out;
329990075Sobrien
330090075Sobrien	mac_init_vnode_label(&intlabel);
330190075Sobrien	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
330290075Sobrien	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
330390075Sobrien	    mac.m_buflen, M_WAITOK);
330490075Sobrien
330590075Sobrien	NDFREE(&nd, 0);
330690075Sobrien	mac_destroy_vnode_label(&intlabel);
330790075Sobrien
330890075Sobrien	if (error == 0)
330990075Sobrien		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
331090075Sobrien
331190075Sobrienout:
331290075Sobrien	mtx_unlock(&Giant);				/* VFS */
331390075Sobrien
331490075Sobrien	free(buffer, M_MACTEMP);
331590075Sobrien	free(elements, M_MACTEMP);
331690075Sobrien
331790075Sobrien	return (error);
331890075Sobrien}
331990075Sobrien
332090075Sobrien/*
332190075Sobrien * MPSAFE
332290075Sobrien */
332390075Sobrienint
332490075Sobrien__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
332590075Sobrien{
332690075Sobrien	char *elements, *buffer;
332790075Sobrien	struct nameidata nd;
332890075Sobrien	struct label intlabel;
332990075Sobrien	struct mac mac;
333090075Sobrien	int error;
333190075Sobrien
333290075Sobrien	error = copyin(uap->mac_p, &mac, sizeof(mac));
333390075Sobrien	if (error)
333490075Sobrien		return (error);
333590075Sobrien
333652284Sobrien	error = mac_check_structmac_consistent(&mac);
333752284Sobrien	if (error)
333852284Sobrien		return (error);
333952284Sobrien
334052284Sobrien	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
334152284Sobrien	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
334252284Sobrien	if (error) {
334352284Sobrien		free(elements, M_MACTEMP);
334452284Sobrien		return (error);
334590075Sobrien	}
334652284Sobrien
334752284Sobrien	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
334852284Sobrien	mtx_lock(&Giant);				/* VFS */
334952284Sobrien	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
335052284Sobrien	    td);
335152284Sobrien	error = namei(&nd);
335252284Sobrien	if (error)
335352284Sobrien		goto out;
335490075Sobrien
335552284Sobrien	mac_init_vnode_label(&intlabel);
335652284Sobrien	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
335752284Sobrien	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
335852284Sobrien	    mac.m_buflen, M_WAITOK);
335952284Sobrien	NDFREE(&nd, 0);
336052284Sobrien	mac_destroy_vnode_label(&intlabel);
336152284Sobrien
336290075Sobrien	if (error == 0)
336390075Sobrien		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
336490075Sobrien
336590075Sobrienout:
336652284Sobrien	mtx_unlock(&Giant);				/* VFS */
336790075Sobrien
336890075Sobrien	free(buffer, M_MACTEMP);
336990075Sobrien	free(elements, M_MACTEMP);
337090075Sobrien
337190075Sobrien	return (error);
337290075Sobrien}
337352284Sobrien
337452284Sobrien/*
337552284Sobrien * MPSAFE
337652284Sobrien */
337752284Sobrienint
337852284Sobrien__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
337952284Sobrien{
338052284Sobrien	struct label intlabel;
338152284Sobrien	struct pipe *pipe;
338252284Sobrien	struct file *fp;
338352284Sobrien	struct mount *mp;
338490075Sobrien	struct vnode *vp;
338552284Sobrien	struct mac mac;
338652284Sobrien	char *buffer;
338790075Sobrien	int error;
338890075Sobrien
338990075Sobrien	error = copyin(uap->mac_p, &mac, sizeof(mac));
339090075Sobrien	if (error)
339152284Sobrien		return (error);
339252284Sobrien
339390075Sobrien	error = mac_check_structmac_consistent(&mac);
339452284Sobrien	if (error)
339590075Sobrien		return (error);
339690075Sobrien
339790075Sobrien	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
339890075Sobrien	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
339990075Sobrien	if (error) {
340018334Speter		free(buffer, M_MACTEMP);
340190075Sobrien		return (error);
340218334Speter	}
340390075Sobrien
340418334Speter	mtx_lock(&Giant);				/* VFS */
340518334Speter
340618334Speter	error = fget(td, SCARG(uap, fd), &fp);
340718334Speter	if (error)
340818334Speter		goto out;
340990075Sobrien
341090075Sobrien	switch (fp->f_type) {
341190075Sobrien	case DTYPE_FIFO:
341290075Sobrien	case DTYPE_VNODE:
341390075Sobrien		mac_init_vnode_label(&intlabel);
341490075Sobrien		error = mac_internalize_vnode_label(&intlabel, buffer);
341518334Speter		if (error) {
341690075Sobrien			mac_destroy_vnode_label(&intlabel);
341790075Sobrien			break;
341890075Sobrien		}
341918334Speter
342018334Speter		vp = (struct vnode *)fp->f_data;
342150397Sobrien		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
342218334Speter		if (error != 0) {
342318334Speter			mac_destroy_vnode_label(&intlabel);
342418334Speter			break;
342518334Speter		}
342618334Speter
342718334Speter		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
342818334Speter		error = vn_setlabel(vp, &intlabel, td->td_ucred);
342918334Speter		VOP_UNLOCK(vp, 0, td);
343018334Speter		vn_finished_write(mp);
343118334Speter
343218334Speter		mac_destroy_vnode_label(&intlabel);
343318334Speter		break;
343418334Speter
343518334Speter	case DTYPE_PIPE:
343618334Speter		mac_init_pipe_label(&intlabel);
343718334Speter		error = mac_internalize_pipe_label(&intlabel, buffer);
343818334Speter		if (error == 0) {
343918334Speter			pipe = (struct pipe *)fp->f_data;
344018334Speter			PIPE_LOCK(pipe);
344118334Speter			error = mac_pipe_label_set(td->td_ucred, pipe,
344218334Speter			    &intlabel);
344318334Speter			PIPE_UNLOCK(pipe);
344418334Speter		}
344518334Speter
344618334Speter		mac_destroy_pipe_label(&intlabel);
344718334Speter		break;
344818334Speter
344950397Sobrien	default:
345090075Sobrien		error = EINVAL;
345190075Sobrien	}
345290075Sobrien
345390075Sobrien	fdrop(fp, td);
345450397Sobrienout:
345550397Sobrien	mtx_unlock(&Giant);				/* VFS */
345618334Speter
345718334Speter	free(buffer, M_MACTEMP);
345818334Speter
345918334Speter	return (error);
346018334Speter}
346118334Speter
346218334Speter/*
346318334Speter * MPSAFE
346418334Speter */
346518334Speterint
346618334Speter__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
346718334Speter{
346818334Speter	struct label intlabel;
346918334Speter	struct nameidata nd;
347018334Speter	struct mount *mp;
347118334Speter	struct mac mac;
347218334Speter	char *buffer;
347318334Speter	int error;
347418334Speter
347518334Speter	error = copyin(uap->mac_p, &mac, sizeof(mac));
347618334Speter	if (error)
347718334Speter		return (error);
347818334Speter
347918334Speter	error = mac_check_structmac_consistent(&mac);
348018334Speter	if (error)
348118334Speter		return (error);
348218334Speter
348350397Sobrien	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
348490075Sobrien	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
348590075Sobrien	if (error) {
348690075Sobrien		free(buffer, M_MACTEMP);
348790075Sobrien		return (error);
348850397Sobrien	}
348950397Sobrien
349018334Speter	mac_init_vnode_label(&intlabel);
349118334Speter	error = mac_internalize_vnode_label(&intlabel, buffer);
349218334Speter	free(buffer, M_MACTEMP);
349318334Speter	if (error) {
349418334Speter		mac_destroy_vnode_label(&intlabel);
349518334Speter		return (error);
349618334Speter	}
349718334Speter
349818334Speter	mtx_lock(&Giant);				/* VFS */
349918334Speter
350018334Speter	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
350118334Speter	    td);
350218334Speter	error = namei(&nd);
350318334Speter	if (error == 0) {
350418334Speter		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
350518334Speter		if (error == 0)
350618334Speter			error = vn_setlabel(nd.ni_vp, &intlabel,
350718334Speter			    td->td_ucred);
350818334Speter		vn_finished_write(mp);
350918334Speter	}
351018334Speter
351118334Speter	NDFREE(&nd, 0);
351218334Speter	mtx_unlock(&Giant);				/* VFS */
351318334Speter	mac_destroy_vnode_label(&intlabel);
351418334Speter
351518334Speter	return (error);
351618334Speter}
351750397Sobrien
351890075Sobrien/*
351990075Sobrien * MPSAFE
352090075Sobrien */
352190075Sobrienint
352250397Sobrien__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
352350397Sobrien{
352418334Speter	struct label intlabel;
352518334Speter	struct nameidata nd;
352618334Speter	struct mount *mp;
352718334Speter	struct mac mac;
352818334Speter	char *buffer;
352918334Speter	int error;
353018334Speter
353118334Speter	error = copyin(uap->mac_p, &mac, sizeof(mac));
353218334Speter	if (error)
353318334Speter		return (error);
353418334Speter
353518334Speter	error = mac_check_structmac_consistent(&mac);
353618334Speter	if (error)
353718334Speter		return (error);
353818334Speter
353918334Speter	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
354018334Speter	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
354118334Speter	if (error) {
354218334Speter		free(buffer, M_MACTEMP);
354318334Speter		return (error);
354418334Speter	}
354518334Speter
354618334Speter	mac_init_vnode_label(&intlabel);
354718334Speter	error = mac_internalize_vnode_label(&intlabel, buffer);
354818334Speter	free(buffer, M_MACTEMP);
354918334Speter	if (error) {
355018334Speter		mac_destroy_vnode_label(&intlabel);
355150397Sobrien		return (error);
355290075Sobrien	}
355390075Sobrien
355490075Sobrien	mtx_lock(&Giant);				/* VFS */
355590075Sobrien
355650397Sobrien	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
355750397Sobrien	    td);
355818334Speter	error = namei(&nd);
355918334Speter	if (error == 0) {
356018334Speter		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
356118334Speter		if (error == 0)
356218334Speter			error = vn_setlabel(nd.ni_vp, &intlabel,
356318334Speter			    td->td_ucred);
356418334Speter		vn_finished_write(mp);
356518334Speter	}
356618334Speter
356718334Speter	NDFREE(&nd, 0);
356818334Speter	mtx_unlock(&Giant);				/* VFS */
356918334Speter	mac_destroy_vnode_label(&intlabel);
357018334Speter
357118334Speter	return (error);
357218334Speter}
357318334Speter
357418334Speter/*
357518334Speter * MPSAFE
357618334Speter */
357718334Speterint
357818334Spetermac_syscall(struct thread *td, struct mac_syscall_args *uap)
357918334Speter{
358018334Speter	struct mac_policy_conf *mpc;
358118334Speter	char target[MAC_MAX_POLICY_NAME];
358218334Speter	int error;
358318334Speter
358418334Speter	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
358550397Sobrien	if (error)
358690075Sobrien		return (error);
358790075Sobrien
358890075Sobrien	error = ENOSYS;
358990075Sobrien	MAC_POLICY_LIST_BUSY();
359050397Sobrien	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
359150397Sobrien		if (strcmp(mpc->mpc_name, target) == 0 &&
359218334Speter		    mpc->mpc_ops->mpo_syscall != NULL) {
359318334Speter			error = mpc->mpc_ops->mpo_syscall(td,
359418334Speter			    SCARG(uap, call), SCARG(uap, arg));
359518334Speter			goto out;
359618334Speter		}
359718334Speter	}
359818334Speter
359918334Speterout:
360018334Speter	MAC_POLICY_LIST_UNBUSY();
360118334Speter	return (error);
360218334Speter}
360318334Speter
360418334SpeterSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
360518334SpeterSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
360690075Sobrien
360790075Sobrien#else /* !MAC */
360890075Sobrien
360918334Speterint
361018334Speter__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
361118334Speter{
361218334Speter
361318334Speter	return (ENOSYS);
361418334Speter}
361518334Speter
361618334Speterint
361718334Speter__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
361890075Sobrien{
361990075Sobrien
362018334Speter	return (ENOSYS);
362150397Sobrien}
362250397Sobrien
362350397Sobrienint
362450397Sobrien__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
362550397Sobrien{
362690075Sobrien
362790075Sobrien	return (ENOSYS);
362890075Sobrien}
362990075Sobrien
363090075Sobrienint
363190075Sobrien__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
363290075Sobrien{
363390075Sobrien
363490075Sobrien	return (ENOSYS);
363590075Sobrien}
363618334Speter
363718334Speterint
363818334Speter__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
363918334Speter{
364018334Speter
364118334Speter	return (ENOSYS);
364218334Speter}
364318334Speter
364490075Sobrienint
364518334Speter__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
364618334Speter{
364718334Speter
364818334Speter	return (ENOSYS);
364918334Speter}
365018334Speter
365118334Speterint
365218334Speter__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
365318334Speter{
365418334Speter
365518334Speter	return (ENOSYS);
365618334Speter}
365718334Speter
365818334Speterint
365918334Speter__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
366018334Speter{
366118334Speter
366218334Speter	return (ENOSYS);
366318334Speter}
366418334Speter
366518334Speterint
366618334Speter__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
366718334Speter{
366818334Speter
366918334Speter	return (ENOSYS);
367018334Speter}
367118334Speter
367218334Speterint
367318334Spetermac_syscall(struct thread *td, struct mac_syscall_args *uap)
367418334Speter{
367518334Speter
367618334Speter	return (ENOSYS);
367718334Speter}
367818334Speter
367918334Speter#endif
368018334Speter