xref: /freebsd/sys/security/mac/mac_framework.c (revision 49bb6870cc71b5c0726b765bcb196b6ebed74156)
17bc82500SRobert Watson /*-
2f6a41092SRobert Watson  * Copyright (c) 1999-2002 Robert N. M. Watson
37bc82500SRobert Watson  * Copyright (c) 2001 Ilmar S. Habibulin
4f0c2044bSRobert Watson  * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
549bb6870SRobert Watson  * Copyright (c) 2005 SPARTA, Inc.
67bc82500SRobert Watson  * All rights reserved.
77bc82500SRobert Watson  *
87bc82500SRobert Watson  * This software was developed by Robert Watson and Ilmar Habibulin for the
97bc82500SRobert Watson  * TrustedBSD Project.
107bc82500SRobert Watson  *
116201265bSRobert Watson  * This software was developed for the FreeBSD Project in part by Network
126201265bSRobert Watson  * Associates Laboratories, the Security Research Division of Network
136201265bSRobert Watson  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
146201265bSRobert Watson  * as part of the DARPA CHATS research program.
157bc82500SRobert Watson  *
1649bb6870SRobert Watson  * This software was enhanced by SPARTA ISSO under SPAWAR contract
1749bb6870SRobert Watson  * N66001-04-C-6019 ("SEFOS").
1849bb6870SRobert Watson  *
197bc82500SRobert Watson  * Redistribution and use in source and binary forms, with or without
207bc82500SRobert Watson  * modification, are permitted provided that the following conditions
217bc82500SRobert Watson  * are met:
227bc82500SRobert Watson  * 1. Redistributions of source code must retain the above copyright
237bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer.
247bc82500SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
257bc82500SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
267bc82500SRobert Watson  *    documentation and/or other materials provided with the distribution.
277bc82500SRobert Watson  *
287bc82500SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
297bc82500SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
307bc82500SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
317bc82500SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
327bc82500SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
337bc82500SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
347bc82500SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
357bc82500SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
367bc82500SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
377bc82500SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
387bc82500SRobert Watson  * SUCH DAMAGE.
397bc82500SRobert Watson  */
40677b542eSDavid E. O'Brien 
41c8e7bf92SRobert Watson /*-
42c8e7bf92SRobert Watson  * Framework for extensible kernel access control.  This file contains
43c8e7bf92SRobert Watson  * Kernel and userland interface to the framework, policy registration
44c8e7bf92SRobert Watson  * and composition.  Per-object interfaces, controls, and labeling may be
4549869305STom Rhodes  * found in src/sys/security/mac/.  Sample policies may be found in
4649869305STom Rhodes  * src/sys/security/mac_*.
477bc82500SRobert Watson  */
487bc82500SRobert Watson 
49677b542eSDavid E. O'Brien #include <sys/cdefs.h>
50677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
51677b542eSDavid E. O'Brien 
527bc82500SRobert Watson #include "opt_mac.h"
53328048bcSPoul-Henning Kamp #include "opt_devfs.h"
54f9d0d524SRobert Watson 
557bc82500SRobert Watson #include <sys/param.h>
56a96acd1aSRobert Watson #include <sys/condvar.h>
5795fab37eSRobert Watson #include <sys/extattr.h>
58670cb89bSRobert Watson #include <sys/imgact.h>
5995fab37eSRobert Watson #include <sys/kernel.h>
6095fab37eSRobert Watson #include <sys/lock.h>
61b656366bSBruce Evans #include <sys/malloc.h>
6295fab37eSRobert Watson #include <sys/mutex.h>
6395fab37eSRobert Watson #include <sys/mac.h>
647ba28492SRobert Watson #include <sys/module.h>
6595fab37eSRobert Watson #include <sys/proc.h>
66f51e5803SRobert Watson #include <sys/sbuf.h>
6795fab37eSRobert Watson #include <sys/systm.h>
687bc82500SRobert Watson #include <sys/sysproto.h>
697bc82500SRobert Watson #include <sys/sysent.h>
7095fab37eSRobert Watson #include <sys/vnode.h>
7195fab37eSRobert Watson #include <sys/mount.h>
7295fab37eSRobert Watson #include <sys/file.h>
7395fab37eSRobert Watson #include <sys/namei.h>
7495fab37eSRobert Watson #include <sys/socket.h>
7595fab37eSRobert Watson #include <sys/pipe.h>
7695fab37eSRobert Watson #include <sys/socketvar.h>
7795fab37eSRobert Watson #include <sys/sysctl.h>
7895fab37eSRobert Watson 
7995fab37eSRobert Watson #include <vm/vm.h>
8095fab37eSRobert Watson #include <vm/pmap.h>
8195fab37eSRobert Watson #include <vm/vm_map.h>
8295fab37eSRobert Watson #include <vm/vm_object.h>
8395fab37eSRobert Watson 
8495fab37eSRobert Watson #include <sys/mac_policy.h>
8595fab37eSRobert Watson 
8695fab37eSRobert Watson #include <fs/devfs/devfs.h>
8795fab37eSRobert Watson 
8895fab37eSRobert Watson #include <net/bpfdesc.h>
8995fab37eSRobert Watson #include <net/if.h>
9095fab37eSRobert Watson #include <net/if_var.h>
9195fab37eSRobert Watson 
9295fab37eSRobert Watson #include <netinet/in.h>
9395fab37eSRobert Watson #include <netinet/ip_var.h>
9495fab37eSRobert Watson 
956fa0475dSRobert Watson #include <security/mac/mac_internal.h>
966fa0475dSRobert Watson 
9795fab37eSRobert Watson #ifdef MAC
9895fab37eSRobert Watson 
997ba28492SRobert Watson /*
1007ba28492SRobert Watson  * Declare that the kernel provides MAC support, version 1.  This permits
1017ba28492SRobert Watson  * modules to refuse to be loaded if the necessary support isn't present,
1027ba28492SRobert Watson  * even if it's pre-boot.
1037ba28492SRobert Watson  */
10449bb6870SRobert Watson MODULE_VERSION(kernel_mac_support, 3);
1057ba28492SRobert Watson 
10695fab37eSRobert Watson SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
10795fab37eSRobert Watson     "TrustedBSD MAC policy controls");
108b2f0927aSRobert Watson 
109b2aef571SRobert Watson #if MAC_MAX_SLOTS > 32
110b2aef571SRobert Watson #error "MAC_MAX_SLOTS too large"
11195fab37eSRobert Watson #endif
112a13c67daSRobert Watson 
113b2aef571SRobert Watson static unsigned int mac_max_slots = MAC_MAX_SLOTS;
114b2aef571SRobert Watson static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
115b2aef571SRobert Watson SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
116b2aef571SRobert Watson     &mac_max_slots, 0, "");
11795fab37eSRobert Watson 
118a67fe518SRobert Watson /*
119a67fe518SRobert Watson  * Has the kernel started generating labeled objects yet?  All read/write
120a67fe518SRobert Watson  * access to this variable is serialized during the boot process.  Following
121a67fe518SRobert Watson  * the end of serialization, we don't update this flag; no locking.
122a67fe518SRobert Watson  */
123089c1bdaSRobert Watson int	mac_late = 0;
124763bbd2fSRobert Watson 
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  */
13619c3e120SRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
137089c1bdaSRobert Watson int	mac_labelmbufs = 0;
138225bff6fSRobert Watson #endif
139225bff6fSRobert Watson 
140f050add5SRobert Watson #ifdef MAC_DEBUG
1416be0c25eSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
1426be0c25eSRobert Watson     "TrustedBSD MAC debug info");
143b2f0927aSRobert Watson SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
144b2f0927aSRobert Watson     "TrustedBSD MAC object counters");
145b2f0927aSRobert Watson 
1466fa0475dSRobert Watson static unsigned int nmactemp;
147b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
14895fab37eSRobert Watson     &nmactemp, 0, "number of temporary labels in use");
149f050add5SRobert Watson #endif
15095fab37eSRobert Watson 
15195fab37eSRobert Watson static int	mac_policy_register(struct mac_policy_conf *mpc);
15295fab37eSRobert Watson static int	mac_policy_unregister(struct mac_policy_conf *mpc);
15395fab37eSRobert Watson 
154f7b951a8SRobert Watson MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
15595fab37eSRobert Watson 
15695fab37eSRobert Watson /*
15741a17fe3SRobert Watson  * mac_static_policy_list holds a list of policy modules that are not
15841a17fe3SRobert Watson  * loaded while the system is "live", and cannot be unloaded.  These
15941a17fe3SRobert Watson  * policies can be invoked without holding the busy count.
16041a17fe3SRobert Watson  *
16141a17fe3SRobert Watson  * mac_policy_list stores the list of dynamic policies.  A busy count is
162a96acd1aSRobert Watson  * maintained for the list, stored in mac_policy_busy.  The busy count
16341a17fe3SRobert Watson  * is protected by mac_policy_mtx; the list may be modified only
164a96acd1aSRobert Watson  * while the busy count is 0, requiring that the lock be held to
165a96acd1aSRobert Watson  * prevent new references to the list from being acquired.  For almost
166a96acd1aSRobert Watson  * all operations, incrementing the busy count is sufficient to
167a96acd1aSRobert Watson  * guarantee consistency, as the list cannot be modified while the
168a96acd1aSRobert Watson  * busy count is elevated.  For a few special operations involving a
16941a17fe3SRobert Watson  * change to the list of active policies, the mtx itself must be held.
17041a17fe3SRobert Watson  * A condition variable, mac_policy_cv, is used to signal potential
17141a17fe3SRobert Watson  * exclusive consumers that they should try to acquire the lock if a
17241a17fe3SRobert Watson  * first attempt at exclusive access fails.
17395fab37eSRobert Watson  */
1740a05006dSRobert Watson #ifndef MAC_STATIC
17541a17fe3SRobert Watson static struct mtx mac_policy_mtx;
17641a17fe3SRobert Watson static struct cv mac_policy_cv;
17741a17fe3SRobert Watson static int mac_policy_count;
1780a05006dSRobert Watson #endif
179089c1bdaSRobert Watson struct mac_policy_list_head mac_policy_list;
180089c1bdaSRobert Watson struct mac_policy_list_head mac_static_policy_list;
181a96acd1aSRobert Watson 
182a96acd1aSRobert Watson /*
18326306795SJohn Baldwin  * We manually invoke WITNESS_WARN() to allow Witness to generate
184a96acd1aSRobert Watson  * warnings even if we don't end up ever triggering the wait at
185a96acd1aSRobert Watson  * run-time.  The consumer of the exclusive interface must not hold
186a96acd1aSRobert Watson  * any locks (other than potentially Giant) since we may sleep for
187a96acd1aSRobert Watson  * long (potentially indefinite) periods of time waiting for the
188a96acd1aSRobert Watson  * framework to become quiescent so that a policy list change may
189a96acd1aSRobert Watson  * be made.
190a96acd1aSRobert Watson  */
191089c1bdaSRobert Watson void
19241a17fe3SRobert Watson mac_policy_grab_exclusive(void)
19341a17fe3SRobert Watson {
194c8e7bf92SRobert Watson 
1950a05006dSRobert Watson #ifndef MAC_STATIC
1961e4cadcbSRobert Watson 	if (!mac_late)
1971e4cadcbSRobert Watson 		return;
1981e4cadcbSRobert Watson 
19941a17fe3SRobert Watson 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
20041a17fe3SRobert Watson  	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
20141a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
20241a17fe3SRobert Watson 	while (mac_policy_count != 0)
20341a17fe3SRobert Watson 		cv_wait(&mac_policy_cv, &mac_policy_mtx);
2040a05006dSRobert Watson #endif
20541a17fe3SRobert Watson }
20695fab37eSRobert Watson 
207089c1bdaSRobert Watson void
20841a17fe3SRobert Watson mac_policy_assert_exclusive(void)
20941a17fe3SRobert Watson {
210c8e7bf92SRobert Watson 
2110a05006dSRobert Watson #ifndef MAC_STATIC
2121e4cadcbSRobert Watson 	if (!mac_late)
2131e4cadcbSRobert Watson 		return;
2141e4cadcbSRobert Watson 
21541a17fe3SRobert Watson 	mtx_assert(&mac_policy_mtx, MA_OWNED);
21641a17fe3SRobert Watson 	KASSERT(mac_policy_count == 0,
21741a17fe3SRobert Watson 	    ("mac_policy_assert_exclusive(): not exclusive"));
2180a05006dSRobert Watson #endif
21941a17fe3SRobert Watson }
220225bff6fSRobert Watson 
221089c1bdaSRobert Watson void
22241a17fe3SRobert Watson mac_policy_release_exclusive(void)
22341a17fe3SRobert Watson {
22495fab37eSRobert Watson 
2250a05006dSRobert Watson #ifndef MAC_STATIC
2261e4cadcbSRobert Watson 	if (!mac_late)
2271e4cadcbSRobert Watson 		return;
2281e4cadcbSRobert Watson 
22941a17fe3SRobert Watson 	KASSERT(mac_policy_count == 0,
23041a17fe3SRobert Watson 	    ("mac_policy_release_exclusive(): not exclusive"));
23141a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
23241a17fe3SRobert Watson 	cv_signal(&mac_policy_cv);
2330a05006dSRobert Watson #endif
23441a17fe3SRobert Watson }
23541a17fe3SRobert Watson 
236089c1bdaSRobert Watson void
23741a17fe3SRobert Watson mac_policy_list_busy(void)
23841a17fe3SRobert Watson {
239c8e7bf92SRobert Watson 
2400a05006dSRobert Watson #ifndef MAC_STATIC
2411e4cadcbSRobert Watson 	if (!mac_late)
2421e4cadcbSRobert Watson 		return;
2431e4cadcbSRobert Watson 
24441a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
24541a17fe3SRobert Watson 	mac_policy_count++;
24641a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
2470a05006dSRobert Watson #endif
24841a17fe3SRobert Watson }
24941a17fe3SRobert Watson 
250089c1bdaSRobert Watson int
25141a17fe3SRobert Watson mac_policy_list_conditional_busy(void)
25241a17fe3SRobert Watson {
2530a05006dSRobert Watson #ifndef MAC_STATIC
25441a17fe3SRobert Watson 	int ret;
25541a17fe3SRobert Watson 
2561e4cadcbSRobert Watson 	if (!mac_late)
2571e4cadcbSRobert Watson 		return (1);
2581e4cadcbSRobert Watson 
25941a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
26041a17fe3SRobert Watson 	if (!LIST_EMPTY(&mac_policy_list)) {
26141a17fe3SRobert Watson 		mac_policy_count++;
26241a17fe3SRobert Watson 		ret = 1;
26341a17fe3SRobert Watson 	} else
26441a17fe3SRobert Watson 		ret = 0;
26541a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
26641a17fe3SRobert Watson 	return (ret);
2670a05006dSRobert Watson #else
2681e4cadcbSRobert Watson 	if (!mac_late)
2691e4cadcbSRobert Watson 		return (1);
2701e4cadcbSRobert Watson 
2710a05006dSRobert Watson 	return (1);
2720a05006dSRobert Watson #endif
27341a17fe3SRobert Watson }
27441a17fe3SRobert Watson 
275089c1bdaSRobert Watson void
27641a17fe3SRobert Watson mac_policy_list_unbusy(void)
27741a17fe3SRobert Watson {
278c8e7bf92SRobert Watson 
2790a05006dSRobert Watson #ifndef MAC_STATIC
2801e4cadcbSRobert Watson 	if (!mac_late)
2811e4cadcbSRobert Watson 		return;
2821e4cadcbSRobert Watson 
28341a17fe3SRobert Watson 	mtx_lock(&mac_policy_mtx);
28441a17fe3SRobert Watson 	mac_policy_count--;
28541a17fe3SRobert Watson 	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
28641a17fe3SRobert Watson 	if (mac_policy_count == 0)
28741a17fe3SRobert Watson 		cv_signal(&mac_policy_cv);
28841a17fe3SRobert Watson 	mtx_unlock(&mac_policy_mtx);
2890a05006dSRobert Watson #endif
29041a17fe3SRobert Watson }
29195fab37eSRobert Watson 
29295fab37eSRobert Watson /*
29395fab37eSRobert Watson  * Initialize the MAC subsystem, including appropriate SMP locks.
29495fab37eSRobert Watson  */
29595fab37eSRobert Watson static void
29695fab37eSRobert Watson mac_init(void)
29795fab37eSRobert Watson {
29895fab37eSRobert Watson 
29941a17fe3SRobert Watson 	LIST_INIT(&mac_static_policy_list);
30095fab37eSRobert Watson 	LIST_INIT(&mac_policy_list);
301eca8a663SRobert Watson 	mac_labelzone_init();
30241a17fe3SRobert Watson 
3030a05006dSRobert Watson #ifndef MAC_STATIC
30441a17fe3SRobert Watson 	mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
30541a17fe3SRobert Watson 	cv_init(&mac_policy_cv, "mac_policy_cv");
3060a05006dSRobert Watson #endif
30795fab37eSRobert Watson }
30895fab37eSRobert Watson 
30995fab37eSRobert Watson /*
31095fab37eSRobert Watson  * For the purposes of modules that want to know if they were loaded
31195fab37eSRobert Watson  * "early", set the mac_late flag once we've processed modules either
31295fab37eSRobert Watson  * linked into the kernel, or loaded before the kernel startup.
31395fab37eSRobert Watson  */
31495fab37eSRobert Watson static void
31595fab37eSRobert Watson mac_late_init(void)
31695fab37eSRobert Watson {
31795fab37eSRobert Watson 
31895fab37eSRobert Watson 	mac_late = 1;
31995fab37eSRobert Watson }
32095fab37eSRobert Watson 
32195fab37eSRobert Watson /*
322225bff6fSRobert Watson  * After the policy list has changed, walk the list to update any global
32319c3e120SRobert Watson  * flags.  Currently, we support only one flag, and it's conditionally
32419c3e120SRobert Watson  * defined; as a result, the entire function is conditional.  Eventually,
32519c3e120SRobert Watson  * the #else case might also iterate across the policies.
326225bff6fSRobert Watson  */
327225bff6fSRobert Watson static void
328225bff6fSRobert Watson mac_policy_updateflags(void)
329225bff6fSRobert Watson {
330225bff6fSRobert Watson #ifndef MAC_ALWAYS_LABEL_MBUF
33119c3e120SRobert Watson 	struct mac_policy_conf *tmpc;
332225bff6fSRobert Watson 	int labelmbufs;
333225bff6fSRobert Watson 
33441a17fe3SRobert Watson 	mac_policy_assert_exclusive();
335225bff6fSRobert Watson 
336225bff6fSRobert Watson 	labelmbufs = 0;
33741a17fe3SRobert Watson 	LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
33841a17fe3SRobert Watson 		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
33941a17fe3SRobert Watson 			labelmbufs++;
34041a17fe3SRobert Watson 	}
341225bff6fSRobert Watson 	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
342225bff6fSRobert Watson 		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
343225bff6fSRobert Watson 			labelmbufs++;
344225bff6fSRobert Watson 	}
345225bff6fSRobert Watson 	mac_labelmbufs = (labelmbufs != 0);
346225bff6fSRobert Watson #endif
347225bff6fSRobert Watson }
348225bff6fSRobert Watson 
349225bff6fSRobert Watson /*
35095fab37eSRobert Watson  * Allow MAC policy modules to register during boot, etc.
35195fab37eSRobert Watson  */
35295fab37eSRobert Watson int
35395fab37eSRobert Watson mac_policy_modevent(module_t mod, int type, void *data)
35495fab37eSRobert Watson {
35595fab37eSRobert Watson 	struct mac_policy_conf *mpc;
35695fab37eSRobert Watson 	int error;
35795fab37eSRobert Watson 
35895fab37eSRobert Watson 	error = 0;
35995fab37eSRobert Watson 	mpc = (struct mac_policy_conf *) data;
36095fab37eSRobert Watson 
3610a05006dSRobert Watson #ifdef MAC_STATIC
3620a05006dSRobert Watson 	if (mac_late) {
3630a05006dSRobert Watson 		printf("mac_policy_modevent: MAC_STATIC and late\n");
3640a05006dSRobert Watson 		return (EBUSY);
3650a05006dSRobert Watson 	}
3660a05006dSRobert Watson #endif
3670a05006dSRobert Watson 
36895fab37eSRobert Watson 	switch (type) {
36995fab37eSRobert Watson 	case MOD_LOAD:
37095fab37eSRobert Watson 		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
37195fab37eSRobert Watson 		    mac_late) {
37295fab37eSRobert Watson 			printf("mac_policy_modevent: can't load %s policy "
37395fab37eSRobert Watson 			    "after booting\n", mpc->mpc_name);
37495fab37eSRobert Watson 			error = EBUSY;
37595fab37eSRobert Watson 			break;
37695fab37eSRobert Watson 		}
37795fab37eSRobert Watson 		error = mac_policy_register(mpc);
37895fab37eSRobert Watson 		break;
37995fab37eSRobert Watson 	case MOD_UNLOAD:
38095fab37eSRobert Watson 		/* Don't unregister the module if it was never registered. */
38195fab37eSRobert Watson 		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
38295fab37eSRobert Watson 		    != 0)
38395fab37eSRobert Watson 			error = mac_policy_unregister(mpc);
38495fab37eSRobert Watson 		else
38595fab37eSRobert Watson 			error = 0;
38695fab37eSRobert Watson 		break;
38795fab37eSRobert Watson 	default:
3883e019deaSPoul-Henning Kamp 		error = EOPNOTSUPP;
38995fab37eSRobert Watson 		break;
39095fab37eSRobert Watson 	}
39195fab37eSRobert Watson 
39295fab37eSRobert Watson 	return (error);
39395fab37eSRobert Watson }
39495fab37eSRobert Watson 
39595fab37eSRobert Watson static int
39695fab37eSRobert Watson mac_policy_register(struct mac_policy_conf *mpc)
39795fab37eSRobert Watson {
39895fab37eSRobert Watson 	struct mac_policy_conf *tmpc;
39941a17fe3SRobert Watson 	int error, slot, static_entry;
40095fab37eSRobert Watson 
40141a17fe3SRobert Watson 	error = 0;
40241a17fe3SRobert Watson 
40341a17fe3SRobert Watson 	/*
40441a17fe3SRobert Watson 	 * We don't technically need exclusive access while !mac_late,
40541a17fe3SRobert Watson 	 * but hold it for assertion consistency.
40641a17fe3SRobert Watson 	 */
40741a17fe3SRobert Watson 	mac_policy_grab_exclusive();
40841a17fe3SRobert Watson 
40941a17fe3SRobert Watson 	/*
41041a17fe3SRobert Watson 	 * If the module can potentially be unloaded, or we're loading
41141a17fe3SRobert Watson 	 * late, we have to stick it in the non-static list and pay
41241a17fe3SRobert Watson 	 * an extra performance overhead.  Otherwise, we can pay a
41341a17fe3SRobert Watson 	 * light locking cost and stick it in the static list.
41441a17fe3SRobert Watson 	 */
41541a17fe3SRobert Watson 	static_entry = (!mac_late &&
41641a17fe3SRobert Watson 	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
41741a17fe3SRobert Watson 
41841a17fe3SRobert Watson 	if (static_entry) {
41941a17fe3SRobert Watson 		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
42041a17fe3SRobert Watson 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
42141a17fe3SRobert Watson 				error = EEXIST;
42241a17fe3SRobert Watson 				goto out;
42341a17fe3SRobert Watson 			}
42441a17fe3SRobert Watson 		}
42541a17fe3SRobert Watson 	} else {
42695fab37eSRobert Watson 		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
42795fab37eSRobert Watson 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
42841a17fe3SRobert Watson 				error = EEXIST;
42941a17fe3SRobert Watson 				goto out;
43041a17fe3SRobert Watson 			}
43195fab37eSRobert Watson 		}
43295fab37eSRobert Watson 	}
43395fab37eSRobert Watson 	if (mpc->mpc_field_off != NULL) {
434b2aef571SRobert Watson 		slot = ffs(mac_slot_offsets_free);
43595fab37eSRobert Watson 		if (slot == 0) {
43641a17fe3SRobert Watson 			error = ENOMEM;
43741a17fe3SRobert Watson 			goto out;
43895fab37eSRobert Watson 		}
43995fab37eSRobert Watson 		slot--;
440b2aef571SRobert Watson 		mac_slot_offsets_free &= ~(1 << slot);
44195fab37eSRobert Watson 		*mpc->mpc_field_off = slot;
44295fab37eSRobert Watson 	}
44395fab37eSRobert Watson 	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
44441a17fe3SRobert Watson 
44541a17fe3SRobert Watson 	/*
44641a17fe3SRobert Watson 	 * If we're loading a MAC module after the framework has
44741a17fe3SRobert Watson 	 * initialized, it has to go into the dynamic list.  If
44841a17fe3SRobert Watson 	 * we're loading it before we've finished initializing,
44941a17fe3SRobert Watson 	 * it can go into the static list with weaker locker
45041a17fe3SRobert Watson 	 * requirements.
45141a17fe3SRobert Watson 	 */
45241a17fe3SRobert Watson 	if (static_entry)
45341a17fe3SRobert Watson 		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
45441a17fe3SRobert Watson 	else
45595fab37eSRobert Watson 		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
45695fab37eSRobert Watson 
45795fab37eSRobert Watson 	/* Per-policy initialization. */
45895fab37eSRobert Watson 	if (mpc->mpc_ops->mpo_init != NULL)
45995fab37eSRobert Watson 		(*(mpc->mpc_ops->mpo_init))(mpc);
460225bff6fSRobert Watson 	mac_policy_updateflags();
46195fab37eSRobert Watson 
46295fab37eSRobert Watson 	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
46395fab37eSRobert Watson 	    mpc->mpc_name);
46495fab37eSRobert Watson 
46541a17fe3SRobert Watson out:
46641a17fe3SRobert Watson 	mac_policy_release_exclusive();
46741a17fe3SRobert Watson 	return (error);
46895fab37eSRobert Watson }
46995fab37eSRobert Watson 
47095fab37eSRobert Watson static int
47195fab37eSRobert Watson mac_policy_unregister(struct mac_policy_conf *mpc)
47295fab37eSRobert Watson {
47395fab37eSRobert Watson 
474ea599aa0SRobert Watson 	/*
475ea599aa0SRobert Watson 	 * If we fail the load, we may get a request to unload.  Check
476ea599aa0SRobert Watson 	 * to see if we did the run-time registration, and if not,
477ea599aa0SRobert Watson 	 * silently succeed.
478ea599aa0SRobert Watson 	 */
47941a17fe3SRobert Watson 	mac_policy_grab_exclusive();
480ea599aa0SRobert Watson 	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
48141a17fe3SRobert Watson 		mac_policy_release_exclusive();
482ea599aa0SRobert Watson 		return (0);
483ea599aa0SRobert Watson 	}
48495fab37eSRobert Watson #if 0
48595fab37eSRobert Watson 	/*
48695fab37eSRobert Watson 	 * Don't allow unloading modules with private data.
48795fab37eSRobert Watson 	 */
488ea599aa0SRobert Watson 	if (mpc->mpc_field_off != NULL) {
489ea599aa0SRobert Watson 		MAC_POLICY_LIST_UNLOCK();
49095fab37eSRobert Watson 		return (EBUSY);
491ea599aa0SRobert Watson 	}
49295fab37eSRobert Watson #endif
493ea599aa0SRobert Watson 	/*
494ea599aa0SRobert Watson 	 * Only allow the unload to proceed if the module is unloadable
495ea599aa0SRobert Watson 	 * by its own definition.
496ea599aa0SRobert Watson 	 */
497ea599aa0SRobert Watson 	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
49841a17fe3SRobert Watson 		mac_policy_release_exclusive();
49995fab37eSRobert Watson 		return (EBUSY);
500ea599aa0SRobert Watson 	}
50195fab37eSRobert Watson 	if (mpc->mpc_ops->mpo_destroy != NULL)
50295fab37eSRobert Watson 		(*(mpc->mpc_ops->mpo_destroy))(mpc);
50395fab37eSRobert Watson 
50495fab37eSRobert Watson 	LIST_REMOVE(mpc, mpc_list);
5059aeffb2bSRobert Watson 	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
506225bff6fSRobert Watson 	mac_policy_updateflags();
50741a17fe3SRobert Watson 
50841a17fe3SRobert Watson 	mac_policy_release_exclusive();
509a96acd1aSRobert Watson 
51095fab37eSRobert Watson 	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
51195fab37eSRobert Watson 	    mpc->mpc_name);
51295fab37eSRobert Watson 
51395fab37eSRobert Watson 	return (0);
51495fab37eSRobert Watson }
51595fab37eSRobert Watson 
51695fab37eSRobert Watson /*
51795fab37eSRobert Watson  * Define an error value precedence, and given two arguments, selects the
51895fab37eSRobert Watson  * value with the higher precedence.
51995fab37eSRobert Watson  */
5209e7bf51cSRobert Watson int
5219e7bf51cSRobert Watson mac_error_select(int error1, int error2)
52295fab37eSRobert Watson {
52395fab37eSRobert Watson 
52495fab37eSRobert Watson 	/* Certain decision-making errors take top priority. */
52595fab37eSRobert Watson 	if (error1 == EDEADLK || error2 == EDEADLK)
52695fab37eSRobert Watson 		return (EDEADLK);
52795fab37eSRobert Watson 
52895fab37eSRobert Watson 	/* Invalid arguments should be reported where possible. */
52995fab37eSRobert Watson 	if (error1 == EINVAL || error2 == EINVAL)
53095fab37eSRobert Watson 		return (EINVAL);
53195fab37eSRobert Watson 
53295fab37eSRobert Watson 	/* Precedence goes to "visibility", with both process and file. */
53395fab37eSRobert Watson 	if (error1 == ESRCH || error2 == ESRCH)
53495fab37eSRobert Watson 		return (ESRCH);
53595fab37eSRobert Watson 
53695fab37eSRobert Watson 	if (error1 == ENOENT || error2 == ENOENT)
53795fab37eSRobert Watson 		return (ENOENT);
53895fab37eSRobert Watson 
53995fab37eSRobert Watson 	/* Precedence goes to DAC/MAC protections. */
54095fab37eSRobert Watson 	if (error1 == EACCES || error2 == EACCES)
54195fab37eSRobert Watson 		return (EACCES);
54295fab37eSRobert Watson 
54395fab37eSRobert Watson 	/* Precedence goes to privilege. */
54495fab37eSRobert Watson 	if (error1 == EPERM || error2 == EPERM)
54595fab37eSRobert Watson 		return (EPERM);
54695fab37eSRobert Watson 
54795fab37eSRobert Watson 	/* Precedence goes to error over success; otherwise, arbitrary. */
54895fab37eSRobert Watson 	if (error1 != 0)
54995fab37eSRobert Watson 		return (error1);
55095fab37eSRobert Watson 	return (error2);
55195fab37eSRobert Watson }
55295fab37eSRobert Watson 
5536fa0475dSRobert Watson void
55408bcdc58SRobert Watson mac_init_label(struct label *label)
55508bcdc58SRobert Watson {
55608bcdc58SRobert Watson 
55708bcdc58SRobert Watson 	bzero(label, sizeof(*label));
55808bcdc58SRobert Watson 	label->l_flags = MAC_FLAG_INITIALIZED;
55908bcdc58SRobert Watson }
56008bcdc58SRobert Watson 
5616fa0475dSRobert Watson void
56208bcdc58SRobert Watson mac_destroy_label(struct label *label)
56308bcdc58SRobert Watson {
56408bcdc58SRobert Watson 
56508bcdc58SRobert Watson 	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
56608bcdc58SRobert Watson 	    ("destroying uninitialized label"));
56708bcdc58SRobert Watson 
56808bcdc58SRobert Watson 	bzero(label, sizeof(*label));
56908bcdc58SRobert Watson 	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
57008bcdc58SRobert Watson }
57108bcdc58SRobert Watson 
5725e7ce478SRobert Watson int
573f7b951a8SRobert Watson mac_check_structmac_consistent(struct mac *mac)
574f7b951a8SRobert Watson {
575f7b951a8SRobert Watson 
576cc7b13bfSRobert Watson 	if (mac->m_buflen < 0 ||
577cc7b13bfSRobert Watson 	    mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
578f7b951a8SRobert Watson 		return (EINVAL);
579f7b951a8SRobert Watson 
580f7b951a8SRobert Watson 	return (0);
581f7b951a8SRobert Watson }
582f7b951a8SRobert Watson 
583f0ab0442SRobert Watson /*
584f0ab0442SRobert Watson  * MPSAFE
585f0ab0442SRobert Watson  */
586f7b951a8SRobert Watson int
587f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
588f7b951a8SRobert Watson {
589f7b951a8SRobert Watson 	char *elements, *buffer;
590f7b951a8SRobert Watson 	struct mac mac;
591f7b951a8SRobert Watson 	struct proc *tproc;
592f7b951a8SRobert Watson 	struct ucred *tcred;
593f7b951a8SRobert Watson 	int error;
594f7b951a8SRobert Watson 
595d1e405c5SAlfred Perlstein 	error = copyin(uap->mac_p, &mac, sizeof(mac));
596f7b951a8SRobert Watson 	if (error)
597f7b951a8SRobert Watson 		return (error);
598f7b951a8SRobert Watson 
599f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
600f7b951a8SRobert Watson 	if (error)
601f7b951a8SRobert Watson 		return (error);
602f7b951a8SRobert Watson 
603f7b951a8SRobert Watson 	tproc = pfind(uap->pid);
604f7b951a8SRobert Watson 	if (tproc == NULL)
605f7b951a8SRobert Watson 		return (ESRCH);
606f7b951a8SRobert Watson 
607f7b951a8SRobert Watson 	tcred = NULL;				/* Satisfy gcc. */
608f7b951a8SRobert Watson 	error = p_cansee(td, tproc);
609f7b951a8SRobert Watson 	if (error == 0)
610f7b951a8SRobert Watson 		tcred = crhold(tproc->p_ucred);
611f7b951a8SRobert Watson 	PROC_UNLOCK(tproc);
612f7b951a8SRobert Watson 	if (error)
613f7b951a8SRobert Watson 		return (error);
614f7b951a8SRobert Watson 
615a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
616f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
617f7b951a8SRobert Watson 	if (error) {
618f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
619f7b951a8SRobert Watson 		crfree(tcred);
620f7b951a8SRobert Watson 		return (error);
621f7b951a8SRobert Watson 	}
622f7b951a8SRobert Watson 
623a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
624eca8a663SRobert Watson 	error = mac_externalize_cred_label(tcred->cr_label, elements,
62583b7b0edSRobert Watson 	    buffer, mac.m_buflen);
626f7b951a8SRobert Watson 	if (error == 0)
627f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
628f7b951a8SRobert Watson 
629f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
630f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
631f7b951a8SRobert Watson 	crfree(tcred);
632f7b951a8SRobert Watson 	return (error);
633f7b951a8SRobert Watson }
634f7b951a8SRobert Watson 
63595fab37eSRobert Watson /*
63695fab37eSRobert Watson  * MPSAFE
63795fab37eSRobert Watson  */
63895fab37eSRobert Watson int
63995fab37eSRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
64095fab37eSRobert Watson {
641f7b951a8SRobert Watson 	char *elements, *buffer;
642f7b951a8SRobert Watson 	struct mac mac;
64395fab37eSRobert Watson 	int error;
64495fab37eSRobert Watson 
645f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
646f7b951a8SRobert Watson 	if (error)
647f7b951a8SRobert Watson 		return (error);
64895fab37eSRobert Watson 
649f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
650f7b951a8SRobert Watson 	if (error)
651f7b951a8SRobert Watson 		return (error);
652f7b951a8SRobert Watson 
653a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
654f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
655f7b951a8SRobert Watson 	if (error) {
656f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
657f7b951a8SRobert Watson 		return (error);
658f7b951a8SRobert Watson 	}
659f7b951a8SRobert Watson 
660a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
661eca8a663SRobert Watson 	error = mac_externalize_cred_label(td->td_ucred->cr_label,
66283b7b0edSRobert Watson 	    elements, buffer, mac.m_buflen);
663f7b951a8SRobert Watson 	if (error == 0)
664f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
665f7b951a8SRobert Watson 
666f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
667f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
66895fab37eSRobert Watson 	return (error);
66995fab37eSRobert Watson }
67095fab37eSRobert Watson 
67195fab37eSRobert Watson /*
67295fab37eSRobert Watson  * MPSAFE
67395fab37eSRobert Watson  */
67495fab37eSRobert Watson int
67595fab37eSRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
67695fab37eSRobert Watson {
67795fab37eSRobert Watson 	struct ucred *newcred, *oldcred;
678eca8a663SRobert Watson 	struct label *intlabel;
679f7b951a8SRobert Watson 	struct proc *p;
680f7b951a8SRobert Watson 	struct mac mac;
681f7b951a8SRobert Watson 	char *buffer;
68295fab37eSRobert Watson 	int error;
68395fab37eSRobert Watson 
684f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
68595fab37eSRobert Watson 	if (error)
68695fab37eSRobert Watson 		return (error);
68795fab37eSRobert Watson 
688f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
68995fab37eSRobert Watson 	if (error)
69095fab37eSRobert Watson 		return (error);
69195fab37eSRobert Watson 
692a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
693f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
694f7b951a8SRobert Watson 	if (error) {
695f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
696f7b951a8SRobert Watson 		return (error);
697f7b951a8SRobert Watson 	}
698f7b951a8SRobert Watson 
699eca8a663SRobert Watson 	intlabel = mac_cred_label_alloc();
700eca8a663SRobert Watson 	error = mac_internalize_cred_label(intlabel, buffer);
701f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
702eca8a663SRobert Watson 	if (error)
703eca8a663SRobert Watson 		goto out;
704f7b951a8SRobert Watson 
70595fab37eSRobert Watson 	newcred = crget();
70695fab37eSRobert Watson 
70795fab37eSRobert Watson 	p = td->td_proc;
70895fab37eSRobert Watson 	PROC_LOCK(p);
70995fab37eSRobert Watson 	oldcred = p->p_ucred;
71095fab37eSRobert Watson 
711eca8a663SRobert Watson 	error = mac_check_cred_relabel(oldcred, intlabel);
71295fab37eSRobert Watson 	if (error) {
71395fab37eSRobert Watson 		PROC_UNLOCK(p);
71495fab37eSRobert Watson 		crfree(newcred);
715f7b951a8SRobert Watson 		goto out;
71695fab37eSRobert Watson 	}
71795fab37eSRobert Watson 
71895fab37eSRobert Watson 	setsugid(p);
71995fab37eSRobert Watson 	crcopy(newcred, oldcred);
720eca8a663SRobert Watson 	mac_relabel_cred(newcred, intlabel);
72195fab37eSRobert Watson 	p->p_ucred = newcred;
722e5cb5e37SRobert Watson 
723e5cb5e37SRobert Watson 	/*
724e5cb5e37SRobert Watson 	 * Grab additional reference for use while revoking mmaps, prior
725e5cb5e37SRobert Watson 	 * to releasing the proc lock and sharing the cred.
726e5cb5e37SRobert Watson 	 */
727e5cb5e37SRobert Watson 	crhold(newcred);
72895fab37eSRobert Watson 	PROC_UNLOCK(p);
729e5cb5e37SRobert Watson 
730f7b951a8SRobert Watson 	if (mac_enforce_vm) {
73116140035SRobert Watson 		mtx_lock(&Giant);
732e5cb5e37SRobert Watson 		mac_cred_mmapped_drop_perms(td, newcred);
73316140035SRobert Watson 		mtx_unlock(&Giant);
734f7b951a8SRobert Watson 	}
735e5cb5e37SRobert Watson 
736e5cb5e37SRobert Watson 	crfree(newcred);	/* Free revocation reference. */
73795fab37eSRobert Watson 	crfree(oldcred);
738f7b951a8SRobert Watson 
739f7b951a8SRobert Watson out:
740eca8a663SRobert Watson 	mac_cred_label_free(intlabel);
741f7b951a8SRobert Watson 	return (error);
74295fab37eSRobert Watson }
74395fab37eSRobert Watson 
74495fab37eSRobert Watson /*
74595fab37eSRobert Watson  * MPSAFE
74695fab37eSRobert Watson  */
74795fab37eSRobert Watson int
74895fab37eSRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
74995fab37eSRobert Watson {
750f7b951a8SRobert Watson 	char *elements, *buffer;
751eca8a663SRobert Watson 	struct label *intlabel;
75295fab37eSRobert Watson 	struct file *fp;
753f7b951a8SRobert Watson 	struct mac mac;
75495fab37eSRobert Watson 	struct vnode *vp;
75595fab37eSRobert Watson 	struct pipe *pipe;
756b0323ea3SRobert Watson 	struct socket *so;
757f7b951a8SRobert Watson 	short label_type;
75895fab37eSRobert Watson 	int error;
75995fab37eSRobert Watson 
760f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
761f7b951a8SRobert Watson 	if (error)
762f7b951a8SRobert Watson 		return (error);
76395fab37eSRobert Watson 
764f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
765f7b951a8SRobert Watson 	if (error)
766f7b951a8SRobert Watson 		return (error);
767f7b951a8SRobert Watson 
768a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
769f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
770f7b951a8SRobert Watson 	if (error) {
771f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
772f7b951a8SRobert Watson 		return (error);
773f7b951a8SRobert Watson 	}
774f7b951a8SRobert Watson 
775a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
776d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
77795fab37eSRobert Watson 	if (error)
77895fab37eSRobert Watson 		goto out;
77995fab37eSRobert Watson 
780f7b951a8SRobert Watson 	label_type = fp->f_type;
78195fab37eSRobert Watson 	switch (fp->f_type) {
78295fab37eSRobert Watson 	case DTYPE_FIFO:
78395fab37eSRobert Watson 	case DTYPE_VNODE:
7843b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
785eca8a663SRobert Watson 		intlabel = mac_vnode_label_alloc();
786f0ab0442SRobert Watson 		mtx_lock(&Giant);				/* VFS */
78795fab37eSRobert Watson 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
788eca8a663SRobert Watson 		mac_copy_vnode_label(vp->v_label, intlabel);
78995fab37eSRobert Watson 		VOP_UNLOCK(vp, 0, td);
790f0ab0442SRobert Watson 		mtx_unlock(&Giant);				/* VFS */
791f0ab0442SRobert Watson 		error = mac_externalize_vnode_label(intlabel, elements,
792f0ab0442SRobert Watson 		    buffer, mac.m_buflen);
793f0ab0442SRobert Watson 		mac_vnode_label_free(intlabel);
79495fab37eSRobert Watson 		break;
795f0ab0442SRobert Watson 
79695fab37eSRobert Watson 	case DTYPE_PIPE:
79748e3128bSMatthew Dillon 		pipe = fp->f_data;
798eca8a663SRobert Watson 		intlabel = mac_pipe_label_alloc();
799f7b951a8SRobert Watson 		PIPE_LOCK(pipe);
8004795b82cSRobert Watson 		mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel);
801f7b951a8SRobert Watson 		PIPE_UNLOCK(pipe);
802eca8a663SRobert Watson 		error = mac_externalize_pipe_label(intlabel, elements,
80383b7b0edSRobert Watson 		    buffer, mac.m_buflen);
804eca8a663SRobert Watson 		mac_pipe_label_free(intlabel);
805f7b951a8SRobert Watson 		break;
80695fab37eSRobert Watson 
807b0323ea3SRobert Watson 	case DTYPE_SOCKET:
808b0323ea3SRobert Watson 		so = fp->f_data;
809b0323ea3SRobert Watson 		intlabel = mac_socket_label_alloc(M_WAITOK);
810f0c2044bSRobert Watson 		NET_LOCK_GIANT();
811f0c2044bSRobert Watson 		SOCK_LOCK(so);
812b0323ea3SRobert Watson 		mac_copy_socket_label(so->so_label, intlabel);
813f0c2044bSRobert Watson 		SOCK_UNLOCK(so);
814f0c2044bSRobert Watson 		NET_UNLOCK_GIANT();
815b0323ea3SRobert Watson 		error = mac_externalize_socket_label(intlabel, elements,
816b0323ea3SRobert Watson 		    buffer, mac.m_buflen);
817b0323ea3SRobert Watson 		mac_socket_label_free(intlabel);
818b0323ea3SRobert Watson 		break;
819b0323ea3SRobert Watson 
820f0ab0442SRobert Watson 	default:
821f0ab0442SRobert Watson 		error = EINVAL;
822f0ab0442SRobert Watson 	}
823f0ab0442SRobert Watson 	fdrop(fp, td);
82495fab37eSRobert Watson 	if (error == 0)
825f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
82695fab37eSRobert Watson 
82795fab37eSRobert Watson out:
828f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
829f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
83095fab37eSRobert Watson 	return (error);
83195fab37eSRobert Watson }
83295fab37eSRobert Watson 
83395fab37eSRobert Watson /*
83495fab37eSRobert Watson  * MPSAFE
83595fab37eSRobert Watson  */
83695fab37eSRobert Watson int
83795fab37eSRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
83895fab37eSRobert Watson {
839f7b951a8SRobert Watson 	char *elements, *buffer;
84095fab37eSRobert Watson 	struct nameidata nd;
841eca8a663SRobert Watson 	struct label *intlabel;
842f7b951a8SRobert Watson 	struct mac mac;
84395fab37eSRobert Watson 	int error;
84495fab37eSRobert Watson 
845f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
846f7b951a8SRobert Watson 	if (error)
847f7b951a8SRobert Watson 		return (error);
848f7b951a8SRobert Watson 
849f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
850f7b951a8SRobert Watson 	if (error)
851f7b951a8SRobert Watson 		return (error);
852f7b951a8SRobert Watson 
853a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
854f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
855f7b951a8SRobert Watson 	if (error) {
856f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
857f7b951a8SRobert Watson 		return (error);
858f7b951a8SRobert Watson 	}
859f7b951a8SRobert Watson 
860a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
861f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
862f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
863f7b951a8SRobert Watson 	    td);
86495fab37eSRobert Watson 	error = namei(&nd);
86595fab37eSRobert Watson 	if (error)
86695fab37eSRobert Watson 		goto out;
86795fab37eSRobert Watson 
868eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
869eca8a663SRobert Watson 	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
870eca8a663SRobert Watson 	error = mac_externalize_vnode_label(intlabel, elements, buffer,
87183b7b0edSRobert Watson 	    mac.m_buflen);
872f7b951a8SRobert Watson 
87395fab37eSRobert Watson 	NDFREE(&nd, 0);
874eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
875f7b951a8SRobert Watson 
876f7b951a8SRobert Watson 	if (error == 0)
877f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
878f7b951a8SRobert Watson 
879f7b951a8SRobert Watson out:
880f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
881f7b951a8SRobert Watson 
882f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
883f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
884f7b951a8SRobert Watson 
885f7b951a8SRobert Watson 	return (error);
886f7b951a8SRobert Watson }
887f7b951a8SRobert Watson 
888f7b951a8SRobert Watson /*
889f7b951a8SRobert Watson  * MPSAFE
890f7b951a8SRobert Watson  */
891f7b951a8SRobert Watson int
892f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
893f7b951a8SRobert Watson {
894f7b951a8SRobert Watson 	char *elements, *buffer;
895f7b951a8SRobert Watson 	struct nameidata nd;
896eca8a663SRobert Watson 	struct label *intlabel;
897f7b951a8SRobert Watson 	struct mac mac;
898f7b951a8SRobert Watson 	int error;
899f7b951a8SRobert Watson 
900f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
901f7b951a8SRobert Watson 	if (error)
902f7b951a8SRobert Watson 		return (error);
903f7b951a8SRobert Watson 
904f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
905f7b951a8SRobert Watson 	if (error)
906f7b951a8SRobert Watson 		return (error);
907f7b951a8SRobert Watson 
908a163d034SWarner Losh 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
909f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
910f7b951a8SRobert Watson 	if (error) {
911f7b951a8SRobert Watson 		free(elements, M_MACTEMP);
912f7b951a8SRobert Watson 		return (error);
913f7b951a8SRobert Watson 	}
914f7b951a8SRobert Watson 
915a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
916f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
917f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
918f7b951a8SRobert Watson 	    td);
919f7b951a8SRobert Watson 	error = namei(&nd);
92095fab37eSRobert Watson 	if (error)
92195fab37eSRobert Watson 		goto out;
92295fab37eSRobert Watson 
923eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
924eca8a663SRobert Watson 	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
925eca8a663SRobert Watson 	error = mac_externalize_vnode_label(intlabel, elements, buffer,
92683b7b0edSRobert Watson 	    mac.m_buflen);
927f7b951a8SRobert Watson 	NDFREE(&nd, 0);
928eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
929f7b951a8SRobert Watson 
930f7b951a8SRobert Watson 	if (error == 0)
931f7b951a8SRobert Watson 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
93295fab37eSRobert Watson 
93395fab37eSRobert Watson out:
934f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
935f7b951a8SRobert Watson 
936f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
937f7b951a8SRobert Watson 	free(elements, M_MACTEMP);
938f7b951a8SRobert Watson 
93995fab37eSRobert Watson 	return (error);
94095fab37eSRobert Watson }
94195fab37eSRobert Watson 
94295fab37eSRobert Watson /*
94395fab37eSRobert Watson  * MPSAFE
94495fab37eSRobert Watson  */
94595fab37eSRobert Watson int
94695fab37eSRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
94795fab37eSRobert Watson {
948eca8a663SRobert Watson 	struct label *intlabel;
949f7b951a8SRobert Watson 	struct pipe *pipe;
950b0323ea3SRobert Watson 	struct socket *so;
951f7b951a8SRobert Watson 	struct file *fp;
95295fab37eSRobert Watson 	struct mount *mp;
95395fab37eSRobert Watson 	struct vnode *vp;
954f7b951a8SRobert Watson 	struct mac mac;
955f7b951a8SRobert Watson 	char *buffer;
95695fab37eSRobert Watson 	int error;
95795fab37eSRobert Watson 
958f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
959f7b951a8SRobert Watson 	if (error)
960f7b951a8SRobert Watson 		return (error);
961f7b951a8SRobert Watson 
962f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
963f7b951a8SRobert Watson 	if (error)
964f7b951a8SRobert Watson 		return (error);
965f7b951a8SRobert Watson 
966a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
967f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
968f7b951a8SRobert Watson 	if (error) {
969f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
970f7b951a8SRobert Watson 		return (error);
971f7b951a8SRobert Watson 	}
972f7b951a8SRobert Watson 
973d1e405c5SAlfred Perlstein 	error = fget(td, uap->fd, &fp);
97495fab37eSRobert Watson 	if (error)
975f7b951a8SRobert Watson 		goto out;
97695fab37eSRobert Watson 
97795fab37eSRobert Watson 	switch (fp->f_type) {
97895fab37eSRobert Watson 	case DTYPE_FIFO:
97995fab37eSRobert Watson 	case DTYPE_VNODE:
980eca8a663SRobert Watson 		intlabel = mac_vnode_label_alloc();
981eca8a663SRobert Watson 		error = mac_internalize_vnode_label(intlabel, buffer);
982f7b951a8SRobert Watson 		if (error) {
983eca8a663SRobert Watson 			mac_vnode_label_free(intlabel);
984f7b951a8SRobert Watson 			break;
985f7b951a8SRobert Watson 		}
9863b6d9652SPoul-Henning Kamp 		vp = fp->f_vnode;
987f0ab0442SRobert Watson 		mtx_lock(&Giant);				/* VFS */
98895fab37eSRobert Watson 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
989f7b951a8SRobert Watson 		if (error != 0) {
990f0ab0442SRobert Watson 			mtx_unlock(&Giant);			/* VFS */
991eca8a663SRobert Watson 			mac_vnode_label_free(intlabel);
99295fab37eSRobert Watson 			break;
993f7b951a8SRobert Watson 		}
99495fab37eSRobert Watson 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
995eca8a663SRobert Watson 		error = vn_setlabel(vp, intlabel, td->td_ucred);
99695fab37eSRobert Watson 		VOP_UNLOCK(vp, 0, td);
99795fab37eSRobert Watson 		vn_finished_write(mp);
998f0ab0442SRobert Watson 		mtx_unlock(&Giant);				/* VFS */
999eca8a663SRobert Watson 		mac_vnode_label_free(intlabel);
100095fab37eSRobert Watson 		break;
1001f7b951a8SRobert Watson 
100295fab37eSRobert Watson 	case DTYPE_PIPE:
1003eca8a663SRobert Watson 		intlabel = mac_pipe_label_alloc();
1004eca8a663SRobert Watson 		error = mac_internalize_pipe_label(intlabel, buffer);
1005f7b951a8SRobert Watson 		if (error == 0) {
100648e3128bSMatthew Dillon 			pipe = fp->f_data;
10071aa37f53SRobert Watson 			PIPE_LOCK(pipe);
10084795b82cSRobert Watson 			error = mac_pipe_label_set(td->td_ucred,
10094795b82cSRobert Watson 			    pipe->pipe_pair, intlabel);
10101aa37f53SRobert Watson 			PIPE_UNLOCK(pipe);
1011f7b951a8SRobert Watson 		}
1012eca8a663SRobert Watson 		mac_pipe_label_free(intlabel);
101395fab37eSRobert Watson 		break;
1014f7b951a8SRobert Watson 
1015b0323ea3SRobert Watson 	case DTYPE_SOCKET:
1016b0323ea3SRobert Watson 		intlabel = mac_socket_label_alloc(M_WAITOK);
1017b0323ea3SRobert Watson 		error = mac_internalize_socket_label(intlabel, buffer);
1018b0323ea3SRobert Watson 		if (error == 0) {
1019b0323ea3SRobert Watson 			so = fp->f_data;
1020f0c2044bSRobert Watson 			NET_LOCK_GIANT();
1021b0323ea3SRobert Watson 			error = mac_socket_label_set(td->td_ucred, so,
1022b0323ea3SRobert Watson 			    intlabel);
1023f0c2044bSRobert Watson 			NET_UNLOCK_GIANT();
1024b0323ea3SRobert Watson 		}
1025b0323ea3SRobert Watson 		mac_socket_label_free(intlabel);
1026b0323ea3SRobert Watson 		break;
1027b0323ea3SRobert Watson 
102895fab37eSRobert Watson 	default:
102995fab37eSRobert Watson 		error = EINVAL;
103095fab37eSRobert Watson 	}
103195fab37eSRobert Watson 	fdrop(fp, td);
1032f7b951a8SRobert Watson out:
1033f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
103495fab37eSRobert Watson 	return (error);
103595fab37eSRobert Watson }
103695fab37eSRobert Watson 
103795fab37eSRobert Watson /*
103895fab37eSRobert Watson  * MPSAFE
103995fab37eSRobert Watson  */
104095fab37eSRobert Watson int
104195fab37eSRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
104295fab37eSRobert Watson {
1043eca8a663SRobert Watson 	struct label *intlabel;
1044f7b951a8SRobert Watson 	struct nameidata nd;
104595fab37eSRobert Watson 	struct mount *mp;
1046f7b951a8SRobert Watson 	struct mac mac;
1047f7b951a8SRobert Watson 	char *buffer;
104895fab37eSRobert Watson 	int error;
104995fab37eSRobert Watson 
1050f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
105195fab37eSRobert Watson 	if (error)
1052f7b951a8SRobert Watson 		return (error);
105395fab37eSRobert Watson 
1054f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
105595fab37eSRobert Watson 	if (error)
1056f7b951a8SRobert Watson 		return (error);
105795fab37eSRobert Watson 
1058a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1059f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1060f7b951a8SRobert Watson 	if (error) {
1061f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
106295fab37eSRobert Watson 		return (error);
106395fab37eSRobert Watson 	}
106495fab37eSRobert Watson 
1065eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
1066eca8a663SRobert Watson 	error = mac_internalize_vnode_label(intlabel, buffer);
1067f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
1068eca8a663SRobert Watson 	if (error)
1069eca8a663SRobert Watson 		goto out;
1070f7b951a8SRobert Watson 
1071f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
1072f7b951a8SRobert Watson 
1073f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
1074f7b951a8SRobert Watson 	    td);
1075f7b951a8SRobert Watson 	error = namei(&nd);
1076f7b951a8SRobert Watson 	if (error == 0) {
1077f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1078f7b951a8SRobert Watson 		if (error == 0)
1079eca8a663SRobert Watson 			error = vn_setlabel(nd.ni_vp, intlabel,
1080f7b951a8SRobert Watson 			    td->td_ucred);
1081f7b951a8SRobert Watson 		vn_finished_write(mp);
1082f7b951a8SRobert Watson 	}
1083f7b951a8SRobert Watson 
1084f7b951a8SRobert Watson 	NDFREE(&nd, 0);
1085f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
1086eca8a663SRobert Watson out:
1087eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
1088f7b951a8SRobert Watson 	return (error);
1089f7b951a8SRobert Watson }
1090f7b951a8SRobert Watson 
1091f7b951a8SRobert Watson /*
1092f7b951a8SRobert Watson  * MPSAFE
1093f7b951a8SRobert Watson  */
1094f7b951a8SRobert Watson int
1095f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1096f7b951a8SRobert Watson {
1097eca8a663SRobert Watson 	struct label *intlabel;
1098f7b951a8SRobert Watson 	struct nameidata nd;
1099f7b951a8SRobert Watson 	struct mount *mp;
1100f7b951a8SRobert Watson 	struct mac mac;
1101f7b951a8SRobert Watson 	char *buffer;
1102f7b951a8SRobert Watson 	int error;
1103f7b951a8SRobert Watson 
1104f7b951a8SRobert Watson 	error = copyin(uap->mac_p, &mac, sizeof(mac));
1105f7b951a8SRobert Watson 	if (error)
1106f7b951a8SRobert Watson 		return (error);
1107f7b951a8SRobert Watson 
1108f7b951a8SRobert Watson 	error = mac_check_structmac_consistent(&mac);
1109f7b951a8SRobert Watson 	if (error)
1110f7b951a8SRobert Watson 		return (error);
1111f7b951a8SRobert Watson 
1112a163d034SWarner Losh 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1113f7b951a8SRobert Watson 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1114f7b951a8SRobert Watson 	if (error) {
1115f7b951a8SRobert Watson 		free(buffer, M_MACTEMP);
1116f7b951a8SRobert Watson 		return (error);
1117f7b951a8SRobert Watson 	}
1118f7b951a8SRobert Watson 
1119eca8a663SRobert Watson 	intlabel = mac_vnode_label_alloc();
1120eca8a663SRobert Watson 	error = mac_internalize_vnode_label(intlabel, buffer);
1121f7b951a8SRobert Watson 	free(buffer, M_MACTEMP);
1122eca8a663SRobert Watson 	if (error)
1123eca8a663SRobert Watson 		goto out;
1124f7b951a8SRobert Watson 
1125f7b951a8SRobert Watson 	mtx_lock(&Giant);				/* VFS */
1126f7b951a8SRobert Watson 
1127f7b951a8SRobert Watson 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
1128f7b951a8SRobert Watson 	    td);
1129f7b951a8SRobert Watson 	error = namei(&nd);
1130f7b951a8SRobert Watson 	if (error == 0) {
1131f7b951a8SRobert Watson 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1132f7b951a8SRobert Watson 		if (error == 0)
1133eca8a663SRobert Watson 			error = vn_setlabel(nd.ni_vp, intlabel,
1134f7b951a8SRobert Watson 			    td->td_ucred);
1135f7b951a8SRobert Watson 		vn_finished_write(mp);
1136f7b951a8SRobert Watson 	}
1137f7b951a8SRobert Watson 
1138f7b951a8SRobert Watson 	NDFREE(&nd, 0);
1139f7b951a8SRobert Watson 	mtx_unlock(&Giant);				/* VFS */
1140eca8a663SRobert Watson out:
1141eca8a663SRobert Watson 	mac_vnode_label_free(intlabel);
1142f7b951a8SRobert Watson 	return (error);
1143f7b951a8SRobert Watson }
1144f7b951a8SRobert Watson 
1145f7b951a8SRobert Watson /*
1146f7b951a8SRobert Watson  * MPSAFE
1147f7b951a8SRobert Watson  */
114827f2eac7SRobert Watson int
114927f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
115027f2eac7SRobert Watson {
115127f2eac7SRobert Watson 	struct mac_policy_conf *mpc;
115227f2eac7SRobert Watson 	char target[MAC_MAX_POLICY_NAME];
115341a17fe3SRobert Watson 	int entrycount, error;
115427f2eac7SRobert Watson 
1155d1e405c5SAlfred Perlstein 	error = copyinstr(uap->policy, target, sizeof(target), NULL);
115627f2eac7SRobert Watson 	if (error)
115727f2eac7SRobert Watson 		return (error);
115827f2eac7SRobert Watson 
115927f2eac7SRobert Watson 	error = ENOSYS;
1160a6a65b05SRobert Watson 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
116127f2eac7SRobert Watson 		if (strcmp(mpc->mpc_name, target) == 0 &&
116227f2eac7SRobert Watson 		    mpc->mpc_ops->mpo_syscall != NULL) {
116327f2eac7SRobert Watson 			error = mpc->mpc_ops->mpo_syscall(td,
1164d1e405c5SAlfred Perlstein 			    uap->call, uap->arg);
116527f2eac7SRobert Watson 			goto out;
116627f2eac7SRobert Watson 		}
116727f2eac7SRobert Watson 	}
116827f2eac7SRobert Watson 
116941a17fe3SRobert Watson 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
117041a17fe3SRobert Watson 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
117141a17fe3SRobert Watson 			if (strcmp(mpc->mpc_name, target) == 0 &&
117241a17fe3SRobert Watson 			    mpc->mpc_ops->mpo_syscall != NULL) {
117341a17fe3SRobert Watson 				error = mpc->mpc_ops->mpo_syscall(td,
117441a17fe3SRobert Watson 				    uap->call, uap->arg);
117541a17fe3SRobert Watson 				break;
117641a17fe3SRobert Watson 			}
117741a17fe3SRobert Watson 		}
117841a17fe3SRobert Watson 		mac_policy_list_unbusy();
117941a17fe3SRobert Watson 	}
118027f2eac7SRobert Watson out:
118127f2eac7SRobert Watson 	return (error);
118227f2eac7SRobert Watson }
118327f2eac7SRobert Watson 
118495fab37eSRobert Watson SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
118595fab37eSRobert Watson SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
118695fab37eSRobert Watson 
118795fab37eSRobert Watson #else /* !MAC */
11887bc82500SRobert Watson 
11897bc82500SRobert Watson int
1190f7b951a8SRobert Watson __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1191f7b951a8SRobert Watson {
1192f7b951a8SRobert Watson 
1193f7b951a8SRobert Watson 	return (ENOSYS);
1194f7b951a8SRobert Watson }
1195f7b951a8SRobert Watson 
1196f7b951a8SRobert Watson int
11977bc82500SRobert Watson __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
11987bc82500SRobert Watson {
11997bc82500SRobert Watson 
12007bc82500SRobert Watson 	return (ENOSYS);
12017bc82500SRobert Watson }
12027bc82500SRobert Watson 
12037bc82500SRobert Watson int
12047bc82500SRobert Watson __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
12057bc82500SRobert Watson {
12067bc82500SRobert Watson 
12077bc82500SRobert Watson 	return (ENOSYS);
12087bc82500SRobert Watson }
12097bc82500SRobert Watson 
12107bc82500SRobert Watson int
12117bc82500SRobert Watson __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
12127bc82500SRobert Watson {
12137bc82500SRobert Watson 
12147bc82500SRobert Watson 	return (ENOSYS);
12157bc82500SRobert Watson }
12167bc82500SRobert Watson 
12177bc82500SRobert Watson int
12187bc82500SRobert Watson __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
12197bc82500SRobert Watson {
12207bc82500SRobert Watson 
12217bc82500SRobert Watson 	return (ENOSYS);
12227bc82500SRobert Watson }
12237bc82500SRobert Watson 
12247bc82500SRobert Watson int
1225f7b951a8SRobert Watson __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1226f7b951a8SRobert Watson {
1227f7b951a8SRobert Watson 
1228f7b951a8SRobert Watson 	return (ENOSYS);
1229f7b951a8SRobert Watson }
1230f7b951a8SRobert Watson 
1231f7b951a8SRobert Watson int
12327bc82500SRobert Watson __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
12337bc82500SRobert Watson {
12347bc82500SRobert Watson 
12357bc82500SRobert Watson 	return (ENOSYS);
12367bc82500SRobert Watson }
12377bc82500SRobert Watson 
12387bc82500SRobert Watson int
12397bc82500SRobert Watson __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
12407bc82500SRobert Watson {
12417bc82500SRobert Watson 
12427bc82500SRobert Watson 	return (ENOSYS);
12437bc82500SRobert Watson }
124495fab37eSRobert Watson 
124527f2eac7SRobert Watson int
1246f7b951a8SRobert Watson __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1247f7b951a8SRobert Watson {
1248f7b951a8SRobert Watson 
1249f7b951a8SRobert Watson 	return (ENOSYS);
1250f7b951a8SRobert Watson }
1251f7b951a8SRobert Watson 
1252f7b951a8SRobert Watson int
125327f2eac7SRobert Watson mac_syscall(struct thread *td, struct mac_syscall_args *uap)
125427f2eac7SRobert Watson {
125527f2eac7SRobert Watson 
125627f2eac7SRobert Watson 	return (ENOSYS);
125727f2eac7SRobert Watson }
125827f2eac7SRobert Watson 
125919b78822SRobert Watson #endif /* !MAC */
1260