xref: /freebsd/sys/security/mac/mac_framework.c (revision 9dba3024c3f1a2df6f42689aac5a2ab4acc7561d)
1 /*-
2  * Copyright (c) 1999-2002 Robert N. M. Watson
3  * Copyright (c) 2001 Ilmar S. Habibulin
4  * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5  * All rights reserved.
6  *
7  * This software was developed by Robert Watson and Ilmar Habibulin for the
8  * TrustedBSD Project.
9  *
10  * This software was developed for the FreeBSD Project in part by Network
11  * Associates Laboratories, the Security Research Division of Network
12  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13  * as part of the DARPA CHATS research program.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 /*-
38  * Framework for extensible kernel access control.  This file contains
39  * Kernel and userland interface to the framework, policy registration
40  * and composition.  Per-object interfaces, controls, and labeling may be
41  * found in src/sys/security/mac/.  Sample policies may be found in
42  * src/sys/security/mac_*.
43  */
44 
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
47 
48 #include "opt_mac.h"
49 #include "opt_devfs.h"
50 
51 #include <sys/param.h>
52 #include <sys/condvar.h>
53 #include <sys/extattr.h>
54 #include <sys/imgact.h>
55 #include <sys/kernel.h>
56 #include <sys/lock.h>
57 #include <sys/malloc.h>
58 #include <sys/mutex.h>
59 #include <sys/mac.h>
60 #include <sys/module.h>
61 #include <sys/proc.h>
62 #include <sys/sbuf.h>
63 #include <sys/systm.h>
64 #include <sys/sysproto.h>
65 #include <sys/sysent.h>
66 #include <sys/vnode.h>
67 #include <sys/mount.h>
68 #include <sys/file.h>
69 #include <sys/namei.h>
70 #include <sys/socket.h>
71 #include <sys/pipe.h>
72 #include <sys/socketvar.h>
73 #include <sys/sysctl.h>
74 
75 #include <vm/vm.h>
76 #include <vm/pmap.h>
77 #include <vm/vm_map.h>
78 #include <vm/vm_object.h>
79 
80 #include <sys/mac_policy.h>
81 
82 #include <fs/devfs/devfs.h>
83 
84 #include <net/bpfdesc.h>
85 #include <net/if.h>
86 #include <net/if_var.h>
87 
88 #include <netinet/in.h>
89 #include <netinet/ip_var.h>
90 
91 #include <security/mac/mac_internal.h>
92 
93 #ifdef MAC
94 
95 /*
96  * Declare that the kernel provides MAC support, version 1.  This permits
97  * modules to refuse to be loaded if the necessary support isn't present,
98  * even if it's pre-boot.
99  */
100 MODULE_VERSION(kernel_mac_support, 2);
101 
102 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
103     "TrustedBSD MAC policy controls");
104 
105 #if MAC_MAX_SLOTS > 32
106 #error "MAC_MAX_SLOTS too large"
107 #endif
108 
109 static unsigned int mac_max_slots = MAC_MAX_SLOTS;
110 static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
111 SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
112     &mac_max_slots, 0, "");
113 
114 /*
115  * Has the kernel started generating labeled objects yet?  All read/write
116  * access to this variable is serialized during the boot process.  Following
117  * the end of serialization, we don't update this flag; no locking.
118  */
119 int	mac_late = 0;
120 
121 /*
122  * Flag to indicate whether or not we should allocate label storage for
123  * new mbufs.  Since most dynamic policies we currently work with don't
124  * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
125  * unless specifically notified of interest.  One result of this is
126  * that if a dynamically loaded policy requests mbuf labels, it must
127  * be able to deal with a NULL label being returned on any mbufs that
128  * were already in flight when the policy was loaded.  Since the policy
129  * already has to deal with uninitialized labels, this probably won't
130  * be a problem.  Note: currently no locking.  Will this be a problem?
131  */
132 #ifndef MAC_ALWAYS_LABEL_MBUF
133 int	mac_labelmbufs = 0;
134 #endif
135 
136 #ifdef MAC_DEBUG
137 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
138     "TrustedBSD MAC debug info");
139 SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
140     "TrustedBSD MAC object counters");
141 
142 static unsigned int nmactemp;
143 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
144     &nmactemp, 0, "number of temporary labels in use");
145 #endif
146 
147 static int	mac_policy_register(struct mac_policy_conf *mpc);
148 static int	mac_policy_unregister(struct mac_policy_conf *mpc);
149 
150 MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
151 
152 /*
153  * mac_static_policy_list holds a list of policy modules that are not
154  * loaded while the system is "live", and cannot be unloaded.  These
155  * policies can be invoked without holding the busy count.
156  *
157  * mac_policy_list stores the list of dynamic policies.  A busy count is
158  * maintained for the list, stored in mac_policy_busy.  The busy count
159  * is protected by mac_policy_mtx; the list may be modified only
160  * while the busy count is 0, requiring that the lock be held to
161  * prevent new references to the list from being acquired.  For almost
162  * all operations, incrementing the busy count is sufficient to
163  * guarantee consistency, as the list cannot be modified while the
164  * busy count is elevated.  For a few special operations involving a
165  * change to the list of active policies, the mtx itself must be held.
166  * A condition variable, mac_policy_cv, is used to signal potential
167  * exclusive consumers that they should try to acquire the lock if a
168  * first attempt at exclusive access fails.
169  */
170 #ifndef MAC_STATIC
171 static struct mtx mac_policy_mtx;
172 static struct cv mac_policy_cv;
173 static int mac_policy_count;
174 #endif
175 struct mac_policy_list_head mac_policy_list;
176 struct mac_policy_list_head mac_static_policy_list;
177 
178 /*
179  * We manually invoke WITNESS_WARN() to allow Witness to generate
180  * warnings even if we don't end up ever triggering the wait at
181  * run-time.  The consumer of the exclusive interface must not hold
182  * any locks (other than potentially Giant) since we may sleep for
183  * long (potentially indefinite) periods of time waiting for the
184  * framework to become quiescent so that a policy list change may
185  * be made.
186  */
187 void
188 mac_policy_grab_exclusive(void)
189 {
190 
191 #ifndef MAC_STATIC
192 	if (!mac_late)
193 		return;
194 
195 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
196  	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
197 	mtx_lock(&mac_policy_mtx);
198 	while (mac_policy_count != 0)
199 		cv_wait(&mac_policy_cv, &mac_policy_mtx);
200 #endif
201 }
202 
203 void
204 mac_policy_assert_exclusive(void)
205 {
206 
207 #ifndef MAC_STATIC
208 	if (!mac_late)
209 		return;
210 
211 	mtx_assert(&mac_policy_mtx, MA_OWNED);
212 	KASSERT(mac_policy_count == 0,
213 	    ("mac_policy_assert_exclusive(): not exclusive"));
214 #endif
215 }
216 
217 void
218 mac_policy_release_exclusive(void)
219 {
220 
221 #ifndef MAC_STATIC
222 	if (!mac_late)
223 		return;
224 
225 	KASSERT(mac_policy_count == 0,
226 	    ("mac_policy_release_exclusive(): not exclusive"));
227 	mtx_unlock(&mac_policy_mtx);
228 	cv_signal(&mac_policy_cv);
229 #endif
230 }
231 
232 void
233 mac_policy_list_busy(void)
234 {
235 
236 #ifndef MAC_STATIC
237 	if (!mac_late)
238 		return;
239 
240 	mtx_lock(&mac_policy_mtx);
241 	mac_policy_count++;
242 	mtx_unlock(&mac_policy_mtx);
243 #endif
244 }
245 
246 int
247 mac_policy_list_conditional_busy(void)
248 {
249 #ifndef MAC_STATIC
250 	int ret;
251 
252 	if (!mac_late)
253 		return (1);
254 
255 	mtx_lock(&mac_policy_mtx);
256 	if (!LIST_EMPTY(&mac_policy_list)) {
257 		mac_policy_count++;
258 		ret = 1;
259 	} else
260 		ret = 0;
261 	mtx_unlock(&mac_policy_mtx);
262 	return (ret);
263 #else
264 	if (!mac_late)
265 		return (1);
266 
267 	return (1);
268 #endif
269 }
270 
271 void
272 mac_policy_list_unbusy(void)
273 {
274 
275 #ifndef MAC_STATIC
276 	if (!mac_late)
277 		return;
278 
279 	mtx_lock(&mac_policy_mtx);
280 	mac_policy_count--;
281 	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
282 	if (mac_policy_count == 0)
283 		cv_signal(&mac_policy_cv);
284 	mtx_unlock(&mac_policy_mtx);
285 #endif
286 }
287 
288 /*
289  * Initialize the MAC subsystem, including appropriate SMP locks.
290  */
291 static void
292 mac_init(void)
293 {
294 
295 	LIST_INIT(&mac_static_policy_list);
296 	LIST_INIT(&mac_policy_list);
297 	mac_labelzone_init();
298 
299 #ifndef MAC_STATIC
300 	mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
301 	cv_init(&mac_policy_cv, "mac_policy_cv");
302 #endif
303 }
304 
305 /*
306  * For the purposes of modules that want to know if they were loaded
307  * "early", set the mac_late flag once we've processed modules either
308  * linked into the kernel, or loaded before the kernel startup.
309  */
310 static void
311 mac_late_init(void)
312 {
313 
314 	mac_late = 1;
315 }
316 
317 /*
318  * After the policy list has changed, walk the list to update any global
319  * flags.  Currently, we support only one flag, and it's conditionally
320  * defined; as a result, the entire function is conditional.  Eventually,
321  * the #else case might also iterate across the policies.
322  */
323 static void
324 mac_policy_updateflags(void)
325 {
326 #ifndef MAC_ALWAYS_LABEL_MBUF
327 	struct mac_policy_conf *tmpc;
328 	int labelmbufs;
329 
330 	mac_policy_assert_exclusive();
331 
332 	labelmbufs = 0;
333 	LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
334 		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
335 			labelmbufs++;
336 	}
337 	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
338 		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
339 			labelmbufs++;
340 	}
341 	mac_labelmbufs = (labelmbufs != 0);
342 #endif
343 }
344 
345 /*
346  * Allow MAC policy modules to register during boot, etc.
347  */
348 int
349 mac_policy_modevent(module_t mod, int type, void *data)
350 {
351 	struct mac_policy_conf *mpc;
352 	int error;
353 
354 	error = 0;
355 	mpc = (struct mac_policy_conf *) data;
356 
357 #ifdef MAC_STATIC
358 	if (mac_late) {
359 		printf("mac_policy_modevent: MAC_STATIC and late\n");
360 		return (EBUSY);
361 	}
362 #endif
363 
364 	switch (type) {
365 	case MOD_LOAD:
366 		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
367 		    mac_late) {
368 			printf("mac_policy_modevent: can't load %s policy "
369 			    "after booting\n", mpc->mpc_name);
370 			error = EBUSY;
371 			break;
372 		}
373 		error = mac_policy_register(mpc);
374 		break;
375 	case MOD_UNLOAD:
376 		/* Don't unregister the module if it was never registered. */
377 		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
378 		    != 0)
379 			error = mac_policy_unregister(mpc);
380 		else
381 			error = 0;
382 		break;
383 	default:
384 		error = EOPNOTSUPP;
385 		break;
386 	}
387 
388 	return (error);
389 }
390 
391 static int
392 mac_policy_register(struct mac_policy_conf *mpc)
393 {
394 	struct mac_policy_conf *tmpc;
395 	int error, slot, static_entry;
396 
397 	error = 0;
398 
399 	/*
400 	 * We don't technically need exclusive access while !mac_late,
401 	 * but hold it for assertion consistency.
402 	 */
403 	mac_policy_grab_exclusive();
404 
405 	/*
406 	 * If the module can potentially be unloaded, or we're loading
407 	 * late, we have to stick it in the non-static list and pay
408 	 * an extra performance overhead.  Otherwise, we can pay a
409 	 * light locking cost and stick it in the static list.
410 	 */
411 	static_entry = (!mac_late &&
412 	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
413 
414 	if (static_entry) {
415 		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
416 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
417 				error = EEXIST;
418 				goto out;
419 			}
420 		}
421 	} else {
422 		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
423 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
424 				error = EEXIST;
425 				goto out;
426 			}
427 		}
428 	}
429 	if (mpc->mpc_field_off != NULL) {
430 		slot = ffs(mac_slot_offsets_free);
431 		if (slot == 0) {
432 			error = ENOMEM;
433 			goto out;
434 		}
435 		slot--;
436 		mac_slot_offsets_free &= ~(1 << slot);
437 		*mpc->mpc_field_off = slot;
438 	}
439 	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
440 
441 	/*
442 	 * If we're loading a MAC module after the framework has
443 	 * initialized, it has to go into the dynamic list.  If
444 	 * we're loading it before we've finished initializing,
445 	 * it can go into the static list with weaker locker
446 	 * requirements.
447 	 */
448 	if (static_entry)
449 		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
450 	else
451 		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
452 
453 	/* Per-policy initialization. */
454 	if (mpc->mpc_ops->mpo_init != NULL)
455 		(*(mpc->mpc_ops->mpo_init))(mpc);
456 	mac_policy_updateflags();
457 
458 	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
459 	    mpc->mpc_name);
460 
461 out:
462 	mac_policy_release_exclusive();
463 	return (error);
464 }
465 
466 static int
467 mac_policy_unregister(struct mac_policy_conf *mpc)
468 {
469 
470 	/*
471 	 * If we fail the load, we may get a request to unload.  Check
472 	 * to see if we did the run-time registration, and if not,
473 	 * silently succeed.
474 	 */
475 	mac_policy_grab_exclusive();
476 	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
477 		mac_policy_release_exclusive();
478 		return (0);
479 	}
480 #if 0
481 	/*
482 	 * Don't allow unloading modules with private data.
483 	 */
484 	if (mpc->mpc_field_off != NULL) {
485 		MAC_POLICY_LIST_UNLOCK();
486 		return (EBUSY);
487 	}
488 #endif
489 	/*
490 	 * Only allow the unload to proceed if the module is unloadable
491 	 * by its own definition.
492 	 */
493 	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
494 		mac_policy_release_exclusive();
495 		return (EBUSY);
496 	}
497 	if (mpc->mpc_ops->mpo_destroy != NULL)
498 		(*(mpc->mpc_ops->mpo_destroy))(mpc);
499 
500 	LIST_REMOVE(mpc, mpc_list);
501 	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
502 	mac_policy_updateflags();
503 
504 	mac_policy_release_exclusive();
505 
506 	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
507 	    mpc->mpc_name);
508 
509 	return (0);
510 }
511 
512 /*
513  * Define an error value precedence, and given two arguments, selects the
514  * value with the higher precedence.
515  */
516 int
517 mac_error_select(int error1, int error2)
518 {
519 
520 	/* Certain decision-making errors take top priority. */
521 	if (error1 == EDEADLK || error2 == EDEADLK)
522 		return (EDEADLK);
523 
524 	/* Invalid arguments should be reported where possible. */
525 	if (error1 == EINVAL || error2 == EINVAL)
526 		return (EINVAL);
527 
528 	/* Precedence goes to "visibility", with both process and file. */
529 	if (error1 == ESRCH || error2 == ESRCH)
530 		return (ESRCH);
531 
532 	if (error1 == ENOENT || error2 == ENOENT)
533 		return (ENOENT);
534 
535 	/* Precedence goes to DAC/MAC protections. */
536 	if (error1 == EACCES || error2 == EACCES)
537 		return (EACCES);
538 
539 	/* Precedence goes to privilege. */
540 	if (error1 == EPERM || error2 == EPERM)
541 		return (EPERM);
542 
543 	/* Precedence goes to error over success; otherwise, arbitrary. */
544 	if (error1 != 0)
545 		return (error1);
546 	return (error2);
547 }
548 
549 void
550 mac_init_label(struct label *label)
551 {
552 
553 	bzero(label, sizeof(*label));
554 	label->l_flags = MAC_FLAG_INITIALIZED;
555 }
556 
557 void
558 mac_destroy_label(struct label *label)
559 {
560 
561 	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
562 	    ("destroying uninitialized label"));
563 
564 	bzero(label, sizeof(*label));
565 	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
566 }
567 
568 int
569 mac_check_structmac_consistent(struct mac *mac)
570 {
571 
572 	if (mac->m_buflen < 0 ||
573 	    mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
574 		return (EINVAL);
575 
576 	return (0);
577 }
578 
579 /*
580  * MPSAFE
581  */
582 int
583 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
584 {
585 	char *elements, *buffer;
586 	struct mac mac;
587 	struct proc *tproc;
588 	struct ucred *tcred;
589 	int error;
590 
591 	error = copyin(uap->mac_p, &mac, sizeof(mac));
592 	if (error)
593 		return (error);
594 
595 	error = mac_check_structmac_consistent(&mac);
596 	if (error)
597 		return (error);
598 
599 	tproc = pfind(uap->pid);
600 	if (tproc == NULL)
601 		return (ESRCH);
602 
603 	tcred = NULL;				/* Satisfy gcc. */
604 	error = p_cansee(td, tproc);
605 	if (error == 0)
606 		tcred = crhold(tproc->p_ucred);
607 	PROC_UNLOCK(tproc);
608 	if (error)
609 		return (error);
610 
611 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
612 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
613 	if (error) {
614 		free(elements, M_MACTEMP);
615 		crfree(tcred);
616 		return (error);
617 	}
618 
619 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
620 	error = mac_externalize_cred_label(tcred->cr_label, elements,
621 	    buffer, mac.m_buflen);
622 	if (error == 0)
623 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
624 
625 	free(buffer, M_MACTEMP);
626 	free(elements, M_MACTEMP);
627 	crfree(tcred);
628 	return (error);
629 }
630 
631 /*
632  * MPSAFE
633  */
634 int
635 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
636 {
637 	char *elements, *buffer;
638 	struct mac mac;
639 	int error;
640 
641 	error = copyin(uap->mac_p, &mac, sizeof(mac));
642 	if (error)
643 		return (error);
644 
645 	error = mac_check_structmac_consistent(&mac);
646 	if (error)
647 		return (error);
648 
649 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
650 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
651 	if (error) {
652 		free(elements, M_MACTEMP);
653 		return (error);
654 	}
655 
656 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
657 	error = mac_externalize_cred_label(td->td_ucred->cr_label,
658 	    elements, buffer, mac.m_buflen);
659 	if (error == 0)
660 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
661 
662 	free(buffer, M_MACTEMP);
663 	free(elements, M_MACTEMP);
664 	return (error);
665 }
666 
667 /*
668  * MPSAFE
669  */
670 int
671 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
672 {
673 	struct ucred *newcred, *oldcred;
674 	struct label *intlabel;
675 	struct proc *p;
676 	struct mac mac;
677 	char *buffer;
678 	int error;
679 
680 	error = copyin(uap->mac_p, &mac, sizeof(mac));
681 	if (error)
682 		return (error);
683 
684 	error = mac_check_structmac_consistent(&mac);
685 	if (error)
686 		return (error);
687 
688 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
689 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
690 	if (error) {
691 		free(buffer, M_MACTEMP);
692 		return (error);
693 	}
694 
695 	intlabel = mac_cred_label_alloc();
696 	error = mac_internalize_cred_label(intlabel, buffer);
697 	free(buffer, M_MACTEMP);
698 	if (error)
699 		goto out;
700 
701 	newcred = crget();
702 
703 	p = td->td_proc;
704 	PROC_LOCK(p);
705 	oldcred = p->p_ucred;
706 
707 	error = mac_check_cred_relabel(oldcred, intlabel);
708 	if (error) {
709 		PROC_UNLOCK(p);
710 		crfree(newcred);
711 		goto out;
712 	}
713 
714 	setsugid(p);
715 	crcopy(newcred, oldcred);
716 	mac_relabel_cred(newcred, intlabel);
717 	p->p_ucred = newcred;
718 
719 	/*
720 	 * Grab additional reference for use while revoking mmaps, prior
721 	 * to releasing the proc lock and sharing the cred.
722 	 */
723 	crhold(newcred);
724 	PROC_UNLOCK(p);
725 
726 	if (mac_enforce_vm) {
727 		mtx_lock(&Giant);
728 		mac_cred_mmapped_drop_perms(td, newcred);
729 		mtx_unlock(&Giant);
730 	}
731 
732 	crfree(newcred);	/* Free revocation reference. */
733 	crfree(oldcred);
734 
735 out:
736 	mac_cred_label_free(intlabel);
737 	return (error);
738 }
739 
740 /*
741  * MPSAFE
742  */
743 int
744 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
745 {
746 	char *elements, *buffer;
747 	struct label *intlabel;
748 	struct file *fp;
749 	struct mac mac;
750 	struct vnode *vp;
751 	struct pipe *pipe;
752 	struct socket *so;
753 	short label_type;
754 	int error;
755 
756 	error = copyin(uap->mac_p, &mac, sizeof(mac));
757 	if (error)
758 		return (error);
759 
760 	error = mac_check_structmac_consistent(&mac);
761 	if (error)
762 		return (error);
763 
764 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
765 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
766 	if (error) {
767 		free(elements, M_MACTEMP);
768 		return (error);
769 	}
770 
771 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
772 	error = fget(td, uap->fd, &fp);
773 	if (error)
774 		goto out;
775 
776 	label_type = fp->f_type;
777 	switch (fp->f_type) {
778 	case DTYPE_FIFO:
779 	case DTYPE_VNODE:
780 		vp = fp->f_vnode;
781 		intlabel = mac_vnode_label_alloc();
782 		mtx_lock(&Giant);				/* VFS */
783 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
784 		mac_copy_vnode_label(vp->v_label, intlabel);
785 		VOP_UNLOCK(vp, 0, td);
786 		mtx_unlock(&Giant);				/* VFS */
787 		error = mac_externalize_vnode_label(intlabel, elements,
788 		    buffer, mac.m_buflen);
789 		mac_vnode_label_free(intlabel);
790 		break;
791 
792 	case DTYPE_PIPE:
793 		pipe = fp->f_data;
794 		intlabel = mac_pipe_label_alloc();
795 		PIPE_LOCK(pipe);
796 		mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel);
797 		PIPE_UNLOCK(pipe);
798 		error = mac_externalize_pipe_label(intlabel, elements,
799 		    buffer, mac.m_buflen);
800 		mac_pipe_label_free(intlabel);
801 		break;
802 
803 	case DTYPE_SOCKET:
804 		so = fp->f_data;
805 		intlabel = mac_socket_label_alloc(M_WAITOK);
806 		NET_LOCK_GIANT();
807 		SOCK_LOCK(so);
808 		mac_copy_socket_label(so->so_label, intlabel);
809 		SOCK_UNLOCK(so);
810 		NET_UNLOCK_GIANT();
811 		error = mac_externalize_socket_label(intlabel, elements,
812 		    buffer, mac.m_buflen);
813 		mac_socket_label_free(intlabel);
814 		break;
815 
816 	default:
817 		error = EINVAL;
818 	}
819 	fdrop(fp, td);
820 	if (error == 0)
821 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
822 
823 out:
824 	free(buffer, M_MACTEMP);
825 	free(elements, M_MACTEMP);
826 	return (error);
827 }
828 
829 /*
830  * MPSAFE
831  */
832 int
833 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
834 {
835 	char *elements, *buffer;
836 	struct nameidata nd;
837 	struct label *intlabel;
838 	struct mac mac;
839 	int error;
840 
841 	error = copyin(uap->mac_p, &mac, sizeof(mac));
842 	if (error)
843 		return (error);
844 
845 	error = mac_check_structmac_consistent(&mac);
846 	if (error)
847 		return (error);
848 
849 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
850 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
851 	if (error) {
852 		free(elements, M_MACTEMP);
853 		return (error);
854 	}
855 
856 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
857 	mtx_lock(&Giant);				/* VFS */
858 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
859 	    td);
860 	error = namei(&nd);
861 	if (error)
862 		goto out;
863 
864 	intlabel = mac_vnode_label_alloc();
865 	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
866 	error = mac_externalize_vnode_label(intlabel, elements, buffer,
867 	    mac.m_buflen);
868 
869 	NDFREE(&nd, 0);
870 	mac_vnode_label_free(intlabel);
871 
872 	if (error == 0)
873 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
874 
875 out:
876 	mtx_unlock(&Giant);				/* VFS */
877 
878 	free(buffer, M_MACTEMP);
879 	free(elements, M_MACTEMP);
880 
881 	return (error);
882 }
883 
884 /*
885  * MPSAFE
886  */
887 int
888 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
889 {
890 	char *elements, *buffer;
891 	struct nameidata nd;
892 	struct label *intlabel;
893 	struct mac mac;
894 	int error;
895 
896 	error = copyin(uap->mac_p, &mac, sizeof(mac));
897 	if (error)
898 		return (error);
899 
900 	error = mac_check_structmac_consistent(&mac);
901 	if (error)
902 		return (error);
903 
904 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
905 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
906 	if (error) {
907 		free(elements, M_MACTEMP);
908 		return (error);
909 	}
910 
911 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
912 	mtx_lock(&Giant);				/* VFS */
913 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
914 	    td);
915 	error = namei(&nd);
916 	if (error)
917 		goto out;
918 
919 	intlabel = mac_vnode_label_alloc();
920 	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
921 	error = mac_externalize_vnode_label(intlabel, elements, buffer,
922 	    mac.m_buflen);
923 	NDFREE(&nd, 0);
924 	mac_vnode_label_free(intlabel);
925 
926 	if (error == 0)
927 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
928 
929 out:
930 	mtx_unlock(&Giant);				/* VFS */
931 
932 	free(buffer, M_MACTEMP);
933 	free(elements, M_MACTEMP);
934 
935 	return (error);
936 }
937 
938 /*
939  * MPSAFE
940  */
941 int
942 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
943 {
944 	struct label *intlabel;
945 	struct pipe *pipe;
946 	struct socket *so;
947 	struct file *fp;
948 	struct mount *mp;
949 	struct vnode *vp;
950 	struct mac mac;
951 	char *buffer;
952 	int error;
953 
954 	error = copyin(uap->mac_p, &mac, sizeof(mac));
955 	if (error)
956 		return (error);
957 
958 	error = mac_check_structmac_consistent(&mac);
959 	if (error)
960 		return (error);
961 
962 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
963 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
964 	if (error) {
965 		free(buffer, M_MACTEMP);
966 		return (error);
967 	}
968 
969 	error = fget(td, uap->fd, &fp);
970 	if (error)
971 		goto out;
972 
973 	switch (fp->f_type) {
974 	case DTYPE_FIFO:
975 	case DTYPE_VNODE:
976 		intlabel = mac_vnode_label_alloc();
977 		error = mac_internalize_vnode_label(intlabel, buffer);
978 		if (error) {
979 			mac_vnode_label_free(intlabel);
980 			break;
981 		}
982 		vp = fp->f_vnode;
983 		mtx_lock(&Giant);				/* VFS */
984 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
985 		if (error != 0) {
986 			mtx_unlock(&Giant);			/* VFS */
987 			mac_vnode_label_free(intlabel);
988 			break;
989 		}
990 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
991 		error = vn_setlabel(vp, intlabel, td->td_ucred);
992 		VOP_UNLOCK(vp, 0, td);
993 		vn_finished_write(mp);
994 		mtx_unlock(&Giant);				/* VFS */
995 		mac_vnode_label_free(intlabel);
996 		break;
997 
998 	case DTYPE_PIPE:
999 		intlabel = mac_pipe_label_alloc();
1000 		error = mac_internalize_pipe_label(intlabel, buffer);
1001 		if (error == 0) {
1002 			pipe = fp->f_data;
1003 			PIPE_LOCK(pipe);
1004 			error = mac_pipe_label_set(td->td_ucred,
1005 			    pipe->pipe_pair, intlabel);
1006 			PIPE_UNLOCK(pipe);
1007 		}
1008 		mac_pipe_label_free(intlabel);
1009 		break;
1010 
1011 	case DTYPE_SOCKET:
1012 		intlabel = mac_socket_label_alloc(M_WAITOK);
1013 		error = mac_internalize_socket_label(intlabel, buffer);
1014 		if (error == 0) {
1015 			so = fp->f_data;
1016 			NET_LOCK_GIANT();
1017 			error = mac_socket_label_set(td->td_ucred, so,
1018 			    intlabel);
1019 			NET_UNLOCK_GIANT();
1020 		}
1021 		mac_socket_label_free(intlabel);
1022 		break;
1023 
1024 	default:
1025 		error = EINVAL;
1026 	}
1027 	fdrop(fp, td);
1028 out:
1029 	free(buffer, M_MACTEMP);
1030 	return (error);
1031 }
1032 
1033 /*
1034  * MPSAFE
1035  */
1036 int
1037 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1038 {
1039 	struct label *intlabel;
1040 	struct nameidata nd;
1041 	struct mount *mp;
1042 	struct mac mac;
1043 	char *buffer;
1044 	int error;
1045 
1046 	error = copyin(uap->mac_p, &mac, sizeof(mac));
1047 	if (error)
1048 		return (error);
1049 
1050 	error = mac_check_structmac_consistent(&mac);
1051 	if (error)
1052 		return (error);
1053 
1054 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1055 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1056 	if (error) {
1057 		free(buffer, M_MACTEMP);
1058 		return (error);
1059 	}
1060 
1061 	intlabel = mac_vnode_label_alloc();
1062 	error = mac_internalize_vnode_label(intlabel, buffer);
1063 	free(buffer, M_MACTEMP);
1064 	if (error)
1065 		goto out;
1066 
1067 	mtx_lock(&Giant);				/* VFS */
1068 
1069 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
1070 	    td);
1071 	error = namei(&nd);
1072 	if (error == 0) {
1073 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1074 		if (error == 0)
1075 			error = vn_setlabel(nd.ni_vp, intlabel,
1076 			    td->td_ucred);
1077 		vn_finished_write(mp);
1078 	}
1079 
1080 	NDFREE(&nd, 0);
1081 	mtx_unlock(&Giant);				/* VFS */
1082 out:
1083 	mac_vnode_label_free(intlabel);
1084 	return (error);
1085 }
1086 
1087 /*
1088  * MPSAFE
1089  */
1090 int
1091 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1092 {
1093 	struct label *intlabel;
1094 	struct nameidata nd;
1095 	struct mount *mp;
1096 	struct mac mac;
1097 	char *buffer;
1098 	int error;
1099 
1100 	error = copyin(uap->mac_p, &mac, sizeof(mac));
1101 	if (error)
1102 		return (error);
1103 
1104 	error = mac_check_structmac_consistent(&mac);
1105 	if (error)
1106 		return (error);
1107 
1108 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1109 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1110 	if (error) {
1111 		free(buffer, M_MACTEMP);
1112 		return (error);
1113 	}
1114 
1115 	intlabel = mac_vnode_label_alloc();
1116 	error = mac_internalize_vnode_label(intlabel, buffer);
1117 	free(buffer, M_MACTEMP);
1118 	if (error)
1119 		goto out;
1120 
1121 	mtx_lock(&Giant);				/* VFS */
1122 
1123 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
1124 	    td);
1125 	error = namei(&nd);
1126 	if (error == 0) {
1127 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1128 		if (error == 0)
1129 			error = vn_setlabel(nd.ni_vp, intlabel,
1130 			    td->td_ucred);
1131 		vn_finished_write(mp);
1132 	}
1133 
1134 	NDFREE(&nd, 0);
1135 	mtx_unlock(&Giant);				/* VFS */
1136 out:
1137 	mac_vnode_label_free(intlabel);
1138 	return (error);
1139 }
1140 
1141 /*
1142  * MPSAFE
1143  */
1144 int
1145 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1146 {
1147 	struct mac_policy_conf *mpc;
1148 	char target[MAC_MAX_POLICY_NAME];
1149 	int entrycount, error;
1150 
1151 	error = copyinstr(uap->policy, target, sizeof(target), NULL);
1152 	if (error)
1153 		return (error);
1154 
1155 	error = ENOSYS;
1156 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
1157 		if (strcmp(mpc->mpc_name, target) == 0 &&
1158 		    mpc->mpc_ops->mpo_syscall != NULL) {
1159 			error = mpc->mpc_ops->mpo_syscall(td,
1160 			    uap->call, uap->arg);
1161 			goto out;
1162 		}
1163 	}
1164 
1165 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
1166 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
1167 			if (strcmp(mpc->mpc_name, target) == 0 &&
1168 			    mpc->mpc_ops->mpo_syscall != NULL) {
1169 				error = mpc->mpc_ops->mpo_syscall(td,
1170 				    uap->call, uap->arg);
1171 				break;
1172 			}
1173 		}
1174 		mac_policy_list_unbusy();
1175 	}
1176 out:
1177 	return (error);
1178 }
1179 
1180 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
1181 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
1182 
1183 #else /* !MAC */
1184 
1185 int
1186 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1187 {
1188 
1189 	return (ENOSYS);
1190 }
1191 
1192 int
1193 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
1194 {
1195 
1196 	return (ENOSYS);
1197 }
1198 
1199 int
1200 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
1201 {
1202 
1203 	return (ENOSYS);
1204 }
1205 
1206 int
1207 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
1208 {
1209 
1210 	return (ENOSYS);
1211 }
1212 
1213 int
1214 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
1215 {
1216 
1217 	return (ENOSYS);
1218 }
1219 
1220 int
1221 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1222 {
1223 
1224 	return (ENOSYS);
1225 }
1226 
1227 int
1228 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
1229 {
1230 
1231 	return (ENOSYS);
1232 }
1233 
1234 int
1235 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1236 {
1237 
1238 	return (ENOSYS);
1239 }
1240 
1241 int
1242 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1243 {
1244 
1245 	return (ENOSYS);
1246 }
1247 
1248 int
1249 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1250 {
1251 
1252 	return (ENOSYS);
1253 }
1254 
1255 #endif /* !MAC */
1256