mac_syscalls.c revision 126097
1100894Srwatson/*-
2126097Srwatson * Copyright (c) 1999-2002 Robert N. M. Watson
3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin
4126097Srwatson * Copyright (c) 2001-2003 Networks Associates Technology, Inc.
5100894Srwatson * All rights reserved.
6100894Srwatson *
7100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the
8100894Srwatson * TrustedBSD Project.
9100894Srwatson *
10106392Srwatson * This software was developed for the FreeBSD Project in part by Network
11106392Srwatson * Associates Laboratories, the Security Research Division of Network
12106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13106392Srwatson * as part of the DARPA CHATS research program.
14100894Srwatson *
15100894Srwatson * Redistribution and use in source and binary forms, with or without
16100894Srwatson * modification, are permitted provided that the following conditions
17100894Srwatson * are met:
18100894Srwatson * 1. Redistributions of source code must retain the above copyright
19100894Srwatson *    notice, this list of conditions and the following disclaimer.
20100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright
21100894Srwatson *    notice, this list of conditions and the following disclaimer in the
22100894Srwatson *    documentation and/or other materials provided with the distribution.
23100894Srwatson *
24100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27100894Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34100894Srwatson * SUCH DAMAGE.
35100894Srwatson */
36116182Sobrien
37122454Srwatson/*-
38122454Srwatson * Framework for extensible kernel access control.  This file contains
39122454Srwatson * Kernel and userland interface to the framework, policy registration
40122454Srwatson * and composition.  Per-object interfaces, controls, and labeling may be
41122454Srwatson * found in src/sys/mac/.  Sample policies may be found in src/sys/mac*.
42100894Srwatson */
43100894Srwatson
44116182Sobrien#include <sys/cdefs.h>
45116182Sobrien__FBSDID("$FreeBSD: head/sys/security/mac/mac_syscalls.c 126097 2004-02-22 00:33:12Z rwatson $");
46116182Sobrien
47100894Srwatson#include "opt_mac.h"
48104300Sphk#include "opt_devfs.h"
49101173Srwatson
50100894Srwatson#include <sys/param.h>
51106856Srwatson#include <sys/condvar.h>
52100979Srwatson#include <sys/extattr.h>
53106468Srwatson#include <sys/imgact.h>
54100979Srwatson#include <sys/kernel.h>
55100979Srwatson#include <sys/lock.h>
56102949Sbde#include <sys/malloc.h>
57100979Srwatson#include <sys/mutex.h>
58100979Srwatson#include <sys/mac.h>
59101712Srwatson#include <sys/module.h>
60100979Srwatson#include <sys/proc.h>
61116701Srwatson#include <sys/sbuf.h>
62100979Srwatson#include <sys/systm.h>
63100894Srwatson#include <sys/sysproto.h>
64100894Srwatson#include <sys/sysent.h>
65100979Srwatson#include <sys/vnode.h>
66100979Srwatson#include <sys/mount.h>
67100979Srwatson#include <sys/file.h>
68100979Srwatson#include <sys/namei.h>
69100979Srwatson#include <sys/socket.h>
70100979Srwatson#include <sys/pipe.h>
71100979Srwatson#include <sys/socketvar.h>
72100979Srwatson#include <sys/sysctl.h>
73100894Srwatson
74100979Srwatson#include <vm/vm.h>
75100979Srwatson#include <vm/pmap.h>
76100979Srwatson#include <vm/vm_map.h>
77100979Srwatson#include <vm/vm_object.h>
78100979Srwatson
79100979Srwatson#include <sys/mac_policy.h>
80100979Srwatson
81100979Srwatson#include <fs/devfs/devfs.h>
82100979Srwatson
83100979Srwatson#include <net/bpfdesc.h>
84100979Srwatson#include <net/if.h>
85100979Srwatson#include <net/if_var.h>
86100979Srwatson
87100979Srwatson#include <netinet/in.h>
88100979Srwatson#include <netinet/ip_var.h>
89100979Srwatson
90121374Srwatson#include <security/mac/mac_internal.h>
91121374Srwatson
92100979Srwatson#ifdef MAC
93100979Srwatson
94101712Srwatson/*
95101712Srwatson * Declare that the kernel provides MAC support, version 1.  This permits
96101712Srwatson * modules to refuse to be loaded if the necessary support isn't present,
97101712Srwatson * even if it's pre-boot.
98101712Srwatson */
99101712SrwatsonMODULE_VERSION(kernel_mac_support, 1);
100101712Srwatson
101100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
102100979Srwatson    "TrustedBSD MAC policy controls");
103104517Srwatson
104114846Srwatson#if MAC_MAX_SLOTS > 32
105114846Srwatson#error "MAC_MAX_SLOTS too large"
106100979Srwatson#endif
107105497Srwatson
108114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS;
109114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
110114846SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
111114846Srwatson    &mac_max_slots, 0, "");
112100979Srwatson
113105959Srwatson/*
114105959Srwatson * Has the kernel started generating labeled objects yet?  All read/write
115105959Srwatson * access to this variable is serialized during the boot process.  Following
116105959Srwatson * the end of serialization, we don't update this flag; no locking.
117105959Srwatson */
118121372Srwatsonint	mac_late = 0;
119100979Srwatson
120105988Srwatson/*
121113487Srwatson * Flag to indicate whether or not we should allocate label storage for
122113487Srwatson * new mbufs.  Since most dynamic policies we currently work with don't
123113487Srwatson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
124113487Srwatson * unless specifically notified of interest.  One result of this is
125113487Srwatson * that if a dynamically loaded policy requests mbuf labels, it must
126113487Srwatson * be able to deal with a NULL label being returned on any mbufs that
127113487Srwatson * were already in flight when the policy was loaded.  Since the policy
128113487Srwatson * already has to deal with uninitialized labels, this probably won't
129113487Srwatson * be a problem.  Note: currently no locking.  Will this be a problem?
130113487Srwatson */
131118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
132121372Srwatsonint	mac_labelmbufs = 0;
133113487Srwatson#endif
134113487Srwatson
135101988Srwatson#ifdef MAC_DEBUG
136104268SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
137104268Srwatson    "TrustedBSD MAC debug info");
138104517SrwatsonSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
139104517Srwatson    "TrustedBSD MAC object counters");
140104517Srwatson
141121374Srwatsonstatic unsigned int nmactemp;
142104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
143100979Srwatson    &nmactemp, 0, "number of temporary labels in use");
144101988Srwatson#endif
145100979Srwatson
146100979Srwatsonstatic int	mac_policy_register(struct mac_policy_conf *mpc);
147100979Srwatsonstatic int	mac_policy_unregister(struct mac_policy_conf *mpc);
148100979Srwatson
149105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
150100979Srwatson
151100979Srwatson/*
152114806Srwatson * mac_static_policy_list holds a list of policy modules that are not
153114806Srwatson * loaded while the system is "live", and cannot be unloaded.  These
154114806Srwatson * policies can be invoked without holding the busy count.
155114806Srwatson *
156114806Srwatson * mac_policy_list stores the list of dynamic policies.  A busy count is
157106856Srwatson * maintained for the list, stored in mac_policy_busy.  The busy count
158114806Srwatson * is protected by mac_policy_mtx; the list may be modified only
159106856Srwatson * while the busy count is 0, requiring that the lock be held to
160106856Srwatson * prevent new references to the list from being acquired.  For almost
161106856Srwatson * all operations, incrementing the busy count is sufficient to
162106856Srwatson * guarantee consistency, as the list cannot be modified while the
163106856Srwatson * busy count is elevated.  For a few special operations involving a
164114806Srwatson * change to the list of active policies, the mtx itself must be held.
165114806Srwatson * A condition variable, mac_policy_cv, is used to signal potential
166114806Srwatson * exclusive consumers that they should try to acquire the lock if a
167114806Srwatson * first attempt at exclusive access fails.
168100979Srwatson */
169114806Srwatsonstatic struct mtx mac_policy_mtx;
170114806Srwatsonstatic struct cv mac_policy_cv;
171114806Srwatsonstatic int mac_policy_count;
172121372Srwatsonstruct mac_policy_list_head mac_policy_list;
173121372Srwatsonstruct mac_policy_list_head mac_static_policy_list;
174100979Srwatson
175106856Srwatson/*
176111883Sjhb * We manually invoke WITNESS_WARN() to allow Witness to generate
177106856Srwatson * warnings even if we don't end up ever triggering the wait at
178106856Srwatson * run-time.  The consumer of the exclusive interface must not hold
179106856Srwatson * any locks (other than potentially Giant) since we may sleep for
180106856Srwatson * long (potentially indefinite) periods of time waiting for the
181106856Srwatson * framework to become quiescent so that a policy list change may
182106856Srwatson * be made.
183106856Srwatson */
184121372Srwatsonvoid
185114806Srwatsonmac_policy_grab_exclusive(void)
186114806Srwatson{
187122454Srwatson
188114806Srwatson	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
189114806Srwatson 	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
190114806Srwatson	mtx_lock(&mac_policy_mtx);
191114806Srwatson	while (mac_policy_count != 0)
192114806Srwatson		cv_wait(&mac_policy_cv, &mac_policy_mtx);
193114806Srwatson}
194106856Srwatson
195121372Srwatsonvoid
196114806Srwatsonmac_policy_assert_exclusive(void)
197114806Srwatson{
198122454Srwatson
199114806Srwatson	mtx_assert(&mac_policy_mtx, MA_OWNED);
200114806Srwatson	KASSERT(mac_policy_count == 0,
201114806Srwatson	    ("mac_policy_assert_exclusive(): not exclusive"));
202114806Srwatson}
203113487Srwatson
204121372Srwatsonvoid
205114806Srwatsonmac_policy_release_exclusive(void)
206114806Srwatson{
207100979Srwatson
208114806Srwatson	KASSERT(mac_policy_count == 0,
209114806Srwatson	    ("mac_policy_release_exclusive(): not exclusive"));
210114806Srwatson	mtx_unlock(&mac_policy_mtx);
211114806Srwatson	cv_signal(&mac_policy_cv);
212114806Srwatson}
213100979Srwatson
214121372Srwatsonvoid
215114806Srwatsonmac_policy_list_busy(void)
216114806Srwatson{
217122454Srwatson
218114806Srwatson	mtx_lock(&mac_policy_mtx);
219114806Srwatson	mac_policy_count++;
220114806Srwatson	mtx_unlock(&mac_policy_mtx);
221114806Srwatson}
222114806Srwatson
223121372Srwatsonint
224114806Srwatsonmac_policy_list_conditional_busy(void)
225114806Srwatson{
226114806Srwatson	int ret;
227114806Srwatson
228114806Srwatson	mtx_lock(&mac_policy_mtx);
229114806Srwatson	if (!LIST_EMPTY(&mac_policy_list)) {
230114806Srwatson		mac_policy_count++;
231114806Srwatson		ret = 1;
232114806Srwatson	} else
233114806Srwatson		ret = 0;
234114806Srwatson	mtx_unlock(&mac_policy_mtx);
235114806Srwatson	return (ret);
236114806Srwatson}
237114806Srwatson
238121372Srwatsonvoid
239114806Srwatsonmac_policy_list_unbusy(void)
240114806Srwatson{
241122454Srwatson
242114806Srwatson	mtx_lock(&mac_policy_mtx);
243114806Srwatson	mac_policy_count--;
244114806Srwatson	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
245114806Srwatson	if (mac_policy_count == 0)
246114806Srwatson		cv_signal(&mac_policy_cv);
247114806Srwatson	mtx_unlock(&mac_policy_mtx);
248114806Srwatson}
249114806Srwatson
250100979Srwatson/*
251100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks.
252100979Srwatson */
253100979Srwatsonstatic void
254100979Srwatsonmac_init(void)
255100979Srwatson{
256100979Srwatson
257114806Srwatson	LIST_INIT(&mac_static_policy_list);
258100979Srwatson	LIST_INIT(&mac_policy_list);
259122524Srwatson	mac_labelzone_init();
260114806Srwatson
261114806Srwatson	mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
262114806Srwatson	cv_init(&mac_policy_cv, "mac_policy_cv");
263100979Srwatson}
264100979Srwatson
265100979Srwatson/*
266100979Srwatson * For the purposes of modules that want to know if they were loaded
267100979Srwatson * "early", set the mac_late flag once we've processed modules either
268100979Srwatson * linked into the kernel, or loaded before the kernel startup.
269100979Srwatson */
270100979Srwatsonstatic void
271100979Srwatsonmac_late_init(void)
272100979Srwatson{
273100979Srwatson
274100979Srwatson	mac_late = 1;
275100979Srwatson}
276100979Srwatson
277100979Srwatson/*
278113487Srwatson * After the policy list has changed, walk the list to update any global
279118308Srwatson * flags.  Currently, we support only one flag, and it's conditionally
280118308Srwatson * defined; as a result, the entire function is conditional.  Eventually,
281118308Srwatson * the #else case might also iterate across the policies.
282113487Srwatson */
283113487Srwatsonstatic void
284113487Srwatsonmac_policy_updateflags(void)
285113487Srwatson{
286118308Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
287113487Srwatson	struct mac_policy_conf *tmpc;
288113487Srwatson	int labelmbufs;
289113487Srwatson
290114806Srwatson	mac_policy_assert_exclusive();
291113487Srwatson
292113487Srwatson	labelmbufs = 0;
293114806Srwatson	LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
294114806Srwatson		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
295114806Srwatson			labelmbufs++;
296114806Srwatson	}
297113487Srwatson	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
298113487Srwatson		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
299113487Srwatson			labelmbufs++;
300113487Srwatson	}
301113487Srwatson	mac_labelmbufs = (labelmbufs != 0);
302113487Srwatson#endif
303113487Srwatson}
304113487Srwatson
305113487Srwatson/*
306100979Srwatson * Allow MAC policy modules to register during boot, etc.
307100979Srwatson */
308100894Srwatsonint
309100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data)
310100979Srwatson{
311100979Srwatson	struct mac_policy_conf *mpc;
312100979Srwatson	int error;
313100979Srwatson
314100979Srwatson	error = 0;
315100979Srwatson	mpc = (struct mac_policy_conf *) data;
316100979Srwatson
317100979Srwatson	switch (type) {
318100979Srwatson	case MOD_LOAD:
319100979Srwatson		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
320100979Srwatson		    mac_late) {
321100979Srwatson			printf("mac_policy_modevent: can't load %s policy "
322100979Srwatson			    "after booting\n", mpc->mpc_name);
323100979Srwatson			error = EBUSY;
324100979Srwatson			break;
325100979Srwatson		}
326100979Srwatson		error = mac_policy_register(mpc);
327100979Srwatson		break;
328100979Srwatson	case MOD_UNLOAD:
329100979Srwatson		/* Don't unregister the module if it was never registered. */
330100979Srwatson		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
331100979Srwatson		    != 0)
332100979Srwatson			error = mac_policy_unregister(mpc);
333100979Srwatson		else
334100979Srwatson			error = 0;
335100979Srwatson		break;
336100979Srwatson	default:
337100979Srwatson		break;
338100979Srwatson	}
339100979Srwatson
340100979Srwatson	return (error);
341100979Srwatson}
342100979Srwatson
343100979Srwatsonstatic int
344100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc)
345100979Srwatson{
346100979Srwatson	struct mac_policy_conf *tmpc;
347114806Srwatson	int error, slot, static_entry;
348100979Srwatson
349114806Srwatson	error = 0;
350114806Srwatson
351114806Srwatson	/*
352114806Srwatson	 * We don't technically need exclusive access while !mac_late,
353114806Srwatson	 * but hold it for assertion consistency.
354114806Srwatson	 */
355114806Srwatson	mac_policy_grab_exclusive();
356114806Srwatson
357114806Srwatson	/*
358114806Srwatson	 * If the module can potentially be unloaded, or we're loading
359114806Srwatson	 * late, we have to stick it in the non-static list and pay
360114806Srwatson	 * an extra performance overhead.  Otherwise, we can pay a
361114806Srwatson	 * light locking cost and stick it in the static list.
362114806Srwatson	 */
363114806Srwatson	static_entry = (!mac_late &&
364114806Srwatson	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
365114806Srwatson
366114806Srwatson	if (static_entry) {
367114806Srwatson		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
368114806Srwatson			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
369114806Srwatson				error = EEXIST;
370114806Srwatson				goto out;
371114806Srwatson			}
372100979Srwatson		}
373114806Srwatson	} else {
374114806Srwatson		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
375114806Srwatson			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
376114806Srwatson				error = EEXIST;
377114806Srwatson				goto out;
378114806Srwatson			}
379114806Srwatson		}
380100979Srwatson	}
381100979Srwatson	if (mpc->mpc_field_off != NULL) {
382114846Srwatson		slot = ffs(mac_slot_offsets_free);
383100979Srwatson		if (slot == 0) {
384114806Srwatson			error = ENOMEM;
385114806Srwatson			goto out;
386100979Srwatson		}
387100979Srwatson		slot--;
388114846Srwatson		mac_slot_offsets_free &= ~(1 << slot);
389100979Srwatson		*mpc->mpc_field_off = slot;
390100979Srwatson	}
391100979Srwatson	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
392100979Srwatson
393114806Srwatson	/*
394114806Srwatson	 * If we're loading a MAC module after the framework has
395114806Srwatson	 * initialized, it has to go into the dynamic list.  If
396114806Srwatson	 * we're loading it before we've finished initializing,
397114806Srwatson	 * it can go into the static list with weaker locker
398114806Srwatson	 * requirements.
399114806Srwatson	 */
400114806Srwatson	if (static_entry)
401114806Srwatson		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
402114806Srwatson	else
403114806Srwatson		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
404114806Srwatson
405100979Srwatson	/* Per-policy initialization. */
406100979Srwatson	if (mpc->mpc_ops->mpo_init != NULL)
407100979Srwatson		(*(mpc->mpc_ops->mpo_init))(mpc);
408113487Srwatson	mac_policy_updateflags();
409100979Srwatson
410100979Srwatson	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
411100979Srwatson	    mpc->mpc_name);
412100979Srwatson
413114806Srwatsonout:
414114806Srwatson	mac_policy_release_exclusive();
415114806Srwatson	return (error);
416100979Srwatson}
417100979Srwatson
418100979Srwatsonstatic int
419100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc)
420100979Srwatson{
421100979Srwatson
422104520Srwatson	/*
423104520Srwatson	 * If we fail the load, we may get a request to unload.  Check
424104520Srwatson	 * to see if we did the run-time registration, and if not,
425104520Srwatson	 * silently succeed.
426104520Srwatson	 */
427114806Srwatson	mac_policy_grab_exclusive();
428104520Srwatson	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
429114806Srwatson		mac_policy_release_exclusive();
430104520Srwatson		return (0);
431104520Srwatson	}
432100979Srwatson#if 0
433100979Srwatson	/*
434100979Srwatson	 * Don't allow unloading modules with private data.
435100979Srwatson	 */
436104520Srwatson	if (mpc->mpc_field_off != NULL) {
437104520Srwatson		MAC_POLICY_LIST_UNLOCK();
438100979Srwatson		return (EBUSY);
439104520Srwatson	}
440100979Srwatson#endif
441104520Srwatson	/*
442104520Srwatson	 * Only allow the unload to proceed if the module is unloadable
443104520Srwatson	 * by its own definition.
444104520Srwatson	 */
445104520Srwatson	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
446114806Srwatson		mac_policy_release_exclusive();
447100979Srwatson		return (EBUSY);
448104520Srwatson	}
449100979Srwatson	if (mpc->mpc_ops->mpo_destroy != NULL)
450100979Srwatson		(*(mpc->mpc_ops->mpo_destroy))(mpc);
451100979Srwatson
452100979Srwatson	LIST_REMOVE(mpc, mpc_list);
453106856Srwatson	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
454113487Srwatson	mac_policy_updateflags();
455100979Srwatson
456114806Srwatson	mac_policy_release_exclusive();
457114806Srwatson
458100979Srwatson	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
459100979Srwatson	    mpc->mpc_name);
460100979Srwatson
461100979Srwatson	return (0);
462100979Srwatson}
463100979Srwatson
464100979Srwatson/*
465100979Srwatson * Define an error value precedence, and given two arguments, selects the
466100979Srwatson * value with the higher precedence.
467100979Srwatson */
468121371Srwatsonint
469121371Srwatsonmac_error_select(int error1, int error2)
470100979Srwatson{
471100979Srwatson
472100979Srwatson	/* Certain decision-making errors take top priority. */
473100979Srwatson	if (error1 == EDEADLK || error2 == EDEADLK)
474100979Srwatson		return (EDEADLK);
475100979Srwatson
476100979Srwatson	/* Invalid arguments should be reported where possible. */
477100979Srwatson	if (error1 == EINVAL || error2 == EINVAL)
478100979Srwatson		return (EINVAL);
479100979Srwatson
480100979Srwatson	/* Precedence goes to "visibility", with both process and file. */
481100979Srwatson	if (error1 == ESRCH || error2 == ESRCH)
482100979Srwatson		return (ESRCH);
483100979Srwatson
484100979Srwatson	if (error1 == ENOENT || error2 == ENOENT)
485100979Srwatson		return (ENOENT);
486100979Srwatson
487100979Srwatson	/* Precedence goes to DAC/MAC protections. */
488100979Srwatson	if (error1 == EACCES || error2 == EACCES)
489100979Srwatson		return (EACCES);
490100979Srwatson
491100979Srwatson	/* Precedence goes to privilege. */
492100979Srwatson	if (error1 == EPERM || error2 == EPERM)
493100979Srwatson		return (EPERM);
494100979Srwatson
495100979Srwatson	/* Precedence goes to error over success; otherwise, arbitrary. */
496100979Srwatson	if (error1 != 0)
497100979Srwatson		return (error1);
498100979Srwatson	return (error2);
499100979Srwatson}
500100979Srwatson
501121374Srwatsonvoid
502104521Srwatsonmac_init_label(struct label *label)
503104521Srwatson{
504104521Srwatson
505104521Srwatson	bzero(label, sizeof(*label));
506104521Srwatson	label->l_flags = MAC_FLAG_INITIALIZED;
507104521Srwatson}
508104521Srwatson
509121374Srwatsonvoid
510104521Srwatsonmac_destroy_label(struct label *label)
511104521Srwatson{
512104521Srwatson
513104521Srwatson	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
514104521Srwatson	    ("destroying uninitialized label"));
515104521Srwatson
516104521Srwatson	bzero(label, sizeof(*label));
517104521Srwatson	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
518104521Srwatson}
519104521Srwatson
520112675Srwatsonint
521105694Srwatsonmac_check_structmac_consistent(struct mac *mac)
522104522Srwatson{
523105694Srwatson
524120582Srwatson	if (mac->m_buflen < 0 ||
525120582Srwatson	    mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
526105694Srwatson		return (EINVAL);
527105694Srwatson
528105694Srwatson	return (0);
529105694Srwatson}
530105694Srwatson
531122584Srwatson/*
532122584Srwatson * MPSAFE
533122584Srwatson */
534105988Srwatsonint
535105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
536105694Srwatson{
537105694Srwatson	char *elements, *buffer;
538105694Srwatson	struct mac mac;
539105694Srwatson	struct proc *tproc;
540105694Srwatson	struct ucred *tcred;
541105694Srwatson	int error;
542105694Srwatson
543107849Salfred	error = copyin(uap->mac_p, &mac, sizeof(mac));
544105694Srwatson	if (error)
545105694Srwatson		return (error);
546105694Srwatson
547105694Srwatson	error = mac_check_structmac_consistent(&mac);
548105694Srwatson	if (error)
549105694Srwatson		return (error);
550105694Srwatson
551105694Srwatson	tproc = pfind(uap->pid);
552105694Srwatson	if (tproc == NULL)
553105694Srwatson		return (ESRCH);
554105694Srwatson
555105694Srwatson	tcred = NULL;				/* Satisfy gcc. */
556105694Srwatson	error = p_cansee(td, tproc);
557105694Srwatson	if (error == 0)
558105694Srwatson		tcred = crhold(tproc->p_ucred);
559105694Srwatson	PROC_UNLOCK(tproc);
560105694Srwatson	if (error)
561105694Srwatson		return (error);
562105694Srwatson
563111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
564105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
565105694Srwatson	if (error) {
566105694Srwatson		free(elements, M_MACTEMP);
567105694Srwatson		crfree(tcred);
568105694Srwatson		return (error);
569105694Srwatson	}
570105694Srwatson
571111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
572122524Srwatson	error = mac_externalize_cred_label(tcred->cr_label, elements,
573122159Srwatson	    buffer, mac.m_buflen);
574105694Srwatson	if (error == 0)
575105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
576105694Srwatson
577105694Srwatson	free(buffer, M_MACTEMP);
578105694Srwatson	free(elements, M_MACTEMP);
579105694Srwatson	crfree(tcred);
580105694Srwatson	return (error);
581105694Srwatson}
582105694Srwatson
583100979Srwatson/*
584100979Srwatson * MPSAFE
585100979Srwatson */
586100979Srwatsonint
587100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
588100894Srwatson{
589105694Srwatson	char *elements, *buffer;
590105694Srwatson	struct mac mac;
591100979Srwatson	int error;
592100894Srwatson
593105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
594105694Srwatson	if (error)
595105694Srwatson		return (error);
596105694Srwatson
597105694Srwatson	error = mac_check_structmac_consistent(&mac);
598105694Srwatson	if (error)
599105694Srwatson		return (error);
600105694Srwatson
601111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
602105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
603105694Srwatson	if (error) {
604105694Srwatson		free(elements, M_MACTEMP);
605105694Srwatson		return (error);
606105694Srwatson	}
607105694Srwatson
608111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
609122524Srwatson	error = mac_externalize_cred_label(td->td_ucred->cr_label,
610122159Srwatson	    elements, buffer, mac.m_buflen);
611100979Srwatson	if (error == 0)
612105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
613100979Srwatson
614105694Srwatson	free(buffer, M_MACTEMP);
615105694Srwatson	free(elements, M_MACTEMP);
616100979Srwatson	return (error);
617100979Srwatson}
618100979Srwatson
619100979Srwatson/*
620100979Srwatson * MPSAFE
621100979Srwatson */
622100979Srwatsonint
623100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
624100979Srwatson{
625100979Srwatson	struct ucred *newcred, *oldcred;
626122524Srwatson	struct label *intlabel;
627100979Srwatson	struct proc *p;
628105694Srwatson	struct mac mac;
629105694Srwatson	char *buffer;
630100979Srwatson	int error;
631100979Srwatson
632105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
633100979Srwatson	if (error)
634100979Srwatson		return (error);
635100979Srwatson
636105694Srwatson	error = mac_check_structmac_consistent(&mac);
637100979Srwatson	if (error)
638100979Srwatson		return (error);
639100979Srwatson
640111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
641105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
642105694Srwatson	if (error) {
643105694Srwatson		free(buffer, M_MACTEMP);
644105694Srwatson		return (error);
645105694Srwatson	}
646105694Srwatson
647122524Srwatson	intlabel = mac_cred_label_alloc();
648122524Srwatson	error = mac_internalize_cred_label(intlabel, buffer);
649105694Srwatson	free(buffer, M_MACTEMP);
650122524Srwatson	if (error)
651122524Srwatson		goto out;
652105694Srwatson
653100979Srwatson	newcred = crget();
654100979Srwatson
655100979Srwatson	p = td->td_proc;
656100979Srwatson	PROC_LOCK(p);
657100979Srwatson	oldcred = p->p_ucred;
658100979Srwatson
659122524Srwatson	error = mac_check_cred_relabel(oldcred, intlabel);
660100979Srwatson	if (error) {
661100979Srwatson		PROC_UNLOCK(p);
662100979Srwatson		crfree(newcred);
663105694Srwatson		goto out;
664100979Srwatson	}
665100979Srwatson
666100979Srwatson	setsugid(p);
667100979Srwatson	crcopy(newcred, oldcred);
668122524Srwatson	mac_relabel_cred(newcred, intlabel);
669102136Srwatson	p->p_ucred = newcred;
670100979Srwatson
671102136Srwatson	/*
672102136Srwatson	 * Grab additional reference for use while revoking mmaps, prior
673102136Srwatson	 * to releasing the proc lock and sharing the cred.
674102136Srwatson	 */
675102136Srwatson	crhold(newcred);
676100979Srwatson	PROC_UNLOCK(p);
677102136Srwatson
678105694Srwatson	if (mac_enforce_vm) {
679105694Srwatson		mtx_lock(&Giant);
680105694Srwatson		mac_cred_mmapped_drop_perms(td, newcred);
681105694Srwatson		mtx_unlock(&Giant);
682105694Srwatson	}
683102136Srwatson
684102136Srwatson	crfree(newcred);	/* Free revocation reference. */
685100979Srwatson	crfree(oldcred);
686105694Srwatson
687105694Srwatsonout:
688122524Srwatson	mac_cred_label_free(intlabel);
689105694Srwatson	return (error);
690100979Srwatson}
691100979Srwatson
692100979Srwatson/*
693100979Srwatson * MPSAFE
694100979Srwatson */
695100979Srwatsonint
696100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
697100979Srwatson{
698105694Srwatson	char *elements, *buffer;
699122524Srwatson	struct label *intlabel;
700100979Srwatson	struct file *fp;
701105694Srwatson	struct mac mac;
702100979Srwatson	struct vnode *vp;
703100979Srwatson	struct pipe *pipe;
704122820Srwatson	struct socket *so;
705105694Srwatson	short label_type;
706100979Srwatson	int error;
707100979Srwatson
708105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
709105694Srwatson	if (error)
710105694Srwatson		return (error);
711100979Srwatson
712105694Srwatson	error = mac_check_structmac_consistent(&mac);
713105694Srwatson	if (error)
714105694Srwatson		return (error);
715105694Srwatson
716111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
717105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
718105694Srwatson	if (error) {
719105694Srwatson		free(elements, M_MACTEMP);
720105694Srwatson		return (error);
721105694Srwatson	}
722105694Srwatson
723111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
724107849Salfred	error = fget(td, uap->fd, &fp);
725100979Srwatson	if (error)
726100979Srwatson		goto out;
727100979Srwatson
728105694Srwatson	label_type = fp->f_type;
729100979Srwatson	switch (fp->f_type) {
730100979Srwatson	case DTYPE_FIFO:
731100979Srwatson	case DTYPE_VNODE:
732116678Sphk		vp = fp->f_vnode;
733122524Srwatson		intlabel = mac_vnode_label_alloc();
734122584Srwatson		mtx_lock(&Giant);				/* VFS */
735100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
736122524Srwatson		mac_copy_vnode_label(vp->v_label, intlabel);
737100979Srwatson		VOP_UNLOCK(vp, 0, td);
738122584Srwatson		mtx_unlock(&Giant);				/* VFS */
739122584Srwatson		error = mac_externalize_vnode_label(intlabel, elements,
740122584Srwatson		    buffer, mac.m_buflen);
741122584Srwatson		mac_vnode_label_free(intlabel);
742122584Srwatson		break;
743105694Srwatson
744100979Srwatson	case DTYPE_PIPE:
745109153Sdillon		pipe = fp->f_data;
746122524Srwatson		intlabel = mac_pipe_label_alloc();
747105694Srwatson		PIPE_LOCK(pipe);
748125293Srwatson		mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel);
749105694Srwatson		PIPE_UNLOCK(pipe);
750122524Srwatson		error = mac_externalize_pipe_label(intlabel, elements,
751122159Srwatson		    buffer, mac.m_buflen);
752122524Srwatson		mac_pipe_label_free(intlabel);
753105694Srwatson		break;
754122584Srwatson
755122820Srwatson	case DTYPE_SOCKET:
756122820Srwatson		so = fp->f_data;
757122820Srwatson		intlabel = mac_socket_label_alloc(M_WAITOK);
758122820Srwatson		mtx_lock(&Giant);				/* Sockets */
759122820Srwatson		/* XXX: Socket lock here. */
760122820Srwatson		mac_copy_socket_label(so->so_label, intlabel);
761122820Srwatson		/* XXX: Socket unlock here. */
762122820Srwatson		mtx_unlock(&Giant);				/* Sockets */
763122820Srwatson		error = mac_externalize_socket_label(intlabel, elements,
764122820Srwatson		    buffer, mac.m_buflen);
765122820Srwatson		mac_socket_label_free(intlabel);
766122820Srwatson		break;
767122820Srwatson
768105694Srwatson	default:
769122584Srwatson		error = EINVAL;
770105694Srwatson	}
771122584Srwatson	fdrop(fp, td);
772100979Srwatson	if (error == 0)
773105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
774100979Srwatson
775105694Srwatsonout:
776105694Srwatson	free(buffer, M_MACTEMP);
777105694Srwatson	free(elements, M_MACTEMP);
778100979Srwatson	return (error);
779100979Srwatson}
780100979Srwatson
781100979Srwatson/*
782100979Srwatson * MPSAFE
783100979Srwatson */
784100979Srwatsonint
785100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
786100979Srwatson{
787105694Srwatson	char *elements, *buffer;
788100979Srwatson	struct nameidata nd;
789122524Srwatson	struct label *intlabel;
790105694Srwatson	struct mac mac;
791100979Srwatson	int error;
792100979Srwatson
793105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
794105694Srwatson	if (error)
795105694Srwatson		return (error);
796105694Srwatson
797105694Srwatson	error = mac_check_structmac_consistent(&mac);
798105694Srwatson	if (error)
799105694Srwatson		return (error);
800105694Srwatson
801111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
802105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
803105694Srwatson	if (error) {
804105694Srwatson		free(elements, M_MACTEMP);
805105694Srwatson		return (error);
806105694Srwatson	}
807105694Srwatson
808111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
809105694Srwatson	mtx_lock(&Giant);				/* VFS */
810105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
811105694Srwatson	    td);
812100979Srwatson	error = namei(&nd);
813100979Srwatson	if (error)
814100979Srwatson		goto out;
815100979Srwatson
816122524Srwatson	intlabel = mac_vnode_label_alloc();
817122524Srwatson	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
818122524Srwatson	error = mac_externalize_vnode_label(intlabel, elements, buffer,
819122159Srwatson	    mac.m_buflen);
820105694Srwatson
821100979Srwatson	NDFREE(&nd, 0);
822122524Srwatson	mac_vnode_label_free(intlabel);
823105694Srwatson
824105694Srwatson	if (error == 0)
825105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
826105694Srwatson
827105694Srwatsonout:
828105694Srwatson	mtx_unlock(&Giant);				/* VFS */
829105694Srwatson
830105694Srwatson	free(buffer, M_MACTEMP);
831105694Srwatson	free(elements, M_MACTEMP);
832105694Srwatson
833105694Srwatson	return (error);
834105694Srwatson}
835105694Srwatson
836105694Srwatson/*
837105694Srwatson * MPSAFE
838105694Srwatson */
839105694Srwatsonint
840105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
841105694Srwatson{
842105694Srwatson	char *elements, *buffer;
843105694Srwatson	struct nameidata nd;
844122524Srwatson	struct label *intlabel;
845105694Srwatson	struct mac mac;
846105694Srwatson	int error;
847105694Srwatson
848105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
849100979Srwatson	if (error)
850105694Srwatson		return (error);
851105694Srwatson
852105694Srwatson	error = mac_check_structmac_consistent(&mac);
853105694Srwatson	if (error)
854105694Srwatson		return (error);
855105694Srwatson
856111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
857105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
858105694Srwatson	if (error) {
859105694Srwatson		free(elements, M_MACTEMP);
860105694Srwatson		return (error);
861105694Srwatson	}
862105694Srwatson
863111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
864105694Srwatson	mtx_lock(&Giant);				/* VFS */
865105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
866105694Srwatson	    td);
867105694Srwatson	error = namei(&nd);
868105694Srwatson	if (error)
869100979Srwatson		goto out;
870100979Srwatson
871122524Srwatson	intlabel = mac_vnode_label_alloc();
872122524Srwatson	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
873122524Srwatson	error = mac_externalize_vnode_label(intlabel, elements, buffer,
874122159Srwatson	    mac.m_buflen);
875105694Srwatson	NDFREE(&nd, 0);
876122524Srwatson	mac_vnode_label_free(intlabel);
877100979Srwatson
878105694Srwatson	if (error == 0)
879105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
880105694Srwatson
881100979Srwatsonout:
882105694Srwatson	mtx_unlock(&Giant);				/* VFS */
883105694Srwatson
884105694Srwatson	free(buffer, M_MACTEMP);
885105694Srwatson	free(elements, M_MACTEMP);
886105694Srwatson
887100979Srwatson	return (error);
888100979Srwatson}
889100979Srwatson
890100979Srwatson/*
891100979Srwatson * MPSAFE
892100979Srwatson */
893100979Srwatsonint
894100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
895100979Srwatson{
896122524Srwatson	struct label *intlabel;
897105694Srwatson	struct pipe *pipe;
898122820Srwatson	struct socket *so;
899100979Srwatson	struct file *fp;
900100979Srwatson	struct mount *mp;
901100979Srwatson	struct vnode *vp;
902105694Srwatson	struct mac mac;
903105694Srwatson	char *buffer;
904100979Srwatson	int error;
905100979Srwatson
906105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
907100979Srwatson	if (error)
908105694Srwatson		return (error);
909100979Srwatson
910105694Srwatson	error = mac_check_structmac_consistent(&mac);
911100979Srwatson	if (error)
912105694Srwatson		return (error);
913100979Srwatson
914111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
915105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
916105694Srwatson	if (error) {
917105694Srwatson		free(buffer, M_MACTEMP);
918105694Srwatson		return (error);
919105694Srwatson	}
920105694Srwatson
921107849Salfred	error = fget(td, uap->fd, &fp);
922100979Srwatson	if (error)
923105694Srwatson		goto out;
924100979Srwatson
925100979Srwatson	switch (fp->f_type) {
926100979Srwatson	case DTYPE_FIFO:
927100979Srwatson	case DTYPE_VNODE:
928122524Srwatson		intlabel = mac_vnode_label_alloc();
929122524Srwatson		error = mac_internalize_vnode_label(intlabel, buffer);
930105694Srwatson		if (error) {
931122524Srwatson			mac_vnode_label_free(intlabel);
932105694Srwatson			break;
933105694Srwatson		}
934116678Sphk		vp = fp->f_vnode;
935122584Srwatson		mtx_lock(&Giant);				/* VFS */
936100979Srwatson		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
937105694Srwatson		if (error != 0) {
938122584Srwatson			mtx_unlock(&Giant);			/* VFS */
939122524Srwatson			mac_vnode_label_free(intlabel);
940100979Srwatson			break;
941105694Srwatson		}
942100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
943122524Srwatson		error = vn_setlabel(vp, intlabel, td->td_ucred);
944100979Srwatson		VOP_UNLOCK(vp, 0, td);
945100979Srwatson		vn_finished_write(mp);
946122584Srwatson		mtx_unlock(&Giant);				/* VFS */
947122524Srwatson		mac_vnode_label_free(intlabel);
948100979Srwatson		break;
949105694Srwatson
950100979Srwatson	case DTYPE_PIPE:
951122524Srwatson		intlabel = mac_pipe_label_alloc();
952122524Srwatson		error = mac_internalize_pipe_label(intlabel, buffer);
953105694Srwatson		if (error == 0) {
954109153Sdillon			pipe = fp->f_data;
955105694Srwatson			PIPE_LOCK(pipe);
956125293Srwatson			error = mac_pipe_label_set(td->td_ucred,
957125293Srwatson			    pipe->pipe_pair, intlabel);
958105694Srwatson			PIPE_UNLOCK(pipe);
959105694Srwatson		}
960122524Srwatson		mac_pipe_label_free(intlabel);
961100979Srwatson		break;
962105694Srwatson
963122820Srwatson	case DTYPE_SOCKET:
964122820Srwatson		intlabel = mac_socket_label_alloc(M_WAITOK);
965122820Srwatson		error = mac_internalize_socket_label(intlabel, buffer);
966122820Srwatson		if (error == 0) {
967122820Srwatson			so = fp->f_data;
968122820Srwatson			mtx_lock(&Giant);			/* Sockets */
969122820Srwatson			/* XXX: Socket lock here. */
970122820Srwatson			error = mac_socket_label_set(td->td_ucred, so,
971122820Srwatson			    intlabel);
972122820Srwatson			/* XXX: Socket unlock here. */
973122820Srwatson			mtx_unlock(&Giant);			/* Sockets */
974122820Srwatson		}
975122820Srwatson		mac_socket_label_free(intlabel);
976122820Srwatson		break;
977122820Srwatson
978100979Srwatson	default:
979100979Srwatson		error = EINVAL;
980100979Srwatson	}
981100979Srwatson	fdrop(fp, td);
982105694Srwatsonout:
983105694Srwatson	free(buffer, M_MACTEMP);
984100979Srwatson	return (error);
985100979Srwatson}
986100979Srwatson
987100979Srwatson/*
988100979Srwatson * MPSAFE
989100979Srwatson */
990100979Srwatsonint
991100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
992100979Srwatson{
993122524Srwatson	struct label *intlabel;
994100979Srwatson	struct nameidata nd;
995100979Srwatson	struct mount *mp;
996105694Srwatson	struct mac mac;
997105694Srwatson	char *buffer;
998100979Srwatson	int error;
999100979Srwatson
1000105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
1001100979Srwatson	if (error)
1002105694Srwatson		return (error);
1003100979Srwatson
1004105694Srwatson	error = mac_check_structmac_consistent(&mac);
1005100979Srwatson	if (error)
1006105694Srwatson		return (error);
1007100979Srwatson
1008111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1009105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1010105694Srwatson	if (error) {
1011105694Srwatson		free(buffer, M_MACTEMP);
1012105694Srwatson		return (error);
1013105694Srwatson	}
1014105694Srwatson
1015122524Srwatson	intlabel = mac_vnode_label_alloc();
1016122524Srwatson	error = mac_internalize_vnode_label(intlabel, buffer);
1017105694Srwatson	free(buffer, M_MACTEMP);
1018122524Srwatson	if (error)
1019122524Srwatson		goto out;
1020105694Srwatson
1021105694Srwatson	mtx_lock(&Giant);				/* VFS */
1022105694Srwatson
1023105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
1024105694Srwatson	    td);
1025100979Srwatson	error = namei(&nd);
1026105694Srwatson	if (error == 0) {
1027105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1028105694Srwatson		if (error == 0)
1029122524Srwatson			error = vn_setlabel(nd.ni_vp, intlabel,
1030105694Srwatson			    td->td_ucred);
1031105694Srwatson		vn_finished_write(mp);
1032105694Srwatson	}
1033105694Srwatson
1034105694Srwatson	NDFREE(&nd, 0);
1035105694Srwatson	mtx_unlock(&Giant);				/* VFS */
1036122524Srwatsonout:
1037122524Srwatson	mac_vnode_label_free(intlabel);
1038105694Srwatson	return (error);
1039105694Srwatson}
1040105694Srwatson
1041105694Srwatson/*
1042105694Srwatson * MPSAFE
1043105694Srwatson */
1044105694Srwatsonint
1045105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1046105694Srwatson{
1047122524Srwatson	struct label *intlabel;
1048105694Srwatson	struct nameidata nd;
1049105694Srwatson	struct mount *mp;
1050105694Srwatson	struct mac mac;
1051105694Srwatson	char *buffer;
1052105694Srwatson	int error;
1053105694Srwatson
1054105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
1055100979Srwatson	if (error)
1056105694Srwatson		return (error);
1057105694Srwatson
1058105694Srwatson	error = mac_check_structmac_consistent(&mac);
1059100979Srwatson	if (error)
1060105694Srwatson		return (error);
1061100979Srwatson
1062111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1063105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1064105694Srwatson	if (error) {
1065105694Srwatson		free(buffer, M_MACTEMP);
1066105694Srwatson		return (error);
1067105694Srwatson	}
1068105694Srwatson
1069122524Srwatson	intlabel = mac_vnode_label_alloc();
1070122524Srwatson	error = mac_internalize_vnode_label(intlabel, buffer);
1071105694Srwatson	free(buffer, M_MACTEMP);
1072122524Srwatson	if (error)
1073122524Srwatson		goto out;
1074105694Srwatson
1075105694Srwatson	mtx_lock(&Giant);				/* VFS */
1076105694Srwatson
1077105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
1078105694Srwatson	    td);
1079105694Srwatson	error = namei(&nd);
1080105694Srwatson	if (error == 0) {
1081105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1082105694Srwatson		if (error == 0)
1083122524Srwatson			error = vn_setlabel(nd.ni_vp, intlabel,
1084105694Srwatson			    td->td_ucred);
1085105694Srwatson		vn_finished_write(mp);
1086105694Srwatson	}
1087105694Srwatson
1088100979Srwatson	NDFREE(&nd, 0);
1089105694Srwatson	mtx_unlock(&Giant);				/* VFS */
1090122524Srwatsonout:
1091122524Srwatson	mac_vnode_label_free(intlabel);
1092100979Srwatson	return (error);
1093100979Srwatson}
1094100979Srwatson
1095105694Srwatson/*
1096105694Srwatson * MPSAFE
1097105694Srwatson */
1098102123Srwatsonint
1099102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
1100102123Srwatson{
1101102123Srwatson	struct mac_policy_conf *mpc;
1102102123Srwatson	char target[MAC_MAX_POLICY_NAME];
1103114806Srwatson	int entrycount, error;
1104102123Srwatson
1105107849Salfred	error = copyinstr(uap->policy, target, sizeof(target), NULL);
1106102123Srwatson	if (error)
1107102123Srwatson		return (error);
1108102123Srwatson
1109102123Srwatson	error = ENOSYS;
1110119494Srwatson	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
1111102123Srwatson		if (strcmp(mpc->mpc_name, target) == 0 &&
1112102123Srwatson		    mpc->mpc_ops->mpo_syscall != NULL) {
1113102123Srwatson			error = mpc->mpc_ops->mpo_syscall(td,
1114107849Salfred			    uap->call, uap->arg);
1115102123Srwatson			goto out;
1116102123Srwatson		}
1117102123Srwatson	}
1118102123Srwatson
1119114806Srwatson	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
1120114806Srwatson		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
1121114806Srwatson			if (strcmp(mpc->mpc_name, target) == 0 &&
1122114806Srwatson			    mpc->mpc_ops->mpo_syscall != NULL) {
1123114806Srwatson				error = mpc->mpc_ops->mpo_syscall(td,
1124114806Srwatson				    uap->call, uap->arg);
1125114806Srwatson				break;
1126114806Srwatson			}
1127114806Srwatson		}
1128114806Srwatson		mac_policy_list_unbusy();
1129114806Srwatson	}
1130102123Srwatsonout:
1131102123Srwatson	return (error);
1132102123Srwatson}
1133102123Srwatson
1134100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
1135100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
1136100979Srwatson
1137100979Srwatson#else /* !MAC */
1138100979Srwatson
1139100979Srwatsonint
1140105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1141105694Srwatson{
1142105694Srwatson
1143105694Srwatson	return (ENOSYS);
1144105694Srwatson}
1145105694Srwatson
1146105694Srwatsonint
1147100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
1148100979Srwatson{
1149100979Srwatson
1150100894Srwatson	return (ENOSYS);
1151100894Srwatson}
1152100894Srwatson
1153100894Srwatsonint
1154100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
1155100894Srwatson{
1156100894Srwatson
1157100894Srwatson	return (ENOSYS);
1158100894Srwatson}
1159100894Srwatson
1160100894Srwatsonint
1161100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
1162100894Srwatson{
1163100894Srwatson
1164100894Srwatson	return (ENOSYS);
1165100894Srwatson}
1166100894Srwatson
1167100894Srwatsonint
1168100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
1169100894Srwatson{
1170100894Srwatson
1171100894Srwatson	return (ENOSYS);
1172100894Srwatson}
1173100894Srwatson
1174100894Srwatsonint
1175105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1176105694Srwatson{
1177105694Srwatson
1178105694Srwatson	return (ENOSYS);
1179105694Srwatson}
1180105694Srwatson
1181105694Srwatsonint
1182100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
1183100894Srwatson{
1184100894Srwatson
1185100894Srwatson	return (ENOSYS);
1186100894Srwatson}
1187100894Srwatson
1188100894Srwatsonint
1189100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1190100894Srwatson{
1191100894Srwatson
1192100894Srwatson	return (ENOSYS);
1193100894Srwatson}
1194100979Srwatson
1195102123Srwatsonint
1196105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1197105694Srwatson{
1198105694Srwatson
1199105694Srwatson	return (ENOSYS);
1200105694Srwatson}
1201105694Srwatson
1202105694Srwatsonint
1203102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
1204102123Srwatson{
1205102123Srwatson
1206102123Srwatson	return (ENOSYS);
1207102123Srwatson}
1208102123Srwatson
1209105694Srwatson#endif
1210