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