xref: /freebsd/sys/security/mac/mac_net.c (revision f51e58036ebe3a3e75527325e659d7ba02b129ed)
17bc82500SRobert Watson /*-
27bc82500SRobert Watson  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
37bc82500SRobert Watson  * Copyright (c) 2001 Ilmar S. Habibulin
42d3db0b8SRobert Watson  * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
57bc82500SRobert Watson  * All rights reserved.
67bc82500SRobert Watson  *
77bc82500SRobert Watson  * This software was developed by Robert Watson and Ilmar Habibulin for the
87bc82500SRobert Watson  * TrustedBSD Project.
97bc82500SRobert Watson  *
106201265bSRobert Watson  * This software was developed for the FreeBSD Project in part by Network
116201265bSRobert Watson  * Associates Laboratories, the Security Research Division of Network
126201265bSRobert Watson  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
136201265bSRobert Watson  * as part of the DARPA CHATS research program.
147bc82500SRobert Watson  *
157bc82500SRobert Watson  * Redistribution and use in source and binary forms, with or without
167bc82500SRobert Watson  * modification, are permitted provided that the following conditions
177bc82500SRobert Watson  * are met:
187bc82500SRobert Watson  * 1. Redistributions of source code must retain the above copyright
197bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer.
207bc82500SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
217bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
227bc82500SRobert Watson  *    documentation and/or other materials provided with the distribution.
237bc82500SRobert Watson  *
247bc82500SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
257bc82500SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
267bc82500SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
277bc82500SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
287bc82500SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
297bc82500SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
307bc82500SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
317bc82500SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
327bc82500SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
337bc82500SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
347bc82500SRobert Watson  * SUCH DAMAGE.
357bc82500SRobert Watson  */
36677b542eSDavid E. O'Brien 
377bc82500SRobert Watson /*
387bc82500SRobert Watson  * Framework for extensible kernel access control.  Kernel and userland
397bc82500SRobert Watson  * interface to the framework, policy registration and composition.
407bc82500SRobert Watson  */
417bc82500SRobert Watson 
42677b542eSDavid E. O'Brien #include <sys/cdefs.h>
43677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
44677b542eSDavid E. O'Brien 
457bc82500SRobert Watson #include "opt_mac.h"
46328048bcSPoul-Henning Kamp #include "opt_devfs.h"
47f9d0d524SRobert Watson 
487bc82500SRobert Watson #include <sys/param.h>
49a96acd1aSRobert Watson #include <sys/condvar.h>
5095fab37eSRobert Watson #include <sys/extattr.h>
51670cb89bSRobert Watson #include <sys/imgact.h>
5295fab37eSRobert Watson #include <sys/kernel.h>
5395fab37eSRobert Watson #include <sys/lock.h>
54b656366bSBruce Evans #include <sys/malloc.h>
5595fab37eSRobert Watson #include <sys/mutex.h>
5695fab37eSRobert Watson #include <sys/mac.h>
577ba28492SRobert Watson #include <sys/module.h>
5895fab37eSRobert Watson #include <sys/proc.h>
59f51e5803SRobert Watson #include <sys/sbuf.h>
6095fab37eSRobert Watson #include <sys/systm.h>
617bc82500SRobert Watson #include <sys/sysproto.h>
627bc82500SRobert Watson #include <sys/sysent.h>
6395fab37eSRobert Watson #include <sys/vnode.h>
6495fab37eSRobert Watson #include <sys/mount.h>
6595fab37eSRobert Watson #include <sys/file.h>
6695fab37eSRobert Watson #include <sys/namei.h>
6795fab37eSRobert Watson #include <sys/socket.h>
6895fab37eSRobert Watson #include <sys/pipe.h>
6995fab37eSRobert Watson #include <sys/socketvar.h>
7095fab37eSRobert Watson #include <sys/sysctl.h>
7195fab37eSRobert Watson 
7295fab37eSRobert Watson #include <vm/vm.h>
7395fab37eSRobert Watson #include <vm/pmap.h>
7495fab37eSRobert Watson #include <vm/vm_map.h>
7595fab37eSRobert Watson #include <vm/vm_object.h>
7695fab37eSRobert Watson 
7795fab37eSRobert Watson #include <sys/mac_policy.h>
7895fab37eSRobert Watson 
7995fab37eSRobert Watson #include <fs/devfs/devfs.h>
8095fab37eSRobert Watson 
8195fab37eSRobert Watson #include <net/bpfdesc.h>
8295fab37eSRobert Watson #include <net/if.h>
8395fab37eSRobert Watson #include <net/if_var.h>
8495fab37eSRobert Watson 
8595fab37eSRobert Watson #include <netinet/in.h>
8695fab37eSRobert Watson #include <netinet/ip_var.h>
8795fab37eSRobert Watson 
8895fab37eSRobert Watson #ifdef MAC
8995fab37eSRobert Watson 
907ba28492SRobert Watson /*
917ba28492SRobert Watson  * Declare that the kernel provides MAC support, version 1.  This permits
927ba28492SRobert Watson  * modules to refuse to be loaded if the necessary support isn't present,
937ba28492SRobert Watson  * even if it's pre-boot.
947ba28492SRobert Watson  */
957ba28492SRobert Watson MODULE_VERSION(kernel_mac_support, 1);
967ba28492SRobert Watson 
9795fab37eSRobert Watson SYSCTL_DECL(_security);
9895fab37eSRobert Watson 
9995fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
10095fab37eSRobert Watson     "TrustedBSD MAC policy controls");
101b2f0927aSRobert Watson 
102b2aef571SRobert Watson #if MAC_MAX_SLOTS > 32
103b2aef571SRobert Watson #error "MAC_MAX_SLOTS too large"
10495fab37eSRobert Watson #endif
105a13c67daSRobert Watson 
106b2aef571SRobert Watson static unsigned int mac_max_slots = MAC_MAX_SLOTS;
107b2aef571SRobert Watson static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
108b2aef571SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
109b2aef571SRobert Watson     &mac_max_slots, 0, "");
11095fab37eSRobert Watson 
111a67fe518SRobert Watson /*
112a67fe518SRobert Watson  * Has the kernel started generating labeled objects yet?  All read/write
113a67fe518SRobert Watson  * access to this variable is serialized during the boot process.  Following
114a67fe518SRobert Watson  * the end of serialization, we don't update this flag; no locking.
115a67fe518SRobert Watson  */
11695fab37eSRobert Watson static int	mac_late = 0;
11795fab37eSRobert Watson 
118763bbd2fSRobert Watson /*
119763bbd2fSRobert Watson  * Warn about EA transactions only the first time they happen.
120763bbd2fSRobert Watson  * Weak coherency, no locking.
121763bbd2fSRobert Watson  */
122763bbd2fSRobert Watson static int	ea_warn_once = 0;
123763bbd2fSRobert Watson 
124225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
125225bff6fSRobert Watson /*
126225bff6fSRobert Watson  * Flag to indicate whether or not we should allocate label storage for
127225bff6fSRobert Watson  * new mbufs.  Since most dynamic policies we currently work with don't
128225bff6fSRobert Watson  * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
129225bff6fSRobert Watson  * unless specifically notified of interest.  One result of this is
130225bff6fSRobert Watson  * that if a dynamically loaded policy requests mbuf labels, it must
131225bff6fSRobert Watson  * be able to deal with a NULL label being returned on any mbufs that
132225bff6fSRobert Watson  * were already in flight when the policy was loaded.  Since the policy
133225bff6fSRobert Watson  * already has to deal with uninitialized labels, this probably won't
134225bff6fSRobert Watson  * be a problem.  Note: currently no locking.  Will this be a problem?
135225bff6fSRobert Watson  */
136225bff6fSRobert Watson static int	mac_labelmbufs = 0;
137225bff6fSRobert Watson #endif
138225bff6fSRobert Watson 
13995fab37eSRobert Watson static int	mac_enforce_fs = 1;
14095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
14195fab37eSRobert Watson     &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
14295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
14395fab37eSRobert Watson 
144a3df768bSRobert Watson static int	mac_enforce_kld = 1;
145a3df768bSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
146a3df768bSRobert Watson     &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
147a3df768bSRobert Watson TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
148a3df768bSRobert Watson 
14995fab37eSRobert Watson static int	mac_enforce_network = 1;
15095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
15195fab37eSRobert Watson     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
15295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
15395fab37eSRobert Watson 
154b88c98f6SRobert Watson static int	mac_enforce_pipe = 1;
155b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
156b88c98f6SRobert Watson     &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
157c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
158b88c98f6SRobert Watson 
15995fab37eSRobert Watson static int	mac_enforce_process = 1;
16095fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
16195fab37eSRobert Watson     &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
16295fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
16395fab37eSRobert Watson 
16495fab37eSRobert Watson static int	mac_enforce_socket = 1;
16595fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
16695fab37eSRobert Watson     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
16795fab37eSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
16895fab37eSRobert Watson 
1699e913ebdSRobert Watson static int	mac_enforce_system = 1;
1709e913ebdSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
1719e913ebdSRobert Watson     &mac_enforce_system, 0, "Enforce MAC policy on system operations");
1729e913ebdSRobert Watson TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
173d3fc69eeSRobert Watson 
174ca7850c3SRobert Watson static int	mac_enforce_vm = 1;
175ca7850c3SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
176ca7850c3SRobert Watson     &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
177c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
178ca7850c3SRobert Watson 
179c0f39905SRobert Watson static int	mac_mmap_revocation = 1;
180c0f39905SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
181c0f39905SRobert Watson     &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
182c0f39905SRobert Watson     "relabel");
18399fa64f8SRobert Watson static int	mac_mmap_revocation_via_cow = 0;
18495fab37eSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
18595fab37eSRobert Watson     &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
18695fab37eSRobert Watson     "copy-on-write semantics, or by removing all write access");
18795fab37eSRobert Watson 
188f050add5SRobert Watson #ifdef MAC_DEBUG
1896be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
1906be0c25eSRobert Watson     "TrustedBSD MAC debug info");
1916be0c25eSRobert Watson 
1926be0c25eSRobert Watson static int	mac_debug_label_fallback = 0;
1936be0c25eSRobert Watson SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
1946be0c25eSRobert Watson     &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
1956be0c25eSRobert Watson     "when label is corrupted.");
1966be0c25eSRobert Watson TUNABLE_INT("security.mac.debug_label_fallback",
1976be0c25eSRobert Watson     &mac_debug_label_fallback);
1986be0c25eSRobert Watson 
199b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
200b2f0927aSRobert Watson     "TrustedBSD MAC object counters");
201b2f0927aSRobert Watson 
20295fab37eSRobert Watson static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
20395fab37eSRobert Watson     nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
2042555374cSRobert Watson     nmacipqs, nmacpipes, nmacprocs;
205b2f0927aSRobert Watson 
206b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
20795fab37eSRobert Watson     &nmacmbufs, 0, "number of mbufs in use");
208b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
20995fab37eSRobert Watson     &nmaccreds, 0, "number of ucreds in use");
210b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
21195fab37eSRobert Watson     &nmacifnets, 0, "number of ifnets in use");
212b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
21395fab37eSRobert Watson     &nmacipqs, 0, "number of ipqs in use");
214b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
21595fab37eSRobert Watson     &nmacbpfdescs, 0, "number of bpfdescs in use");
216b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
21795fab37eSRobert Watson     &nmacsockets, 0, "number of sockets in use");
218b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
21995fab37eSRobert Watson     &nmacpipes, 0, "number of pipes in use");
2202555374cSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
2212555374cSRobert Watson     &nmacprocs, 0, "number of procs in use");
222b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
22395fab37eSRobert Watson     &nmacmounts, 0, "number of mounts in use");
224b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
22595fab37eSRobert Watson     &nmactemp, 0, "number of temporary labels in use");
226b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
22795fab37eSRobert Watson     &nmacvnodes, 0, "number of vnodes in use");
228b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
22995fab37eSRobert Watson     &nmacdevfsdirents, 0, "number of devfs dirents inuse");
230f050add5SRobert Watson #endif
23195fab37eSRobert Watson 
23295fab37eSRobert Watson static int	error_select(int error1, int error2);
23395fab37eSRobert Watson static int	mac_policy_register(struct mac_policy_conf *mpc);
23495fab37eSRobert Watson static int	mac_policy_unregister(struct mac_policy_conf *mpc);
23595fab37eSRobert Watson 
236e183f80eSRobert Watson static void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
237e183f80eSRobert Watson 		    struct vnode *vp, int *prot);
23895fab37eSRobert Watson static void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
23995fab37eSRobert Watson 		    struct ucred *cred, struct vm_map *map);
24095fab37eSRobert Watson 
24183985c26SRobert Watson static void	mac_destroy_socket_label(struct label *label);
24283985c26SRobert Watson 
243763bbd2fSRobert Watson static int	mac_setlabel_vnode_extattr(struct ucred *cred,
244763bbd2fSRobert Watson 		    struct vnode *vp, struct label *intlabel);
245763bbd2fSRobert Watson 
24695fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
247f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
24895fab37eSRobert Watson 
24995fab37eSRobert Watson /*
25041a17fe3SRobert Watson  * mac_static_policy_list holds a list of policy modules that are not
25141a17fe3SRobert Watson  * loaded while the system is "live", and cannot be unloaded.  These
25241a17fe3SRobert Watson  * policies can be invoked without holding the busy count.
25341a17fe3SRobert Watson  *
25441a17fe3SRobert Watson  * mac_policy_list stores the list of dynamic policies.  A busy count is
255a96acd1aSRobert Watson  * maintained for the list, stored in mac_policy_busy.  The busy count
25641a17fe3SRobert Watson  * is protected by mac_policy_mtx; the list may be modified only
257a96acd1aSRobert Watson  * while the busy count is 0, requiring that the lock be held to
258a96acd1aSRobert Watson  * prevent new references to the list from being acquired.  For almost
259a96acd1aSRobert Watson  * all operations, incrementing the busy count is sufficient to
260a96acd1aSRobert Watson  * guarantee consistency, as the list cannot be modified while the
261a96acd1aSRobert Watson  * busy count is elevated.  For a few special operations involving a
26241a17fe3SRobert Watson  * change to the list of active policies, the mtx itself must be held.
26341a17fe3SRobert Watson  * A condition variable, mac_policy_cv, is used to signal potential
26441a17fe3SRobert Watson  * exclusive consumers that they should try to acquire the lock if a
26541a17fe3SRobert Watson  * first attempt at exclusive access fails.
26695fab37eSRobert Watson  */
26741a17fe3SRobert Watson static struct mtx mac_policy_mtx;
26841a17fe3SRobert Watson static struct cv mac_policy_cv;
26941a17fe3SRobert Watson static int mac_policy_count;
27095fab37eSRobert Watson static LIST_HEAD(, mac_policy_conf) mac_policy_list;
27141a17fe3SRobert Watson static LIST_HEAD(, mac_policy_conf) mac_static_policy_list;
272a96acd1aSRobert Watson 
273a96acd1aSRobert Watson /*
27426306795SJohn Baldwin  * We manually invoke WITNESS_WARN() to allow Witness to generate
275a96acd1aSRobert Watson  * warnings even if we don't end up ever triggering the wait at
276a96acd1aSRobert Watson  * run-time.  The consumer of the exclusive interface must not hold
277a96acd1aSRobert Watson  * any locks (other than potentially Giant) since we may sleep for
278a96acd1aSRobert Watson  * long (potentially indefinite) periods of time waiting for the
279a96acd1aSRobert Watson  * framework to become quiescent so that a policy list change may
280a96acd1aSRobert Watson  * be made.
281a96acd1aSRobert Watson  */
28241a17fe3SRobert Watson static __inline void
28341a17fe3SRobert Watson mac_policy_grab_exclusive(void)
28441a17fe3SRobert Watson {
28541a17fe3SRobert Watson 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
28641a17fe3SRobert Watson  	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
28741a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
28841a17fe3SRobert Watson 	while (mac_policy_count != 0)
28941a17fe3SRobert Watson 		cv_wait(&mac_policy_cv, &mac_policy_mtx);
29041a17fe3SRobert Watson }
29195fab37eSRobert Watson 
29241a17fe3SRobert Watson static __inline void
29341a17fe3SRobert Watson mac_policy_assert_exclusive(void)
29441a17fe3SRobert Watson {
29541a17fe3SRobert Watson 	mtx_assert(&mac_policy_mtx, MA_OWNED);
29641a17fe3SRobert Watson 	KASSERT(mac_policy_count == 0,
29741a17fe3SRobert Watson 	    ("mac_policy_assert_exclusive(): not exclusive"));
29841a17fe3SRobert Watson }
299225bff6fSRobert Watson 
30041a17fe3SRobert Watson static __inline void
30141a17fe3SRobert Watson mac_policy_release_exclusive(void)
30241a17fe3SRobert Watson {
30395fab37eSRobert Watson 
30441a17fe3SRobert Watson 	KASSERT(mac_policy_count == 0,
30541a17fe3SRobert Watson 	    ("mac_policy_release_exclusive(): not exclusive"));
30641a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
30741a17fe3SRobert Watson 	cv_signal(&mac_policy_cv);
30841a17fe3SRobert Watson }
30941a17fe3SRobert Watson 
31041a17fe3SRobert Watson static __inline void
31141a17fe3SRobert Watson mac_policy_list_busy(void)
31241a17fe3SRobert Watson {
31341a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
31441a17fe3SRobert Watson 	mac_policy_count++;
31541a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
31641a17fe3SRobert Watson }
31741a17fe3SRobert Watson 
31841a17fe3SRobert Watson static __inline int
31941a17fe3SRobert Watson mac_policy_list_conditional_busy(void)
32041a17fe3SRobert Watson {
32141a17fe3SRobert Watson 	int ret;
32241a17fe3SRobert Watson 
32341a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
32441a17fe3SRobert Watson 	if (!LIST_EMPTY(&mac_policy_list)) {
32541a17fe3SRobert Watson 		mac_policy_count++;
32641a17fe3SRobert Watson 		ret = 1;
32741a17fe3SRobert Watson 	} else
32841a17fe3SRobert Watson 		ret = 0;
32941a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
33041a17fe3SRobert Watson 	return (ret);
33141a17fe3SRobert Watson }
33241a17fe3SRobert Watson 
33341a17fe3SRobert Watson static __inline void
33441a17fe3SRobert Watson mac_policy_list_unbusy(void)
33541a17fe3SRobert Watson {
33641a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
33741a17fe3SRobert Watson 	mac_policy_count--;
33841a17fe3SRobert Watson 	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
33941a17fe3SRobert Watson 	if (mac_policy_count == 0)
34041a17fe3SRobert Watson 		cv_signal(&mac_policy_cv);
34141a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
34241a17fe3SRobert Watson }
34395fab37eSRobert Watson 
34495fab37eSRobert Watson /*
34595fab37eSRobert Watson  * MAC_CHECK performs the designated check by walking the policy
34695fab37eSRobert Watson  * module list and checking with each as to how it feels about the
34795fab37eSRobert Watson  * request.  Note that it returns its value via 'error' in the scope
34895fab37eSRobert Watson  * of the caller.
34995fab37eSRobert Watson  */
35095fab37eSRobert Watson #define	MAC_CHECK(check, args...) do {					\
35195fab37eSRobert Watson 	struct mac_policy_conf *mpc;					\
35241a17fe3SRobert Watson 	int entrycount;							\
35395fab37eSRobert Watson 									\
35495fab37eSRobert Watson 	error = 0;							\
35541a17fe3SRobert Watson 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
35641a17fe3SRobert Watson 		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
35741a17fe3SRobert Watson 			error = error_select(				\
35841a17fe3SRobert Watson 			    mpc->mpc_ops->mpo_ ## check (args),		\
35941a17fe3SRobert Watson 			    error);					\
36041a17fe3SRobert Watson 	}								\
36141a17fe3SRobert Watson 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
36295fab37eSRobert Watson 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
36395fab37eSRobert Watson 			if (mpc->mpc_ops->mpo_ ## check != NULL)	\
36495fab37eSRobert Watson 				error = error_select(			\
36595fab37eSRobert Watson 				    mpc->mpc_ops->mpo_ ## check (args),	\
36695fab37eSRobert Watson 				    error);				\
36795fab37eSRobert Watson 		}							\
36841a17fe3SRobert Watson 		mac_policy_list_unbusy();				\
36941a17fe3SRobert Watson 	}								\
37095fab37eSRobert Watson } while (0)
37195fab37eSRobert Watson 
37295fab37eSRobert Watson /*
37395fab37eSRobert Watson  * MAC_BOOLEAN performs the designated boolean composition by walking
37495fab37eSRobert Watson  * the module list, invoking each instance of the operation, and
37595fab37eSRobert Watson  * combining the results using the passed C operator.  Note that it
37695fab37eSRobert Watson  * returns its value via 'result' in the scope of the caller, which
37795fab37eSRobert Watson  * should be initialized by the caller in a meaningful way to get
37895fab37eSRobert Watson  * a meaningful result.
37995fab37eSRobert Watson  */
38095fab37eSRobert Watson #define	MAC_BOOLEAN(operation, composition, args...) do {		\
38195fab37eSRobert Watson 	struct mac_policy_conf *mpc;					\
38241a17fe3SRobert Watson 	int entrycount;							\
38395fab37eSRobert Watson 									\
38441a17fe3SRobert Watson 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
38595fab37eSRobert Watson 		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
38695fab37eSRobert Watson 			result = result composition			\
38795fab37eSRobert Watson 			    mpc->mpc_ops->mpo_ ## operation (args);	\
38895fab37eSRobert Watson 	}								\
38941a17fe3SRobert Watson 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
39041a17fe3SRobert Watson 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
39141a17fe3SRobert Watson 			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
39241a17fe3SRobert Watson 				result = result composition		\
39341a17fe3SRobert Watson 				    mpc->mpc_ops->mpo_ ## operation	\
39441a17fe3SRobert Watson 				    (args);				\
39541a17fe3SRobert Watson 		}							\
39641a17fe3SRobert Watson 		mac_policy_list_unbusy();				\
39741a17fe3SRobert Watson 	}								\
39895fab37eSRobert Watson } while (0)
39995fab37eSRobert Watson 
400f7b951a8SRobert Watson #define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
401f7b951a8SRobert Watson     outbuflen) do {							\
402f51e5803SRobert Watson 	int claimed, first, ignorenotfound, savedlen;			\
403f51e5803SRobert Watson 	char *element_name, *element_temp;				\
404f51e5803SRobert Watson 	struct sbuf sb;							\
405f7b951a8SRobert Watson 									\
406f7b951a8SRobert Watson 	error = 0;							\
407f7b951a8SRobert Watson 	first = 1;							\
408f51e5803SRobert Watson 	sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN);		\
409f51e5803SRobert Watson 	element_temp = elementlist;					\
410f7b951a8SRobert Watson 	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
411f7b951a8SRobert Watson 		if (element_name[0] == '?') {				\
412f7b951a8SRobert Watson 			element_name++;					\
413f7b951a8SRobert Watson 			ignorenotfound = 1;				\
414f7b951a8SRobert Watson 		 } else							\
415f7b951a8SRobert Watson 			ignorenotfound = 0;				\
416f51e5803SRobert Watson 		savedlen = sbuf_len(&sb);				\
417f7b951a8SRobert Watson 		if (first) {						\
418f51e5803SRobert Watson 			error = sbuf_printf(&sb, "%s/", element_name);	\
419f7b951a8SRobert Watson 			first = 0;					\
420f7b951a8SRobert Watson 		} else							\
421f51e5803SRobert Watson 			error = sbuf_printf(&sb, ",%s/", element_name);	\
422f51e5803SRobert Watson 		if (error == -1) {					\
423f51e5803SRobert Watson 			error = EINVAL;	/* XXX: E2BIG? */		\
424f7b951a8SRobert Watson 			break;						\
425f7b951a8SRobert Watson 		}							\
426f51e5803SRobert Watson 		claimed = 0;						\
427f7b951a8SRobert Watson 		MAC_CHECK(externalize_ ## type, label, element_name,	\
428f51e5803SRobert Watson 		    &sb, &claimed);					\
429f7b951a8SRobert Watson 		if (error)						\
430f7b951a8SRobert Watson 			break;						\
431f51e5803SRobert Watson 		if (claimed == 0 && ignorenotfound) {			\
432f51e5803SRobert Watson 			/* Revert last label name. */			\
433f51e5803SRobert Watson 			sbuf_setpos(&sb, savedlen);			\
434f51e5803SRobert Watson 		} else if (claimed != 1) {				\
435f51e5803SRobert Watson 			error = EINVAL;	/* XXX: ENOLABEL? */		\
436f7b951a8SRobert Watson 			break;						\
437f7b951a8SRobert Watson 		}							\
438f7b951a8SRobert Watson 	}								\
439f51e5803SRobert Watson 	sbuf_finish(&sb);						\
440f7b951a8SRobert Watson } while (0)
441f7b951a8SRobert Watson 
442f7b951a8SRobert Watson #define	MAC_INTERNALIZE(type, label, instring) do {			\
443f7b951a8SRobert Watson 	char *element, *element_name, *element_data;			\
444f7b951a8SRobert Watson 	int claimed;							\
445f7b951a8SRobert Watson 									\
446f7b951a8SRobert Watson 	error = 0;							\
447f7b951a8SRobert Watson 	element = instring;						\
448f7b951a8SRobert Watson 	while ((element_name = strsep(&element, ",")) != NULL) {	\
449f7b951a8SRobert Watson 		element_data = element_name;				\
450f7b951a8SRobert Watson 		element_name = strsep(&element_data, "/");		\
451f7b951a8SRobert Watson 		if (element_data == NULL) {				\
452f7b951a8SRobert Watson 			error = EINVAL;					\
453f7b951a8SRobert Watson 			break;						\
454f7b951a8SRobert Watson 		}							\
455f7b951a8SRobert Watson 		claimed = 0;						\
456f7b951a8SRobert Watson 		MAC_CHECK(internalize_ ## type, label, element_name,	\
457f7b951a8SRobert Watson 		    element_data, &claimed);				\
458f7b951a8SRobert Watson 		if (error)						\
459f7b951a8SRobert Watson 			break;						\
460f7b951a8SRobert Watson 		if (claimed != 1) {					\
461f7b951a8SRobert Watson 			/* XXXMAC: Another error here? */		\
462f7b951a8SRobert Watson 			error = EINVAL;					\
463f7b951a8SRobert Watson 			break;						\
464f7b951a8SRobert Watson 		}							\
465f7b951a8SRobert Watson 	}								\
466f7b951a8SRobert Watson } while (0)
467f7b951a8SRobert Watson 
46895fab37eSRobert Watson /*
46995fab37eSRobert Watson  * MAC_PERFORM performs the designated operation by walking the policy
47095fab37eSRobert Watson  * module list and invoking that operation for each policy.
47195fab37eSRobert Watson  */
47295fab37eSRobert Watson #define	MAC_PERFORM(operation, args...) do {				\
47395fab37eSRobert Watson 	struct mac_policy_conf *mpc;					\
47441a17fe3SRobert Watson 	int entrycount;							\
47595fab37eSRobert Watson 									\
47641a17fe3SRobert Watson 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
47741a17fe3SRobert Watson 		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
47841a17fe3SRobert Watson 			mpc->mpc_ops->mpo_ ## operation (args);		\
47941a17fe3SRobert Watson 	}								\
48041a17fe3SRobert Watson 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
48195fab37eSRobert Watson 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
48295fab37eSRobert Watson 			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
48395fab37eSRobert Watson 				mpc->mpc_ops->mpo_ ## operation (args);	\
48495fab37eSRobert Watson 		}							\
48541a17fe3SRobert Watson 		mac_policy_list_unbusy();				\
48641a17fe3SRobert Watson 	}								\
48795fab37eSRobert Watson } while (0)
48895fab37eSRobert Watson 
48995fab37eSRobert Watson /*
49095fab37eSRobert Watson  * Initialize the MAC subsystem, including appropriate SMP locks.
49195fab37eSRobert Watson  */
49295fab37eSRobert Watson static void
49395fab37eSRobert Watson mac_init(void)
49495fab37eSRobert Watson {
49595fab37eSRobert Watson 
49641a17fe3SRobert Watson 	LIST_INIT(&mac_static_policy_list);
49795fab37eSRobert Watson 	LIST_INIT(&mac_policy_list);
49841a17fe3SRobert Watson 
49941a17fe3SRobert Watson 	mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
50041a17fe3SRobert Watson 	cv_init(&mac_policy_cv, "mac_policy_cv");
50195fab37eSRobert Watson }
50295fab37eSRobert Watson 
50395fab37eSRobert Watson /*
50495fab37eSRobert Watson  * For the purposes of modules that want to know if they were loaded
50595fab37eSRobert Watson  * "early", set the mac_late flag once we've processed modules either
50695fab37eSRobert Watson  * linked into the kernel, or loaded before the kernel startup.
50795fab37eSRobert Watson  */
50895fab37eSRobert Watson static void
50995fab37eSRobert Watson mac_late_init(void)
51095fab37eSRobert Watson {
51195fab37eSRobert Watson 
51295fab37eSRobert Watson 	mac_late = 1;
51395fab37eSRobert Watson }
51495fab37eSRobert Watson 
51595fab37eSRobert Watson /*
516225bff6fSRobert Watson  * After the policy list has changed, walk the list to update any global
517225bff6fSRobert Watson  * flags.
518225bff6fSRobert Watson  */
519225bff6fSRobert Watson static void
520225bff6fSRobert Watson mac_policy_updateflags(void)
521225bff6fSRobert Watson {
522225bff6fSRobert Watson 	struct mac_policy_conf *tmpc;
523225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
524225bff6fSRobert Watson 	int labelmbufs;
525225bff6fSRobert Watson #endif
526225bff6fSRobert Watson 
52741a17fe3SRobert Watson 	mac_policy_assert_exclusive();
528225bff6fSRobert Watson 
529225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
530225bff6fSRobert Watson 	labelmbufs = 0;
531225bff6fSRobert Watson #endif
53241a17fe3SRobert Watson 
53341a17fe3SRobert Watson 	LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
53441a17fe3SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
53541a17fe3SRobert Watson 		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
53641a17fe3SRobert Watson 			labelmbufs++;
53741a17fe3SRobert Watson #endif
53841a17fe3SRobert Watson 	}
539225bff6fSRobert Watson 	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
540225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
541225bff6fSRobert Watson 		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
542225bff6fSRobert Watson 			labelmbufs++;
543225bff6fSRobert Watson #endif
544225bff6fSRobert Watson 	}
545225bff6fSRobert Watson 
546225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
547225bff6fSRobert Watson 	mac_labelmbufs = (labelmbufs != 0);
548225bff6fSRobert Watson #endif
549225bff6fSRobert Watson }
550225bff6fSRobert Watson 
551225bff6fSRobert Watson /*
55295fab37eSRobert Watson  * Allow MAC policy modules to register during boot, etc.
55395fab37eSRobert Watson  */
55495fab37eSRobert Watson int
55595fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data)
55695fab37eSRobert Watson {
55795fab37eSRobert Watson 	struct mac_policy_conf *mpc;
55895fab37eSRobert Watson 	int error;
55995fab37eSRobert Watson 
56095fab37eSRobert Watson 	error = 0;
56195fab37eSRobert Watson 	mpc = (struct mac_policy_conf *) data;
56295fab37eSRobert Watson 
56395fab37eSRobert Watson 	switch (type) {
56495fab37eSRobert Watson 	case MOD_LOAD:
56595fab37eSRobert Watson 		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
56695fab37eSRobert Watson 		    mac_late) {
56795fab37eSRobert Watson 			printf("mac_policy_modevent: can't load %s policy "
56895fab37eSRobert Watson 			    "after booting\n", mpc->mpc_name);
56995fab37eSRobert Watson 			error = EBUSY;
57095fab37eSRobert Watson 			break;
57195fab37eSRobert Watson 		}
57295fab37eSRobert Watson 		error = mac_policy_register(mpc);
57395fab37eSRobert Watson 		break;
57495fab37eSRobert Watson 	case MOD_UNLOAD:
57595fab37eSRobert Watson 		/* Don't unregister the module if it was never registered. */
57695fab37eSRobert Watson 		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
57795fab37eSRobert Watson 		    != 0)
57895fab37eSRobert Watson 			error = mac_policy_unregister(mpc);
57995fab37eSRobert Watson 		else
58095fab37eSRobert Watson 			error = 0;
58195fab37eSRobert Watson 		break;
58295fab37eSRobert Watson 	default:
58395fab37eSRobert Watson 		break;
58495fab37eSRobert Watson 	}
58595fab37eSRobert Watson 
58695fab37eSRobert Watson 	return (error);
58795fab37eSRobert Watson }
58895fab37eSRobert Watson 
58995fab37eSRobert Watson static int
59095fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc)
59195fab37eSRobert Watson {
59295fab37eSRobert Watson 	struct mac_policy_conf *tmpc;
59341a17fe3SRobert Watson 	int error, slot, static_entry;
59495fab37eSRobert Watson 
59541a17fe3SRobert Watson 	error = 0;
59641a17fe3SRobert Watson 
59741a17fe3SRobert Watson 	/*
59841a17fe3SRobert Watson 	 * We don't technically need exclusive access while !mac_late,
59941a17fe3SRobert Watson 	 * but hold it for assertion consistency.
60041a17fe3SRobert Watson 	 */
60141a17fe3SRobert Watson 	mac_policy_grab_exclusive();
60241a17fe3SRobert Watson 
60341a17fe3SRobert Watson 	/*
60441a17fe3SRobert Watson 	 * If the module can potentially be unloaded, or we're loading
60541a17fe3SRobert Watson 	 * late, we have to stick it in the non-static list and pay
60641a17fe3SRobert Watson 	 * an extra performance overhead.  Otherwise, we can pay a
60741a17fe3SRobert Watson 	 * light locking cost and stick it in the static list.
60841a17fe3SRobert Watson 	 */
60941a17fe3SRobert Watson 	static_entry = (!mac_late &&
61041a17fe3SRobert Watson 	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
61141a17fe3SRobert Watson 
61241a17fe3SRobert Watson 	if (static_entry) {
61341a17fe3SRobert Watson 		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
61441a17fe3SRobert Watson 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
61541a17fe3SRobert Watson 				error = EEXIST;
61641a17fe3SRobert Watson 				goto out;
61741a17fe3SRobert Watson 			}
61841a17fe3SRobert Watson 		}
61941a17fe3SRobert Watson 	} else {
62095fab37eSRobert Watson 		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
62195fab37eSRobert Watson 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
62241a17fe3SRobert Watson 				error = EEXIST;
62341a17fe3SRobert Watson 				goto out;
62441a17fe3SRobert Watson 			}
62595fab37eSRobert Watson 		}
62695fab37eSRobert Watson 	}
62795fab37eSRobert Watson 	if (mpc->mpc_field_off != NULL) {
628b2aef571SRobert Watson 		slot = ffs(mac_slot_offsets_free);
62995fab37eSRobert Watson 		if (slot == 0) {
63041a17fe3SRobert Watson 			error = ENOMEM;
63141a17fe3SRobert Watson 			goto out;
63295fab37eSRobert Watson 		}
63395fab37eSRobert Watson 		slot--;
634b2aef571SRobert Watson 		mac_slot_offsets_free &= ~(1 << slot);
63595fab37eSRobert Watson 		*mpc->mpc_field_off = slot;
63695fab37eSRobert Watson 	}
63795fab37eSRobert Watson 	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
63841a17fe3SRobert Watson 
63941a17fe3SRobert Watson 	/*
64041a17fe3SRobert Watson 	 * If we're loading a MAC module after the framework has
64141a17fe3SRobert Watson 	 * initialized, it has to go into the dynamic list.  If
64241a17fe3SRobert Watson 	 * we're loading it before we've finished initializing,
64341a17fe3SRobert Watson 	 * it can go into the static list with weaker locker
64441a17fe3SRobert Watson 	 * requirements.
64541a17fe3SRobert Watson 	 */
64641a17fe3SRobert Watson 	if (static_entry)
64741a17fe3SRobert Watson 		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
64841a17fe3SRobert Watson 	else
64995fab37eSRobert Watson 		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
65095fab37eSRobert Watson 
65195fab37eSRobert Watson 	/* Per-policy initialization. */
65295fab37eSRobert Watson 	if (mpc->mpc_ops->mpo_init != NULL)
65395fab37eSRobert Watson 		(*(mpc->mpc_ops->mpo_init))(mpc);
654225bff6fSRobert Watson 	mac_policy_updateflags();
65595fab37eSRobert Watson 
65695fab37eSRobert Watson 	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
65795fab37eSRobert Watson 	    mpc->mpc_name);
65895fab37eSRobert Watson 
65941a17fe3SRobert Watson out:
66041a17fe3SRobert Watson 	mac_policy_release_exclusive();
66141a17fe3SRobert Watson 	return (error);
66295fab37eSRobert Watson }
66395fab37eSRobert Watson 
66495fab37eSRobert Watson static int
66595fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc)
66695fab37eSRobert Watson {
66795fab37eSRobert Watson 
668ea599aa0SRobert Watson 	/*
669ea599aa0SRobert Watson 	 * If we fail the load, we may get a request to unload.  Check
670ea599aa0SRobert Watson 	 * to see if we did the run-time registration, and if not,
671ea599aa0SRobert Watson 	 * silently succeed.
672ea599aa0SRobert Watson 	 */
67341a17fe3SRobert Watson 	mac_policy_grab_exclusive();
674ea599aa0SRobert Watson 	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
67541a17fe3SRobert Watson 		mac_policy_release_exclusive();
676ea599aa0SRobert Watson 		return (0);
677ea599aa0SRobert Watson 	}
67895fab37eSRobert Watson #if 0
67995fab37eSRobert Watson 	/*
68095fab37eSRobert Watson 	 * Don't allow unloading modules with private data.
68195fab37eSRobert Watson 	 */
682ea599aa0SRobert Watson 	if (mpc->mpc_field_off != NULL) {
683ea599aa0SRobert Watson 		MAC_POLICY_LIST_UNLOCK();
68495fab37eSRobert Watson 		return (EBUSY);
685ea599aa0SRobert Watson 	}
68695fab37eSRobert Watson #endif
687ea599aa0SRobert Watson 	/*
688ea599aa0SRobert Watson 	 * Only allow the unload to proceed if the module is unloadable
689ea599aa0SRobert Watson 	 * by its own definition.
690ea599aa0SRobert Watson 	 */
691ea599aa0SRobert Watson 	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
69241a17fe3SRobert Watson 		mac_policy_release_exclusive();
69395fab37eSRobert Watson 		return (EBUSY);
694ea599aa0SRobert Watson 	}
69595fab37eSRobert Watson 	if (mpc->mpc_ops->mpo_destroy != NULL)
69695fab37eSRobert Watson 		(*(mpc->mpc_ops->mpo_destroy))(mpc);
69795fab37eSRobert Watson 
69895fab37eSRobert Watson 	LIST_REMOVE(mpc, mpc_list);
6999aeffb2bSRobert Watson 	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
700225bff6fSRobert Watson 	mac_policy_updateflags();
70141a17fe3SRobert Watson 
70241a17fe3SRobert Watson 	mac_policy_release_exclusive();
703a96acd1aSRobert Watson 
70495fab37eSRobert Watson 	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
70595fab37eSRobert Watson 	    mpc->mpc_name);
70695fab37eSRobert Watson 
70795fab37eSRobert Watson 	return (0);
70895fab37eSRobert Watson }
70995fab37eSRobert Watson 
71095fab37eSRobert Watson /*
71195fab37eSRobert Watson  * Define an error value precedence, and given two arguments, selects the
71295fab37eSRobert Watson  * value with the higher precedence.
71395fab37eSRobert Watson  */
71495fab37eSRobert Watson static int
71595fab37eSRobert Watson error_select(int error1, int error2)
71695fab37eSRobert Watson {
71795fab37eSRobert Watson 
71895fab37eSRobert Watson 	/* Certain decision-making errors take top priority. */
71995fab37eSRobert Watson 	if (error1 == EDEADLK || error2 == EDEADLK)
72095fab37eSRobert Watson 		return (EDEADLK);
72195fab37eSRobert Watson 
72295fab37eSRobert Watson 	/* Invalid arguments should be reported where possible. */
72395fab37eSRobert Watson 	if (error1 == EINVAL || error2 == EINVAL)
72495fab37eSRobert Watson 		return (EINVAL);
72595fab37eSRobert Watson 
72695fab37eSRobert Watson 	/* Precedence goes to "visibility", with both process and file. */
72795fab37eSRobert Watson 	if (error1 == ESRCH || error2 == ESRCH)
72895fab37eSRobert Watson 		return (ESRCH);
72995fab37eSRobert Watson 
73095fab37eSRobert Watson 	if (error1 == ENOENT || error2 == ENOENT)
73195fab37eSRobert Watson 		return (ENOENT);
73295fab37eSRobert Watson 
73395fab37eSRobert Watson 	/* Precedence goes to DAC/MAC protections. */
73495fab37eSRobert Watson 	if (error1 == EACCES || error2 == EACCES)
73595fab37eSRobert Watson 		return (EACCES);
73695fab37eSRobert Watson 
73795fab37eSRobert Watson 	/* Precedence goes to privilege. */
73895fab37eSRobert Watson 	if (error1 == EPERM || error2 == EPERM)
73995fab37eSRobert Watson 		return (EPERM);
74095fab37eSRobert Watson 
74195fab37eSRobert Watson 	/* Precedence goes to error over success; otherwise, arbitrary. */
74295fab37eSRobert Watson 	if (error1 != 0)
74395fab37eSRobert Watson 		return (error1);
74495fab37eSRobert Watson 	return (error2);
74595fab37eSRobert Watson }
74695fab37eSRobert Watson 
74710eeb10cSRobert Watson static struct label *
74810eeb10cSRobert Watson mbuf_to_label(struct mbuf *mbuf)
74910eeb10cSRobert Watson {
750225bff6fSRobert Watson 	struct m_tag *tag;
75110eeb10cSRobert Watson 	struct label *label;
75210eeb10cSRobert Watson 
753225bff6fSRobert Watson 	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
754225bff6fSRobert Watson 	label = (struct label *)(tag+1);
75510eeb10cSRobert Watson 
75610eeb10cSRobert Watson 	return (label);
75710eeb10cSRobert Watson }
75810eeb10cSRobert Watson 
75908bcdc58SRobert Watson static void
76008bcdc58SRobert Watson mac_init_label(struct label *label)
76108bcdc58SRobert Watson {
76208bcdc58SRobert Watson 
76308bcdc58SRobert Watson 	bzero(label, sizeof(*label));
76408bcdc58SRobert Watson 	label->l_flags = MAC_FLAG_INITIALIZED;
76508bcdc58SRobert Watson }
76608bcdc58SRobert Watson 
76708bcdc58SRobert Watson static void
76808bcdc58SRobert Watson mac_destroy_label(struct label *label)
76908bcdc58SRobert Watson {
77008bcdc58SRobert Watson 
77108bcdc58SRobert Watson 	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
77208bcdc58SRobert Watson 	    ("destroying uninitialized label"));
77308bcdc58SRobert Watson 
77408bcdc58SRobert Watson 	bzero(label, sizeof(*label));
77508bcdc58SRobert Watson 	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
77608bcdc58SRobert Watson }
77708bcdc58SRobert Watson 
77808bcdc58SRobert Watson void
77987807196SRobert Watson mac_init_bpfdesc(struct bpf_d *bpf_d)
78008bcdc58SRobert Watson {
78108bcdc58SRobert Watson 
78287807196SRobert Watson 	mac_init_label(&bpf_d->bd_label);
78387807196SRobert Watson 	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
78408bcdc58SRobert Watson #ifdef MAC_DEBUG
78587807196SRobert Watson 	atomic_add_int(&nmacbpfdescs, 1);
78608bcdc58SRobert Watson #endif
78708bcdc58SRobert Watson }
78808bcdc58SRobert Watson 
789f7b951a8SRobert Watson static void
790f7b951a8SRobert Watson mac_init_cred_label(struct label *label)
79108bcdc58SRobert Watson {
79208bcdc58SRobert Watson 
793f7b951a8SRobert Watson 	mac_init_label(label);
794f7b951a8SRobert Watson 	MAC_PERFORM(init_cred_label, label);
79508bcdc58SRobert Watson #ifdef MAC_DEBUG
79608bcdc58SRobert Watson 	atomic_add_int(&nmaccreds, 1);
79708bcdc58SRobert Watson #endif
79808bcdc58SRobert Watson }
79908bcdc58SRobert Watson 
80008bcdc58SRobert Watson void
801f7b951a8SRobert Watson mac_init_cred(struct ucred *cred)
802f7b951a8SRobert Watson {
803f7b951a8SRobert Watson 
804f7b951a8SRobert Watson 	mac_init_cred_label(&cred->cr_label);
805f7b951a8SRobert Watson }
806f7b951a8SRobert Watson 
807f7b951a8SRobert Watson void
80887807196SRobert Watson mac_init_devfsdirent(struct devfs_dirent *de)
80908bcdc58SRobert Watson {
81008bcdc58SRobert Watson 
81187807196SRobert Watson 	mac_init_label(&de->de_label);
81287807196SRobert Watson 	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
81308bcdc58SRobert Watson #ifdef MAC_DEBUG
81487807196SRobert Watson 	atomic_add_int(&nmacdevfsdirents, 1);
81508bcdc58SRobert Watson #endif
81608bcdc58SRobert Watson }
81708bcdc58SRobert Watson 
818f7b951a8SRobert Watson static void
819f7b951a8SRobert Watson mac_init_ifnet_label(struct label *label)
820f7b951a8SRobert Watson {
821f7b951a8SRobert Watson 
822f7b951a8SRobert Watson 	mac_init_label(label);
823f7b951a8SRobert Watson 	MAC_PERFORM(init_ifnet_label, label);
824f7b951a8SRobert Watson #ifdef MAC_DEBUG
825f7b951a8SRobert Watson 	atomic_add_int(&nmacifnets, 1);
826f7b951a8SRobert Watson #endif
827f7b951a8SRobert Watson }
828f7b951a8SRobert Watson 
82908bcdc58SRobert Watson void
83008bcdc58SRobert Watson mac_init_ifnet(struct ifnet *ifp)
83108bcdc58SRobert Watson {
83208bcdc58SRobert Watson 
833f7b951a8SRobert Watson 	mac_init_ifnet_label(&ifp->if_label);
83408bcdc58SRobert Watson }
83508bcdc58SRobert Watson 
8365e7ce478SRobert Watson int
8375e7ce478SRobert Watson mac_init_ipq(struct ipq *ipq, int flag)
83808bcdc58SRobert Watson {
8395e7ce478SRobert Watson 	int error;
84008bcdc58SRobert Watson 
84108bcdc58SRobert Watson 	mac_init_label(&ipq->ipq_label);
8425e7ce478SRobert Watson 
8435e7ce478SRobert Watson 	MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag);
8445e7ce478SRobert Watson 	if (error) {
8455e7ce478SRobert Watson 		MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
8465e7ce478SRobert Watson 		mac_destroy_label(&ipq->ipq_label);
8475e7ce478SRobert Watson 	}
84808bcdc58SRobert Watson #ifdef MAC_DEBUG
8495e7ce478SRobert Watson 	if (error == 0)
85008bcdc58SRobert Watson 		atomic_add_int(&nmacipqs, 1);
85108bcdc58SRobert Watson #endif
8525e7ce478SRobert Watson 	return (error);
85308bcdc58SRobert Watson }
85408bcdc58SRobert Watson 
85587807196SRobert Watson int
856225bff6fSRobert Watson mac_init_mbuf_tag(struct m_tag *tag, int flag)
85708bcdc58SRobert Watson {
858225bff6fSRobert Watson 	struct label *label;
8596d1a6a9aSRobert Watson 	int error;
86056c15412SRobert Watson 
861225bff6fSRobert Watson 	label = (struct label *) (tag + 1);
862225bff6fSRobert Watson 	mac_init_label(label);
86308bcdc58SRobert Watson 
8646d1a6a9aSRobert Watson 	MAC_CHECK(init_mbuf_label, label, flag);
86556c15412SRobert Watson 	if (error) {
866225bff6fSRobert Watson 		MAC_PERFORM(destroy_mbuf_label, label);
867225bff6fSRobert Watson 		mac_destroy_label(label);
86856c15412SRobert Watson 	}
86908bcdc58SRobert Watson #ifdef MAC_DEBUG
87056c15412SRobert Watson 	if (error == 0)
87187807196SRobert Watson 		atomic_add_int(&nmacmbufs, 1);
87208bcdc58SRobert Watson #endif
87356c15412SRobert Watson 	return (error);
87408bcdc58SRobert Watson }
87508bcdc58SRobert Watson 
876225bff6fSRobert Watson int
877225bff6fSRobert Watson mac_init_mbuf(struct mbuf *m, int flag)
878225bff6fSRobert Watson {
879225bff6fSRobert Watson 	struct m_tag *tag;
880225bff6fSRobert Watson 	int error;
881225bff6fSRobert Watson 
882225bff6fSRobert Watson 	M_ASSERTPKTHDR(m);
883225bff6fSRobert Watson 
884225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
885225bff6fSRobert Watson 	/*
886225bff6fSRobert Watson 	 * Don't reserve space for labels on mbufs unless we have a policy
887225bff6fSRobert Watson 	 * that uses the labels.
888225bff6fSRobert Watson 	 */
889225bff6fSRobert Watson 	if (mac_labelmbufs) {
890225bff6fSRobert Watson #endif
891225bff6fSRobert Watson 		tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
892225bff6fSRobert Watson 		    flag);
893225bff6fSRobert Watson 		if (tag == NULL)
894225bff6fSRobert Watson 			return (ENOMEM);
895225bff6fSRobert Watson 		error = mac_init_mbuf_tag(tag, flag);
896225bff6fSRobert Watson 		if (error) {
897225bff6fSRobert Watson 			m_tag_free(tag);
898225bff6fSRobert Watson 			return (error);
899225bff6fSRobert Watson 		}
900225bff6fSRobert Watson 		m_tag_prepend(m, tag);
901225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
902225bff6fSRobert Watson 	}
903225bff6fSRobert Watson #endif
904225bff6fSRobert Watson 	return (0);
905225bff6fSRobert Watson }
906225bff6fSRobert Watson 
90708bcdc58SRobert Watson void
90887807196SRobert Watson mac_init_mount(struct mount *mp)
90908bcdc58SRobert Watson {
91008bcdc58SRobert Watson 
91187807196SRobert Watson 	mac_init_label(&mp->mnt_mntlabel);
91287807196SRobert Watson 	mac_init_label(&mp->mnt_fslabel);
91387807196SRobert Watson 	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
91487807196SRobert Watson 	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
91508bcdc58SRobert Watson #ifdef MAC_DEBUG
91687807196SRobert Watson 	atomic_add_int(&nmacmounts, 1);
91708bcdc58SRobert Watson #endif
91808bcdc58SRobert Watson }
91908bcdc58SRobert Watson 
920f7b951a8SRobert Watson static void
921f7b951a8SRobert Watson mac_init_pipe_label(struct label *label)
922f7b951a8SRobert Watson {
923f7b951a8SRobert Watson 
924f7b951a8SRobert Watson 	mac_init_label(label);
925f7b951a8SRobert Watson 	MAC_PERFORM(init_pipe_label, label);
926f7b951a8SRobert Watson #ifdef MAC_DEBUG
927f7b951a8SRobert Watson 	atomic_add_int(&nmacpipes, 1);
928f7b951a8SRobert Watson #endif
929f7b951a8SRobert Watson }
930f7b951a8SRobert Watson 
93108bcdc58SRobert Watson void
93208bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe)
93308bcdc58SRobert Watson {
93408bcdc58SRobert Watson 	struct label *label;
93508bcdc58SRobert Watson 
936a163d034SWarner Losh 	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
93708bcdc58SRobert Watson 	pipe->pipe_label = label;
93808bcdc58SRobert Watson 	pipe->pipe_peer->pipe_label = label;
939f7b951a8SRobert Watson 	mac_init_pipe_label(label);
94008bcdc58SRobert Watson }
94108bcdc58SRobert Watson 
9422555374cSRobert Watson void
9432555374cSRobert Watson mac_init_proc(struct proc *p)
9442555374cSRobert Watson {
9452555374cSRobert Watson 
9462555374cSRobert Watson 	mac_init_label(&p->p_label);
9472555374cSRobert Watson 	MAC_PERFORM(init_proc_label, &p->p_label);
9482555374cSRobert Watson #ifdef MAC_DEBUG
9492555374cSRobert Watson 	atomic_add_int(&nmacprocs, 1);
9502555374cSRobert Watson #endif
9512555374cSRobert Watson }
9522555374cSRobert Watson 
95383985c26SRobert Watson static int
95483985c26SRobert Watson mac_init_socket_label(struct label *label, int flag)
95508bcdc58SRobert Watson {
95683985c26SRobert Watson 	int error;
95708bcdc58SRobert Watson 
95883985c26SRobert Watson 	mac_init_label(label);
95983985c26SRobert Watson 
96083985c26SRobert Watson 	MAC_CHECK(init_socket_label, label, flag);
96183985c26SRobert Watson 	if (error) {
96283985c26SRobert Watson 		MAC_PERFORM(destroy_socket_label, label);
96383985c26SRobert Watson 		mac_destroy_label(label);
96483985c26SRobert Watson 	}
96583985c26SRobert Watson 
96608bcdc58SRobert Watson #ifdef MAC_DEBUG
96783985c26SRobert Watson 	if (error == 0)
96887807196SRobert Watson 		atomic_add_int(&nmacsockets, 1);
96987807196SRobert Watson #endif
97083985c26SRobert Watson 
97183985c26SRobert Watson 	return (error);
97283985c26SRobert Watson }
97383985c26SRobert Watson 
97483985c26SRobert Watson static int
97583985c26SRobert Watson mac_init_socket_peer_label(struct label *label, int flag)
97683985c26SRobert Watson {
97783985c26SRobert Watson 	int error;
97883985c26SRobert Watson 
97983985c26SRobert Watson 	mac_init_label(label);
98083985c26SRobert Watson 
98183985c26SRobert Watson 	MAC_CHECK(init_socket_peer_label, label, flag);
98283985c26SRobert Watson 	if (error) {
98383985c26SRobert Watson 		MAC_PERFORM(destroy_socket_label, label);
98483985c26SRobert Watson 		mac_destroy_label(label);
98583985c26SRobert Watson 	}
98683985c26SRobert Watson 
98783985c26SRobert Watson 	return (error);
98883985c26SRobert Watson }
98983985c26SRobert Watson 
99083985c26SRobert Watson int
99183985c26SRobert Watson mac_init_socket(struct socket *socket, int flag)
99283985c26SRobert Watson {
99383985c26SRobert Watson 	int error;
99483985c26SRobert Watson 
99583985c26SRobert Watson 	error = mac_init_socket_label(&socket->so_label, flag);
99683985c26SRobert Watson 	if (error)
99783985c26SRobert Watson 		return (error);
99883985c26SRobert Watson 
99983985c26SRobert Watson 	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
100083985c26SRobert Watson 	if (error)
100183985c26SRobert Watson 		mac_destroy_socket_label(&socket->so_label);
100283985c26SRobert Watson 
100383985c26SRobert Watson 	return (error);
100487807196SRobert Watson }
100587807196SRobert Watson 
1006763bbd2fSRobert Watson void
1007f7b951a8SRobert Watson mac_init_vnode_label(struct label *label)
100887807196SRobert Watson {
100987807196SRobert Watson 
101087807196SRobert Watson 	mac_init_label(label);
1011f7b951a8SRobert Watson 	MAC_PERFORM(init_vnode_label, label);
101287807196SRobert Watson #ifdef MAC_DEBUG
1013f7b951a8SRobert Watson 	atomic_add_int(&nmacvnodes, 1);
101408bcdc58SRobert Watson #endif
101508bcdc58SRobert Watson }
101608bcdc58SRobert Watson 
101708bcdc58SRobert Watson void
101887807196SRobert Watson mac_init_vnode(struct vnode *vp)
101908bcdc58SRobert Watson {
102008bcdc58SRobert Watson 
1021f7b951a8SRobert Watson 	mac_init_vnode_label(&vp->v_label);
102208bcdc58SRobert Watson }
102308bcdc58SRobert Watson 
102408bcdc58SRobert Watson void
102508bcdc58SRobert Watson mac_destroy_bpfdesc(struct bpf_d *bpf_d)
102608bcdc58SRobert Watson {
102708bcdc58SRobert Watson 
102808bcdc58SRobert Watson 	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
102908bcdc58SRobert Watson 	mac_destroy_label(&bpf_d->bd_label);
103008bcdc58SRobert Watson #ifdef MAC_DEBUG
103108bcdc58SRobert Watson 	atomic_subtract_int(&nmacbpfdescs, 1);
103208bcdc58SRobert Watson #endif
103308bcdc58SRobert Watson }
103408bcdc58SRobert Watson 
1035f7b951a8SRobert Watson static void
1036f7b951a8SRobert Watson mac_destroy_cred_label(struct label *label)
103708bcdc58SRobert Watson {
103808bcdc58SRobert Watson 
1039f7b951a8SRobert Watson 	MAC_PERFORM(destroy_cred_label, label);
1040f7b951a8SRobert Watson 	mac_destroy_label(label);
104108bcdc58SRobert Watson #ifdef MAC_DEBUG
104287807196SRobert Watson 	atomic_subtract_int(&nmaccreds, 1);
104387807196SRobert Watson #endif
104487807196SRobert Watson }
104587807196SRobert Watson 
104687807196SRobert Watson void
1047f7b951a8SRobert Watson mac_destroy_cred(struct ucred *cred)
1048f7b951a8SRobert Watson {
1049f7b951a8SRobert Watson 
1050f7b951a8SRobert Watson 	mac_destroy_cred_label(&cred->cr_label);
1051f7b951a8SRobert Watson }
1052f7b951a8SRobert Watson 
1053f7b951a8SRobert Watson void
105487807196SRobert Watson mac_destroy_devfsdirent(struct devfs_dirent *de)
105587807196SRobert Watson {
105687807196SRobert Watson 
105787807196SRobert Watson 	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
105887807196SRobert Watson 	mac_destroy_label(&de->de_label);
105987807196SRobert Watson #ifdef MAC_DEBUG
106087807196SRobert Watson 	atomic_subtract_int(&nmacdevfsdirents, 1);
106187807196SRobert Watson #endif
106287807196SRobert Watson }
106387807196SRobert Watson 
1064f7b951a8SRobert Watson static void
1065f7b951a8SRobert Watson mac_destroy_ifnet_label(struct label *label)
1066f7b951a8SRobert Watson {
1067f7b951a8SRobert Watson 
1068f7b951a8SRobert Watson 	MAC_PERFORM(destroy_ifnet_label, label);
1069f7b951a8SRobert Watson 	mac_destroy_label(label);
1070f7b951a8SRobert Watson #ifdef MAC_DEBUG
1071f7b951a8SRobert Watson 	atomic_subtract_int(&nmacifnets, 1);
1072f7b951a8SRobert Watson #endif
1073f7b951a8SRobert Watson }
1074f7b951a8SRobert Watson 
107587807196SRobert Watson void
107687807196SRobert Watson mac_destroy_ifnet(struct ifnet *ifp)
107787807196SRobert Watson {
107887807196SRobert Watson 
1079f7b951a8SRobert Watson 	mac_destroy_ifnet_label(&ifp->if_label);
108087807196SRobert Watson }
108187807196SRobert Watson 
108287807196SRobert Watson void
108387807196SRobert Watson mac_destroy_ipq(struct ipq *ipq)
108487807196SRobert Watson {
108587807196SRobert Watson 
108687807196SRobert Watson 	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
108787807196SRobert Watson 	mac_destroy_label(&ipq->ipq_label);
108887807196SRobert Watson #ifdef MAC_DEBUG
108987807196SRobert Watson 	atomic_subtract_int(&nmacipqs, 1);
109087807196SRobert Watson #endif
109187807196SRobert Watson }
109287807196SRobert Watson 
109387807196SRobert Watson void
1094225bff6fSRobert Watson mac_destroy_mbuf_tag(struct m_tag *tag)
109587807196SRobert Watson {
1096225bff6fSRobert Watson 	struct label *label;
109787807196SRobert Watson 
1098225bff6fSRobert Watson 	label = (struct label *)(tag+1);
1099225bff6fSRobert Watson 
1100225bff6fSRobert Watson 	MAC_PERFORM(destroy_mbuf_label, label);
1101225bff6fSRobert Watson 	mac_destroy_label(label);
110287807196SRobert Watson #ifdef MAC_DEBUG
110387807196SRobert Watson 	atomic_subtract_int(&nmacmbufs, 1);
110408bcdc58SRobert Watson #endif
110508bcdc58SRobert Watson }
110608bcdc58SRobert Watson 
110708bcdc58SRobert Watson void
110808bcdc58SRobert Watson mac_destroy_mount(struct mount *mp)
110908bcdc58SRobert Watson {
111008bcdc58SRobert Watson 
111108bcdc58SRobert Watson 	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
111208bcdc58SRobert Watson 	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
111308bcdc58SRobert Watson 	mac_destroy_label(&mp->mnt_fslabel);
111408bcdc58SRobert Watson 	mac_destroy_label(&mp->mnt_mntlabel);
111508bcdc58SRobert Watson #ifdef MAC_DEBUG
111608bcdc58SRobert Watson 	atomic_subtract_int(&nmacmounts, 1);
111708bcdc58SRobert Watson #endif
111808bcdc58SRobert Watson }
111908bcdc58SRobert Watson 
1120f7b951a8SRobert Watson static void
1121f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label)
1122f7b951a8SRobert Watson {
1123f7b951a8SRobert Watson 
1124f7b951a8SRobert Watson 	MAC_PERFORM(destroy_pipe_label, label);
1125f7b951a8SRobert Watson 	mac_destroy_label(label);
1126f7b951a8SRobert Watson #ifdef MAC_DEBUG
1127f7b951a8SRobert Watson 	atomic_subtract_int(&nmacpipes, 1);
1128f7b951a8SRobert Watson #endif
1129f7b951a8SRobert Watson }
1130f7b951a8SRobert Watson 
113187807196SRobert Watson void
113287807196SRobert Watson mac_destroy_pipe(struct pipe *pipe)
113308bcdc58SRobert Watson {
113408bcdc58SRobert Watson 
1135f7b951a8SRobert Watson 	mac_destroy_pipe_label(pipe->pipe_label);
113687807196SRobert Watson 	free(pipe->pipe_label, M_MACPIPELABEL);
113787807196SRobert Watson }
113887807196SRobert Watson 
11392555374cSRobert Watson void
11402555374cSRobert Watson mac_destroy_proc(struct proc *p)
11412555374cSRobert Watson {
11422555374cSRobert Watson 
11432555374cSRobert Watson 	MAC_PERFORM(destroy_proc_label, &p->p_label);
11442555374cSRobert Watson 	mac_destroy_label(&p->p_label);
11452555374cSRobert Watson #ifdef MAC_DEBUG
11462555374cSRobert Watson 	atomic_subtract_int(&nmacprocs, 1);
11472555374cSRobert Watson #endif
11482555374cSRobert Watson }
11492555374cSRobert Watson 
115083985c26SRobert Watson static void
115183985c26SRobert Watson mac_destroy_socket_label(struct label *label)
115283985c26SRobert Watson {
115383985c26SRobert Watson 
115483985c26SRobert Watson 	MAC_PERFORM(destroy_socket_label, label);
115583985c26SRobert Watson 	mac_destroy_label(label);
115683985c26SRobert Watson #ifdef MAC_DEBUG
115783985c26SRobert Watson 	atomic_subtract_int(&nmacsockets, 1);
115883985c26SRobert Watson #endif
115983985c26SRobert Watson }
116083985c26SRobert Watson 
116183985c26SRobert Watson static void
116283985c26SRobert Watson mac_destroy_socket_peer_label(struct label *label)
116383985c26SRobert Watson {
116483985c26SRobert Watson 
116583985c26SRobert Watson 	MAC_PERFORM(destroy_socket_peer_label, label);
116683985c26SRobert Watson 	mac_destroy_label(label);
116783985c26SRobert Watson }
116883985c26SRobert Watson 
116987807196SRobert Watson void
117087807196SRobert Watson mac_destroy_socket(struct socket *socket)
117187807196SRobert Watson {
117287807196SRobert Watson 
117383985c26SRobert Watson 	mac_destroy_socket_label(&socket->so_label);
117483985c26SRobert Watson 	mac_destroy_socket_peer_label(&socket->so_peerlabel);
117508bcdc58SRobert Watson }
117608bcdc58SRobert Watson 
1177763bbd2fSRobert Watson void
1178f7b951a8SRobert Watson mac_destroy_vnode_label(struct label *label)
117908bcdc58SRobert Watson {
118008bcdc58SRobert Watson 
1181f7b951a8SRobert Watson 	MAC_PERFORM(destroy_vnode_label, label);
118208bcdc58SRobert Watson 	mac_destroy_label(label);
118308bcdc58SRobert Watson #ifdef MAC_DEBUG
1184f7b951a8SRobert Watson 	atomic_subtract_int(&nmacvnodes, 1);
118508bcdc58SRobert Watson #endif
118608bcdc58SRobert Watson }
118708bcdc58SRobert Watson 
118808bcdc58SRobert Watson void
118908bcdc58SRobert Watson mac_destroy_vnode(struct vnode *vp)
119008bcdc58SRobert Watson {
119108bcdc58SRobert Watson 
1192f7b951a8SRobert Watson 	mac_destroy_vnode_label(&vp->v_label);
1193f7b951a8SRobert Watson }
1194f7b951a8SRobert Watson 
1195225bff6fSRobert Watson void
1196225bff6fSRobert Watson mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
1197225bff6fSRobert Watson {
1198225bff6fSRobert Watson 	struct label *src_label, *dest_label;
1199225bff6fSRobert Watson 
1200225bff6fSRobert Watson 	src_label = (struct label *)(src+1);
1201225bff6fSRobert Watson 	dest_label = (struct label *)(dest+1);
1202225bff6fSRobert Watson 
1203225bff6fSRobert Watson 	/*
1204225bff6fSRobert Watson 	 * mac_init_mbuf_tag() is called on the target tag in
1205225bff6fSRobert Watson 	 * m_tag_copy(), so we don't need to call it here.
1206225bff6fSRobert Watson 	 */
1207225bff6fSRobert Watson 	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
1208225bff6fSRobert Watson }
1209225bff6fSRobert Watson 
1210f7b951a8SRobert Watson static void
1211f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest)
1212f7b951a8SRobert Watson {
1213f7b951a8SRobert Watson 
1214f7b951a8SRobert Watson 	MAC_PERFORM(copy_pipe_label, src, dest);
1215f7b951a8SRobert Watson }
1216f7b951a8SRobert Watson 
1217763bbd2fSRobert Watson void
1218f7b951a8SRobert Watson mac_copy_vnode_label(struct label *src, struct label *dest)
1219f7b951a8SRobert Watson {
1220f7b951a8SRobert Watson 
1221f7b951a8SRobert Watson 	MAC_PERFORM(copy_vnode_label, src, dest);
122208bcdc58SRobert Watson }
122308bcdc58SRobert Watson 
122469bbb5b1SRobert Watson static int
1225f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac)
1226f7b951a8SRobert Watson {
1227f7b951a8SRobert Watson 
1228f7b951a8SRobert Watson 	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1229f7b951a8SRobert Watson 		return (EINVAL);
1230f7b951a8SRobert Watson 
1231f7b951a8SRobert Watson 	return (0);
1232f7b951a8SRobert Watson }
1233f7b951a8SRobert Watson 
1234f7b951a8SRobert Watson static int
1235f7b951a8SRobert Watson mac_externalize_cred_label(struct label *label, char *elements,
1236f7b951a8SRobert Watson     char *outbuf, size_t outbuflen, int flags)
123769bbb5b1SRobert Watson {
123869bbb5b1SRobert Watson 	int error;
123969bbb5b1SRobert Watson 
1240f7b951a8SRobert Watson 	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
124169bbb5b1SRobert Watson 
124269bbb5b1SRobert Watson 	return (error);
124369bbb5b1SRobert Watson }
124469bbb5b1SRobert Watson 
124569bbb5b1SRobert Watson static int
1246f7b951a8SRobert Watson mac_externalize_ifnet_label(struct label *label, char *elements,
1247f7b951a8SRobert Watson     char *outbuf, size_t outbuflen, int flags)
124869bbb5b1SRobert Watson {
124969bbb5b1SRobert Watson 	int error;
125069bbb5b1SRobert Watson 
1251f7b951a8SRobert Watson 	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1252f7b951a8SRobert Watson 
1253f7b951a8SRobert Watson 	return (error);
1254f7b951a8SRobert Watson }
1255f7b951a8SRobert Watson 
1256f7b951a8SRobert Watson static int
1257f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements,
1258f7b951a8SRobert Watson     char *outbuf, size_t outbuflen, int flags)
1259f7b951a8SRobert Watson {
1260f7b951a8SRobert Watson 	int error;
1261f7b951a8SRobert Watson 
1262f7b951a8SRobert Watson 	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1263f7b951a8SRobert Watson 
1264f7b951a8SRobert Watson 	return (error);
1265f7b951a8SRobert Watson }
1266f7b951a8SRobert Watson 
1267f7b951a8SRobert Watson static int
1268f7b951a8SRobert Watson mac_externalize_socket_label(struct label *label, char *elements,
1269f7b951a8SRobert Watson     char *outbuf, size_t outbuflen, int flags)
1270f7b951a8SRobert Watson {
1271f7b951a8SRobert Watson 	int error;
1272f7b951a8SRobert Watson 
1273f7b951a8SRobert Watson 	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1274f7b951a8SRobert Watson 
1275f7b951a8SRobert Watson 	return (error);
1276f7b951a8SRobert Watson }
1277f7b951a8SRobert Watson 
1278f7b951a8SRobert Watson static int
1279f7b951a8SRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements,
1280f7b951a8SRobert Watson     char *outbuf, size_t outbuflen, int flags)
1281f7b951a8SRobert Watson {
1282f7b951a8SRobert Watson 	int error;
1283f7b951a8SRobert Watson 
1284f7b951a8SRobert Watson 	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1285f7b951a8SRobert Watson 
1286f7b951a8SRobert Watson 	return (error);
1287f7b951a8SRobert Watson }
1288f7b951a8SRobert Watson 
1289f7b951a8SRobert Watson static int
1290f7b951a8SRobert Watson mac_externalize_vnode_label(struct label *label, char *elements,
1291f7b951a8SRobert Watson     char *outbuf, size_t outbuflen, int flags)
1292f7b951a8SRobert Watson {
1293f7b951a8SRobert Watson 	int error;
1294f7b951a8SRobert Watson 
1295f7b951a8SRobert Watson 	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1296f7b951a8SRobert Watson 
1297f7b951a8SRobert Watson 	return (error);
1298f7b951a8SRobert Watson }
1299f7b951a8SRobert Watson 
1300f7b951a8SRobert Watson static int
1301f7b951a8SRobert Watson mac_internalize_cred_label(struct label *label, char *string)
1302f7b951a8SRobert Watson {
1303f7b951a8SRobert Watson 	int error;
1304f7b951a8SRobert Watson 
1305f7b951a8SRobert Watson 	MAC_INTERNALIZE(cred_label, label, string);
1306f7b951a8SRobert Watson 
1307f7b951a8SRobert Watson 	return (error);
1308f7b951a8SRobert Watson }
1309f7b951a8SRobert Watson 
1310f7b951a8SRobert Watson static int
1311f7b951a8SRobert Watson mac_internalize_ifnet_label(struct label *label, char *string)
1312f7b951a8SRobert Watson {
1313f7b951a8SRobert Watson 	int error;
1314f7b951a8SRobert Watson 
1315f7b951a8SRobert Watson 	MAC_INTERNALIZE(ifnet_label, label, string);
1316f7b951a8SRobert Watson 
1317f7b951a8SRobert Watson 	return (error);
1318f7b951a8SRobert Watson }
1319f7b951a8SRobert Watson 
1320f7b951a8SRobert Watson static int
1321f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string)
1322f7b951a8SRobert Watson {
1323f7b951a8SRobert Watson 	int error;
1324f7b951a8SRobert Watson 
1325f7b951a8SRobert Watson 	MAC_INTERNALIZE(pipe_label, label, string);
1326f7b951a8SRobert Watson 
1327f7b951a8SRobert Watson 	return (error);
1328f7b951a8SRobert Watson }
1329f7b951a8SRobert Watson 
1330f7b951a8SRobert Watson static int
1331f7b951a8SRobert Watson mac_internalize_socket_label(struct label *label, char *string)
1332f7b951a8SRobert Watson {
1333f7b951a8SRobert Watson 	int error;
1334f7b951a8SRobert Watson 
1335f7b951a8SRobert Watson 	MAC_INTERNALIZE(socket_label, label, string);
1336f7b951a8SRobert Watson 
1337f7b951a8SRobert Watson 	return (error);
1338f7b951a8SRobert Watson }
1339f7b951a8SRobert Watson 
1340f7b951a8SRobert Watson static int
1341f7b951a8SRobert Watson mac_internalize_vnode_label(struct label *label, char *string)
1342f7b951a8SRobert Watson {
1343f7b951a8SRobert Watson 	int error;
1344f7b951a8SRobert Watson 
1345f7b951a8SRobert Watson 	MAC_INTERNALIZE(vnode_label, label, string);
134669bbb5b1SRobert Watson 
134769bbb5b1SRobert Watson 	return (error);
134869bbb5b1SRobert Watson }
134969bbb5b1SRobert Watson 
135069bbb5b1SRobert Watson /*
135169bbb5b1SRobert Watson  * Initialize MAC label for the first kernel process, from which other
135269bbb5b1SRobert Watson  * kernel processes and threads are spawned.
135369bbb5b1SRobert Watson  */
135469bbb5b1SRobert Watson void
135569bbb5b1SRobert Watson mac_create_proc0(struct ucred *cred)
135669bbb5b1SRobert Watson {
135769bbb5b1SRobert Watson 
135869bbb5b1SRobert Watson 	MAC_PERFORM(create_proc0, cred);
135969bbb5b1SRobert Watson }
136069bbb5b1SRobert Watson 
136169bbb5b1SRobert Watson /*
136269bbb5b1SRobert Watson  * Initialize MAC label for the first userland process, from which other
136369bbb5b1SRobert Watson  * userland processes and threads are spawned.
136469bbb5b1SRobert Watson  */
136569bbb5b1SRobert Watson void
136669bbb5b1SRobert Watson mac_create_proc1(struct ucred *cred)
136769bbb5b1SRobert Watson {
136869bbb5b1SRobert Watson 
136969bbb5b1SRobert Watson 	MAC_PERFORM(create_proc1, cred);
137069bbb5b1SRobert Watson }
137169bbb5b1SRobert Watson 
137269bbb5b1SRobert Watson void
137369bbb5b1SRobert Watson mac_thread_userret(struct thread *td)
137469bbb5b1SRobert Watson {
137569bbb5b1SRobert Watson 
137669bbb5b1SRobert Watson 	MAC_PERFORM(thread_userret, td);
137769bbb5b1SRobert Watson }
137869bbb5b1SRobert Watson 
137969bbb5b1SRobert Watson /*
138069bbb5b1SRobert Watson  * When a new process is created, its label must be initialized.  Generally,
138169bbb5b1SRobert Watson  * this involves inheritence from the parent process, modulo possible
138269bbb5b1SRobert Watson  * deltas.  This function allows that processing to take place.
138369bbb5b1SRobert Watson  */
138469bbb5b1SRobert Watson void
138569bbb5b1SRobert Watson mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
138669bbb5b1SRobert Watson {
138769bbb5b1SRobert Watson 
138869bbb5b1SRobert Watson 	MAC_PERFORM(create_cred, parent_cred, child_cred);
138969bbb5b1SRobert Watson }
139069bbb5b1SRobert Watson 
139195fab37eSRobert Watson void
1392990b4b2dSRobert Watson mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1393990b4b2dSRobert Watson     struct vnode *vp)
139495fab37eSRobert Watson {
139595fab37eSRobert Watson 
1396990b4b2dSRobert Watson 	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1397990b4b2dSRobert Watson 	    &vp->v_label);
139895fab37eSRobert Watson }
139995fab37eSRobert Watson 
140095fab37eSRobert Watson void
1401763bbd2fSRobert Watson mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1402763bbd2fSRobert Watson     struct vnode *vp)
140395fab37eSRobert Watson {
140495fab37eSRobert Watson 
1405763bbd2fSRobert Watson 	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1406763bbd2fSRobert Watson 	    &de->de_label, vp, &vp->v_label);
140795fab37eSRobert Watson }
140895fab37eSRobert Watson 
1409763bbd2fSRobert Watson int
1410763bbd2fSRobert Watson mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
141195fab37eSRobert Watson {
141295fab37eSRobert Watson 	int error;
141395fab37eSRobert Watson 
1414763bbd2fSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1415763bbd2fSRobert Watson 
1416763bbd2fSRobert Watson 	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1417763bbd2fSRobert Watson 	    &vp->v_label);
141895fab37eSRobert Watson 
141995fab37eSRobert Watson 	return (error);
142095fab37eSRobert Watson }
142195fab37eSRobert Watson 
142295fab37eSRobert Watson void
1423763bbd2fSRobert Watson mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
142495fab37eSRobert Watson {
142595fab37eSRobert Watson 
1426763bbd2fSRobert Watson 	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1427763bbd2fSRobert Watson 	    &vp->v_label);
142895fab37eSRobert Watson }
142995fab37eSRobert Watson 
143095fab37eSRobert Watson int
1431763bbd2fSRobert Watson mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1432763bbd2fSRobert Watson     struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
143395fab37eSRobert Watson {
1434763bbd2fSRobert Watson 	int error;
143595fab37eSRobert Watson 
1436763bbd2fSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1437763bbd2fSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
143895fab37eSRobert Watson 
1439763bbd2fSRobert Watson 	error = VOP_OPENEXTATTR(vp, cred, curthread);
1440763bbd2fSRobert Watson 	if (error == EOPNOTSUPP) {
1441763bbd2fSRobert Watson 		/* XXX: Optionally abort if transactions not supported. */
1442763bbd2fSRobert Watson 		if (ea_warn_once == 0) {
1443763bbd2fSRobert Watson 			printf("Warning: transactions not supported "
1444763bbd2fSRobert Watson 			    "in EA write.\n");
1445763bbd2fSRobert Watson 			ea_warn_once = 1;
1446763bbd2fSRobert Watson 		}
1447763bbd2fSRobert Watson 	} else if (error)
144895fab37eSRobert Watson 		return (error);
144995fab37eSRobert Watson 
1450763bbd2fSRobert Watson 	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1451763bbd2fSRobert Watson 	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
145295fab37eSRobert Watson 
1453763bbd2fSRobert Watson 	if (error) {
1454763bbd2fSRobert Watson 		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
145595fab37eSRobert Watson 		return (error);
145695fab37eSRobert Watson 	}
145795fab37eSRobert Watson 
1458763bbd2fSRobert Watson 	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
145995fab37eSRobert Watson 
1460763bbd2fSRobert Watson 	if (error == EOPNOTSUPP)
1461763bbd2fSRobert Watson 		error = 0;				/* XXX */
146295fab37eSRobert Watson 
146395fab37eSRobert Watson 	return (error);
146495fab37eSRobert Watson }
146595fab37eSRobert Watson 
146695fab37eSRobert Watson static int
1467763bbd2fSRobert Watson mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1468763bbd2fSRobert Watson     struct label *intlabel)
146995fab37eSRobert Watson {
147095fab37eSRobert Watson 	int error;
147195fab37eSRobert Watson 
1472763bbd2fSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
147395fab37eSRobert Watson 
1474763bbd2fSRobert Watson 	error = VOP_OPENEXTATTR(vp, cred, curthread);
1475763bbd2fSRobert Watson 	if (error == EOPNOTSUPP) {
1476763bbd2fSRobert Watson 		/* XXX: Optionally abort if transactions not supported. */
1477763bbd2fSRobert Watson 		if (ea_warn_once == 0) {
1478763bbd2fSRobert Watson 			printf("Warning: transactions not supported "
1479763bbd2fSRobert Watson 			    "in EA write.\n");
1480763bbd2fSRobert Watson 			ea_warn_once = 1;
148195fab37eSRobert Watson 		}
1482763bbd2fSRobert Watson 	} else if (error)
148395fab37eSRobert Watson 		return (error);
148495fab37eSRobert Watson 
1485763bbd2fSRobert Watson 	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
148695fab37eSRobert Watson 
1487763bbd2fSRobert Watson 	if (error) {
1488763bbd2fSRobert Watson 		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
148995fab37eSRobert Watson 		return (error);
149095fab37eSRobert Watson 	}
149195fab37eSRobert Watson 
1492763bbd2fSRobert Watson 	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1493763bbd2fSRobert Watson 
1494763bbd2fSRobert Watson 	if (error == EOPNOTSUPP)
1495763bbd2fSRobert Watson 		error = 0;				/* XXX */
1496763bbd2fSRobert Watson 
1497763bbd2fSRobert Watson 	return (error);
149895fab37eSRobert Watson }
149995fab37eSRobert Watson 
1500670cb89bSRobert Watson int
1501670cb89bSRobert Watson mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1502670cb89bSRobert Watson     struct label *execlabelstorage)
1503670cb89bSRobert Watson {
1504670cb89bSRobert Watson 	struct mac mac;
1505670cb89bSRobert Watson 	char *buffer;
1506670cb89bSRobert Watson 	int error;
1507670cb89bSRobert Watson 
1508670cb89bSRobert Watson 	if (mac_p == NULL)
1509670cb89bSRobert Watson 		return (0);
1510670cb89bSRobert Watson 
1511670cb89bSRobert Watson 	error = copyin(mac_p, &mac, sizeof(mac));
1512670cb89bSRobert Watson 	if (error)
1513670cb89bSRobert Watson 		return (error);
1514670cb89bSRobert Watson 
1515670cb89bSRobert Watson 	error = mac_check_structmac_consistent(&mac);
1516670cb89bSRobert Watson 	if (error)
1517670cb89bSRobert Watson 		return (error);
1518670cb89bSRobert Watson 
1519a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1520670cb89bSRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1521670cb89bSRobert Watson 	if (error) {
1522670cb89bSRobert Watson 		free(buffer, M_MACTEMP);
1523670cb89bSRobert Watson 		return (error);
1524670cb89bSRobert Watson 	}
1525670cb89bSRobert Watson 
1526670cb89bSRobert Watson 	mac_init_cred_label(execlabelstorage);
1527670cb89bSRobert Watson 	error = mac_internalize_cred_label(execlabelstorage, buffer);
1528670cb89bSRobert Watson 	free(buffer, M_MACTEMP);
1529670cb89bSRobert Watson 	if (error) {
1530670cb89bSRobert Watson 		mac_destroy_cred_label(execlabelstorage);
1531670cb89bSRobert Watson 		return (error);
1532670cb89bSRobert Watson 	}
1533670cb89bSRobert Watson 	imgp->execlabel = execlabelstorage;
1534670cb89bSRobert Watson 	return (0);
1535670cb89bSRobert Watson }
1536670cb89bSRobert Watson 
153795fab37eSRobert Watson void
1538670cb89bSRobert Watson mac_execve_exit(struct image_params *imgp)
1539670cb89bSRobert Watson {
1540670cb89bSRobert Watson 	if (imgp->execlabel != NULL)
1541670cb89bSRobert Watson 		mac_destroy_cred_label(imgp->execlabel);
1542670cb89bSRobert Watson }
1543670cb89bSRobert Watson 
1544670cb89bSRobert Watson void
1545670cb89bSRobert Watson mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1546670cb89bSRobert Watson     struct label *interpvnodelabel, struct image_params *imgp)
154795fab37eSRobert Watson {
154895fab37eSRobert Watson 
154995fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
155095fab37eSRobert Watson 
15514443e9ffSRobert Watson 	if (!mac_enforce_process && !mac_enforce_fs)
15524443e9ffSRobert Watson 		return;
15534443e9ffSRobert Watson 
1554670cb89bSRobert Watson 	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
15559fa3506eSRobert Watson 	    interpvnodelabel, imgp, imgp->execlabel);
155695fab37eSRobert Watson }
155795fab37eSRobert Watson 
155895fab37eSRobert Watson int
1559670cb89bSRobert Watson mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1560670cb89bSRobert Watson     struct label *interpvnodelabel, struct image_params *imgp)
156195fab37eSRobert Watson {
1562763bbd2fSRobert Watson 	int result;
156395fab37eSRobert Watson 
15644443e9ffSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
15654443e9ffSRobert Watson 
15664443e9ffSRobert Watson 	if (!mac_enforce_process && !mac_enforce_fs)
15674443e9ffSRobert Watson 		return (0);
15684443e9ffSRobert Watson 
156995fab37eSRobert Watson 	result = 0;
1570670cb89bSRobert Watson 	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
15719fa3506eSRobert Watson 	    interpvnodelabel, imgp, imgp->execlabel);
157295fab37eSRobert Watson 
157395fab37eSRobert Watson 	return (result);
157495fab37eSRobert Watson }
157595fab37eSRobert Watson 
157695fab37eSRobert Watson int
1577b914de36SRobert Watson mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
157895fab37eSRobert Watson {
157995fab37eSRobert Watson 	int error;
158095fab37eSRobert Watson 
158195fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
158295fab37eSRobert Watson 
158395fab37eSRobert Watson 	if (!mac_enforce_fs)
158495fab37eSRobert Watson 		return (0);
158595fab37eSRobert Watson 
1586b914de36SRobert Watson 	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
158795fab37eSRobert Watson 	return (error);
158895fab37eSRobert Watson }
158995fab37eSRobert Watson 
159095fab37eSRobert Watson int
159195fab37eSRobert Watson mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
159295fab37eSRobert Watson {
159395fab37eSRobert Watson 	int error;
159495fab37eSRobert Watson 
159595fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
159695fab37eSRobert Watson 
159795fab37eSRobert Watson 	if (!mac_enforce_fs)
159895fab37eSRobert Watson 		return (0);
159995fab37eSRobert Watson 
160095fab37eSRobert Watson 	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
160195fab37eSRobert Watson 	return (error);
160295fab37eSRobert Watson }
160395fab37eSRobert Watson 
160495fab37eSRobert Watson int
160595fab37eSRobert Watson mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
160695fab37eSRobert Watson {
160795fab37eSRobert Watson 	int error;
160895fab37eSRobert Watson 
160995fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
161095fab37eSRobert Watson 
161195fab37eSRobert Watson 	if (!mac_enforce_fs)
161295fab37eSRobert Watson 		return (0);
161395fab37eSRobert Watson 
161495fab37eSRobert Watson 	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
161595fab37eSRobert Watson 	return (error);
161695fab37eSRobert Watson }
161795fab37eSRobert Watson 
161895fab37eSRobert Watson int
161995fab37eSRobert Watson mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
162095fab37eSRobert Watson     struct componentname *cnp, struct vattr *vap)
162195fab37eSRobert Watson {
162295fab37eSRobert Watson 	int error;
162395fab37eSRobert Watson 
162495fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
162595fab37eSRobert Watson 
162695fab37eSRobert Watson 	if (!mac_enforce_fs)
162795fab37eSRobert Watson 		return (0);
162895fab37eSRobert Watson 
162995fab37eSRobert Watson 	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
163095fab37eSRobert Watson 	return (error);
163195fab37eSRobert Watson }
163295fab37eSRobert Watson 
163395fab37eSRobert Watson int
163495fab37eSRobert Watson mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
163595fab37eSRobert Watson     struct componentname *cnp)
163695fab37eSRobert Watson {
163795fab37eSRobert Watson 	int error;
163895fab37eSRobert Watson 
163995fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
164095fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
164195fab37eSRobert Watson 
164295fab37eSRobert Watson 	if (!mac_enforce_fs)
164395fab37eSRobert Watson 		return (0);
164495fab37eSRobert Watson 
164595fab37eSRobert Watson 	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
164695fab37eSRobert Watson 	    &vp->v_label, cnp);
164795fab37eSRobert Watson 	return (error);
164895fab37eSRobert Watson }
164995fab37eSRobert Watson 
165095fab37eSRobert Watson int
165195fab37eSRobert Watson mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
165295fab37eSRobert Watson     acl_type_t type)
165395fab37eSRobert Watson {
165495fab37eSRobert Watson 	int error;
165595fab37eSRobert Watson 
165695fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
165795fab37eSRobert Watson 
165895fab37eSRobert Watson 	if (!mac_enforce_fs)
165995fab37eSRobert Watson 		return (0);
166095fab37eSRobert Watson 
166195fab37eSRobert Watson 	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
166295fab37eSRobert Watson 	return (error);
166395fab37eSRobert Watson }
166495fab37eSRobert Watson 
166595fab37eSRobert Watson int
1666670cb89bSRobert Watson mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1667670cb89bSRobert Watson     struct image_params *imgp)
166895fab37eSRobert Watson {
166995fab37eSRobert Watson 	int error;
167095fab37eSRobert Watson 
1671851704bbSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1672851704bbSRobert Watson 
167395fab37eSRobert Watson 	if (!mac_enforce_process && !mac_enforce_fs)
167495fab37eSRobert Watson 		return (0);
167595fab37eSRobert Watson 
16769fa3506eSRobert Watson 	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
16779fa3506eSRobert Watson 	    imgp->execlabel);
167895fab37eSRobert Watson 
167995fab37eSRobert Watson 	return (error);
168095fab37eSRobert Watson }
168195fab37eSRobert Watson 
168295fab37eSRobert Watson int
168395fab37eSRobert Watson mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
168495fab37eSRobert Watson {
168595fab37eSRobert Watson 	int error;
168695fab37eSRobert Watson 
168795fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
168895fab37eSRobert Watson 
168995fab37eSRobert Watson 	if (!mac_enforce_fs)
169095fab37eSRobert Watson 		return (0);
169195fab37eSRobert Watson 
169295fab37eSRobert Watson 	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
169395fab37eSRobert Watson 	return (error);
169495fab37eSRobert Watson }
169595fab37eSRobert Watson 
169695fab37eSRobert Watson int
169795fab37eSRobert Watson mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
169895fab37eSRobert Watson     int attrnamespace, const char *name, struct uio *uio)
169995fab37eSRobert Watson {
170095fab37eSRobert Watson 	int error;
170195fab37eSRobert Watson 
170295fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
170395fab37eSRobert Watson 
170495fab37eSRobert Watson 	if (!mac_enforce_fs)
170595fab37eSRobert Watson 		return (0);
170695fab37eSRobert Watson 
170795fab37eSRobert Watson 	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
170895fab37eSRobert Watson 	    attrnamespace, name, uio);
170995fab37eSRobert Watson 	return (error);
171095fab37eSRobert Watson }
171195fab37eSRobert Watson 
171295fab37eSRobert Watson int
17130a694196SRobert Watson mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
17140a694196SRobert Watson     struct vnode *vp, struct componentname *cnp)
17150a694196SRobert Watson {
17160a694196SRobert Watson 	int error;
17170a694196SRobert Watson 
17180a694196SRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
17190a694196SRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
17200a694196SRobert Watson 
17210a694196SRobert Watson 	if (!mac_enforce_fs)
17220a694196SRobert Watson 		return (0);
17230a694196SRobert Watson 
17240a694196SRobert Watson 	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
17250a694196SRobert Watson 	    &vp->v_label, cnp);
17260a694196SRobert Watson 	return (error);
17270a694196SRobert Watson }
17280a694196SRobert Watson 
17290a694196SRobert Watson int
173095fab37eSRobert Watson mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
173195fab37eSRobert Watson     struct componentname *cnp)
173295fab37eSRobert Watson {
173395fab37eSRobert Watson 	int error;
173495fab37eSRobert Watson 
173595fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
173695fab37eSRobert Watson 
173795fab37eSRobert Watson 	if (!mac_enforce_fs)
173895fab37eSRobert Watson 		return (0);
173995fab37eSRobert Watson 
174095fab37eSRobert Watson 	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
174195fab37eSRobert Watson 	return (error);
174295fab37eSRobert Watson }
174395fab37eSRobert Watson 
1744e183f80eSRobert Watson int
1745e183f80eSRobert Watson mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
174695fab37eSRobert Watson {
1747e183f80eSRobert Watson 	int error;
174895fab37eSRobert Watson 
1749e183f80eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1750ca7850c3SRobert Watson 
1751e183f80eSRobert Watson 	if (!mac_enforce_fs || !mac_enforce_vm)
1752e183f80eSRobert Watson 		return (0);
1753e183f80eSRobert Watson 
1754e183f80eSRobert Watson 	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1755e183f80eSRobert Watson 	return (error);
1756e183f80eSRobert Watson }
1757e183f80eSRobert Watson 
1758e183f80eSRobert Watson void
1759e183f80eSRobert Watson mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1760e183f80eSRobert Watson {
1761e183f80eSRobert Watson 	int result = *prot;
1762e183f80eSRobert Watson 
1763e183f80eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1764e183f80eSRobert Watson 
1765e183f80eSRobert Watson 	if (!mac_enforce_fs || !mac_enforce_vm)
1766e183f80eSRobert Watson 		return;
1767e183f80eSRobert Watson 
1768e183f80eSRobert Watson 	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1769e183f80eSRobert Watson 	    &result);
1770e183f80eSRobert Watson 
1771e183f80eSRobert Watson 	*prot = result;
1772e183f80eSRobert Watson }
1773e183f80eSRobert Watson 
1774e183f80eSRobert Watson int
1775e183f80eSRobert Watson mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1776e183f80eSRobert Watson {
1777e183f80eSRobert Watson 	int error;
1778e183f80eSRobert Watson 
1779e183f80eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1780e183f80eSRobert Watson 
1781e183f80eSRobert Watson 	if (!mac_enforce_fs || !mac_enforce_vm)
1782e183f80eSRobert Watson 		return (0);
1783e183f80eSRobert Watson 
1784e183f80eSRobert Watson 	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1785e183f80eSRobert Watson 	return (error);
178695fab37eSRobert Watson }
178795fab37eSRobert Watson 
178895fab37eSRobert Watson int
1789b914de36SRobert Watson mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
179095fab37eSRobert Watson {
179195fab37eSRobert Watson 	int error;
179295fab37eSRobert Watson 
179395fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
179495fab37eSRobert Watson 
179595fab37eSRobert Watson 	if (!mac_enforce_fs)
179695fab37eSRobert Watson 		return (0);
179795fab37eSRobert Watson 
179895fab37eSRobert Watson 	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
179995fab37eSRobert Watson 	return (error);
180095fab37eSRobert Watson }
180195fab37eSRobert Watson 
180295fab37eSRobert Watson int
1803177142e4SRobert Watson mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1804177142e4SRobert Watson     struct vnode *vp)
18057f724f8bSRobert Watson {
18067f724f8bSRobert Watson 	int error;
18077f724f8bSRobert Watson 
18087f724f8bSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
18097f724f8bSRobert Watson 
18107f724f8bSRobert Watson 	if (!mac_enforce_fs)
18117f724f8bSRobert Watson 		return (0);
18127f724f8bSRobert Watson 
1813177142e4SRobert Watson 	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1814177142e4SRobert Watson 	    &vp->v_label);
18157f724f8bSRobert Watson 
18167f724f8bSRobert Watson 	return (error);
18177f724f8bSRobert Watson }
18187f724f8bSRobert Watson 
18197f724f8bSRobert Watson int
1820177142e4SRobert Watson mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1821177142e4SRobert Watson     struct vnode *vp)
18227f724f8bSRobert Watson {
18237f724f8bSRobert Watson 	int error;
18247f724f8bSRobert Watson 
18257f724f8bSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
18267f724f8bSRobert Watson 
18277f724f8bSRobert Watson 	if (!mac_enforce_fs)
18287f724f8bSRobert Watson 		return (0);
18297f724f8bSRobert Watson 
1830177142e4SRobert Watson 	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1831177142e4SRobert Watson 	    &vp->v_label);
18327f724f8bSRobert Watson 
18337f724f8bSRobert Watson 	return (error);
18347f724f8bSRobert Watson }
18357f724f8bSRobert Watson 
18367f724f8bSRobert Watson int
183795fab37eSRobert Watson mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
183895fab37eSRobert Watson {
183995fab37eSRobert Watson 	int error;
184095fab37eSRobert Watson 
184195fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
184295fab37eSRobert Watson 
184395fab37eSRobert Watson 	if (!mac_enforce_fs)
184495fab37eSRobert Watson 		return (0);
184595fab37eSRobert Watson 
184695fab37eSRobert Watson 	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
184795fab37eSRobert Watson 	return (error);
184895fab37eSRobert Watson }
184995fab37eSRobert Watson 
185095fab37eSRobert Watson int
185195fab37eSRobert Watson mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
185295fab37eSRobert Watson {
185395fab37eSRobert Watson 	int error;
185495fab37eSRobert Watson 
185595fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
185695fab37eSRobert Watson 
185795fab37eSRobert Watson 	if (!mac_enforce_fs)
185895fab37eSRobert Watson 		return (0);
185995fab37eSRobert Watson 
186095fab37eSRobert Watson 	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
186195fab37eSRobert Watson 	return (error);
186295fab37eSRobert Watson }
186395fab37eSRobert Watson 
186495fab37eSRobert Watson static int
186595fab37eSRobert Watson mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
186695fab37eSRobert Watson     struct label *newlabel)
186795fab37eSRobert Watson {
186895fab37eSRobert Watson 	int error;
186995fab37eSRobert Watson 
187095fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
187195fab37eSRobert Watson 
187295fab37eSRobert Watson 	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
187395fab37eSRobert Watson 
187495fab37eSRobert Watson 	return (error);
187595fab37eSRobert Watson }
187695fab37eSRobert Watson 
187795fab37eSRobert Watson int
187895fab37eSRobert Watson mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
187995fab37eSRobert Watson     struct vnode *vp, struct componentname *cnp)
188095fab37eSRobert Watson {
188195fab37eSRobert Watson 	int error;
188295fab37eSRobert Watson 
188395fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
188495fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
188595fab37eSRobert Watson 
188695fab37eSRobert Watson 	if (!mac_enforce_fs)
188795fab37eSRobert Watson 		return (0);
188895fab37eSRobert Watson 
188995fab37eSRobert Watson 	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
189095fab37eSRobert Watson 	    &vp->v_label, cnp);
189195fab37eSRobert Watson 	return (error);
189295fab37eSRobert Watson }
189395fab37eSRobert Watson 
189495fab37eSRobert Watson int
189595fab37eSRobert Watson mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
189695fab37eSRobert Watson     struct vnode *vp, int samedir, struct componentname *cnp)
189795fab37eSRobert Watson {
189895fab37eSRobert Watson 	int error;
189995fab37eSRobert Watson 
190095fab37eSRobert Watson 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
190195fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
190295fab37eSRobert Watson 
190395fab37eSRobert Watson 	if (!mac_enforce_fs)
190495fab37eSRobert Watson 		return (0);
190595fab37eSRobert Watson 
190695fab37eSRobert Watson 	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
190795fab37eSRobert Watson 	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
190895fab37eSRobert Watson 	return (error);
190995fab37eSRobert Watson }
191095fab37eSRobert Watson 
191195fab37eSRobert Watson int
191295fab37eSRobert Watson mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
191395fab37eSRobert Watson {
191495fab37eSRobert Watson 	int error;
191595fab37eSRobert Watson 
191695fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
191795fab37eSRobert Watson 
191895fab37eSRobert Watson 	if (!mac_enforce_fs)
191995fab37eSRobert Watson 		return (0);
192095fab37eSRobert Watson 
192195fab37eSRobert Watson 	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
192295fab37eSRobert Watson 	return (error);
192395fab37eSRobert Watson }
192495fab37eSRobert Watson 
192595fab37eSRobert Watson int
192695fab37eSRobert Watson mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
192795fab37eSRobert Watson     struct acl *acl)
192895fab37eSRobert Watson {
192995fab37eSRobert Watson 	int error;
193095fab37eSRobert Watson 
193195fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
193295fab37eSRobert Watson 
193395fab37eSRobert Watson 	if (!mac_enforce_fs)
193495fab37eSRobert Watson 		return (0);
193595fab37eSRobert Watson 
193695fab37eSRobert Watson 	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
193795fab37eSRobert Watson 	return (error);
193895fab37eSRobert Watson }
193995fab37eSRobert Watson 
194095fab37eSRobert Watson int
194195fab37eSRobert Watson mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
194295fab37eSRobert Watson     int attrnamespace, const char *name, struct uio *uio)
194395fab37eSRobert Watson {
194495fab37eSRobert Watson 	int error;
194595fab37eSRobert Watson 
194695fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
194795fab37eSRobert Watson 
194895fab37eSRobert Watson 	if (!mac_enforce_fs)
194995fab37eSRobert Watson 		return (0);
195095fab37eSRobert Watson 
195195fab37eSRobert Watson 	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
195295fab37eSRobert Watson 	    attrnamespace, name, uio);
195395fab37eSRobert Watson 	return (error);
195495fab37eSRobert Watson }
195595fab37eSRobert Watson 
195695fab37eSRobert Watson int
195795fab37eSRobert Watson mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
195895fab37eSRobert Watson {
195995fab37eSRobert Watson 	int error;
196095fab37eSRobert Watson 
196195fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
196295fab37eSRobert Watson 
196395fab37eSRobert Watson 	if (!mac_enforce_fs)
196495fab37eSRobert Watson 		return (0);
196595fab37eSRobert Watson 
196695fab37eSRobert Watson 	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
196795fab37eSRobert Watson 	return (error);
196895fab37eSRobert Watson }
196995fab37eSRobert Watson 
197095fab37eSRobert Watson int
197195fab37eSRobert Watson mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
197295fab37eSRobert Watson {
197395fab37eSRobert Watson 	int error;
197495fab37eSRobert Watson 
197595fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
197695fab37eSRobert Watson 
197795fab37eSRobert Watson 	if (!mac_enforce_fs)
197895fab37eSRobert Watson 		return (0);
197995fab37eSRobert Watson 
198095fab37eSRobert Watson 	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
198195fab37eSRobert Watson 	return (error);
198295fab37eSRobert Watson }
198395fab37eSRobert Watson 
198495fab37eSRobert Watson int
198595fab37eSRobert Watson mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
198695fab37eSRobert Watson     gid_t gid)
198795fab37eSRobert Watson {
198895fab37eSRobert Watson 	int error;
198995fab37eSRobert Watson 
199095fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
199195fab37eSRobert Watson 
199295fab37eSRobert Watson 	if (!mac_enforce_fs)
199395fab37eSRobert Watson 		return (0);
199495fab37eSRobert Watson 
199595fab37eSRobert Watson 	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
199695fab37eSRobert Watson 	return (error);
199795fab37eSRobert Watson }
199895fab37eSRobert Watson 
199995fab37eSRobert Watson int
200095fab37eSRobert Watson mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
200195fab37eSRobert Watson     struct timespec atime, struct timespec mtime)
200295fab37eSRobert Watson {
200395fab37eSRobert Watson 	int error;
200495fab37eSRobert Watson 
200595fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
200695fab37eSRobert Watson 
200795fab37eSRobert Watson 	if (!mac_enforce_fs)
200895fab37eSRobert Watson 		return (0);
200995fab37eSRobert Watson 
201095fab37eSRobert Watson 	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
201195fab37eSRobert Watson 	    mtime);
201295fab37eSRobert Watson 	return (error);
201395fab37eSRobert Watson }
201495fab37eSRobert Watson 
201595fab37eSRobert Watson int
2016177142e4SRobert Watson mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2017177142e4SRobert Watson     struct vnode *vp)
201895fab37eSRobert Watson {
201995fab37eSRobert Watson 	int error;
202095fab37eSRobert Watson 
202195fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
202295fab37eSRobert Watson 
202395fab37eSRobert Watson 	if (!mac_enforce_fs)
202495fab37eSRobert Watson 		return (0);
202595fab37eSRobert Watson 
2026177142e4SRobert Watson 	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2027177142e4SRobert Watson 	    &vp->v_label);
202895fab37eSRobert Watson 	return (error);
202995fab37eSRobert Watson }
203095fab37eSRobert Watson 
20317f724f8bSRobert Watson int
2032177142e4SRobert Watson mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2033177142e4SRobert Watson     struct vnode *vp)
20347f724f8bSRobert Watson {
20357f724f8bSRobert Watson 	int error;
20367f724f8bSRobert Watson 
20377f724f8bSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
20387f724f8bSRobert Watson 
20397f724f8bSRobert Watson 	if (!mac_enforce_fs)
20407f724f8bSRobert Watson 		return (0);
20417f724f8bSRobert Watson 
2042177142e4SRobert Watson 	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2043177142e4SRobert Watson 	    &vp->v_label);
20447f724f8bSRobert Watson 
20457f724f8bSRobert Watson 	return (error);
20467f724f8bSRobert Watson }
20477f724f8bSRobert Watson 
204895fab37eSRobert Watson /*
204995fab37eSRobert Watson  * When relabeling a process, call out to the policies for the maximum
205095fab37eSRobert Watson  * permission allowed for each object type we know about in its
205195fab37eSRobert Watson  * memory space, and revoke access (in the least surprising ways we
205295fab37eSRobert Watson  * know) when necessary.  The process lock is not held here.
205395fab37eSRobert Watson  */
20544d10c0ceSRobert Watson void
205595fab37eSRobert Watson mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
205695fab37eSRobert Watson {
205795fab37eSRobert Watson 
205895fab37eSRobert Watson 	/* XXX freeze all other threads */
205995fab37eSRobert Watson 	mac_cred_mmapped_drop_perms_recurse(td, cred,
206095fab37eSRobert Watson 	    &td->td_proc->p_vmspace->vm_map);
206195fab37eSRobert Watson 	/* XXX allow other threads to continue */
206295fab37eSRobert Watson }
206395fab37eSRobert Watson 
206495fab37eSRobert Watson static __inline const char *
206595fab37eSRobert Watson prot2str(vm_prot_t prot)
206695fab37eSRobert Watson {
206795fab37eSRobert Watson 
206895fab37eSRobert Watson 	switch (prot & VM_PROT_ALL) {
206995fab37eSRobert Watson 	case VM_PROT_READ:
207095fab37eSRobert Watson 		return ("r--");
207195fab37eSRobert Watson 	case VM_PROT_READ | VM_PROT_WRITE:
207295fab37eSRobert Watson 		return ("rw-");
207395fab37eSRobert Watson 	case VM_PROT_READ | VM_PROT_EXECUTE:
207495fab37eSRobert Watson 		return ("r-x");
207595fab37eSRobert Watson 	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
207695fab37eSRobert Watson 		return ("rwx");
207795fab37eSRobert Watson 	case VM_PROT_WRITE:
207895fab37eSRobert Watson 		return ("-w-");
207995fab37eSRobert Watson 	case VM_PROT_EXECUTE:
208095fab37eSRobert Watson 		return ("--x");
208195fab37eSRobert Watson 	case VM_PROT_WRITE | VM_PROT_EXECUTE:
208295fab37eSRobert Watson 		return ("-wx");
208395fab37eSRobert Watson 	default:
208495fab37eSRobert Watson 		return ("---");
208595fab37eSRobert Watson 	}
208695fab37eSRobert Watson }
208795fab37eSRobert Watson 
208895fab37eSRobert Watson static void
208995fab37eSRobert Watson mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
209095fab37eSRobert Watson     struct vm_map *map)
209195fab37eSRobert Watson {
209295fab37eSRobert Watson 	struct vm_map_entry *vme;
2093e183f80eSRobert Watson 	int result;
2094e183f80eSRobert Watson 	vm_prot_t revokeperms;
209595fab37eSRobert Watson 	vm_object_t object;
209695fab37eSRobert Watson 	vm_ooffset_t offset;
209795fab37eSRobert Watson 	struct vnode *vp;
209895fab37eSRobert Watson 
2099c0f39905SRobert Watson 	if (!mac_mmap_revocation)
2100c0f39905SRobert Watson 		return;
2101c0f39905SRobert Watson 
210295fab37eSRobert Watson 	vm_map_lock_read(map);
210395fab37eSRobert Watson 	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
210495fab37eSRobert Watson 		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
210595fab37eSRobert Watson 			mac_cred_mmapped_drop_perms_recurse(td, cred,
210695fab37eSRobert Watson 			    vme->object.sub_map);
210795fab37eSRobert Watson 			continue;
210895fab37eSRobert Watson 		}
210995fab37eSRobert Watson 		/*
211095fab37eSRobert Watson 		 * Skip over entries that obviously are not shared.
211195fab37eSRobert Watson 		 */
211295fab37eSRobert Watson 		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
211395fab37eSRobert Watson 		    !vme->max_protection)
211495fab37eSRobert Watson 			continue;
211595fab37eSRobert Watson 		/*
211695fab37eSRobert Watson 		 * Drill down to the deepest backing object.
211795fab37eSRobert Watson 		 */
211895fab37eSRobert Watson 		offset = vme->offset;
211995fab37eSRobert Watson 		object = vme->object.vm_object;
212095fab37eSRobert Watson 		if (object == NULL)
212195fab37eSRobert Watson 			continue;
212295fab37eSRobert Watson 		while (object->backing_object != NULL) {
212395fab37eSRobert Watson 			object = object->backing_object;
212495fab37eSRobert Watson 			offset += object->backing_object_offset;
212595fab37eSRobert Watson 		}
212695fab37eSRobert Watson 		/*
212795fab37eSRobert Watson 		 * At the moment, vm_maps and objects aren't considered
212895fab37eSRobert Watson 		 * by the MAC system, so only things with backing by a
212995fab37eSRobert Watson 		 * normal object (read: vnodes) are checked.
213095fab37eSRobert Watson 		 */
213195fab37eSRobert Watson 		if (object->type != OBJT_VNODE)
213295fab37eSRobert Watson 			continue;
213395fab37eSRobert Watson 		vp = (struct vnode *)object->handle;
213495fab37eSRobert Watson 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2135e183f80eSRobert Watson 		result = vme->max_protection;
2136e183f80eSRobert Watson 		mac_check_vnode_mmap_downgrade(cred, vp, &result);
213795fab37eSRobert Watson 		VOP_UNLOCK(vp, 0, td);
213895fab37eSRobert Watson 		/*
213995fab37eSRobert Watson 		 * Find out what maximum protection we may be allowing
214095fab37eSRobert Watson 		 * now but a policy needs to get removed.
214195fab37eSRobert Watson 		 */
214295fab37eSRobert Watson 		revokeperms = vme->max_protection & ~result;
214395fab37eSRobert Watson 		if (!revokeperms)
214495fab37eSRobert Watson 			continue;
2145b656366bSBruce Evans 		printf("pid %ld: revoking %s perms from %#lx:%ld "
2146b656366bSBruce Evans 		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2147b656366bSBruce Evans 		    prot2str(revokeperms), (u_long)vme->start,
2148b656366bSBruce Evans 		    (long)(vme->end - vme->start),
214995fab37eSRobert Watson 		    prot2str(vme->max_protection), prot2str(vme->protection));
215095fab37eSRobert Watson 		vm_map_lock_upgrade(map);
215195fab37eSRobert Watson 		/*
215295fab37eSRobert Watson 		 * This is the really simple case: if a map has more
215395fab37eSRobert Watson 		 * max_protection than is allowed, but it's not being
215495fab37eSRobert Watson 		 * actually used (that is, the current protection is
215595fab37eSRobert Watson 		 * still allowed), we can just wipe it out and do
215695fab37eSRobert Watson 		 * nothing more.
215795fab37eSRobert Watson 		 */
215895fab37eSRobert Watson 		if ((vme->protection & revokeperms) == 0) {
215995fab37eSRobert Watson 			vme->max_protection -= revokeperms;
216095fab37eSRobert Watson 		} else {
216195fab37eSRobert Watson 			if (revokeperms & VM_PROT_WRITE) {
216295fab37eSRobert Watson 				/*
216395fab37eSRobert Watson 				 * In the more complicated case, flush out all
216495fab37eSRobert Watson 				 * pending changes to the object then turn it
216595fab37eSRobert Watson 				 * copy-on-write.
216695fab37eSRobert Watson 				 */
216795fab37eSRobert Watson 				vm_object_reference(object);
216895fab37eSRobert Watson 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2169b6e48e03SAlan Cox 				VM_OBJECT_LOCK(object);
217095fab37eSRobert Watson 				vm_object_page_clean(object,
217195fab37eSRobert Watson 				    OFF_TO_IDX(offset),
217295fab37eSRobert Watson 				    OFF_TO_IDX(offset + vme->end - vme->start +
217395fab37eSRobert Watson 					PAGE_MASK),
217495fab37eSRobert Watson 				    OBJPC_SYNC);
2175b6e48e03SAlan Cox 				VM_OBJECT_UNLOCK(object);
217695fab37eSRobert Watson 				VOP_UNLOCK(vp, 0, td);
217795fab37eSRobert Watson 				vm_object_deallocate(object);
217895fab37eSRobert Watson 				/*
217995fab37eSRobert Watson 				 * Why bother if there's no read permissions
218095fab37eSRobert Watson 				 * anymore?  For the rest, we need to leave
218195fab37eSRobert Watson 				 * the write permissions on for COW, or
218295fab37eSRobert Watson 				 * remove them entirely if configured to.
218395fab37eSRobert Watson 				 */
218495fab37eSRobert Watson 				if (!mac_mmap_revocation_via_cow) {
218595fab37eSRobert Watson 					vme->max_protection &= ~VM_PROT_WRITE;
218695fab37eSRobert Watson 					vme->protection &= ~VM_PROT_WRITE;
218795fab37eSRobert Watson 				} if ((revokeperms & VM_PROT_READ) == 0)
218895fab37eSRobert Watson 					vme->eflags |= MAP_ENTRY_COW |
218995fab37eSRobert Watson 					    MAP_ENTRY_NEEDS_COPY;
219095fab37eSRobert Watson 			}
219195fab37eSRobert Watson 			if (revokeperms & VM_PROT_EXECUTE) {
219295fab37eSRobert Watson 				vme->max_protection &= ~VM_PROT_EXECUTE;
219395fab37eSRobert Watson 				vme->protection &= ~VM_PROT_EXECUTE;
219495fab37eSRobert Watson 			}
219595fab37eSRobert Watson 			if (revokeperms & VM_PROT_READ) {
219695fab37eSRobert Watson 				vme->max_protection = 0;
219795fab37eSRobert Watson 				vme->protection = 0;
219895fab37eSRobert Watson 			}
219995fab37eSRobert Watson 			pmap_protect(map->pmap, vme->start, vme->end,
220095fab37eSRobert Watson 			    vme->protection & ~revokeperms);
220195fab37eSRobert Watson 			vm_map_simplify_entry(map, vme);
220295fab37eSRobert Watson 		}
220395fab37eSRobert Watson 		vm_map_lock_downgrade(map);
220495fab37eSRobert Watson 	}
220595fab37eSRobert Watson 	vm_map_unlock_read(map);
220695fab37eSRobert Watson }
220795fab37eSRobert Watson 
220895fab37eSRobert Watson /*
220995fab37eSRobert Watson  * When the subject's label changes, it may require revocation of privilege
221095fab37eSRobert Watson  * to mapped objects.  This can't be done on-the-fly later with a unified
221195fab37eSRobert Watson  * buffer cache.
221295fab37eSRobert Watson  */
221395fab37eSRobert Watson static void
221495fab37eSRobert Watson mac_relabel_cred(struct ucred *cred, struct label *newlabel)
221595fab37eSRobert Watson {
221695fab37eSRobert Watson 
221795fab37eSRobert Watson 	MAC_PERFORM(relabel_cred, cred, newlabel);
221895fab37eSRobert Watson }
221995fab37eSRobert Watson 
222095fab37eSRobert Watson void
222195fab37eSRobert Watson mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
222295fab37eSRobert Watson {
222395fab37eSRobert Watson 
222495fab37eSRobert Watson 	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
222595fab37eSRobert Watson }
222695fab37eSRobert Watson 
222795fab37eSRobert Watson void
222895fab37eSRobert Watson mac_create_ifnet(struct ifnet *ifnet)
222995fab37eSRobert Watson {
223095fab37eSRobert Watson 
223195fab37eSRobert Watson 	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
223295fab37eSRobert Watson }
223395fab37eSRobert Watson 
223495fab37eSRobert Watson void
223595fab37eSRobert Watson mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
223695fab37eSRobert Watson {
223795fab37eSRobert Watson 
223895fab37eSRobert Watson 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
223995fab37eSRobert Watson }
224095fab37eSRobert Watson 
224195fab37eSRobert Watson void
224295fab37eSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket)
224395fab37eSRobert Watson {
224495fab37eSRobert Watson 
224595fab37eSRobert Watson 	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
224695fab37eSRobert Watson }
224795fab37eSRobert Watson 
224895fab37eSRobert Watson void
224995fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe)
225095fab37eSRobert Watson {
225195fab37eSRobert Watson 
225295fab37eSRobert Watson 	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
225395fab37eSRobert Watson }
225495fab37eSRobert Watson 
225595fab37eSRobert Watson void
225695fab37eSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket,
225795fab37eSRobert Watson     struct socket *newsocket)
225895fab37eSRobert Watson {
225995fab37eSRobert Watson 
226095fab37eSRobert Watson 	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
226195fab37eSRobert Watson 	    newsocket, &newsocket->so_label);
226295fab37eSRobert Watson }
226395fab37eSRobert Watson 
226495fab37eSRobert Watson static void
226595fab37eSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket,
226695fab37eSRobert Watson     struct label *newlabel)
226795fab37eSRobert Watson {
226895fab37eSRobert Watson 
226995fab37eSRobert Watson 	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
227095fab37eSRobert Watson }
227195fab37eSRobert Watson 
227295fab37eSRobert Watson static void
227395fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
227495fab37eSRobert Watson {
227595fab37eSRobert Watson 
227695fab37eSRobert Watson 	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
227795fab37eSRobert Watson }
227895fab37eSRobert Watson 
227995fab37eSRobert Watson void
228095fab37eSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
228195fab37eSRobert Watson {
228210eeb10cSRobert Watson 	struct label *label;
228395fab37eSRobert Watson 
228410eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
228510eeb10cSRobert Watson 
228610eeb10cSRobert Watson 	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
228710eeb10cSRobert Watson 	    &socket->so_peerlabel);
228895fab37eSRobert Watson }
228995fab37eSRobert Watson 
229095fab37eSRobert Watson void
229195fab37eSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket,
229295fab37eSRobert Watson     struct socket *newsocket)
229395fab37eSRobert Watson {
229495fab37eSRobert Watson 
229595fab37eSRobert Watson 	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
229695fab37eSRobert Watson 	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
229795fab37eSRobert Watson }
229895fab37eSRobert Watson 
229995fab37eSRobert Watson void
230095fab37eSRobert Watson mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
230195fab37eSRobert Watson {
230210eeb10cSRobert Watson 	struct label *label;
230310eeb10cSRobert Watson 
230410eeb10cSRobert Watson 	label = mbuf_to_label(datagram);
230595fab37eSRobert Watson 
230695fab37eSRobert Watson 	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
230710eeb10cSRobert Watson 	    datagram, label);
230895fab37eSRobert Watson }
230995fab37eSRobert Watson 
231095fab37eSRobert Watson void
231195fab37eSRobert Watson mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
231295fab37eSRobert Watson {
231310eeb10cSRobert Watson 	struct label *datagramlabel, *fragmentlabel;
231495fab37eSRobert Watson 
231510eeb10cSRobert Watson 	datagramlabel = mbuf_to_label(datagram);
231610eeb10cSRobert Watson 	fragmentlabel = mbuf_to_label(fragment);
231710eeb10cSRobert Watson 
231810eeb10cSRobert Watson 	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
231910eeb10cSRobert Watson 	    fragmentlabel);
232095fab37eSRobert Watson }
232195fab37eSRobert Watson 
232295fab37eSRobert Watson void
232395fab37eSRobert Watson mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
232495fab37eSRobert Watson {
232510eeb10cSRobert Watson 	struct label *label;
232695fab37eSRobert Watson 
232710eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
232810eeb10cSRobert Watson 
232910eeb10cSRobert Watson 	MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
233095fab37eSRobert Watson }
233195fab37eSRobert Watson 
233295fab37eSRobert Watson void
233395fab37eSRobert Watson mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
233495fab37eSRobert Watson {
233510eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
233695fab37eSRobert Watson 
233710eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
233810eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
233910eeb10cSRobert Watson 
234010eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
234110eeb10cSRobert Watson 	    newmbuflabel);
234295fab37eSRobert Watson }
234395fab37eSRobert Watson 
234495fab37eSRobert Watson void
234595fab37eSRobert Watson mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
234695fab37eSRobert Watson {
234710eeb10cSRobert Watson 	struct label *label;
234810eeb10cSRobert Watson 
234910eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
235095fab37eSRobert Watson 
235195fab37eSRobert Watson 	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
235210eeb10cSRobert Watson 	    label);
235395fab37eSRobert Watson }
235495fab37eSRobert Watson 
235595fab37eSRobert Watson void
235695fab37eSRobert Watson mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
235795fab37eSRobert Watson {
235810eeb10cSRobert Watson 	struct label *label;
235910eeb10cSRobert Watson 
236010eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
236195fab37eSRobert Watson 
236295fab37eSRobert Watson 	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
236310eeb10cSRobert Watson 	    label);
236495fab37eSRobert Watson }
236595fab37eSRobert Watson 
236695fab37eSRobert Watson void
236795fab37eSRobert Watson mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
236895fab37eSRobert Watson {
236910eeb10cSRobert Watson 	struct label *label;
237010eeb10cSRobert Watson 
237110eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
237295fab37eSRobert Watson 
237395fab37eSRobert Watson 	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
237410eeb10cSRobert Watson 	    label);
237595fab37eSRobert Watson }
237695fab37eSRobert Watson 
237795fab37eSRobert Watson void
237895fab37eSRobert Watson mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
237995fab37eSRobert Watson     struct mbuf *newmbuf)
238095fab37eSRobert Watson {
238110eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
238295fab37eSRobert Watson 
238310eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
238410eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
238510eeb10cSRobert Watson 
238610eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
238710eeb10cSRobert Watson 	    ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
238895fab37eSRobert Watson }
238995fab37eSRobert Watson 
239095fab37eSRobert Watson void
239195fab37eSRobert Watson mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
239295fab37eSRobert Watson {
239310eeb10cSRobert Watson 	struct label *oldmbuflabel, *newmbuflabel;
239495fab37eSRobert Watson 
239510eeb10cSRobert Watson 	oldmbuflabel = mbuf_to_label(oldmbuf);
239610eeb10cSRobert Watson 	newmbuflabel = mbuf_to_label(newmbuf);
239710eeb10cSRobert Watson 
239810eeb10cSRobert Watson 	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
239910eeb10cSRobert Watson 	    newmbuflabel);
240095fab37eSRobert Watson }
240195fab37eSRobert Watson 
240295fab37eSRobert Watson int
240395fab37eSRobert Watson mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
240495fab37eSRobert Watson {
240510eeb10cSRobert Watson 	struct label *label;
240695fab37eSRobert Watson 	int result;
240795fab37eSRobert Watson 
240810eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
240910eeb10cSRobert Watson 
241095fab37eSRobert Watson 	result = 1;
241110eeb10cSRobert Watson 	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
241210eeb10cSRobert Watson 	    &ipq->ipq_label);
241395fab37eSRobert Watson 
241495fab37eSRobert Watson 	return (result);
241595fab37eSRobert Watson }
241695fab37eSRobert Watson 
241795fab37eSRobert Watson void
241895fab37eSRobert Watson mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
241995fab37eSRobert Watson {
242010eeb10cSRobert Watson 	struct label *label;
242195fab37eSRobert Watson 
242210eeb10cSRobert Watson 	label = mbuf_to_label(fragment);
242310eeb10cSRobert Watson 
242410eeb10cSRobert Watson 	MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
242595fab37eSRobert Watson }
242695fab37eSRobert Watson 
242795fab37eSRobert Watson void
242895fab37eSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
242995fab37eSRobert Watson {
243010eeb10cSRobert Watson 	struct label *label;
243110eeb10cSRobert Watson 
243210eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
243395fab37eSRobert Watson 
243495fab37eSRobert Watson 	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
243510eeb10cSRobert Watson 	    label);
243695fab37eSRobert Watson }
243795fab37eSRobert Watson 
243895fab37eSRobert Watson void
243995fab37eSRobert Watson mac_create_mount(struct ucred *cred, struct mount *mp)
244095fab37eSRobert Watson {
244195fab37eSRobert Watson 
244295fab37eSRobert Watson 	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
244395fab37eSRobert Watson 	    &mp->mnt_fslabel);
244495fab37eSRobert Watson }
244595fab37eSRobert Watson 
244695fab37eSRobert Watson void
244795fab37eSRobert Watson mac_create_root_mount(struct ucred *cred, struct mount *mp)
244895fab37eSRobert Watson {
244995fab37eSRobert Watson 
245095fab37eSRobert Watson 	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
245195fab37eSRobert Watson 	    &mp->mnt_fslabel);
245295fab37eSRobert Watson }
245395fab37eSRobert Watson 
245495fab37eSRobert Watson int
245595fab37eSRobert Watson mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
245695fab37eSRobert Watson {
245795fab37eSRobert Watson 	int error;
245895fab37eSRobert Watson 
245995fab37eSRobert Watson 	if (!mac_enforce_network)
246095fab37eSRobert Watson 		return (0);
246195fab37eSRobert Watson 
246295fab37eSRobert Watson 	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
246395fab37eSRobert Watson 	    &ifnet->if_label);
246495fab37eSRobert Watson 
246595fab37eSRobert Watson 	return (error);
246695fab37eSRobert Watson }
246795fab37eSRobert Watson 
246895fab37eSRobert Watson static int
246995fab37eSRobert Watson mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
247095fab37eSRobert Watson {
247195fab37eSRobert Watson 	int error;
247295fab37eSRobert Watson 
247395fab37eSRobert Watson 	MAC_CHECK(check_cred_relabel, cred, newlabel);
247495fab37eSRobert Watson 
247595fab37eSRobert Watson 	return (error);
247695fab37eSRobert Watson }
247795fab37eSRobert Watson 
247895fab37eSRobert Watson int
247995fab37eSRobert Watson mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
248095fab37eSRobert Watson {
248195fab37eSRobert Watson 	int error;
248295fab37eSRobert Watson 
248395fab37eSRobert Watson 	if (!mac_enforce_process)
248495fab37eSRobert Watson 		return (0);
248595fab37eSRobert Watson 
248695fab37eSRobert Watson 	MAC_CHECK(check_cred_visible, u1, u2);
248795fab37eSRobert Watson 
248895fab37eSRobert Watson 	return (error);
248995fab37eSRobert Watson }
249095fab37eSRobert Watson 
249195fab37eSRobert Watson int
249295fab37eSRobert Watson mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
249395fab37eSRobert Watson {
249410eeb10cSRobert Watson 	struct label *label;
249595fab37eSRobert Watson 	int error;
249695fab37eSRobert Watson 
2497225bff6fSRobert Watson 	M_ASSERTPKTHDR(mbuf);
2498225bff6fSRobert Watson 
249995fab37eSRobert Watson 	if (!mac_enforce_network)
250095fab37eSRobert Watson 		return (0);
250195fab37eSRobert Watson 
250210eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
250395fab37eSRobert Watson 
250495fab37eSRobert Watson 	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
250510eeb10cSRobert Watson 	    label);
250695fab37eSRobert Watson 
250795fab37eSRobert Watson 	return (error);
250895fab37eSRobert Watson }
250995fab37eSRobert Watson 
251095fab37eSRobert Watson int
2511e686e5aeSRobert Watson mac_check_kenv_dump(struct ucred *cred)
2512e686e5aeSRobert Watson {
2513e686e5aeSRobert Watson 	int error;
2514e686e5aeSRobert Watson 
2515e686e5aeSRobert Watson 	if (!mac_enforce_system)
2516e686e5aeSRobert Watson 		return (0);
2517e686e5aeSRobert Watson 
2518e686e5aeSRobert Watson 	MAC_CHECK(check_kenv_dump, cred);
2519e686e5aeSRobert Watson 
2520e686e5aeSRobert Watson 	return (error);
2521e686e5aeSRobert Watson }
2522e686e5aeSRobert Watson 
2523e686e5aeSRobert Watson int
2524e686e5aeSRobert Watson mac_check_kenv_get(struct ucred *cred, char *name)
2525e686e5aeSRobert Watson {
2526e686e5aeSRobert Watson 	int error;
2527e686e5aeSRobert Watson 
2528e686e5aeSRobert Watson 	if (!mac_enforce_system)
2529e686e5aeSRobert Watson 		return (0);
2530e686e5aeSRobert Watson 
2531e686e5aeSRobert Watson 	MAC_CHECK(check_kenv_get, cred, name);
2532e686e5aeSRobert Watson 
2533e686e5aeSRobert Watson 	return (error);
2534e686e5aeSRobert Watson }
2535e686e5aeSRobert Watson 
2536e686e5aeSRobert Watson int
2537e686e5aeSRobert Watson mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2538e686e5aeSRobert Watson {
2539e686e5aeSRobert Watson 	int error;
2540e686e5aeSRobert Watson 
2541e686e5aeSRobert Watson 	if (!mac_enforce_system)
2542e686e5aeSRobert Watson 		return (0);
2543e686e5aeSRobert Watson 
2544e686e5aeSRobert Watson 	MAC_CHECK(check_kenv_set, cred, name, value);
2545e686e5aeSRobert Watson 
2546e686e5aeSRobert Watson 	return (error);
2547e686e5aeSRobert Watson }
2548e686e5aeSRobert Watson 
2549e686e5aeSRobert Watson int
2550e686e5aeSRobert Watson mac_check_kenv_unset(struct ucred *cred, char *name)
2551e686e5aeSRobert Watson {
2552e686e5aeSRobert Watson 	int error;
2553e686e5aeSRobert Watson 
2554e686e5aeSRobert Watson 	if (!mac_enforce_system)
2555e686e5aeSRobert Watson 		return (0);
2556e686e5aeSRobert Watson 
2557e686e5aeSRobert Watson 	MAC_CHECK(check_kenv_unset, cred, name);
2558e686e5aeSRobert Watson 
2559e686e5aeSRobert Watson 	return (error);
2560e686e5aeSRobert Watson }
2561e686e5aeSRobert Watson 
2562e686e5aeSRobert Watson int
2563a3df768bSRobert Watson mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2564a3df768bSRobert Watson {
2565a3df768bSRobert Watson 	int error;
2566a3df768bSRobert Watson 
2567a3df768bSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2568a3df768bSRobert Watson 
2569a3df768bSRobert Watson 	if (!mac_enforce_kld)
2570a3df768bSRobert Watson 		return (0);
2571a3df768bSRobert Watson 
2572a3df768bSRobert Watson 	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2573a3df768bSRobert Watson 
2574a3df768bSRobert Watson 	return (error);
2575a3df768bSRobert Watson }
2576a3df768bSRobert Watson 
2577a3df768bSRobert Watson int
2578a3df768bSRobert Watson mac_check_kld_stat(struct ucred *cred)
2579a3df768bSRobert Watson {
2580a3df768bSRobert Watson 	int error;
2581a3df768bSRobert Watson 
2582a3df768bSRobert Watson 	if (!mac_enforce_kld)
2583a3df768bSRobert Watson 		return (0);
2584a3df768bSRobert Watson 
2585a3df768bSRobert Watson 	MAC_CHECK(check_kld_stat, cred);
2586a3df768bSRobert Watson 
2587a3df768bSRobert Watson 	return (error);
2588a3df768bSRobert Watson }
2589a3df768bSRobert Watson 
2590a3df768bSRobert Watson int
2591a3df768bSRobert Watson mac_check_kld_unload(struct ucred *cred)
2592a3df768bSRobert Watson {
2593a3df768bSRobert Watson 	int error;
2594a3df768bSRobert Watson 
2595a3df768bSRobert Watson 	if (!mac_enforce_kld)
2596a3df768bSRobert Watson 		return (0);
2597a3df768bSRobert Watson 
2598a3df768bSRobert Watson 	MAC_CHECK(check_kld_unload, cred);
2599a3df768bSRobert Watson 
2600a3df768bSRobert Watson 	return (error);
2601a3df768bSRobert Watson }
2602a3df768bSRobert Watson 
2603a3df768bSRobert Watson int
260495fab37eSRobert Watson mac_check_mount_stat(struct ucred *cred, struct mount *mount)
260595fab37eSRobert Watson {
260695fab37eSRobert Watson 	int error;
260795fab37eSRobert Watson 
260895fab37eSRobert Watson 	if (!mac_enforce_fs)
260995fab37eSRobert Watson 		return (0);
261095fab37eSRobert Watson 
261195fab37eSRobert Watson 	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
261295fab37eSRobert Watson 
261395fab37eSRobert Watson 	return (error);
261495fab37eSRobert Watson }
261595fab37eSRobert Watson 
261695fab37eSRobert Watson int
261795fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
261895fab37eSRobert Watson     void *data)
261995fab37eSRobert Watson {
262095fab37eSRobert Watson 	int error;
262195fab37eSRobert Watson 
26221aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
26231aa37f53SRobert Watson 
26241aa37f53SRobert Watson 	if (!mac_enforce_pipe)
26251aa37f53SRobert Watson 		return (0);
26261aa37f53SRobert Watson 
262795fab37eSRobert Watson 	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
262895fab37eSRobert Watson 
262995fab37eSRobert Watson 	return (error);
263095fab37eSRobert Watson }
263195fab37eSRobert Watson 
263295fab37eSRobert Watson int
2633c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
263495fab37eSRobert Watson {
263595fab37eSRobert Watson 	int error;
263695fab37eSRobert Watson 
26371aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
26381aa37f53SRobert Watson 
26391aa37f53SRobert Watson 	if (!mac_enforce_pipe)
26401aa37f53SRobert Watson 		return (0);
26411aa37f53SRobert Watson 
2642c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2643c024c3eeSRobert Watson 
2644c024c3eeSRobert Watson 	return (error);
2645c024c3eeSRobert Watson }
2646c024c3eeSRobert Watson 
2647c024c3eeSRobert Watson int
2648c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2649c024c3eeSRobert Watson {
2650c024c3eeSRobert Watson 	int error;
2651c024c3eeSRobert Watson 
26521aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
26531aa37f53SRobert Watson 
26541aa37f53SRobert Watson 	if (!mac_enforce_pipe)
26551aa37f53SRobert Watson 		return (0);
26561aa37f53SRobert Watson 
2657c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
265895fab37eSRobert Watson 
265995fab37eSRobert Watson 	return (error);
266095fab37eSRobert Watson }
266195fab37eSRobert Watson 
266295fab37eSRobert Watson static int
266395fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
266495fab37eSRobert Watson     struct label *newlabel)
266595fab37eSRobert Watson {
266695fab37eSRobert Watson 	int error;
266795fab37eSRobert Watson 
26681aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
26691aa37f53SRobert Watson 
26701aa37f53SRobert Watson 	if (!mac_enforce_pipe)
26711aa37f53SRobert Watson 		return (0);
26721aa37f53SRobert Watson 
267395fab37eSRobert Watson 	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
267495fab37eSRobert Watson 
267595fab37eSRobert Watson 	return (error);
267695fab37eSRobert Watson }
267795fab37eSRobert Watson 
267895fab37eSRobert Watson int
2679c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2680c024c3eeSRobert Watson {
2681c024c3eeSRobert Watson 	int error;
2682c024c3eeSRobert Watson 
26831aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
26841aa37f53SRobert Watson 
26851aa37f53SRobert Watson 	if (!mac_enforce_pipe)
26861aa37f53SRobert Watson 		return (0);
26871aa37f53SRobert Watson 
2688c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2689c024c3eeSRobert Watson 
2690c024c3eeSRobert Watson 	return (error);
2691c024c3eeSRobert Watson }
2692c024c3eeSRobert Watson 
2693c024c3eeSRobert Watson int
2694c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2695c024c3eeSRobert Watson {
2696c024c3eeSRobert Watson 	int error;
2697c024c3eeSRobert Watson 
26981aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
26991aa37f53SRobert Watson 
27001aa37f53SRobert Watson 	if (!mac_enforce_pipe)
27011aa37f53SRobert Watson 		return (0);
27021aa37f53SRobert Watson 
2703c024c3eeSRobert Watson 	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2704c024c3eeSRobert Watson 
2705c024c3eeSRobert Watson 	return (error);
2706c024c3eeSRobert Watson }
2707c024c3eeSRobert Watson 
2708c024c3eeSRobert Watson int
270995fab37eSRobert Watson mac_check_proc_debug(struct ucred *cred, struct proc *proc)
271095fab37eSRobert Watson {
271195fab37eSRobert Watson 	int error;
271295fab37eSRobert Watson 
2713b12baf55SRobert Watson 	PROC_LOCK_ASSERT(proc, MA_OWNED);
2714b12baf55SRobert Watson 
271595fab37eSRobert Watson 	if (!mac_enforce_process)
271695fab37eSRobert Watson 		return (0);
271795fab37eSRobert Watson 
271895fab37eSRobert Watson 	MAC_CHECK(check_proc_debug, cred, proc);
271995fab37eSRobert Watson 
272095fab37eSRobert Watson 	return (error);
272195fab37eSRobert Watson }
272295fab37eSRobert Watson 
272395fab37eSRobert Watson int
272495fab37eSRobert Watson mac_check_proc_sched(struct ucred *cred, struct proc *proc)
272595fab37eSRobert Watson {
272695fab37eSRobert Watson 	int error;
272795fab37eSRobert Watson 
2728b12baf55SRobert Watson 	PROC_LOCK_ASSERT(proc, MA_OWNED);
2729b12baf55SRobert Watson 
273095fab37eSRobert Watson 	if (!mac_enforce_process)
273195fab37eSRobert Watson 		return (0);
273295fab37eSRobert Watson 
273395fab37eSRobert Watson 	MAC_CHECK(check_proc_sched, cred, proc);
273495fab37eSRobert Watson 
273595fab37eSRobert Watson 	return (error);
273695fab37eSRobert Watson }
273795fab37eSRobert Watson 
273895fab37eSRobert Watson int
273995fab37eSRobert Watson mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
274095fab37eSRobert Watson {
274195fab37eSRobert Watson 	int error;
274295fab37eSRobert Watson 
2743b12baf55SRobert Watson 	PROC_LOCK_ASSERT(proc, MA_OWNED);
2744b12baf55SRobert Watson 
274595fab37eSRobert Watson 	if (!mac_enforce_process)
274695fab37eSRobert Watson 		return (0);
274795fab37eSRobert Watson 
274895fab37eSRobert Watson 	MAC_CHECK(check_proc_signal, cred, proc, signum);
274995fab37eSRobert Watson 
275095fab37eSRobert Watson 	return (error);
275195fab37eSRobert Watson }
275295fab37eSRobert Watson 
275395fab37eSRobert Watson int
275495fab37eSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
275595fab37eSRobert Watson     struct sockaddr *sockaddr)
275695fab37eSRobert Watson {
275795fab37eSRobert Watson 	int error;
275895fab37eSRobert Watson 
275995fab37eSRobert Watson 	if (!mac_enforce_socket)
276095fab37eSRobert Watson 		return (0);
276195fab37eSRobert Watson 
276295fab37eSRobert Watson 	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
276395fab37eSRobert Watson 	    sockaddr);
276495fab37eSRobert Watson 
276595fab37eSRobert Watson 	return (error);
276695fab37eSRobert Watson }
276795fab37eSRobert Watson 
276895fab37eSRobert Watson int
276995fab37eSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket,
277095fab37eSRobert Watson     struct sockaddr *sockaddr)
277195fab37eSRobert Watson {
277295fab37eSRobert Watson 	int error;
277395fab37eSRobert Watson 
277495fab37eSRobert Watson 	if (!mac_enforce_socket)
277595fab37eSRobert Watson 		return (0);
277695fab37eSRobert Watson 
277795fab37eSRobert Watson 	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
277895fab37eSRobert Watson 	    sockaddr);
277995fab37eSRobert Watson 
278095fab37eSRobert Watson 	return (error);
278195fab37eSRobert Watson }
278295fab37eSRobert Watson 
278395fab37eSRobert Watson int
2784d61198e4SRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2785d61198e4SRobert Watson {
278610eeb10cSRobert Watson 	struct label *label;
2787d61198e4SRobert Watson 	int error;
2788d61198e4SRobert Watson 
2789d61198e4SRobert Watson 	if (!mac_enforce_socket)
2790d61198e4SRobert Watson 		return (0);
2791d61198e4SRobert Watson 
279210eeb10cSRobert Watson 	label = mbuf_to_label(mbuf);
279310eeb10cSRobert Watson 
2794d61198e4SRobert Watson 	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
279510eeb10cSRobert Watson 	    label);
2796d61198e4SRobert Watson 
2797d61198e4SRobert Watson 	return (error);
2798d61198e4SRobert Watson }
2799d61198e4SRobert Watson 
2800d61198e4SRobert Watson int
280195fab37eSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket)
280295fab37eSRobert Watson {
280395fab37eSRobert Watson 	int error;
280495fab37eSRobert Watson 
280595fab37eSRobert Watson 	if (!mac_enforce_socket)
280695fab37eSRobert Watson 		return (0);
280795fab37eSRobert Watson 
280895fab37eSRobert Watson 	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
280995fab37eSRobert Watson 	return (error);
281095fab37eSRobert Watson }
281195fab37eSRobert Watson 
2812b371c939SRobert Watson int
2813b371c939SRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so)
2814b371c939SRobert Watson {
2815b371c939SRobert Watson 	int error;
2816b371c939SRobert Watson 
2817b371c939SRobert Watson 	if (!mac_enforce_socket)
2818b371c939SRobert Watson 		return (0);
2819b371c939SRobert Watson 
2820b371c939SRobert Watson 	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2821b371c939SRobert Watson 
2822b371c939SRobert Watson 	return (error);
2823b371c939SRobert Watson }
2824b371c939SRobert Watson 
282595fab37eSRobert Watson static int
282695fab37eSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
282795fab37eSRobert Watson     struct label *newlabel)
282895fab37eSRobert Watson {
282995fab37eSRobert Watson 	int error;
283095fab37eSRobert Watson 
283195fab37eSRobert Watson 	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
283295fab37eSRobert Watson 	    newlabel);
283395fab37eSRobert Watson 
283495fab37eSRobert Watson 	return (error);
283595fab37eSRobert Watson }
283695fab37eSRobert Watson 
283795fab37eSRobert Watson int
2838b371c939SRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so)
2839b371c939SRobert Watson {
2840b371c939SRobert Watson 	int error;
2841b371c939SRobert Watson 
2842b371c939SRobert Watson 	if (!mac_enforce_socket)
2843b371c939SRobert Watson 		return (0);
2844b371c939SRobert Watson 
2845b371c939SRobert Watson 	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2846b371c939SRobert Watson 
2847b371c939SRobert Watson 	return (error);
2848b371c939SRobert Watson }
2849b371c939SRobert Watson 
2850b371c939SRobert Watson int
285195fab37eSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket)
285295fab37eSRobert Watson {
285395fab37eSRobert Watson 	int error;
285495fab37eSRobert Watson 
285595fab37eSRobert Watson 	if (!mac_enforce_socket)
285695fab37eSRobert Watson 		return (0);
285795fab37eSRobert Watson 
285895fab37eSRobert Watson 	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
285995fab37eSRobert Watson 
286095fab37eSRobert Watson 	return (error);
286195fab37eSRobert Watson }
286295fab37eSRobert Watson 
286395fab37eSRobert Watson int
286492835789SRobert Watson mac_check_sysarch_ioperm(struct ucred *cred)
286592835789SRobert Watson {
286692835789SRobert Watson 	int error;
286792835789SRobert Watson 
286892835789SRobert Watson 	if (!mac_enforce_system)
286992835789SRobert Watson 		return (0);
287092835789SRobert Watson 
287192835789SRobert Watson 	MAC_CHECK(check_sysarch_ioperm, cred);
287292835789SRobert Watson 	return (error);
287392835789SRobert Watson }
287492835789SRobert Watson 
287592835789SRobert Watson int
2876e5e820fdSRobert Watson mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2877e5e820fdSRobert Watson {
2878e5e820fdSRobert Watson 	int error;
2879e5e820fdSRobert Watson 
2880e5e820fdSRobert Watson 	if (vp != NULL) {
2881e5e820fdSRobert Watson 		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2882e5e820fdSRobert Watson 	}
2883e5e820fdSRobert Watson 
2884e5e820fdSRobert Watson 	if (!mac_enforce_system)
2885e5e820fdSRobert Watson 		return (0);
2886e5e820fdSRobert Watson 
2887e5e820fdSRobert Watson 	MAC_CHECK(check_system_acct, cred, vp,
2888e5e820fdSRobert Watson 	    vp != NULL ? &vp->v_label : NULL);
2889e5e820fdSRobert Watson 
2890e5e820fdSRobert Watson 	return (error);
2891e5e820fdSRobert Watson }
2892e5e820fdSRobert Watson 
2893e5e820fdSRobert Watson int
2894e5e820fdSRobert Watson mac_check_system_nfsd(struct ucred *cred)
2895e5e820fdSRobert Watson {
2896e5e820fdSRobert Watson 	int error;
2897e5e820fdSRobert Watson 
2898e5e820fdSRobert Watson 	if (!mac_enforce_system)
2899e5e820fdSRobert Watson 		return (0);
2900e5e820fdSRobert Watson 
2901e5e820fdSRobert Watson 	MAC_CHECK(check_system_nfsd, cred);
2902e5e820fdSRobert Watson 
2903e5e820fdSRobert Watson 	return (error);
2904e5e820fdSRobert Watson }
2905e5e820fdSRobert Watson 
2906e5e820fdSRobert Watson int
2907a2ecb9b7SRobert Watson mac_check_system_reboot(struct ucred *cred, int howto)
2908a2ecb9b7SRobert Watson {
2909a2ecb9b7SRobert Watson 	int error;
2910a2ecb9b7SRobert Watson 
29119e913ebdSRobert Watson 	if (!mac_enforce_system)
2912a2ecb9b7SRobert Watson 		return (0);
2913a2ecb9b7SRobert Watson 
2914a2ecb9b7SRobert Watson 	MAC_CHECK(check_system_reboot, cred, howto);
29159e913ebdSRobert Watson 
2916a2ecb9b7SRobert Watson 	return (error);
2917a2ecb9b7SRobert Watson }
2918a2ecb9b7SRobert Watson 
2919a2ecb9b7SRobert Watson int
29204b8d5f2dSRobert Watson mac_check_system_settime(struct ucred *cred)
29214b8d5f2dSRobert Watson {
29224b8d5f2dSRobert Watson 	int error;
29234b8d5f2dSRobert Watson 
29244b8d5f2dSRobert Watson 	if (!mac_enforce_system)
29254b8d5f2dSRobert Watson 		return (0);
29264b8d5f2dSRobert Watson 
29274b8d5f2dSRobert Watson 	MAC_CHECK(check_system_settime, cred);
29284b8d5f2dSRobert Watson 
29294b8d5f2dSRobert Watson 	return (error);
29304b8d5f2dSRobert Watson }
29314b8d5f2dSRobert Watson 
29324b8d5f2dSRobert Watson int
293303ce2c0cSRobert Watson mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
293403ce2c0cSRobert Watson {
293503ce2c0cSRobert Watson 	int error;
293603ce2c0cSRobert Watson 
293703ce2c0cSRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
293803ce2c0cSRobert Watson 
29399e913ebdSRobert Watson 	if (!mac_enforce_system)
294003ce2c0cSRobert Watson 		return (0);
294103ce2c0cSRobert Watson 
294203ce2c0cSRobert Watson 	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
294303ce2c0cSRobert Watson 	return (error);
294403ce2c0cSRobert Watson }
294503ce2c0cSRobert Watson 
294603ce2c0cSRobert Watson int
29471b2c2ab2SRobert Watson mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
29481b2c2ab2SRobert Watson {
29491b2c2ab2SRobert Watson 	int error;
29501b2c2ab2SRobert Watson 
29511b2c2ab2SRobert Watson 	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
29521b2c2ab2SRobert Watson 
29531b2c2ab2SRobert Watson 	if (!mac_enforce_system)
29541b2c2ab2SRobert Watson 		return (0);
29551b2c2ab2SRobert Watson 
29561b2c2ab2SRobert Watson 	MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
29571b2c2ab2SRobert Watson 	return (error);
29581b2c2ab2SRobert Watson }
29591b2c2ab2SRobert Watson 
29601b2c2ab2SRobert Watson int
2961d3fc69eeSRobert Watson mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2962d3fc69eeSRobert Watson     void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2963d3fc69eeSRobert Watson {
2964d3fc69eeSRobert Watson 	int error;
2965d3fc69eeSRobert Watson 
2966d3fc69eeSRobert Watson 	/*
2967d3fc69eeSRobert Watson 	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2968d3fc69eeSRobert Watson 	 * but since it's not exported from kern_sysctl.c, we can't.
2969d3fc69eeSRobert Watson 	 */
29709e913ebdSRobert Watson 	if (!mac_enforce_system)
2971d3fc69eeSRobert Watson 		return (0);
2972d3fc69eeSRobert Watson 
2973d3fc69eeSRobert Watson 	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2974d3fc69eeSRobert Watson 	    inkernel, new, newlen);
2975d3fc69eeSRobert Watson 
2976d3fc69eeSRobert Watson 	return (error);
2977d3fc69eeSRobert Watson }
2978d3fc69eeSRobert Watson 
2979d3fc69eeSRobert Watson int
298095fab37eSRobert Watson mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
298195fab37eSRobert Watson     struct ifnet *ifnet)
298295fab37eSRobert Watson {
2983f7b951a8SRobert Watson 	char *elements, *buffer;
2984f7b951a8SRobert Watson 	struct mac mac;
298595fab37eSRobert Watson 	int error;
298695fab37eSRobert Watson 
2987f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
298895fab37eSRobert Watson 	if (error)
298995fab37eSRobert Watson 		return (error);
299095fab37eSRobert Watson 
2991f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
2992f7b951a8SRobert Watson 	if (error)
2993f7b951a8SRobert Watson 		return (error);
2994f7b951a8SRobert Watson 
2995a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2996f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2997f7b951a8SRobert Watson 	if (error) {
2998f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
2999f7b951a8SRobert Watson 		return (error);
3000f7b951a8SRobert Watson 	}
3001f7b951a8SRobert Watson 
3002a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3003f7b951a8SRobert Watson 	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3004a163d034SWarner Losh 	    buffer, mac.m_buflen, M_WAITOK);
3005f7b951a8SRobert Watson 	if (error == 0)
3006f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3007f7b951a8SRobert Watson 
3008f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3009f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
3010f7b951a8SRobert Watson 
3011f7b951a8SRobert Watson 	return (error);
301295fab37eSRobert Watson }
301395fab37eSRobert Watson 
301495fab37eSRobert Watson int
301595fab37eSRobert Watson mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
301695fab37eSRobert Watson     struct ifnet *ifnet)
301795fab37eSRobert Watson {
301895fab37eSRobert Watson 	struct label intlabel;
3019f7b951a8SRobert Watson 	struct mac mac;
3020f7b951a8SRobert Watson 	char *buffer;
302195fab37eSRobert Watson 	int error;
302295fab37eSRobert Watson 
3023f7b951a8SRobert Watson 	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
302495fab37eSRobert Watson 	if (error)
302595fab37eSRobert Watson 		return (error);
302695fab37eSRobert Watson 
3027f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
302895fab37eSRobert Watson 	if (error)
302995fab37eSRobert Watson 		return (error);
303095fab37eSRobert Watson 
3031a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3032f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3033f7b951a8SRobert Watson 	if (error) {
3034f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
3035f7b951a8SRobert Watson 		return (error);
3036f7b951a8SRobert Watson 	}
3037f7b951a8SRobert Watson 
3038f7b951a8SRobert Watson 	mac_init_ifnet_label(&intlabel);
3039f7b951a8SRobert Watson 	error = mac_internalize_ifnet_label(&intlabel, buffer);
3040f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3041f7b951a8SRobert Watson 	if (error) {
3042f7b951a8SRobert Watson 		mac_destroy_ifnet_label(&intlabel);
3043f7b951a8SRobert Watson 		return (error);
3044f7b951a8SRobert Watson 	}
3045f7b951a8SRobert Watson 
304695fab37eSRobert Watson 	/*
304795fab37eSRobert Watson 	 * XXX: Note that this is a redundant privilege check, since
304895fab37eSRobert Watson 	 * policies impose this check themselves if required by the
304995fab37eSRobert Watson 	 * policy.  Eventually, this should go away.
305095fab37eSRobert Watson 	 */
305195fab37eSRobert Watson 	error = suser_cred(cred, 0);
3052f7b951a8SRobert Watson 	if (error) {
3053f7b951a8SRobert Watson 		mac_destroy_ifnet_label(&intlabel);
3054f7b951a8SRobert Watson 		return (error);
3055f7b951a8SRobert Watson 	}
305695fab37eSRobert Watson 
305795fab37eSRobert Watson 	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
305895fab37eSRobert Watson 	    &intlabel);
3059f7b951a8SRobert Watson 	if (error) {
3060f7b951a8SRobert Watson 		mac_destroy_ifnet_label(&intlabel);
3061f7b951a8SRobert Watson 		return (error);
3062f7b951a8SRobert Watson 	}
306395fab37eSRobert Watson 
306495fab37eSRobert Watson 	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
306595fab37eSRobert Watson 
3066f7b951a8SRobert Watson 	mac_destroy_ifnet_label(&intlabel);
3067f7b951a8SRobert Watson 	return (0);
306895fab37eSRobert Watson }
306995fab37eSRobert Watson 
307095fab37eSRobert Watson void
3071990b4b2dSRobert Watson mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
307295fab37eSRobert Watson {
307395fab37eSRobert Watson 
3074990b4b2dSRobert Watson 	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
307595fab37eSRobert Watson }
307695fab37eSRobert Watson 
307774e62b1bSRobert Watson void
3078990b4b2dSRobert Watson mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3079990b4b2dSRobert Watson     struct devfs_dirent *dd, struct devfs_dirent *de)
308074e62b1bSRobert Watson {
308174e62b1bSRobert Watson 
3082990b4b2dSRobert Watson 	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
308374e62b1bSRobert Watson 	    &de->de_label);
308474e62b1bSRobert Watson }
308574e62b1bSRobert Watson 
308695fab37eSRobert Watson void
3087990b4b2dSRobert Watson mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
308895fab37eSRobert Watson     struct devfs_dirent *de)
308995fab37eSRobert Watson {
309095fab37eSRobert Watson 
3091990b4b2dSRobert Watson 	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
309295fab37eSRobert Watson 	    &de->de_label);
309395fab37eSRobert Watson }
309495fab37eSRobert Watson 
309595fab37eSRobert Watson int
309695fab37eSRobert Watson mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3097f7b951a8SRobert Watson     struct mac *mac)
309895fab37eSRobert Watson {
309995fab37eSRobert Watson 	struct label intlabel;
3100f7b951a8SRobert Watson 	char *buffer;
310195fab37eSRobert Watson 	int error;
310295fab37eSRobert Watson 
3103f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
310495fab37eSRobert Watson 	if (error)
310595fab37eSRobert Watson 		return (error);
310695fab37eSRobert Watson 
3107a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3108f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3109f7b951a8SRobert Watson 	if (error) {
3110f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
3111f7b951a8SRobert Watson 		return (error);
3112f7b951a8SRobert Watson 	}
3113f7b951a8SRobert Watson 
3114a163d034SWarner Losh 	mac_init_socket_label(&intlabel, M_WAITOK);
3115f7b951a8SRobert Watson 	error = mac_internalize_socket_label(&intlabel, buffer);
3116f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3117f7b951a8SRobert Watson 	if (error) {
3118f7b951a8SRobert Watson 		mac_destroy_socket_label(&intlabel);
3119f7b951a8SRobert Watson 		return (error);
3120f7b951a8SRobert Watson 	}
3121f7b951a8SRobert Watson 
312295fab37eSRobert Watson 	mac_check_socket_relabel(cred, so, &intlabel);
312395fab37eSRobert Watson 	if (error) {
3124f7b951a8SRobert Watson 		mac_destroy_socket_label(&intlabel);
312595fab37eSRobert Watson 		return (error);
312695fab37eSRobert Watson 	}
312795fab37eSRobert Watson 
312895fab37eSRobert Watson 	mac_relabel_socket(cred, so, &intlabel);
312995fab37eSRobert Watson 
3130f7b951a8SRobert Watson 	mac_destroy_socket_label(&intlabel);
313195fab37eSRobert Watson 	return (0);
313295fab37eSRobert Watson }
313395fab37eSRobert Watson 
313495fab37eSRobert Watson int
313595fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
313695fab37eSRobert Watson {
313795fab37eSRobert Watson 	int error;
313895fab37eSRobert Watson 
31391aa37f53SRobert Watson 	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
31401aa37f53SRobert Watson 
314195fab37eSRobert Watson 	error = mac_check_pipe_relabel(cred, pipe, label);
314295fab37eSRobert Watson 	if (error)
314395fab37eSRobert Watson 		return (error);
314495fab37eSRobert Watson 
314595fab37eSRobert Watson 	mac_relabel_pipe(cred, pipe, label);
314695fab37eSRobert Watson 
314795fab37eSRobert Watson 	return (0);
314895fab37eSRobert Watson }
314995fab37eSRobert Watson 
315095fab37eSRobert Watson int
315195fab37eSRobert Watson mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3152f7b951a8SRobert Watson     struct mac *mac)
315395fab37eSRobert Watson {
3154f7b951a8SRobert Watson 	char *buffer, *elements;
3155f7b951a8SRobert Watson 	int error;
315695fab37eSRobert Watson 
3157f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
3158f7b951a8SRobert Watson 	if (error)
3159f7b951a8SRobert Watson 		return (error);
3160f7b951a8SRobert Watson 
3161a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3162f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3163f7b951a8SRobert Watson 	if (error) {
3164f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
3165f7b951a8SRobert Watson 		return (error);
3166f7b951a8SRobert Watson 	}
3167f7b951a8SRobert Watson 
3168a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3169f7b951a8SRobert Watson 	error = mac_externalize_socket_label(&so->so_label, elements,
3170a163d034SWarner Losh 	    buffer, mac->m_buflen, M_WAITOK);
3171f7b951a8SRobert Watson 	if (error == 0)
3172f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3173f7b951a8SRobert Watson 
3174f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3175f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
3176f7b951a8SRobert Watson 
3177f7b951a8SRobert Watson 	return (error);
317895fab37eSRobert Watson }
317995fab37eSRobert Watson 
318095fab37eSRobert Watson int
318195fab37eSRobert Watson mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3182f7b951a8SRobert Watson     struct mac *mac)
318395fab37eSRobert Watson {
3184f7b951a8SRobert Watson 	char *elements, *buffer;
3185f7b951a8SRobert Watson 	int error;
318695fab37eSRobert Watson 
3187f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(mac);
3188f7b951a8SRobert Watson 	if (error)
3189f7b951a8SRobert Watson 		return (error);
3190f7b951a8SRobert Watson 
3191a163d034SWarner Losh 	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3192f7b951a8SRobert Watson 	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3193f7b951a8SRobert Watson 	if (error) {
3194f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
3195f7b951a8SRobert Watson 		return (error);
3196f7b951a8SRobert Watson 	}
3197f7b951a8SRobert Watson 
3198a163d034SWarner Losh 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3199f7b951a8SRobert Watson 	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3200a163d034SWarner Losh 	    elements, buffer, mac->m_buflen, M_WAITOK);
3201f7b951a8SRobert Watson 	if (error == 0)
3202f7b951a8SRobert Watson 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3203f7b951a8SRobert Watson 
3204f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3205f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
3206f7b951a8SRobert Watson 
3207f7b951a8SRobert Watson 	return (error);
320895fab37eSRobert Watson }
320995fab37eSRobert Watson 
321095fab37eSRobert Watson /*
321195fab37eSRobert Watson  * Implementation of VOP_SETLABEL() that relies on extended attributes
321295fab37eSRobert Watson  * to store label data.  Can be referenced by filesystems supporting
321395fab37eSRobert Watson  * extended attributes.
321495fab37eSRobert Watson  */
321595fab37eSRobert Watson int
321695fab37eSRobert Watson vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
321795fab37eSRobert Watson {
321895fab37eSRobert Watson 	struct vnode *vp = ap->a_vp;
321995fab37eSRobert Watson 	struct label *intlabel = ap->a_label;
322095fab37eSRobert Watson 	int error;
322195fab37eSRobert Watson 
322295fab37eSRobert Watson 	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
322395fab37eSRobert Watson 
3224763bbd2fSRobert Watson 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3225763bbd2fSRobert Watson 		return (EOPNOTSUPP);
322695fab37eSRobert Watson 
3227763bbd2fSRobert Watson 	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
322895fab37eSRobert Watson 	if (error)
322995fab37eSRobert Watson 		return (error);
323095fab37eSRobert Watson 
323195fab37eSRobert Watson 	mac_relabel_vnode(ap->a_cred, vp, intlabel);
323295fab37eSRobert Watson 
323395fab37eSRobert Watson 	return (0);
323495fab37eSRobert Watson }
323595fab37eSRobert Watson 
323695fab37eSRobert Watson static int
323795fab37eSRobert Watson vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
323895fab37eSRobert Watson {
323995fab37eSRobert Watson 	int error;
324095fab37eSRobert Watson 
324195fab37eSRobert Watson 	if (vp->v_mount == NULL) {
324295fab37eSRobert Watson 		/* printf("vn_setlabel: null v_mount\n"); */
324306be2aaaSNate Lawson 		if (vp->v_type != VNON)
324406be2aaaSNate Lawson 			printf("vn_setlabel: null v_mount with non-VNON\n");
324595fab37eSRobert Watson 		return (EBADF);
324695fab37eSRobert Watson 	}
324795fab37eSRobert Watson 
324895fab37eSRobert Watson 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
324995fab37eSRobert Watson 		return (EOPNOTSUPP);
325095fab37eSRobert Watson 
325195fab37eSRobert Watson 	/*
325295fab37eSRobert Watson 	 * Multi-phase commit.  First check the policies to confirm the
325395fab37eSRobert Watson 	 * change is OK.  Then commit via the filesystem.  Finally,
325495fab37eSRobert Watson 	 * update the actual vnode label.  Question: maybe the filesystem
325595fab37eSRobert Watson 	 * should update the vnode at the end as part of VOP_SETLABEL()?
325695fab37eSRobert Watson 	 */
325795fab37eSRobert Watson 	error = mac_check_vnode_relabel(cred, vp, intlabel);
325895fab37eSRobert Watson 	if (error)
325995fab37eSRobert Watson 		return (error);
326095fab37eSRobert Watson 
326195fab37eSRobert Watson 	/*
326295fab37eSRobert Watson 	 * VADMIN provides the opportunity for the filesystem to make
326395fab37eSRobert Watson 	 * decisions about who is and is not able to modify labels
326495fab37eSRobert Watson 	 * and protections on files.  This might not be right.  We can't
326595fab37eSRobert Watson 	 * assume VOP_SETLABEL() will do it, because we might implement
326695fab37eSRobert Watson 	 * that as part of vop_stdsetlabel_ea().
326795fab37eSRobert Watson 	 */
326895fab37eSRobert Watson 	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
326995fab37eSRobert Watson 	if (error)
327095fab37eSRobert Watson 		return (error);
327195fab37eSRobert Watson 
327295fab37eSRobert Watson 	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
327395fab37eSRobert Watson 	if (error)
327495fab37eSRobert Watson 		return (error);
327595fab37eSRobert Watson 
327695fab37eSRobert Watson 	return (0);
327795fab37eSRobert Watson }
327895fab37eSRobert Watson 
3279f7b951a8SRobert Watson int
3280f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3281f7b951a8SRobert Watson {
3282f7b951a8SRobert Watson 	char *elements, *buffer;
3283f7b951a8SRobert Watson 	struct mac mac;
3284f7b951a8SRobert Watson 	struct proc *tproc;
3285f7b951a8SRobert Watson 	struct ucred *tcred;
3286f7b951a8SRobert Watson 	int error;
3287f7b951a8SRobert Watson 
3288d1e405c5SAlfred Perlstein 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3289f7b951a8SRobert Watson 	if (error)
3290f7b951a8SRobert Watson 		return (error);
3291f7b951a8SRobert Watson 
3292f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
3293f7b951a8SRobert Watson 	if (error)
3294f7b951a8SRobert Watson 		return (error);
3295f7b951a8SRobert Watson 
3296f7b951a8SRobert Watson 	tproc = pfind(uap->pid);
3297f7b951a8SRobert Watson 	if (tproc == NULL)
3298f7b951a8SRobert Watson 		return (ESRCH);
3299f7b951a8SRobert Watson 
3300f7b951a8SRobert Watson 	tcred = NULL;				/* Satisfy gcc. */
3301f7b951a8SRobert Watson 	error = p_cansee(td, tproc);
3302f7b951a8SRobert Watson 	if (error == 0)
3303f7b951a8SRobert Watson 		tcred = crhold(tproc->p_ucred);
3304f7b951a8SRobert Watson 	PROC_UNLOCK(tproc);
3305f7b951a8SRobert Watson 	if (error)
3306f7b951a8SRobert Watson 		return (error);
3307f7b951a8SRobert Watson 
3308a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3309f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3310f7b951a8SRobert Watson 	if (error) {
3311f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
3312f7b951a8SRobert Watson 		crfree(tcred);
3313f7b951a8SRobert Watson 		return (error);
3314f7b951a8SRobert Watson 	}
3315f7b951a8SRobert Watson 
3316a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3317f7b951a8SRobert Watson 	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3318a163d034SWarner Losh 	    buffer, mac.m_buflen, M_WAITOK);
3319f7b951a8SRobert Watson 	if (error == 0)
3320f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3321f7b951a8SRobert Watson 
3322f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3323f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
3324f7b951a8SRobert Watson 	crfree(tcred);
3325f7b951a8SRobert Watson 	return (error);
3326f7b951a8SRobert Watson }
3327f7b951a8SRobert Watson 
332895fab37eSRobert Watson /*
332995fab37eSRobert Watson  * MPSAFE
333095fab37eSRobert Watson  */
333195fab37eSRobert Watson int
333295fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
333395fab37eSRobert Watson {
3334f7b951a8SRobert Watson 	char *elements, *buffer;
3335f7b951a8SRobert Watson 	struct mac mac;
333695fab37eSRobert Watson 	int error;
333795fab37eSRobert Watson 
3338f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3339f7b951a8SRobert Watson 	if (error)
3340f7b951a8SRobert Watson 		return (error);
334195fab37eSRobert Watson 
3342f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
3343f7b951a8SRobert Watson 	if (error)
3344f7b951a8SRobert Watson 		return (error);
3345f7b951a8SRobert Watson 
3346a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3347f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3348f7b951a8SRobert Watson 	if (error) {
3349f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
3350f7b951a8SRobert Watson 		return (error);
3351f7b951a8SRobert Watson 	}
3352f7b951a8SRobert Watson 
3353a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3354f7b951a8SRobert Watson 	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3355a163d034SWarner Losh 	    elements, buffer, mac.m_buflen, M_WAITOK);
3356f7b951a8SRobert Watson 	if (error == 0)
3357f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3358f7b951a8SRobert Watson 
3359f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3360f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
336195fab37eSRobert Watson 	return (error);
336295fab37eSRobert Watson }
336395fab37eSRobert Watson 
336495fab37eSRobert Watson /*
336595fab37eSRobert Watson  * MPSAFE
336695fab37eSRobert Watson  */
336795fab37eSRobert Watson int
336895fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
336995fab37eSRobert Watson {
337095fab37eSRobert Watson 	struct ucred *newcred, *oldcred;
337195fab37eSRobert Watson 	struct label intlabel;
3372f7b951a8SRobert Watson 	struct proc *p;
3373f7b951a8SRobert Watson 	struct mac mac;
3374f7b951a8SRobert Watson 	char *buffer;
337595fab37eSRobert Watson 	int error;
337695fab37eSRobert Watson 
3377f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
337895fab37eSRobert Watson 	if (error)
337995fab37eSRobert Watson 		return (error);
338095fab37eSRobert Watson 
3381f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
338295fab37eSRobert Watson 	if (error)
338395fab37eSRobert Watson 		return (error);
338495fab37eSRobert Watson 
3385a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3386f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3387f7b951a8SRobert Watson 	if (error) {
3388f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
3389f7b951a8SRobert Watson 		return (error);
3390f7b951a8SRobert Watson 	}
3391f7b951a8SRobert Watson 
3392f7b951a8SRobert Watson 	mac_init_cred_label(&intlabel);
3393f7b951a8SRobert Watson 	error = mac_internalize_cred_label(&intlabel, buffer);
3394f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3395f7b951a8SRobert Watson 	if (error) {
3396f7b951a8SRobert Watson 		mac_destroy_cred_label(&intlabel);
3397f7b951a8SRobert Watson 		return (error);
3398f7b951a8SRobert Watson 	}
3399f7b951a8SRobert Watson 
340095fab37eSRobert Watson 	newcred = crget();
340195fab37eSRobert Watson 
340295fab37eSRobert Watson 	p = td->td_proc;
340395fab37eSRobert Watson 	PROC_LOCK(p);
340495fab37eSRobert Watson 	oldcred = p->p_ucred;
340595fab37eSRobert Watson 
340695fab37eSRobert Watson 	error = mac_check_cred_relabel(oldcred, &intlabel);
340795fab37eSRobert Watson 	if (error) {
340895fab37eSRobert Watson 		PROC_UNLOCK(p);
340995fab37eSRobert Watson 		crfree(newcred);
3410f7b951a8SRobert Watson 		goto out;
341195fab37eSRobert Watson 	}
341295fab37eSRobert Watson 
341395fab37eSRobert Watson 	setsugid(p);
341495fab37eSRobert Watson 	crcopy(newcred, oldcred);
341595fab37eSRobert Watson 	mac_relabel_cred(newcred, &intlabel);
341695fab37eSRobert Watson 	p->p_ucred = newcred;
3417e5cb5e37SRobert Watson 
3418e5cb5e37SRobert Watson 	/*
3419e5cb5e37SRobert Watson 	 * Grab additional reference for use while revoking mmaps, prior
3420e5cb5e37SRobert Watson 	 * to releasing the proc lock and sharing the cred.
3421e5cb5e37SRobert Watson 	 */
3422e5cb5e37SRobert Watson 	crhold(newcred);
342395fab37eSRobert Watson 	PROC_UNLOCK(p);
3424e5cb5e37SRobert Watson 
3425f7b951a8SRobert Watson 	if (mac_enforce_vm) {
342616140035SRobert Watson 		mtx_lock(&Giant);
3427e5cb5e37SRobert Watson 		mac_cred_mmapped_drop_perms(td, newcred);
342816140035SRobert Watson 		mtx_unlock(&Giant);
3429f7b951a8SRobert Watson 	}
3430e5cb5e37SRobert Watson 
3431e5cb5e37SRobert Watson 	crfree(newcred);	/* Free revocation reference. */
343295fab37eSRobert Watson 	crfree(oldcred);
3433f7b951a8SRobert Watson 
3434f7b951a8SRobert Watson out:
3435f7b951a8SRobert Watson 	mac_destroy_cred_label(&intlabel);
3436f7b951a8SRobert Watson 	return (error);
343795fab37eSRobert Watson }
343895fab37eSRobert Watson 
343995fab37eSRobert Watson /*
344095fab37eSRobert Watson  * MPSAFE
344195fab37eSRobert Watson  */
344295fab37eSRobert Watson int
344395fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
344495fab37eSRobert Watson {
3445f7b951a8SRobert Watson 	char *elements, *buffer;
3446f7b951a8SRobert Watson 	struct label intlabel;
344795fab37eSRobert Watson 	struct file *fp;
3448f7b951a8SRobert Watson 	struct mac mac;
344995fab37eSRobert Watson 	struct vnode *vp;
345095fab37eSRobert Watson 	struct pipe *pipe;
3451f7b951a8SRobert Watson 	short label_type;
345295fab37eSRobert Watson 	int error;
345395fab37eSRobert Watson 
3454f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3455f7b951a8SRobert Watson 	if (error)
3456f7b951a8SRobert Watson 		return (error);
345795fab37eSRobert Watson 
3458f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
3459f7b951a8SRobert Watson 	if (error)
3460f7b951a8SRobert Watson 		return (error);
3461f7b951a8SRobert Watson 
3462a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3463f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3464f7b951a8SRobert Watson 	if (error) {
3465f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
3466f7b951a8SRobert Watson 		return (error);
3467f7b951a8SRobert Watson 	}
3468f7b951a8SRobert Watson 
3469a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3470f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
3471d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
347295fab37eSRobert Watson 	if (error)
347395fab37eSRobert Watson 		goto out;
347495fab37eSRobert Watson 
3475f7b951a8SRobert Watson 	label_type = fp->f_type;
347695fab37eSRobert Watson 	switch (fp->f_type) {
347795fab37eSRobert Watson 	case DTYPE_FIFO:
347895fab37eSRobert Watson 	case DTYPE_VNODE:
34793b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
348095fab37eSRobert Watson 
3481f7b951a8SRobert Watson 		mac_init_vnode_label(&intlabel);
3482f7b951a8SRobert Watson 
348395fab37eSRobert Watson 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3484f7b951a8SRobert Watson 		mac_copy_vnode_label(&vp->v_label, &intlabel);
348595fab37eSRobert Watson 		VOP_UNLOCK(vp, 0, td);
3486f7b951a8SRobert Watson 
348795fab37eSRobert Watson 		break;
348895fab37eSRobert Watson 	case DTYPE_PIPE:
348948e3128bSMatthew Dillon 		pipe = fp->f_data;
3490f7b951a8SRobert Watson 
3491f7b951a8SRobert Watson 		mac_init_pipe_label(&intlabel);
3492f7b951a8SRobert Watson 
3493f7b951a8SRobert Watson 		PIPE_LOCK(pipe);
3494f7b951a8SRobert Watson 		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3495f7b951a8SRobert Watson 		PIPE_UNLOCK(pipe);
349695fab37eSRobert Watson 		break;
349795fab37eSRobert Watson 	default:
349895fab37eSRobert Watson 		error = EINVAL;
3499f7b951a8SRobert Watson 		fdrop(fp, td);
3500f7b951a8SRobert Watson 		goto out;
3501f7b951a8SRobert Watson 	}
3502f7b951a8SRobert Watson 	fdrop(fp, td);
3503f7b951a8SRobert Watson 
3504f7b951a8SRobert Watson 	switch (label_type) {
3505f7b951a8SRobert Watson 	case DTYPE_FIFO:
3506f7b951a8SRobert Watson 	case DTYPE_VNODE:
3507f7b951a8SRobert Watson 		if (error == 0)
3508f7b951a8SRobert Watson 			error = mac_externalize_vnode_label(&intlabel,
3509a163d034SWarner Losh 			    elements, buffer, mac.m_buflen, M_WAITOK);
3510f7b951a8SRobert Watson 		mac_destroy_vnode_label(&intlabel);
3511f7b951a8SRobert Watson 		break;
3512f7b951a8SRobert Watson 	case DTYPE_PIPE:
3513f7b951a8SRobert Watson 		error = mac_externalize_pipe_label(&intlabel, elements,
3514a163d034SWarner Losh 		    buffer, mac.m_buflen, M_WAITOK);
3515f7b951a8SRobert Watson 		mac_destroy_pipe_label(&intlabel);
3516f7b951a8SRobert Watson 		break;
3517f7b951a8SRobert Watson 	default:
3518f7b951a8SRobert Watson 		panic("__mac_get_fd: corrupted label_type");
351995fab37eSRobert Watson 	}
352095fab37eSRobert Watson 
352195fab37eSRobert Watson 	if (error == 0)
3522f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
352395fab37eSRobert Watson 
352495fab37eSRobert Watson out:
3525f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
3526f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3527f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
3528f7b951a8SRobert Watson 
352995fab37eSRobert Watson 	return (error);
353095fab37eSRobert Watson }
353195fab37eSRobert Watson 
353295fab37eSRobert Watson /*
353395fab37eSRobert Watson  * MPSAFE
353495fab37eSRobert Watson  */
353595fab37eSRobert Watson int
353695fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
353795fab37eSRobert Watson {
3538f7b951a8SRobert Watson 	char *elements, *buffer;
353995fab37eSRobert Watson 	struct nameidata nd;
3540f7b951a8SRobert Watson 	struct label intlabel;
3541f7b951a8SRobert Watson 	struct mac mac;
354295fab37eSRobert Watson 	int error;
354395fab37eSRobert Watson 
3544f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3545f7b951a8SRobert Watson 	if (error)
3546f7b951a8SRobert Watson 		return (error);
3547f7b951a8SRobert Watson 
3548f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
3549f7b951a8SRobert Watson 	if (error)
3550f7b951a8SRobert Watson 		return (error);
3551f7b951a8SRobert Watson 
3552a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3553f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3554f7b951a8SRobert Watson 	if (error) {
3555f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
3556f7b951a8SRobert Watson 		return (error);
3557f7b951a8SRobert Watson 	}
3558f7b951a8SRobert Watson 
3559a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3560f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
3561f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3562f7b951a8SRobert Watson 	    td);
356395fab37eSRobert Watson 	error = namei(&nd);
356495fab37eSRobert Watson 	if (error)
356595fab37eSRobert Watson 		goto out;
356695fab37eSRobert Watson 
3567f7b951a8SRobert Watson 	mac_init_vnode_label(&intlabel);
3568f7b951a8SRobert Watson 	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3569763bbd2fSRobert Watson 	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3570a163d034SWarner Losh 	    mac.m_buflen, M_WAITOK);
3571f7b951a8SRobert Watson 
357295fab37eSRobert Watson 	NDFREE(&nd, 0);
3573f7b951a8SRobert Watson 	mac_destroy_vnode_label(&intlabel);
3574f7b951a8SRobert Watson 
3575f7b951a8SRobert Watson 	if (error == 0)
3576f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3577f7b951a8SRobert Watson 
3578f7b951a8SRobert Watson out:
3579f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
3580f7b951a8SRobert Watson 
3581f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3582f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
3583f7b951a8SRobert Watson 
3584f7b951a8SRobert Watson 	return (error);
3585f7b951a8SRobert Watson }
3586f7b951a8SRobert Watson 
3587f7b951a8SRobert Watson /*
3588f7b951a8SRobert Watson  * MPSAFE
3589f7b951a8SRobert Watson  */
3590f7b951a8SRobert Watson int
3591f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3592f7b951a8SRobert Watson {
3593f7b951a8SRobert Watson 	char *elements, *buffer;
3594f7b951a8SRobert Watson 	struct nameidata nd;
3595f7b951a8SRobert Watson 	struct label intlabel;
3596f7b951a8SRobert Watson 	struct mac mac;
3597f7b951a8SRobert Watson 	int error;
3598f7b951a8SRobert Watson 
3599f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3600f7b951a8SRobert Watson 	if (error)
3601f7b951a8SRobert Watson 		return (error);
3602f7b951a8SRobert Watson 
3603f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
3604f7b951a8SRobert Watson 	if (error)
3605f7b951a8SRobert Watson 		return (error);
3606f7b951a8SRobert Watson 
3607a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3608f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3609f7b951a8SRobert Watson 	if (error) {
3610f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
3611f7b951a8SRobert Watson 		return (error);
3612f7b951a8SRobert Watson 	}
3613f7b951a8SRobert Watson 
3614a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3615f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
3616f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3617f7b951a8SRobert Watson 	    td);
3618f7b951a8SRobert Watson 	error = namei(&nd);
361995fab37eSRobert Watson 	if (error)
362095fab37eSRobert Watson 		goto out;
362195fab37eSRobert Watson 
3622f7b951a8SRobert Watson 	mac_init_vnode_label(&intlabel);
3623f7b951a8SRobert Watson 	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3624763bbd2fSRobert Watson 	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3625a163d034SWarner Losh 	    mac.m_buflen, M_WAITOK);
3626f7b951a8SRobert Watson 	NDFREE(&nd, 0);
3627f7b951a8SRobert Watson 	mac_destroy_vnode_label(&intlabel);
3628f7b951a8SRobert Watson 
3629f7b951a8SRobert Watson 	if (error == 0)
3630f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
363195fab37eSRobert Watson 
363295fab37eSRobert Watson out:
3633f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
3634f7b951a8SRobert Watson 
3635f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3636f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
3637f7b951a8SRobert Watson 
363895fab37eSRobert Watson 	return (error);
363995fab37eSRobert Watson }
364095fab37eSRobert Watson 
364195fab37eSRobert Watson /*
364295fab37eSRobert Watson  * MPSAFE
364395fab37eSRobert Watson  */
364495fab37eSRobert Watson int
364595fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
364695fab37eSRobert Watson {
364795fab37eSRobert Watson 	struct label intlabel;
3648f7b951a8SRobert Watson 	struct pipe *pipe;
3649f7b951a8SRobert Watson 	struct file *fp;
365095fab37eSRobert Watson 	struct mount *mp;
365195fab37eSRobert Watson 	struct vnode *vp;
3652f7b951a8SRobert Watson 	struct mac mac;
3653f7b951a8SRobert Watson 	char *buffer;
365495fab37eSRobert Watson 	int error;
365595fab37eSRobert Watson 
3656f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3657f7b951a8SRobert Watson 	if (error)
3658f7b951a8SRobert Watson 		return (error);
3659f7b951a8SRobert Watson 
3660f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
3661f7b951a8SRobert Watson 	if (error)
3662f7b951a8SRobert Watson 		return (error);
3663f7b951a8SRobert Watson 
3664a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3665f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3666f7b951a8SRobert Watson 	if (error) {
3667f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
3668f7b951a8SRobert Watson 		return (error);
3669f7b951a8SRobert Watson 	}
3670f7b951a8SRobert Watson 
3671f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
3672f7b951a8SRobert Watson 
3673d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
367495fab37eSRobert Watson 	if (error)
3675f7b951a8SRobert Watson 		goto out;
367695fab37eSRobert Watson 
367795fab37eSRobert Watson 	switch (fp->f_type) {
367895fab37eSRobert Watson 	case DTYPE_FIFO:
367995fab37eSRobert Watson 	case DTYPE_VNODE:
3680f7b951a8SRobert Watson 		mac_init_vnode_label(&intlabel);
3681f7b951a8SRobert Watson 		error = mac_internalize_vnode_label(&intlabel, buffer);
3682f7b951a8SRobert Watson 		if (error) {
3683f7b951a8SRobert Watson 			mac_destroy_vnode_label(&intlabel);
3684f7b951a8SRobert Watson 			break;
3685f7b951a8SRobert Watson 		}
3686f7b951a8SRobert Watson 
36873b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
368895fab37eSRobert Watson 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3689f7b951a8SRobert Watson 		if (error != 0) {
3690f7b951a8SRobert Watson 			mac_destroy_vnode_label(&intlabel);
369195fab37eSRobert Watson 			break;
3692f7b951a8SRobert Watson 		}
369395fab37eSRobert Watson 
369495fab37eSRobert Watson 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
369595fab37eSRobert Watson 		error = vn_setlabel(vp, &intlabel, td->td_ucred);
369695fab37eSRobert Watson 		VOP_UNLOCK(vp, 0, td);
369795fab37eSRobert Watson 		vn_finished_write(mp);
3698f7b951a8SRobert Watson 
3699f7b951a8SRobert Watson 		mac_destroy_vnode_label(&intlabel);
370095fab37eSRobert Watson 		break;
3701f7b951a8SRobert Watson 
370295fab37eSRobert Watson 	case DTYPE_PIPE:
3703f7b951a8SRobert Watson 		mac_init_pipe_label(&intlabel);
3704f7b951a8SRobert Watson 		error = mac_internalize_pipe_label(&intlabel, buffer);
3705f7b951a8SRobert Watson 		if (error == 0) {
370648e3128bSMatthew Dillon 			pipe = fp->f_data;
37071aa37f53SRobert Watson 			PIPE_LOCK(pipe);
3708f7b951a8SRobert Watson 			error = mac_pipe_label_set(td->td_ucred, pipe,
3709f7b951a8SRobert Watson 			    &intlabel);
37101aa37f53SRobert Watson 			PIPE_UNLOCK(pipe);
3711f7b951a8SRobert Watson 		}
3712f7b951a8SRobert Watson 
3713f7b951a8SRobert Watson 		mac_destroy_pipe_label(&intlabel);
371495fab37eSRobert Watson 		break;
3715f7b951a8SRobert Watson 
371695fab37eSRobert Watson 	default:
371795fab37eSRobert Watson 		error = EINVAL;
371895fab37eSRobert Watson 	}
371995fab37eSRobert Watson 
372095fab37eSRobert Watson 	fdrop(fp, td);
3721f7b951a8SRobert Watson out:
3722f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
3723f7b951a8SRobert Watson 
3724f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3725f7b951a8SRobert Watson 
372695fab37eSRobert Watson 	return (error);
372795fab37eSRobert Watson }
372895fab37eSRobert Watson 
372995fab37eSRobert Watson /*
373095fab37eSRobert Watson  * MPSAFE
373195fab37eSRobert Watson  */
373295fab37eSRobert Watson int
373395fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
373495fab37eSRobert Watson {
373595fab37eSRobert Watson 	struct label intlabel;
3736f7b951a8SRobert Watson 	struct nameidata nd;
373795fab37eSRobert Watson 	struct mount *mp;
3738f7b951a8SRobert Watson 	struct mac mac;
3739f7b951a8SRobert Watson 	char *buffer;
374095fab37eSRobert Watson 	int error;
374195fab37eSRobert Watson 
3742f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
374395fab37eSRobert Watson 	if (error)
3744f7b951a8SRobert Watson 		return (error);
374595fab37eSRobert Watson 
3746f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
374795fab37eSRobert Watson 	if (error)
3748f7b951a8SRobert Watson 		return (error);
374995fab37eSRobert Watson 
3750a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3751f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3752f7b951a8SRobert Watson 	if (error) {
3753f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
375495fab37eSRobert Watson 		return (error);
375595fab37eSRobert Watson 	}
375695fab37eSRobert Watson 
3757f7b951a8SRobert Watson 	mac_init_vnode_label(&intlabel);
3758f7b951a8SRobert Watson 	error = mac_internalize_vnode_label(&intlabel, buffer);
3759f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3760f7b951a8SRobert Watson 	if (error) {
3761f7b951a8SRobert Watson 		mac_destroy_vnode_label(&intlabel);
3762f7b951a8SRobert Watson 		return (error);
3763f7b951a8SRobert Watson 	}
3764f7b951a8SRobert Watson 
3765f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
3766f7b951a8SRobert Watson 
3767f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3768f7b951a8SRobert Watson 	    td);
3769f7b951a8SRobert Watson 	error = namei(&nd);
3770f7b951a8SRobert Watson 	if (error == 0) {
3771f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3772f7b951a8SRobert Watson 		if (error == 0)
3773f7b951a8SRobert Watson 			error = vn_setlabel(nd.ni_vp, &intlabel,
3774f7b951a8SRobert Watson 			    td->td_ucred);
3775f7b951a8SRobert Watson 		vn_finished_write(mp);
3776f7b951a8SRobert Watson 	}
3777f7b951a8SRobert Watson 
3778f7b951a8SRobert Watson 	NDFREE(&nd, 0);
3779f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
3780f7b951a8SRobert Watson 	mac_destroy_vnode_label(&intlabel);
3781f7b951a8SRobert Watson 
3782f7b951a8SRobert Watson 	return (error);
3783f7b951a8SRobert Watson }
3784f7b951a8SRobert Watson 
3785f7b951a8SRobert Watson /*
3786f7b951a8SRobert Watson  * MPSAFE
3787f7b951a8SRobert Watson  */
3788f7b951a8SRobert Watson int
3789f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3790f7b951a8SRobert Watson {
3791f7b951a8SRobert Watson 	struct label intlabel;
3792f7b951a8SRobert Watson 	struct nameidata nd;
3793f7b951a8SRobert Watson 	struct mount *mp;
3794f7b951a8SRobert Watson 	struct mac mac;
3795f7b951a8SRobert Watson 	char *buffer;
3796f7b951a8SRobert Watson 	int error;
3797f7b951a8SRobert Watson 
3798f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
3799f7b951a8SRobert Watson 	if (error)
3800f7b951a8SRobert Watson 		return (error);
3801f7b951a8SRobert Watson 
3802f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
3803f7b951a8SRobert Watson 	if (error)
3804f7b951a8SRobert Watson 		return (error);
3805f7b951a8SRobert Watson 
3806a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3807f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3808f7b951a8SRobert Watson 	if (error) {
3809f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
3810f7b951a8SRobert Watson 		return (error);
3811f7b951a8SRobert Watson 	}
3812f7b951a8SRobert Watson 
3813f7b951a8SRobert Watson 	mac_init_vnode_label(&intlabel);
3814f7b951a8SRobert Watson 	error = mac_internalize_vnode_label(&intlabel, buffer);
3815f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
3816f7b951a8SRobert Watson 	if (error) {
3817f7b951a8SRobert Watson 		mac_destroy_vnode_label(&intlabel);
3818f7b951a8SRobert Watson 		return (error);
3819f7b951a8SRobert Watson 	}
3820f7b951a8SRobert Watson 
3821f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
3822f7b951a8SRobert Watson 
3823f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3824f7b951a8SRobert Watson 	    td);
3825f7b951a8SRobert Watson 	error = namei(&nd);
3826f7b951a8SRobert Watson 	if (error == 0) {
3827f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3828f7b951a8SRobert Watson 		if (error == 0)
3829f7b951a8SRobert Watson 			error = vn_setlabel(nd.ni_vp, &intlabel,
3830f7b951a8SRobert Watson 			    td->td_ucred);
3831f7b951a8SRobert Watson 		vn_finished_write(mp);
3832f7b951a8SRobert Watson 	}
3833f7b951a8SRobert Watson 
3834f7b951a8SRobert Watson 	NDFREE(&nd, 0);
3835f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
3836f7b951a8SRobert Watson 	mac_destroy_vnode_label(&intlabel);
3837f7b951a8SRobert Watson 
3838f7b951a8SRobert Watson 	return (error);
3839f7b951a8SRobert Watson }
3840f7b951a8SRobert Watson 
3841f7b951a8SRobert Watson /*
3842f7b951a8SRobert Watson  * MPSAFE
3843f7b951a8SRobert Watson  */
384427f2eac7SRobert Watson int
384527f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
384627f2eac7SRobert Watson {
384727f2eac7SRobert Watson 	struct mac_policy_conf *mpc;
384827f2eac7SRobert Watson 	char target[MAC_MAX_POLICY_NAME];
384941a17fe3SRobert Watson 	int entrycount, error;
385027f2eac7SRobert Watson 
3851d1e405c5SAlfred Perlstein 	error = copyinstr(uap->policy, target, sizeof(target), NULL);
385227f2eac7SRobert Watson 	if (error)
385327f2eac7SRobert Watson 		return (error);
385427f2eac7SRobert Watson 
385527f2eac7SRobert Watson 	error = ENOSYS;
385627f2eac7SRobert Watson 	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
385727f2eac7SRobert Watson 		if (strcmp(mpc->mpc_name, target) == 0 &&
385827f2eac7SRobert Watson 		    mpc->mpc_ops->mpo_syscall != NULL) {
385927f2eac7SRobert Watson 			error = mpc->mpc_ops->mpo_syscall(td,
3860d1e405c5SAlfred Perlstein 			    uap->call, uap->arg);
386127f2eac7SRobert Watson 			goto out;
386227f2eac7SRobert Watson 		}
386327f2eac7SRobert Watson 	}
386427f2eac7SRobert Watson 
386541a17fe3SRobert Watson 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
386641a17fe3SRobert Watson 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
386741a17fe3SRobert Watson 			if (strcmp(mpc->mpc_name, target) == 0 &&
386841a17fe3SRobert Watson 			    mpc->mpc_ops->mpo_syscall != NULL) {
386941a17fe3SRobert Watson 				error = mpc->mpc_ops->mpo_syscall(td,
387041a17fe3SRobert Watson 				    uap->call, uap->arg);
387141a17fe3SRobert Watson 				break;
387241a17fe3SRobert Watson 			}
387341a17fe3SRobert Watson 		}
387441a17fe3SRobert Watson 		mac_policy_list_unbusy();
387541a17fe3SRobert Watson 	}
387627f2eac7SRobert Watson out:
387727f2eac7SRobert Watson 	return (error);
387827f2eac7SRobert Watson }
387927f2eac7SRobert Watson 
388095fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
388195fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
388295fab37eSRobert Watson 
388395fab37eSRobert Watson #else /* !MAC */
38847bc82500SRobert Watson 
38857bc82500SRobert Watson int
3886f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3887f7b951a8SRobert Watson {
3888f7b951a8SRobert Watson 
3889f7b951a8SRobert Watson 	return (ENOSYS);
3890f7b951a8SRobert Watson }
3891f7b951a8SRobert Watson 
3892f7b951a8SRobert Watson int
38937bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
38947bc82500SRobert Watson {
38957bc82500SRobert Watson 
38967bc82500SRobert Watson 	return (ENOSYS);
38977bc82500SRobert Watson }
38987bc82500SRobert Watson 
38997bc82500SRobert Watson int
39007bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
39017bc82500SRobert Watson {
39027bc82500SRobert Watson 
39037bc82500SRobert Watson 	return (ENOSYS);
39047bc82500SRobert Watson }
39057bc82500SRobert Watson 
39067bc82500SRobert Watson int
39077bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
39087bc82500SRobert Watson {
39097bc82500SRobert Watson 
39107bc82500SRobert Watson 	return (ENOSYS);
39117bc82500SRobert Watson }
39127bc82500SRobert Watson 
39137bc82500SRobert Watson int
39147bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
39157bc82500SRobert Watson {
39167bc82500SRobert Watson 
39177bc82500SRobert Watson 	return (ENOSYS);
39187bc82500SRobert Watson }
39197bc82500SRobert Watson 
39207bc82500SRobert Watson int
3921f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3922f7b951a8SRobert Watson {
3923f7b951a8SRobert Watson 
3924f7b951a8SRobert Watson 	return (ENOSYS);
3925f7b951a8SRobert Watson }
3926f7b951a8SRobert Watson 
3927f7b951a8SRobert Watson int
39287bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
39297bc82500SRobert Watson {
39307bc82500SRobert Watson 
39317bc82500SRobert Watson 	return (ENOSYS);
39327bc82500SRobert Watson }
39337bc82500SRobert Watson 
39347bc82500SRobert Watson int
39357bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
39367bc82500SRobert Watson {
39377bc82500SRobert Watson 
39387bc82500SRobert Watson 	return (ENOSYS);
39397bc82500SRobert Watson }
394095fab37eSRobert Watson 
394127f2eac7SRobert Watson int
3942f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3943f7b951a8SRobert Watson {
3944f7b951a8SRobert Watson 
3945f7b951a8SRobert Watson 	return (ENOSYS);
3946f7b951a8SRobert Watson }
3947f7b951a8SRobert Watson 
3948f7b951a8SRobert Watson int
394927f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
395027f2eac7SRobert Watson {
395127f2eac7SRobert Watson 
395227f2eac7SRobert Watson 	return (ENOSYS);
395327f2eac7SRobert Watson }
395427f2eac7SRobert Watson 
3955f7b951a8SRobert Watson #endif
3956