1/*
2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*-
29 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
30 * Copyright (c) 2001 Ilmar S. Habibulin
31 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc.
32 * Copyright (c) 2005-2006 SPARTA, Inc.
33 *
34 * This software was developed by Robert Watson and Ilmar Habibulin for the
35 * TrustedBSD Project.
36 *
37 * This software was developed for the FreeBSD Project in part by Network
38 * Associates Laboratories, the Security Research Division of Network
39 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
40 * as part of the DARPA CHATS research program.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 *    notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 *    notice, this list of conditions and the following disclaimer in the
49 *    documentation and/or other materials provided with the distribution.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 */
64
65/*-
66 * Framework for extensible kernel access control.  This file contains
67 * Kernel and userland interface to the framework, policy registration
68 * and composition.  Per-object interfaces, controls, and labeling may be
69 * found in src/sys/mac/.  Sample policies may be found in src/sys/mac*.
70 */
71
72#include <stdarg.h>
73#include <string.h>
74#include <security/mac_internal.h>
75#include <security/mac_mach_internal.h>
76#include <sys/param.h>
77#include <sys/vnode.h>
78#include <sys/vnode_internal.h>
79#include <sys/vfs_context.h>
80#include <sys/namei.h>
81#include <bsd/bsm/audit.h>
82#include <bsd/security/audit/audit.h>
83#include <sys/file.h>
84#include <sys/file_internal.h>
85#include <sys/filedesc.h>
86#include <sys/proc.h>
87#include <sys/proc_internal.h>
88#include <sys/kauth.h>
89#include <sys/sysproto.h>
90
91#include <mach/exception_types.h>
92#include <mach/vm_types.h>
93#include <mach/vm_prot.h>
94
95#include <kern/zalloc.h>
96#include <kern/sched_prim.h>
97#include <osfmk/kern/task.h>
98#include <osfmk/kern/kalloc.h>
99
100#if CONFIG_MACF
101#include <security/mac.h>
102#include <security/mac_policy.h>
103#include <security/mac_framework.h>
104#include <security/mac_internal.h>
105#include <security/mac_mach_internal.h>
106#endif
107
108
109/*
110 * define MB_DEBUG to display run-time debugging information
111 * #define MB_DEBUG 1
112 */
113
114#ifdef MB_DEBUG
115#define DPRINTF(x)	printf x
116#else
117#define MB_DEBUG
118#define DPRINTF(x)
119#endif
120
121#if CONFIG_MACF
122SYSCTL_NODE(, OID_AUTO, security, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
123    "Security Controls");
124SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
125    "TrustedBSD MAC policy controls");
126
127#if DEBUG
128#define SECURITY_MAC_CTLFLAGS CTLFLAG_RW | CTLFLAG_LOCKED
129#else
130#define SECURITY_MAC_CTLFLAGS CTLFLAG_RD | CTLFLAG_LOCKED
131#endif
132
133/*
134 * Declare that the kernel provides MAC support, version 1.  This permits
135 * modules to refuse to be loaded if the necessary support isn't present,
136 * even if it's pre-boot.
137 */
138#if 0
139MODULE_VERSION(kernel_mac_support, 1);
140#endif
141
142#if MAC_MAX_SLOTS > 32
143#error "MAC_MAX_SLOTS too large"
144#endif
145
146static unsigned int mac_max_slots = MAC_MAX_SLOTS;
147static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
148SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD | CTLFLAG_LOCKED,
149    &mac_max_slots, 0, "");
150
151/*
152 * Has the kernel started generating labeled objects yet?  All read/write
153 * access to this variable is serialized during the boot process.  Following
154 * the end of serialization, we don't update this flag; no locking.
155 */
156int	mac_late = 0;
157
158/*
159 * Flag to indicate whether or not we should allocate label storage for
160 * new mbufs.  Since most dynamic policies we currently work with don't
161 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
162 * unless specifically notified of interest.  One result of this is
163 * that if a dynamically loaded policy requests mbuf labels, it must
164 * be able to deal with a NULL label being returned on any mbufs that
165 * were already in flight when the policy was loaded.  Since the policy
166 * already has to deal with uninitialized labels, this probably won't
167 * be a problem.  Note: currently no locking.  Will this be a problem?
168 */
169#if CONFIG_MACF_NET
170unsigned int mac_label_mbufs	= 1;
171SYSCTL_UINT(_security_mac, OID_AUTO, label_mbufs, SECURITY_MAC_CTLFLAGS,
172	&mac_label_mbufs, 0, "Label all MBUFs");
173#endif
174
175
176/*
177 * Flag to indicate whether or not we should allocate label storage for
178 * new vnodes.  Since most dynamic policies we currently work with don't
179 * rely on vnode labeling, try to avoid paying the cost of mtag allocation
180 * unless specifically notified of interest.  One result of this is
181 * that if a dynamically loaded policy requests vnode labels, it must
182 * be able to deal with a NULL label being returned on any vnodes that
183 * were already in flight when the policy was loaded.  Since the policy
184 * already has to deal with uninitialized labels, this probably won't
185 * be a problem.
186 */
187unsigned int	mac_label_vnodes = 0;
188SYSCTL_UINT(_security_mac, OID_AUTO, labelvnodes, SECURITY_MAC_CTLFLAGS,
189    &mac_label_vnodes, 0, "Label all vnodes");
190
191
192unsigned int	mac_mmap_revocation = 0;
193SYSCTL_UINT(_security_mac, OID_AUTO, mmap_revocation, SECURITY_MAC_CTLFLAGS,
194    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
195    "relabel");
196
197unsigned int	mac_mmap_revocation_via_cow = 0;
198SYSCTL_UINT(_security_mac, OID_AUTO, mmap_revocation_via_cow, SECURITY_MAC_CTLFLAGS,
199    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
200    "copy-on-write semantics, or by removing all write access");
201
202unsigned int mac_device_enforce = 1;
203SYSCTL_UINT(_security_mac, OID_AUTO, device_enforce, SECURITY_MAC_CTLFLAGS,
204	   &mac_device_enforce, 0, "Enforce MAC policy on device operations");
205
206unsigned int	mac_pipe_enforce = 1;
207SYSCTL_UINT(_security_mac, OID_AUTO, pipe_enforce, SECURITY_MAC_CTLFLAGS,
208    &mac_pipe_enforce, 0, "Enforce MAC policy on pipe operations");
209
210unsigned int	mac_posixsem_enforce = 1;
211SYSCTL_UINT(_security_mac, OID_AUTO, posixsem_enforce, SECURITY_MAC_CTLFLAGS,
212    &mac_posixsem_enforce, 0, "Enforce MAC policy on POSIX semaphores");
213
214unsigned int mac_posixshm_enforce = 1;
215SYSCTL_UINT(_security_mac, OID_AUTO, posixshm_enforce, SECURITY_MAC_CTLFLAGS,
216    &mac_posixshm_enforce, 0, "Enforce MAC policy on Posix Shared Memory");
217
218unsigned int	mac_proc_enforce = 1;
219SYSCTL_UINT(_security_mac, OID_AUTO, proc_enforce, SECURITY_MAC_CTLFLAGS,
220	   &mac_proc_enforce, 0, "Enforce MAC policy on process operations");
221
222unsigned int mac_socket_enforce = 1;
223SYSCTL_UINT(_security_mac, OID_AUTO, socket_enforce, SECURITY_MAC_CTLFLAGS,
224	&mac_socket_enforce, 0, "Enforce MAC policy on socket operations");
225
226unsigned int	mac_system_enforce = 1;
227SYSCTL_UINT(_security_mac, OID_AUTO, system_enforce, SECURITY_MAC_CTLFLAGS,
228    &mac_system_enforce, 0, "Enforce MAC policy on system-wide interfaces");
229
230unsigned int	mac_sysvmsg_enforce = 1;
231SYSCTL_UINT(_security_mac, OID_AUTO, sysvmsg_enforce, SECURITY_MAC_CTLFLAGS,
232    &mac_sysvmsg_enforce, 0, "Enforce MAC policy on System V IPC message queues");
233
234unsigned int	mac_sysvsem_enforce = 1;
235SYSCTL_UINT(_security_mac, OID_AUTO, sysvsem_enforce, SECURITY_MAC_CTLFLAGS,
236    &mac_sysvsem_enforce, 0, "Enforce MAC policy on System V IPC semaphores");
237
238unsigned int	mac_sysvshm_enforce = 1;
239SYSCTL_INT(_security_mac, OID_AUTO, sysvshm_enforce, SECURITY_MAC_CTLFLAGS,
240    &mac_sysvshm_enforce, 0, "Enforce MAC policy on System V Shared Memory");
241
242unsigned int	mac_vm_enforce = 1;
243SYSCTL_INT(_security_mac, OID_AUTO, vm_enforce, SECURITY_MAC_CTLFLAGS,
244	   &mac_vm_enforce, 0, "Enforce MAC policy on VM operations");
245
246unsigned int	mac_vnode_enforce = 1;
247SYSCTL_UINT(_security_mac, OID_AUTO, vnode_enforce, SECURITY_MAC_CTLFLAGS,
248	   &mac_vnode_enforce, 0, "Enforce MAC policy on vnode operations");
249
250#if CONFIG_AUDIT
251/*
252 * mac_audit_data_zone is the zone used for data pushed into the audit
253 * record by policies. Using a zone simplifies memory management of this
254 * data, and allows tracking of the amount of data in flight.
255 */
256extern zone_t mac_audit_data_zone;
257#endif
258
259/*
260 * mac_policy_list holds the list of policy modules.  Modules with a
261 * handle lower than staticmax are considered "static" and cannot be
262 * unloaded.  Such policies can be invoked without holding the busy count.
263 *
264 * Modules with a handle at or above the staticmax high water mark
265 * are considered to be "dynamic" policies.  A busy count is maintained
266 * for the list, stored in mac_policy_busy.  The busy count is protected
267 * by mac_policy_mtx; the list may be modified only while the busy
268 * count is 0, requiring that the lock be held to prevent new references
269 * to the list from being acquired.  For almost all operations,
270 * incrementing the busy count is sufficient to guarantee consistency,
271 * as the list cannot be modified while the busy count is elevated.
272 * For a few special operations involving a change to the list of
273 * active policies, the mtx itself must be held.
274 */
275static lck_mtx_t *mac_policy_mtx;
276
277/*
278 * Policy list array allocation chunk size. Trying to set this so that we
279 * allocate a page at a time.
280 */
281#define MAC_POLICY_LIST_CHUNKSIZE 512
282
283static int mac_policy_busy;
284
285mac_policy_list_t mac_policy_list;
286
287/*
288 * mac_label_element_list holds the master list of label namespaces for
289 * all the policies. When a policy is loaded, each of it's label namespace
290 * elements is added to the master list if not already present. When a
291 * policy is unloaded, the namespace elements are removed if no other
292 * policy is interested in that namespace element.
293 */
294struct mac_label_element_list_t mac_label_element_list;
295struct mac_label_element_list_t mac_static_label_element_list;
296
297static __inline void
298mac_policy_grab_exclusive(void)
299{
300	lck_mtx_lock(mac_policy_mtx);
301	while (mac_policy_busy != 0) {
302		lck_mtx_sleep(mac_policy_mtx, LCK_SLEEP_UNLOCK,
303			      (event_t)&mac_policy_busy, THREAD_UNINT);
304		lck_mtx_lock(mac_policy_mtx);
305	}
306}
307
308static __inline void
309mac_policy_release_exclusive(void)
310{
311
312	KASSERT(mac_policy_busy == 0,
313	    ("mac_policy_release_exclusive(): not exclusive"));
314	lck_mtx_unlock(mac_policy_mtx);
315	thread_wakeup((event_t) &mac_policy_busy);
316}
317
318void
319mac_policy_list_busy(void)
320{
321        lck_mtx_lock(mac_policy_mtx);
322	mac_policy_busy++;
323	lck_mtx_unlock(mac_policy_mtx);
324}
325
326int
327mac_policy_list_conditional_busy(void)
328{
329	int ret;
330
331	if (mac_policy_list.numloaded <= mac_policy_list.staticmax)
332		return(0);
333
334	lck_mtx_lock(mac_policy_mtx);
335	if (mac_policy_list.numloaded > mac_policy_list.staticmax) {
336		mac_policy_busy++;
337		ret = 1;
338	} else
339		ret = 0;
340	lck_mtx_unlock(mac_policy_mtx);
341	return (ret);
342}
343
344void
345mac_policy_list_unbusy(void)
346{
347	lck_mtx_lock(mac_policy_mtx);
348	mac_policy_busy--;
349	KASSERT(mac_policy_busy >= 0, ("MAC_POLICY_LIST_LOCK"));
350	if (mac_policy_busy == 0)
351		thread_wakeup(&mac_policy_busy);
352	lck_mtx_unlock(mac_policy_mtx);
353}
354
355/*
356 * Early pre-malloc MAC initialization, including appropriate SMP locks.
357 */
358void
359mac_policy_init(void)
360{
361	lck_grp_attr_t *mac_lck_grp_attr;
362	lck_attr_t *mac_lck_attr;
363	lck_grp_t *mac_lck_grp;
364
365	mac_policy_list.numloaded = 0;
366	mac_policy_list.max = MAC_POLICY_LIST_CHUNKSIZE;
367	mac_policy_list.maxindex = 0;
368	mac_policy_list.staticmax = 0;
369	mac_policy_list.freehint = 0;
370	mac_policy_list.chunks = 1;
371
372	mac_policy_list.entries = kalloc(sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE);
373	bzero(mac_policy_list.entries, sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE);
374
375	LIST_INIT(&mac_label_element_list);
376	LIST_INIT(&mac_static_label_element_list);
377
378	mac_lck_grp_attr = lck_grp_attr_alloc_init();
379	lck_grp_attr_setstat(mac_lck_grp_attr);
380	mac_lck_grp = lck_grp_alloc_init("MAC lock", mac_lck_grp_attr);
381	mac_lck_attr = lck_attr_alloc_init();
382	lck_attr_setdefault(mac_lck_attr);
383	mac_policy_mtx = lck_mtx_alloc_init(mac_lck_grp, mac_lck_attr);
384	lck_attr_free(mac_lck_attr);
385	lck_grp_attr_free(mac_lck_grp_attr);
386	lck_grp_free(mac_lck_grp);
387
388	mac_labelzone_init();
389}
390
391/* Function pointer set up for loading security extensions.
392 * It is set to an actual function after OSlibkernInit()
393 * has been called, and is set back to 0 by OSKextRemoveKextBootstrap()
394 * after bsd_init().
395 */
396void (*load_security_extensions_function)(void) = 0;
397
398/*
399 * Init after early Mach startup, but before BSD
400 */
401void
402mac_policy_initmach(void)
403{
404
405	/*
406	 * For the purposes of modules that want to know if they were
407	 * loaded "early", set the mac_late flag once we've processed
408	 * modules either linked into the kernel, or loaded before the
409	 * kernel startup.
410	 */
411
412	if (load_security_extensions_function) {
413		load_security_extensions_function();
414	}
415	mac_late = 1;
416}
417
418/*
419 * BSD startup.
420 */
421void
422mac_policy_initbsd(void)
423{
424	struct mac_policy_conf *mpc;
425	u_int i;
426
427#if CONFIG_AUDIT
428	mac_audit_data_zone = zinit(MAC_AUDIT_DATA_LIMIT,
429				    AQ_HIWATER * MAC_AUDIT_DATA_LIMIT,
430				    8192, "mac_audit_data_zone");
431#endif
432
433	printf("MAC Framework successfully initialized\n");
434
435	/* Call bsd init functions of already loaded policies */
436
437	/*
438	 * Using the exclusive lock means no other framework entry
439	 * points can proceed while initializations are running.
440	 * This may not be necessary.
441	 */
442	mac_policy_grab_exclusive();
443
444	for (i = 0; i <= mac_policy_list.maxindex; i++) {
445		mpc = mac_get_mpc(i);
446		if ((mpc != NULL) && (mpc->mpc_ops->mpo_policy_initbsd != NULL))
447			(*(mpc->mpc_ops->mpo_policy_initbsd))(mpc);
448	}
449
450	mac_policy_release_exclusive();
451}
452
453/*
454 * After a policy has been loaded, add the label namespaces managed by the
455 * policy to either the static or non-static label namespace list.
456 * A namespace is added to the the list only if it is not already on one of
457 * the lists.
458 */
459void
460mac_policy_addto_labellist(mac_policy_handle_t handle, int static_entry)
461{
462	struct mac_label_listener **new_mlls;
463	struct mac_label_element *mle, **new_mles;
464	struct mac_label_element_list_t *list;
465	struct mac_policy_conf *mpc;
466	const char *name, *name2;
467	u_int idx, mle_free, mll_free;
468
469	mpc = mac_get_mpc(handle);
470
471	if (mpc->mpc_labelnames == NULL)
472		return;
473
474	if (mpc->mpc_labelname_count == 0)
475		return;
476
477	if (static_entry)
478		list = &mac_static_label_element_list;
479	else
480		list = &mac_label_element_list;
481
482	/*
483	 * Before we grab the policy list lock, allocate enough memory
484	 * to contain the potential new elements so we don't have to
485	 * give up the lock, or allocate with the lock held.
486	 */
487	MALLOC(new_mles, struct mac_label_element **,
488	    sizeof(struct mac_label_element *) *
489	    mpc->mpc_labelname_count, M_MACTEMP, M_WAITOK | M_ZERO);
490	for (idx = 0; idx < mpc->mpc_labelname_count; idx++)
491		MALLOC(new_mles[idx], struct mac_label_element *,
492		    sizeof(struct mac_label_element),
493		    M_MACTEMP, M_WAITOK);
494	mle_free = 0;
495	MALLOC(new_mlls, struct mac_label_listener **,
496	    sizeof(struct mac_label_listener *) *
497	    mpc->mpc_labelname_count, M_MACTEMP, M_WAITOK);
498	for (idx = 0; idx < mpc->mpc_labelname_count; idx++)
499		MALLOC(new_mlls[idx], struct mac_label_listener *,
500		    sizeof(struct mac_label_listener), M_MACTEMP, M_WAITOK);
501	mll_free = 0;
502
503	if (mac_late)
504		mac_policy_grab_exclusive();
505	for (idx = 0; idx < mpc->mpc_labelname_count; idx++) {
506
507		if (*(name = mpc->mpc_labelnames[idx]) == '?')
508			name++;
509		/*
510		 * Check both label element lists and add to the
511		 * appropriate list only if not already on a list.
512		 */
513		LIST_FOREACH(mle, &mac_static_label_element_list, mle_list) {
514			if (*(name2 = mle->mle_name) == '?')
515				name2++;
516			if (strcmp(name, name2) == 0)
517				break;
518		}
519		if (mle == NULL) {
520			LIST_FOREACH(mle, &mac_label_element_list, mle_list) {
521				if (*(name2 = mle->mle_name) == '?')
522					name2++;
523				if (strcmp(name, name2) == 0)
524					break;
525			}
526		}
527		if (mle == NULL) {
528			mle = new_mles[mle_free];
529			strlcpy(mle->mle_name, mpc->mpc_labelnames[idx],
530					MAC_MAX_LABEL_ELEMENT_NAME);
531			LIST_INIT(&mle->mle_listeners);
532			LIST_INSERT_HEAD(list, mle, mle_list);
533			mle_free++;
534		}
535		/* Add policy handler as a listener. */
536		new_mlls[mll_free]->mll_handle = handle;
537		LIST_INSERT_HEAD(&mle->mle_listeners, new_mlls[mll_free],
538		    mll_list);
539		mll_free++;
540	}
541	if (mac_late)
542		mac_policy_release_exclusive();
543
544	/* Free up any unused label elements and listeners */
545	for (idx = mle_free; idx < mpc->mpc_labelname_count; idx++)
546		FREE(new_mles[idx], M_MACTEMP);
547	FREE(new_mles, M_MACTEMP);
548	for (idx = mll_free; idx < mpc->mpc_labelname_count; idx++)
549		FREE(new_mlls[idx], M_MACTEMP);
550	FREE(new_mlls, M_MACTEMP);
551}
552
553/*
554 * After a policy has been unloaded, remove the label namespaces that the
555 * the policy manages from the non-static list of namespaces.
556 * The removal only takes place when no other policy is interested in the
557 * namespace.
558 *
559 * Must be called with the policy exclusive lock held.
560 */
561void
562mac_policy_removefrom_labellist(mac_policy_handle_t handle)
563{
564	struct mac_label_listener *mll;
565	struct mac_label_element *mle;
566	struct mac_policy_conf *mpc;
567
568	mpc = mac_get_mpc(handle);
569
570	if (mpc->mpc_labelnames == NULL)
571		return;
572
573	if (mpc->mpc_labelname_count == 0)
574		return;
575
576	/*
577	 * Unregister policy as being interested in any label
578	 * namespaces.  If no other policy is listening, remove
579	 * that label element from the list.  Note that we only
580	 * have to worry about the non-static list.
581	 */
582	LIST_FOREACH(mle, &mac_label_element_list, mle_list) {
583		LIST_FOREACH(mll, &mle->mle_listeners, mll_list) {
584			if (mll->mll_handle == handle) {
585				LIST_REMOVE(mll, mll_list);
586				FREE(mll, M_MACTEMP);
587				if (LIST_EMPTY(&mle->mle_listeners)) {
588					LIST_REMOVE(mle, mle_list);
589					FREE(mle, M_MACTEMP);
590				}
591				return;
592			}
593		}
594	}
595}
596
597/*
598 * After the policy list has changed, walk the list to update any global
599 * flags.
600 */
601static void
602mac_policy_updateflags(void)
603{
604}
605
606static __inline void
607mac_policy_fixup_mmd_list(struct mac_module_data *new)
608{
609	struct mac_module_data *old;
610	struct mac_module_data_element *ele, *aele;
611	struct mac_module_data_list *arr, *dict;
612	unsigned int i, j, k;
613
614	old = new->base_addr;
615	DPRINTF(("fixup_mmd: old %p new %p\n", old, new));
616	for (i = 0; i < new->count; i++) {
617		ele = &(new->data[i]);
618		DPRINTF(("fixup_mmd: ele %p\n", ele));
619		DPRINTF(("   key %p value %p\n", ele->key, ele->value));
620		mmd_fixup_ele(old, new, ele); /* Fix up key/value ptrs.       */
621		DPRINTF(("   key %p value %p\n", ele->key, ele->value));
622		if (ele->value_type == MAC_DATA_TYPE_ARRAY) {
623			arr = (struct mac_module_data_list *)ele->value;
624			DPRINTF(("fixup_mmd: array @%p\n", arr));
625			for (j = 0; j < arr->count; j++) {
626				aele = &(arr->list[j]);
627				DPRINTF(("fixup_mmd: aele %p\n", aele));
628				DPRINTF(("   key %p value %p\n", aele->key, aele->value));
629				mmd_fixup_ele(old, new, aele);
630				DPRINTF(("   key %p value %p\n", aele->key, aele->value));
631				if (arr->type == MAC_DATA_TYPE_DICT) {
632					dict = (struct mac_module_data_list *)aele->value;
633					DPRINTF(("fixup_mmd: dict @%p\n", dict));
634					for (k = 0; k < dict->count; k++)
635						mmd_fixup_ele(old, new,
636						    &(dict->list[k]));
637				}
638			}
639		}
640	}
641	new->base_addr = new;
642}
643
644int
645mac_policy_register(struct mac_policy_conf *mpc, mac_policy_handle_t *handlep,
646    void *xd)
647{
648	struct mac_policy_list_element *tmac_policy_list_element;
649	int error, slot, static_entry = 0;
650	u_int i;
651
652	/*
653	 * Some preliminary checks to make sure the policy's conf structure
654	 * contains the required fields.
655	 */
656	if (mpc->mpc_name == NULL)
657		panic("policy's name is not set\n");
658
659	if (mpc->mpc_fullname == NULL)
660		panic("policy's full name is not set\n");
661
662	if (mpc->mpc_labelname_count > MAC_MAX_MANAGED_NAMESPACES)
663		panic("policy's managed label namespaces exceeds maximum\n");
664
665	if (mpc->mpc_ops == NULL)
666		panic("policy's OPs field is NULL\n");
667
668	error = 0;
669
670	if (mac_late) {
671		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE) {
672			printf("Module %s does not support late loading.\n",
673			    mpc->mpc_name);
674			return (EPERM);
675		}
676		mac_policy_grab_exclusive();
677	}
678
679	if (mac_policy_list.numloaded >= mac_policy_list.max) {
680		/* allocate new policy list array, zero new chunk */
681		tmac_policy_list_element =
682		    kalloc((sizeof(struct mac_policy_list_element) *
683		    MAC_POLICY_LIST_CHUNKSIZE) * (mac_policy_list.chunks + 1));
684		bzero(&tmac_policy_list_element[mac_policy_list.max],
685		    sizeof(struct mac_policy_list_element) *
686		    MAC_POLICY_LIST_CHUNKSIZE);
687
688		/* copy old entries into new list */
689		memcpy(tmac_policy_list_element, mac_policy_list.entries,
690		   sizeof(struct mac_policy_list_element) *
691		   MAC_POLICY_LIST_CHUNKSIZE * mac_policy_list.chunks);
692
693		/* free old array */
694		kfree(mac_policy_list.entries,
695		    sizeof(struct mac_policy_list_element) *
696		    MAC_POLICY_LIST_CHUNKSIZE * mac_policy_list.chunks);
697
698		mac_policy_list.entries = tmac_policy_list_element;
699
700		/* Update maximums, etc */
701		mac_policy_list.max += MAC_POLICY_LIST_CHUNKSIZE;
702		mac_policy_list.chunks++;
703	}
704
705	/* Check for policy with same name already loaded */
706	for (i = 0; i <= mac_policy_list.maxindex; i++) {
707		if (mac_policy_list.entries[i].mpc == NULL)
708			continue;
709
710		if (strcmp(mac_policy_list.entries[i].mpc->mpc_name,
711		    mpc->mpc_name) == 0) {
712			error = EEXIST;
713			goto out;
714		}
715	}
716
717	if (mpc->mpc_field_off != NULL) {
718		slot = ffs(mac_slot_offsets_free);
719		if (slot == 0) {
720			error = ENOMEM;
721			goto out;
722		}
723		slot--;
724		mac_slot_offsets_free &= ~(1 << slot);
725		*mpc->mpc_field_off = slot;
726	}
727	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
728
729	if (xd) {
730		struct mac_module_data *mmd = xd; /* module data from plist */
731
732		/* Make a copy of the data. */
733		mpc->mpc_data = (void *)kalloc(mmd->size);
734		if (mpc->mpc_data != NULL) {
735			memcpy(mpc->mpc_data, mmd, mmd->size);
736
737			/* Fix up pointers after copy. */
738			mac_policy_fixup_mmd_list(mpc->mpc_data);
739		}
740	}
741
742	/* Find the first free handle in the list (using our hint). */
743	for (i = mac_policy_list.freehint; i < mac_policy_list.max; i++) {
744		if (mac_policy_list.entries[i].mpc == NULL) {
745			*handlep = i;
746			mac_policy_list.freehint = ++i;
747			break;
748		}
749	}
750
751	/*
752	 * If we are loading a MAC module before the framework has
753	 * finished initializing or the module is not unloadable and
754	 * we can place its handle adjacent to the last static entry,
755	 * bump the static policy high water mark.
756	 * Static policies can get by with weaker locking requirements.
757	 */
758	if (!mac_late ||
759	    ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0 &&
760	    *handlep == mac_policy_list.staticmax)) {
761		static_entry = 1;
762		mac_policy_list.staticmax++;
763	}
764
765	mac_policy_list.entries[*handlep].mpc = mpc;
766
767	/* Update counters, etc */
768	if (*handlep > mac_policy_list.maxindex)
769		mac_policy_list.maxindex = *handlep;
770	mac_policy_list.numloaded++;
771
772	/* Per-policy initialization. */
773	printf ("calling mpo_policy_init for %s\n", mpc->mpc_name);
774	if (mpc->mpc_ops->mpo_policy_init != NULL)
775		(*(mpc->mpc_ops->mpo_policy_init))(mpc);
776
777	if (mac_late && mpc->mpc_ops->mpo_policy_initbsd != NULL) {
778		printf ("calling mpo_policy_initbsd for %s\n", mpc->mpc_name);
779		(*(mpc->mpc_ops->mpo_policy_initbsd))(mpc);
780	}
781
782	mac_policy_updateflags();
783
784	if (mac_late)
785		mac_policy_release_exclusive();
786
787	mac_policy_addto_labellist(*handlep, static_entry);
788
789	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
790	    mpc->mpc_name);
791
792	return (0);
793
794out:
795	if (mac_late)
796		mac_policy_release_exclusive();
797
798	return (error);
799}
800
801int
802mac_policy_unregister(mac_policy_handle_t handle)
803{
804	struct mac_policy_conf *mpc;
805
806	/*
807	 * If we fail the load, we may get a request to unload.  Check
808	 * to see if we did the run-time registration, and if not,
809	 * silently succeed.
810	 */
811	mac_policy_grab_exclusive();
812	mpc = mac_get_mpc(handle);
813	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
814		mac_policy_release_exclusive();
815		return (0);
816	}
817
818#if 0
819	/*
820	 * Don't allow unloading modules with private data.
821	 */
822	if (mpc->mpc_field_off != NULL) {
823		MAC_POLICY_LIST_UNLOCK();
824		return (EBUSY);
825	}
826#endif
827	/*
828	 * Only allow the unload to proceed if the module is unloadable
829	 * by its own definition.
830	 */
831	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
832		mac_policy_release_exclusive();
833		return (EBUSY);
834	}
835
836	mac_policy_removefrom_labellist(handle);
837
838	mac_get_mpc(handle) = NULL;
839	if (handle < mac_policy_list.freehint &&
840	    handle >= mac_policy_list.staticmax)
841		mac_policy_list.freehint = handle;
842
843	if (handle == mac_policy_list.maxindex)
844		mac_policy_list.maxindex--;
845
846	mac_policy_list.numloaded--;
847	if (mpc->mpc_field_off != NULL) {
848		mac_slot_offsets_free |= (1 << *mpc->mpc_field_off);
849	}
850
851	if (mpc->mpc_ops->mpo_policy_destroy != NULL)
852		(*(mpc->mpc_ops->mpo_policy_destroy))(mpc);
853
854	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
855	mac_policy_updateflags();
856
857	mac_policy_release_exclusive();
858
859	if (mpc->mpc_data) {
860		struct mac_module_data *mmd = mpc->mpc_data;
861		kfree(mmd, mmd->size);
862		mpc->mpc_data = NULL;
863	}
864
865	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
866	    mpc->mpc_name);
867
868	return (0);
869}
870
871/*
872 * Define an error value precedence, and given two arguments, selects the
873 * value with the higher precedence.
874 */
875int
876mac_error_select(int error1, int error2)
877{
878
879	/* Certain decision-making errors take top priority. */
880	if (error1 == EDEADLK || error2 == EDEADLK)
881		return (EDEADLK);
882
883	/* Invalid arguments should be reported where possible. */
884	if (error1 == EINVAL || error2 == EINVAL)
885		return (EINVAL);
886
887	/* Precedence goes to "visibility", with both process and file. */
888	if (error1 == ESRCH || error2 == ESRCH)
889		return (ESRCH);
890
891	if (error1 == ENOENT || error2 == ENOENT)
892		return (ENOENT);
893
894	/* Precedence goes to DAC/MAC protections. */
895	if (error1 == EACCES || error2 == EACCES)
896		return (EACCES);
897
898	/* Precedence goes to privilege. */
899	if (error1 == EPERM || error2 == EPERM)
900		return (EPERM);
901
902	/* Precedence goes to error over success; otherwise, arbitrary. */
903	if (error1 != 0)
904		return (error1);
905	return (error2);
906}
907
908void
909mac_label_init(struct label *label)
910{
911
912	bzero(label, sizeof(*label));
913	label->l_flags = MAC_FLAG_INITIALIZED;
914}
915
916void
917mac_label_destroy(struct label *label)
918{
919
920	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
921	    ("destroying uninitialized label"));
922
923	bzero(label, sizeof(*label));
924	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
925}
926
927int
928mac_check_structmac_consistent(struct user_mac *mac)
929{
930
931	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN || mac->m_buflen == 0)
932		return (EINVAL);
933
934	return (0);
935}
936
937/*
938 * Get the external forms of labels from all policies, for a single
939 * label namespace or "*" for all namespaces.  Returns ENOENT if no policy
940 * is registered for the namespace, unless the namespace begins with a '?'.
941 */
942static int
943mac_label_externalize(size_t mpo_externalize_off, struct label *label,
944    const char *element, struct sbuf *sb)
945{
946	struct mac_policy_conf *mpc;
947	struct mac_label_listener *mll;
948	struct mac_label_element *mle;
949	struct mac_label_element_list_t *element_list;
950	const char *name;
951	int (*mpo_externalize)(struct label *, char *, struct sbuf *);
952	int all_labels = 0, ignorenotfound = 0, error = 0, busy = FALSE;
953	unsigned int count = 0;
954
955	if (element[0] == '?') {
956		element++;
957		ignorenotfound = 1;
958	} else if (element[0] == '*' && element[1] == '\0')
959		all_labels = 1;
960
961	element_list = &mac_static_label_element_list;
962element_loop:
963	LIST_FOREACH(mle, element_list, mle_list) {
964		name = mle->mle_name;
965		if (all_labels) {
966			if (*name == '?')
967			    continue;
968		} else {
969			if (*name == '?')
970				name++;
971			if (strcmp(name, element) != 0)
972				continue;
973		}
974		LIST_FOREACH(mll, &mle->mle_listeners, mll_list) {
975			mpc = mac_policy_list.entries[mll->mll_handle].mpc;
976			if (mpc == NULL)
977				continue;
978			mpo_externalize = *(typeof(mpo_externalize) *)
979			    ((char *)mpc->mpc_ops + mpo_externalize_off);
980			if (mpo_externalize == NULL)
981				continue;
982			error = sbuf_printf(sb, "%s/", name);
983			if (error)
984				goto done;
985			error = mpo_externalize(label, mle->mle_name, sb);
986			if (error) {
987				if (error != ENOENT)
988					goto done;
989				/*
990				 * If a policy doesn't have a label to
991				 * externalize it returns ENOENT.  This
992				 * may occur for policies that support
993				 * multiple label elements for some
994				 * (but not all) object types.
995				 */
996				sbuf_setpos(sb, sbuf_len(sb) -
997				    (strlen(name) + 1));
998				error = 0;
999				continue;
1000			}
1001			error = sbuf_putc(sb, ',');
1002			if (error)
1003				goto done;
1004			count++;
1005		}
1006	}
1007	/* If there are dynamic policies present, check their elements too. */
1008	if (!busy && mac_policy_list_conditional_busy() == 1) {
1009		element_list = &mac_label_element_list;
1010		busy = TRUE;
1011		goto element_loop;
1012	}
1013done:
1014	if (busy)
1015		mac_policy_list_unbusy();
1016	if (!error && count == 0) {
1017		if (!all_labels && !ignorenotfound)
1018			error = ENOENT;	/* XXX: ENOLABEL? */
1019	}
1020	return (error);
1021}
1022
1023/*
1024 * Get the external forms of labels from all policies, for all label
1025 * namespaces contained in a list.
1026 *
1027 * XXX This may be leaking an sbuf.
1028 */
1029int
1030mac_externalize(size_t mpo_externalize_off, struct label *label,
1031    const char *elementlist, char *outbuf, size_t outbuflen)
1032{
1033	char *element;
1034	char *scratch_base;
1035	char *scratch;
1036	struct sbuf sb;
1037	int error = 0, len;
1038
1039	/* allocate a scratch buffer the size of the string */
1040	MALLOC(scratch_base, char *, strlen(elementlist)+1, M_MACTEMP, M_WAITOK);
1041	if (scratch_base == NULL) {
1042		error = ENOMEM;
1043		goto out;
1044	}
1045
1046	/* copy the elementlist to the scratch buffer */
1047	strlcpy(scratch_base, elementlist, strlen(elementlist)+1);
1048
1049	/*
1050	 * set up a temporary pointer that can be used to iterate the
1051	 * scratch buffer without losing the allocation address
1052	 */
1053	scratch = scratch_base;
1054
1055	/* get an sbuf */
1056	if (sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN) == NULL) {
1057		/* could not allocate interior buffer */
1058		error = ENOMEM;
1059		goto out;
1060	}
1061	/* iterate the scratch buffer; NOTE: buffer contents modified! */
1062	while ((element = strsep(&scratch, ",")) != NULL) {
1063		error = mac_label_externalize(mpo_externalize_off, label,
1064		    element, &sb);
1065		if (error)
1066			break;
1067	}
1068	if ((len = sbuf_len(&sb)) > 0)
1069		sbuf_setpos(&sb, len - 1);	/* trim trailing comma */
1070	sbuf_finish(&sb);
1071
1072out:
1073	if (scratch_base != NULL)
1074		FREE(scratch_base, M_MACTEMP);
1075
1076	return (error);
1077}
1078
1079/*
1080 * Have all policies set the internal form of a label, for a single
1081 * label namespace.
1082 */
1083static int
1084mac_label_internalize(size_t mpo_internalize_off, struct label *label,
1085    char *element_name, char *element_data)
1086{
1087	struct mac_policy_conf *mpc;
1088	struct mac_label_listener *mll;
1089	struct mac_label_element *mle;
1090	struct mac_label_element_list_t *element_list;
1091	int (*mpo_internalize)(struct label *, char *, char *);
1092	int error = 0, busy = FALSE;
1093	unsigned int count = 0;
1094	const char *name;
1095
1096	element_list = &mac_static_label_element_list;
1097element_loop:
1098	LIST_FOREACH(mle, element_list, mle_list) {
1099		if (*(name = mle->mle_name) == '?')
1100			name++;
1101		if (strcmp(element_name, name) != 0)
1102			continue;
1103		LIST_FOREACH(mll, &mle->mle_listeners, mll_list) {
1104			mpc = mac_policy_list.entries[mll->mll_handle].mpc;
1105			if (mpc == NULL)
1106				continue;
1107			mpo_internalize = *(typeof(mpo_internalize) *)
1108			    ((char *)mpc->mpc_ops + mpo_internalize_off);
1109			if (mpo_internalize == NULL)
1110				continue;
1111			error = mpo_internalize(label, element_name,
1112			    element_data);
1113			if (error)
1114				goto done;
1115			count++;
1116		}
1117	}
1118	/* If there are dynamic policies present, check their elements too. */
1119	if (!busy && mac_policy_list_conditional_busy() == 1) {
1120		element_list = &mac_label_element_list;
1121		busy = TRUE;
1122		goto element_loop;
1123	}
1124done:
1125	if (busy)
1126		mac_policy_list_unbusy();
1127	if (!error && count == 0)
1128		error = ENOPOLICY;
1129	return (error);
1130}
1131
1132int
1133mac_internalize(size_t mpo_internalize_off, struct label *label,
1134    char *textlabels)
1135{
1136	char *element_name, *element_data;
1137	int error = 0;
1138
1139	while (!error && (element_name = strsep(&textlabels, ",")) != NULL) {
1140		element_data = strchr(element_name, '/');
1141		if (element_data == NULL) {
1142			error = EINVAL;
1143			break;
1144		}
1145		*element_data++ = '\0';
1146		error = mac_label_internalize(mpo_internalize_off, label,
1147		    element_name, element_data);
1148	}
1149	return (error);
1150}
1151
1152/* system calls */
1153
1154int
1155__mac_get_pid(struct proc *p, struct __mac_get_pid_args *uap, int *ret __unused)
1156{
1157	char *elements, *buffer;
1158	struct user_mac mac;
1159	struct proc *tproc;
1160	struct ucred *tcred;
1161	int error;
1162	size_t ulen;
1163
1164	AUDIT_ARG(pid, uap->pid);
1165	if (IS_64BIT_PROCESS(p)) {
1166		struct user64_mac mac64;
1167		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1168		mac.m_buflen = mac64.m_buflen;
1169		mac.m_string = mac64.m_string;
1170	} else {
1171		struct user32_mac mac32;
1172		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1173		mac.m_buflen = mac32.m_buflen;
1174		mac.m_string = mac32.m_string;
1175	}
1176	if (error)
1177		return (error);
1178
1179	error = mac_check_structmac_consistent(&mac);
1180	if (error)
1181		return (error);
1182
1183	tproc = proc_find(uap->pid);
1184	if (tproc == NULL)
1185		return (ESRCH);
1186	tcred = kauth_cred_proc_ref(tproc);
1187	proc_rele(tproc);
1188
1189	MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1190	error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1191	if (error) {
1192		FREE(elements, M_MACTEMP);
1193		kauth_cred_unref(&tcred);
1194		return (error);
1195	}
1196	AUDIT_ARG(mac_string, elements);
1197
1198	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1199	error = mac_cred_label_externalize(tcred->cr_label, elements,
1200	    buffer, mac.m_buflen, M_WAITOK);
1201	if (error == 0)
1202		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
1203
1204	FREE(buffer, M_MACTEMP);
1205	FREE(elements, M_MACTEMP);
1206	kauth_cred_unref(&tcred);
1207	return (error);
1208}
1209
1210int
1211__mac_get_proc(proc_t p, struct __mac_get_proc_args *uap, int *ret __unused)
1212{
1213	char *elements, *buffer;
1214	struct user_mac mac;
1215	kauth_cred_t cr;
1216	int error;
1217	size_t ulen;
1218
1219	if (IS_64BIT_PROCESS(p)) {
1220		struct user64_mac mac64;
1221		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1222		mac.m_buflen = mac64.m_buflen;
1223		mac.m_string = mac64.m_string;
1224	} else {
1225		struct user32_mac mac32;
1226		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1227		mac.m_buflen = mac32.m_buflen;
1228		mac.m_string = mac32.m_string;
1229	}
1230	if (error)
1231		return (error);
1232
1233	error = mac_check_structmac_consistent(&mac);
1234	if (error)
1235		return (error);
1236
1237	MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1238	error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1239	if (error) {
1240		FREE(elements, M_MACTEMP);
1241		return (error);
1242	}
1243	AUDIT_ARG(mac_string, elements);
1244
1245	cr = kauth_cred_proc_ref(p);
1246
1247	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1248	error = mac_cred_label_externalize(cr->cr_label,
1249	    elements, buffer, mac.m_buflen, M_WAITOK);
1250	if (error == 0)
1251		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
1252
1253	FREE(buffer, M_MACTEMP);
1254	FREE(elements, M_MACTEMP);
1255	kauth_cred_unref(&cr);
1256	return (error);
1257}
1258
1259int
1260__mac_set_proc(proc_t p, struct __mac_set_proc_args *uap, int *ret __unused)
1261{
1262	struct label *intlabel;
1263	struct user_mac mac;
1264	char *buffer;
1265	int error;
1266	size_t ulen;
1267
1268	if (IS_64BIT_PROCESS(p)) {
1269		struct user64_mac mac64;
1270		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1271		mac.m_buflen = mac64.m_buflen;
1272		mac.m_string = mac64.m_string;
1273	} else {
1274		struct user32_mac mac32;
1275		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1276		mac.m_buflen = mac32.m_buflen;
1277		mac.m_string = mac32.m_string;
1278	}
1279	if (error)
1280		return (error);
1281
1282	error = mac_check_structmac_consistent(&mac);
1283	if (error)
1284		return (error);
1285
1286	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1287	error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
1288	if (error) {
1289		FREE(buffer, M_MACTEMP);
1290		return (error);
1291	}
1292	AUDIT_ARG(mac_string, buffer);
1293
1294	intlabel = mac_cred_label_alloc();
1295	error = mac_cred_label_internalize(intlabel, buffer);
1296	FREE(buffer, M_MACTEMP);
1297	if (error)
1298		goto out;
1299
1300	error = mac_cred_check_label_update(kauth_cred_get(), intlabel);
1301	if (error) {
1302		goto out;
1303	}
1304
1305	error = kauth_proc_label_update(p, intlabel);
1306	if (error)
1307		goto out;
1308
1309out:
1310	mac_cred_label_free(intlabel);
1311	return (error);
1312}
1313
1314#if CONFIG_LCTX
1315/*
1316 * __mac_get_lcid:
1317 *	Get login context ID.  A login context associates a BSD process
1318 *	with an instance of a user.  For more information see getlcid(2) man page.
1319 *
1320 * Parameters:    p                        Process requesting the get
1321 *                uap                      User argument descriptor (see below)
1322 *                ret                      (ignored)
1323 *
1324 * Indirect:      uap->lcid                login context ID to search
1325 *                uap->mac_p.m_buflen      MAC info buffer size
1326 *                uap->mac_p.m_string      MAC info user address
1327 *
1328 * Returns:        0                       Success
1329 *                !0                       Not success
1330 */
1331int
1332__mac_get_lcid(proc_t p, struct __mac_get_lcid_args *uap, int *ret __unused)
1333{
1334	char *elements, *buffer;
1335	struct user_mac mac;
1336	struct lctx *l;
1337	int error;
1338	size_t ulen;
1339
1340	AUDIT_ARG(value32, uap->lcid);
1341	if (IS_64BIT_PROCESS(p)) {
1342		struct user64_mac mac64;
1343		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1344		mac.m_buflen = mac64.m_buflen;
1345		mac.m_string = mac64.m_string;
1346	} else {
1347		struct user32_mac mac32;
1348		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1349		mac.m_buflen = mac32.m_buflen;
1350		mac.m_string = mac32.m_string;
1351	}
1352
1353	if (error)
1354		return (error);
1355
1356	error = mac_check_structmac_consistent(&mac);
1357	if (error)
1358		return (error);
1359
1360	l = lcfind(uap->lcid);
1361	if (l == NULL)
1362		return (ESRCH);
1363
1364	MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1365	error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1366	if (error) {
1367		LCTX_UNLOCK(l);
1368		FREE(elements, M_MACTEMP);
1369		return (error);
1370	}
1371	AUDIT_ARG(mac_string, elements);
1372	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1373	error = mac_lctx_label_externalize(l->lc_label, elements,
1374					   buffer, mac.m_buflen);
1375	if (error == 0)
1376		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
1377
1378	LCTX_UNLOCK(l);
1379	FREE(buffer, M_MACTEMP);
1380	FREE(elements, M_MACTEMP);
1381	return (error);
1382}
1383
1384/*
1385 * __mac_get_lctx:
1386 *	Get login context label.  A login context associates a BSD process
1387 *	associated with an instance of a user.
1388 *
1389 * Parameters:    p                        Process requesting the get
1390 *                uap                      User argument descriptor (see below)
1391 *                ret                      (ignored)
1392 *
1393 * Indirect:      uap->lcid                login context ID to search
1394 *                uap->mac_p               MAC info
1395 *
1396 * Returns:        0                       Success
1397 *                !0                       Not success
1398 *
1399 */
1400int
1401__mac_get_lctx(proc_t p, struct __mac_get_lctx_args *uap, int *ret __unused)
1402{
1403	char *elements, *buffer;
1404	struct user_mac mac;
1405	int error;
1406	size_t ulen;
1407
1408	if (IS_64BIT_PROCESS(p)) {
1409		struct user64_mac mac64;
1410		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1411		mac.m_buflen = mac64.m_buflen;
1412		mac.m_string = mac64.m_string;
1413	} else {
1414		struct user32_mac mac32;
1415		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1416		mac.m_buflen = mac32.m_buflen;
1417		mac.m_string = mac32.m_string;
1418	}
1419
1420	if (error)
1421		return (error);
1422
1423	error = mac_check_structmac_consistent(&mac);
1424	if (error)
1425		return (error);
1426
1427	MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1428	error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1429	if (error) {
1430		FREE(elements, M_MACTEMP);
1431		return (error);
1432	}
1433	AUDIT_ARG(mac_string, elements);
1434	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1435
1436	proc_lock(p);
1437	if (p->p_lctx == NULL) {
1438		proc_unlock(p);
1439		error = ENOENT;
1440		goto out;
1441	}
1442
1443	error = mac_lctx_label_externalize(p->p_lctx->lc_label,
1444					   elements, buffer, mac.m_buflen);
1445	proc_unlock(p);
1446	if (error == 0)
1447		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
1448
1449out:
1450	FREE(buffer, M_MACTEMP);
1451	FREE(elements, M_MACTEMP);
1452	return (error);
1453}
1454
1455int
1456__mac_set_lctx(proc_t p, struct __mac_set_lctx_args *uap, int *ret __unused)
1457{
1458	struct user_mac mac;
1459	struct label *intlabel;
1460	char *buffer;
1461	int error;
1462	size_t ulen;
1463
1464	if (IS_64BIT_PROCESS(p)) {
1465		struct user64_mac mac64;
1466		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1467		mac.m_buflen = mac64.m_buflen;
1468		mac.m_string = mac64.m_string;
1469	} else {
1470		struct user32_mac mac32;
1471		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1472		mac.m_buflen = mac32.m_buflen;
1473		mac.m_string = mac32.m_string;
1474	}
1475	if (error)
1476		return (error);
1477
1478	error = mac_check_structmac_consistent(&mac);
1479	if (error)
1480		return (error);
1481
1482	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1483	error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
1484	if (error) {
1485		FREE(buffer, M_MACTEMP);
1486		return (error);
1487	}
1488	AUDIT_ARG(mac_string, buffer);
1489
1490	intlabel = mac_lctx_label_alloc();
1491	error = mac_lctx_label_internalize(intlabel, buffer);
1492	FREE(buffer, M_MACTEMP);
1493	if (error)
1494		goto out;
1495
1496	proc_lock(p);
1497	if (p->p_lctx == NULL) {
1498		proc_unlock(p);
1499		error = ENOENT;
1500		goto out;
1501	}
1502
1503	error = mac_lctx_check_label_update(p->p_lctx, intlabel);
1504	if (error) {
1505		proc_unlock(p);
1506		goto out;
1507	}
1508	mac_lctx_label_update(p->p_lctx, intlabel);
1509	proc_unlock(p);
1510out:
1511	mac_lctx_label_free(intlabel);
1512	return (error);
1513}
1514
1515#else	/* LCTX */
1516
1517int
1518__mac_get_lcid(proc_t p __unused, struct __mac_get_lcid_args *uap __unused, int *ret __unused)
1519{
1520
1521	return (ENOSYS);
1522}
1523
1524int
1525__mac_get_lctx(proc_t p __unused, struct __mac_get_lctx_args *uap __unused, int *ret __unused)
1526{
1527
1528	return (ENOSYS);
1529}
1530
1531int
1532__mac_set_lctx(proc_t p __unused, struct __mac_set_lctx_args *uap __unused, int *ret __unused)
1533{
1534
1535	return (ENOSYS);
1536}
1537#endif	/* !LCTX */
1538
1539int
1540__mac_get_fd(proc_t p, struct __mac_get_fd_args *uap, int *ret __unused)
1541{
1542	struct fileproc *fp;
1543	struct vnode *vp;
1544	struct user_mac mac;
1545	char *elements, *buffer;
1546	int error;
1547	size_t ulen;
1548	kauth_cred_t my_cred;
1549#if CONFIG_MACF_SOCKET
1550	struct socket *so;
1551#endif	/* MAC_SOCKET */
1552	struct label *intlabel;
1553
1554	AUDIT_ARG(fd, uap->fd);
1555
1556	if (IS_64BIT_PROCESS(p)) {
1557		struct user64_mac mac64;
1558		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1559		mac.m_buflen = mac64.m_buflen;
1560		mac.m_string = mac64.m_string;
1561	} else {
1562		struct user32_mac mac32;
1563		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1564		mac.m_buflen = mac32.m_buflen;
1565		mac.m_string = mac32.m_string;
1566	}
1567
1568	if (error)
1569		return (error);
1570
1571	error = mac_check_structmac_consistent(&mac);
1572	if (error)
1573		return (error);
1574
1575	MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1576	error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1577	if (error) {
1578		FREE(elements, M_MACTEMP);
1579		return (error);
1580	}
1581	AUDIT_ARG(mac_string, elements);
1582
1583	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1584	error = fp_lookup(p, uap->fd, &fp, 0);
1585	if (error) {
1586		FREE(buffer, M_MACTEMP);
1587		FREE(elements, M_MACTEMP);
1588		return (error);
1589	}
1590
1591	my_cred = kauth_cred_proc_ref(p);
1592	error = mac_file_check_get(my_cred, fp->f_fglob, elements, mac.m_buflen);
1593	kauth_cred_unref(&my_cred);
1594	if (error) {
1595		fp_drop(p, uap->fd, fp, 0);
1596		FREE(buffer, M_MACTEMP);
1597		FREE(elements, M_MACTEMP);
1598		return (error);
1599	}
1600
1601	switch (FILEGLOB_DTYPE(fp->f_fglob)) {
1602		case DTYPE_VNODE:
1603			intlabel = mac_vnode_label_alloc();
1604			if (intlabel == NULL) {
1605				error = ENOMEM;
1606				break;
1607			}
1608			vp = (struct vnode *)fp->f_fglob->fg_data;
1609			error = vnode_getwithref(vp);
1610			if (error == 0) {
1611				mac_vnode_label_copy(vp->v_label, intlabel);
1612				error = mac_vnode_label_externalize(intlabel,
1613						elements, buffer,
1614						mac.m_buflen, M_WAITOK);
1615				vnode_put(vp);
1616			}
1617			mac_vnode_label_free(intlabel);
1618			break;
1619		case DTYPE_SOCKET:
1620#if CONFIG_MACF_SOCKET
1621			so = (struct socket *) fp->f_fglob->fg_data;
1622			intlabel = mac_socket_label_alloc(MAC_WAITOK);
1623			sock_lock(so, 1);
1624			mac_socket_label_copy(so->so_label, intlabel);
1625			sock_unlock(so, 1);
1626			error = mac_socket_label_externalize(intlabel, elements, buffer, mac.m_buflen);
1627			mac_socket_label_free(intlabel);
1628			break;
1629#endif
1630		case DTYPE_PSXSHM:
1631		case DTYPE_PSXSEM:
1632		case DTYPE_PIPE:
1633		case DTYPE_KQUEUE:
1634		case DTYPE_FSEVENTS:
1635		default:
1636			error = ENOSYS;   // only sockets/vnodes so far
1637			break;
1638	}
1639	fp_drop(p, uap->fd, fp, 0);
1640
1641	if (error == 0)
1642		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
1643
1644	FREE(buffer, M_MACTEMP);
1645	FREE(elements, M_MACTEMP);
1646	return (error);
1647}
1648
1649static int
1650mac_get_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p, int follow)
1651{
1652	struct vnode *vp;
1653	vfs_context_t ctx;
1654	char *elements, *buffer;
1655	struct nameidata nd;
1656	struct label *intlabel;
1657	struct user_mac mac;
1658	int error;
1659	size_t ulen;
1660
1661	if (IS_64BIT_PROCESS(p)) {
1662		struct user64_mac mac64;
1663		error = copyin(mac_p, &mac64, sizeof(mac64));
1664		mac.m_buflen = mac64.m_buflen;
1665		mac.m_string = mac64.m_string;
1666	} else {
1667		struct user32_mac mac32;
1668		error = copyin(mac_p, &mac32, sizeof(mac32));
1669		mac.m_buflen = mac32.m_buflen;
1670		mac.m_string = mac32.m_string;
1671	}
1672
1673	if (error)
1674		return (error);
1675
1676	error = mac_check_structmac_consistent(&mac);
1677	if (error)
1678		return (error);
1679
1680	MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1681	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1682
1683	error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1684	if (error) {
1685		FREE(buffer, M_MACTEMP);
1686		FREE(elements, M_MACTEMP);
1687		return (error);
1688	}
1689	AUDIT_ARG(mac_string, elements);
1690
1691	ctx = vfs_context_current();
1692
1693	NDINIT(&nd, LOOKUP, OP_LOOKUP,
1694		LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1,
1695		UIO_USERSPACE, path_p, ctx);
1696	error = namei(&nd);
1697	if (error) {
1698		FREE(buffer, M_MACTEMP);
1699		FREE(elements, M_MACTEMP);
1700		return (error);
1701	}
1702	vp = nd.ni_vp;
1703
1704	nameidone(&nd);
1705
1706	intlabel = mac_vnode_label_alloc();
1707	mac_vnode_label_copy(vp->v_label, intlabel);
1708	error = mac_vnode_label_externalize(intlabel, elements, buffer,
1709				    	    mac.m_buflen, M_WAITOK);
1710	mac_vnode_label_free(intlabel);
1711	if (error == 0)
1712		error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
1713
1714	vnode_put(vp);
1715
1716	FREE(buffer, M_MACTEMP);
1717	FREE(elements, M_MACTEMP);
1718
1719	return (error);
1720}
1721
1722int
1723__mac_get_file(proc_t p, struct __mac_get_file_args *uap,
1724	       int *ret __unused)
1725{
1726
1727	return (mac_get_filelink(p, uap->mac_p, uap->path_p, 1));
1728}
1729
1730int
1731__mac_get_link(proc_t p, struct __mac_get_link_args *uap,
1732	       int *ret __unused)
1733{
1734
1735	return (mac_get_filelink(p, uap->mac_p, uap->path_p, 0));
1736}
1737
1738int
1739__mac_set_fd(proc_t p, struct __mac_set_fd_args *uap, int *ret __unused)
1740{
1741
1742	struct fileproc *fp;
1743	struct user_mac mac;
1744	struct vfs_context *ctx = vfs_context_current();
1745	int error;
1746	size_t ulen;
1747	char *buffer;
1748	struct label *intlabel;
1749#if CONFIG_MACF_SOCKET
1750	struct socket *so;
1751#endif
1752	struct vnode *vp;
1753
1754	AUDIT_ARG(fd, uap->fd);
1755
1756	if (IS_64BIT_PROCESS(p)) {
1757		struct user64_mac mac64;
1758		error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1759		mac.m_buflen = mac64.m_buflen;
1760		mac.m_string = mac64.m_string;
1761	} else {
1762		struct user32_mac mac32;
1763		error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1764		mac.m_buflen = mac32.m_buflen;
1765		mac.m_string = mac32.m_string;
1766	}
1767	if (error)
1768		return (error);
1769
1770	error = mac_check_structmac_consistent(&mac);
1771	if (error)
1772		return (error);
1773
1774	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1775	error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
1776	if (error) {
1777		FREE(buffer, M_MACTEMP);
1778		return (error);
1779	}
1780	AUDIT_ARG(mac_string, buffer);
1781
1782	error = fp_lookup(p, uap->fd, &fp, 0);
1783	if (error) {
1784		FREE(buffer, M_MACTEMP);
1785		return (error);
1786	}
1787
1788
1789	error = mac_file_check_set(vfs_context_ucred(ctx), fp->f_fglob, buffer, mac.m_buflen);
1790	if (error) {
1791		fp_drop(p, uap->fd, fp, 0);
1792		FREE(buffer, M_MACTEMP);
1793		return (error);
1794	}
1795
1796	switch (FILEGLOB_DTYPE(fp->f_fglob)) {
1797
1798		case DTYPE_VNODE:
1799			if (mac_label_vnodes == 0) {
1800				error = ENOSYS;
1801				break;
1802			}
1803
1804			intlabel = mac_vnode_label_alloc();
1805
1806			error = mac_vnode_label_internalize(intlabel, buffer);
1807			if (error) {
1808				mac_vnode_label_free(intlabel);
1809				break;
1810			}
1811
1812
1813			vp = (struct vnode *)fp->f_fglob->fg_data;
1814
1815			error = vnode_getwithref(vp);
1816			if (error == 0) {
1817				error = vn_setlabel(vp, intlabel, ctx);
1818				vnode_put(vp);
1819			}
1820			mac_vnode_label_free(intlabel);
1821			break;
1822
1823		case DTYPE_SOCKET:
1824#if CONFIG_MACF_SOCKET
1825			intlabel = mac_socket_label_alloc(MAC_WAITOK);
1826			error = mac_socket_label_internalize(intlabel, buffer);
1827			if (error == 0) {
1828				so = (struct socket *) fp->f_fglob->fg_data;
1829				SOCK_LOCK(so);
1830				error = mac_socket_label_update(vfs_context_ucred(ctx), so, intlabel);
1831				SOCK_UNLOCK(so);
1832			}
1833			mac_socket_label_free(intlabel);
1834			break;
1835#endif
1836		case DTYPE_PSXSHM:
1837		case DTYPE_PSXSEM:
1838		case DTYPE_PIPE:
1839		case DTYPE_KQUEUE:
1840		case DTYPE_FSEVENTS:
1841		default:
1842			error = ENOSYS;  // only sockets/vnodes so far
1843			break;
1844	}
1845
1846	fp_drop(p, uap->fd, fp, 0);
1847	FREE(buffer, M_MACTEMP);
1848	return (error);
1849}
1850
1851static int
1852mac_set_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p,
1853		 int follow)
1854{
1855	register struct vnode *vp;
1856	struct vfs_context *ctx = vfs_context_current();
1857	struct label *intlabel;
1858	struct nameidata nd;
1859	struct user_mac mac;
1860	char *buffer;
1861	int error;
1862	size_t ulen;
1863
1864	if (mac_label_vnodes == 0)
1865		return ENOSYS;
1866
1867	if (IS_64BIT_PROCESS(p)) {
1868		struct user64_mac mac64;
1869		error = copyin(mac_p, &mac64, sizeof(mac64));
1870		mac.m_buflen = mac64.m_buflen;
1871		mac.m_string = mac64.m_string;
1872	} else {
1873		struct user32_mac mac32;
1874		error = copyin(mac_p, &mac32, sizeof(mac32));
1875		mac.m_buflen = mac32.m_buflen;
1876		mac.m_string = mac32.m_string;
1877	}
1878	if (error)
1879		return (error);
1880
1881	error = mac_check_structmac_consistent(&mac);
1882	if (error) {
1883		printf("mac_set_file: failed structure consistency check\n");
1884		return (error);
1885	}
1886
1887	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1888	error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
1889	if (error) {
1890		FREE(buffer, M_MACTEMP);
1891		return (error);
1892	}
1893	AUDIT_ARG(mac_string, buffer);
1894
1895	intlabel = mac_vnode_label_alloc();
1896	error = mac_vnode_label_internalize(intlabel, buffer);
1897	FREE(buffer, M_MACTEMP);
1898	if (error) {
1899		mac_vnode_label_free(intlabel);
1900		return (error);
1901	}
1902
1903	NDINIT(&nd, LOOKUP, OP_LOOKUP,
1904		LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1,
1905		UIO_USERSPACE, path_p, ctx);
1906	error = namei(&nd);
1907	if (error) {
1908		mac_vnode_label_free(intlabel);
1909		return (error);
1910	}
1911	vp = nd.ni_vp;
1912
1913	nameidone(&nd);
1914
1915	error = vn_setlabel(vp, intlabel, ctx);
1916	vnode_put(vp);
1917	mac_vnode_label_free(intlabel);
1918
1919	return (error);
1920}
1921
1922int
1923__mac_set_file(proc_t p, struct __mac_set_file_args *uap,
1924	       int *ret __unused)
1925{
1926
1927	return (mac_set_filelink(p, uap->mac_p, uap->path_p, 1));
1928}
1929
1930int
1931__mac_set_link(proc_t p, struct __mac_set_link_args *uap,
1932	       int *ret __unused)
1933{
1934
1935	return (mac_set_filelink(p, uap->mac_p, uap->path_p, 0));
1936}
1937
1938/*
1939 * __mac_syscall: Perform a MAC policy system call
1940 *
1941 * Parameters:    p                       Process calling this routine
1942 *                uap                     User argument descriptor (see below)
1943 *                retv                    (Unused)
1944 *
1945 * Indirect:      uap->policy             Name of target MAC policy
1946 *                uap->call               MAC policy-specific system call to perform
1947 *                uap->arg                MAC policy-specific system call arguments
1948 *
1949 * Returns:        0                      Success
1950 *                !0                      Not success
1951 *
1952 */
1953int
1954__mac_syscall(proc_t p, struct __mac_syscall_args *uap, int *retv __unused)
1955{
1956	struct mac_policy_conf *mpc;
1957	char target[MAC_MAX_POLICY_NAME];
1958	int error;
1959	u_int i;
1960	size_t ulen;
1961
1962	error = copyinstr(uap->policy, target, sizeof(target), &ulen);
1963	if (error)
1964		return (error);
1965	AUDIT_ARG(value32, uap->call);
1966	AUDIT_ARG(mac_string, target);
1967
1968	error = ENOPOLICY;
1969
1970	for (i = 0; i < mac_policy_list.staticmax; i++) {
1971		mpc = mac_policy_list.entries[i].mpc;
1972		if (mpc == NULL)
1973			continue;
1974
1975		if (strcmp(mpc->mpc_name, target) == 0 &&
1976		    mpc->mpc_ops->mpo_policy_syscall != NULL) {
1977			error = mpc->mpc_ops->mpo_policy_syscall(p,
1978			    uap->call, uap->arg);
1979			goto done;
1980 		}
1981	}
1982	if (mac_policy_list_conditional_busy() != 0) {
1983		for (; i <= mac_policy_list.maxindex; i++) {
1984			mpc = mac_policy_list.entries[i].mpc;
1985			if (mpc == NULL)
1986				continue;
1987
1988			if (strcmp(mpc->mpc_name, target) == 0 &&
1989			    mpc->mpc_ops->mpo_policy_syscall != NULL) {
1990				error = mpc->mpc_ops->mpo_policy_syscall(p,
1991				    uap->call, uap->arg);
1992				break;
1993			}
1994		}
1995		mac_policy_list_unbusy();
1996	}
1997
1998done:
1999	return (error);
2000}
2001
2002int
2003mac_mount_label_get(struct mount *mp, user_addr_t mac_p)
2004{
2005	char *elements, *buffer;
2006	struct label *label;
2007	struct user_mac mac;
2008	int error;
2009	size_t ulen;
2010
2011	if (IS_64BIT_PROCESS(current_proc())) {
2012		struct user64_mac mac64;
2013		error = copyin(mac_p, &mac64, sizeof(mac64));
2014		mac.m_buflen = mac64.m_buflen;
2015		mac.m_string = mac64.m_string;
2016	} else {
2017		struct user32_mac mac32;
2018		error = copyin(mac_p, &mac32, sizeof(mac32));
2019		mac.m_buflen = mac32.m_buflen;
2020		mac.m_string = mac32.m_string;
2021	}
2022	if (error)
2023		return (error);
2024
2025	error = mac_check_structmac_consistent(&mac);
2026	if (error)
2027		return (error);
2028
2029	MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
2030	error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
2031	if (error) {
2032		FREE(elements, M_MACTEMP);
2033		return (error);
2034	}
2035	AUDIT_ARG(mac_string, elements);
2036
2037	label = mp->mnt_mntlabel;
2038	MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2039	error = mac_mount_label_externalize(label, elements, buffer,
2040	    mac.m_buflen);
2041	FREE(elements, M_MACTEMP);
2042
2043	if (error == 0)
2044		error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
2045	FREE(buffer, M_MACTEMP);
2046
2047	return (error);
2048}
2049
2050/*
2051 * __mac_get_mount: Get mount point label information for a given pathname
2052 *
2053 * Parameters:    p                        (ignored)
2054 *                uap                      User argument descriptor (see below)
2055 *                ret                      (ignored)
2056 *
2057 * Indirect:      uap->path                Pathname
2058 *                uap->mac_p               MAC info
2059 *
2060 * Returns:        0                       Success
2061 *                !0                       Not success
2062 */
2063int
2064__mac_get_mount(proc_t p __unused, struct __mac_get_mount_args *uap,
2065    int *ret __unused)
2066{
2067	struct nameidata nd;
2068	struct vfs_context *ctx = vfs_context_current();
2069	struct mount *mp;
2070	int error;
2071
2072	NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | AUDITVNPATH1,
2073		UIO_USERSPACE, uap->path, ctx);
2074	error = namei(&nd);
2075	if (error) {
2076		return (error);
2077	}
2078	mp = nd.ni_vp->v_mount;
2079	vnode_put(nd.ni_vp);
2080	nameidone(&nd);
2081
2082	return mac_mount_label_get(mp, uap->mac_p);
2083}
2084
2085/*
2086 * mac_schedule_userret()
2087 *
2088 * Schedule a callback to the mpo_thread_userret hook. The mpo_thread_userret
2089 * hook is called just before the thread exit from the kernel in ast_taken().
2090 *
2091 * Returns:	 0		Success
2092 * 		!0		Not successful
2093 */
2094int
2095mac_schedule_userret(void)
2096{
2097
2098	act_set_astmacf(current_thread());
2099	return (0);
2100}
2101
2102/*
2103 * mac_do_machexc()
2104 *
2105 * Do a Mach exception.  This should only be done in the mpo_thread_userret
2106 * callback.
2107 *
2108 * params:	code		exception code
2109 * 		subcode		exception subcode
2110 * 		flags		flags:
2111 * 				MAC_DOEXCF_TRACED  Only do exception if being
2112 * 						   ptrace()'ed.
2113 *
2114 *
2115 * Returns:	 0		Success
2116 * 		!0		Not successful
2117 */
2118int
2119mac_do_machexc(int64_t code, int64_t subcode, uint32_t flags)
2120{
2121	mach_exception_data_type_t  codes[EXCEPTION_CODE_MAX];
2122	proc_t p = current_proc();
2123
2124	/* Only allow execption codes in MACF's reserved range. */
2125	if ((code < EXC_MACF_MIN) || (code > EXC_MACF_MAX))
2126		return (1);
2127
2128	if (flags & MAC_DOEXCF_TRACED &&
2129	    !(p->p_lflag & P_LTRACED && (p->p_lflag & P_LPPWAIT) == 0))
2130		return (0);
2131
2132
2133	/* Send the Mach exception */
2134	codes[0] = (mach_exception_data_type_t)code;
2135	codes[1] = (mach_exception_data_type_t)subcode;
2136
2137	return (bsd_exception(EXC_SOFTWARE, codes, 2) != KERN_SUCCESS);
2138}
2139
2140#else /* MAC */
2141
2142void (*load_security_extensions_function)(void) = 0;
2143
2144struct sysctl_oid_list sysctl__security_mac_children;
2145
2146int
2147mac_policy_register(struct mac_policy_conf *mpc __unused,
2148	mac_policy_handle_t *handlep __unused, void *xd __unused)
2149{
2150
2151	return (0);
2152}
2153
2154int
2155mac_policy_unregister(mac_policy_handle_t handle __unused)
2156{
2157
2158	return (0);
2159}
2160
2161int
2162mac_audit_text(char *text __unused, mac_policy_handle_t handle __unused)
2163{
2164
2165	return (0);
2166}
2167
2168int
2169mac_vnop_setxattr(struct vnode *vp __unused, const char *name __unused, char *buf __unused, size_t len __unused)
2170{
2171
2172	return (ENOENT);
2173}
2174
2175int
2176mac_vnop_getxattr(struct vnode *vp __unused, const char *name __unused,
2177	char *buf __unused, size_t len __unused, size_t *attrlen __unused)
2178{
2179
2180	return (ENOENT);
2181}
2182
2183int
2184mac_vnop_removexattr(struct vnode *vp __unused, const char *name __unused)
2185{
2186
2187	return (ENOENT);
2188}
2189
2190intptr_t mac_label_get(struct label *l __unused, int slot __unused)
2191{
2192        return 0;
2193}
2194
2195void mac_label_set(struct label *l __unused, int slot __unused, intptr_t v __unused)
2196{
2197		return;
2198}
2199
2200struct label *mac_thread_get_threadlabel(struct thread *thread __unused)
2201{
2202        return NULL;
2203}
2204
2205struct label *mac_thread_get_uthreadlabel(struct uthread *uthread __unused)
2206{
2207        return NULL;
2208}
2209
2210void mac_proc_set_enforce(proc_t p, int enforce_flags);
2211void mac_proc_set_enforce(proc_t p __unused, int enforce_flags __unused)
2212{
2213		return;
2214}
2215
2216int mac_iokit_check_hid_control(kauth_cred_t cred __unused);
2217int mac_iokit_check_hid_control(kauth_cred_t cred __unused)
2218{
2219        return 0;
2220}
2221
2222#endif /* !MAC */
2223