xref: /freebsd/sys/security/mac/mac_framework.c (revision eca8a663d442468f64e21ed869817b9048ab5a7b)
1 /*-
2  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3  * Copyright (c) 2001 Ilmar S. Habibulin
4  * Copyright (c) 2001, 2002, 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 int
532 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
533 {
534 	char *elements, *buffer;
535 	struct mac mac;
536 	struct proc *tproc;
537 	struct ucred *tcred;
538 	int error;
539 
540 	error = copyin(uap->mac_p, &mac, sizeof(mac));
541 	if (error)
542 		return (error);
543 
544 	error = mac_check_structmac_consistent(&mac);
545 	if (error)
546 		return (error);
547 
548 	tproc = pfind(uap->pid);
549 	if (tproc == NULL)
550 		return (ESRCH);
551 
552 	tcred = NULL;				/* Satisfy gcc. */
553 	error = p_cansee(td, tproc);
554 	if (error == 0)
555 		tcred = crhold(tproc->p_ucred);
556 	PROC_UNLOCK(tproc);
557 	if (error)
558 		return (error);
559 
560 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
561 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
562 	if (error) {
563 		free(elements, M_MACTEMP);
564 		crfree(tcred);
565 		return (error);
566 	}
567 
568 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
569 	error = mac_externalize_cred_label(tcred->cr_label, elements,
570 	    buffer, mac.m_buflen);
571 	if (error == 0)
572 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
573 
574 	free(buffer, M_MACTEMP);
575 	free(elements, M_MACTEMP);
576 	crfree(tcred);
577 	return (error);
578 }
579 
580 /*
581  * MPSAFE
582  */
583 int
584 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
585 {
586 	char *elements, *buffer;
587 	struct mac mac;
588 	int error;
589 
590 	error = copyin(uap->mac_p, &mac, sizeof(mac));
591 	if (error)
592 		return (error);
593 
594 	error = mac_check_structmac_consistent(&mac);
595 	if (error)
596 		return (error);
597 
598 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
599 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
600 	if (error) {
601 		free(elements, M_MACTEMP);
602 		return (error);
603 	}
604 
605 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
606 	error = mac_externalize_cred_label(td->td_ucred->cr_label,
607 	    elements, buffer, mac.m_buflen);
608 	if (error == 0)
609 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
610 
611 	free(buffer, M_MACTEMP);
612 	free(elements, M_MACTEMP);
613 	return (error);
614 }
615 
616 /*
617  * MPSAFE
618  */
619 int
620 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
621 {
622 	struct ucred *newcred, *oldcred;
623 	struct label *intlabel;
624 	struct proc *p;
625 	struct mac mac;
626 	char *buffer;
627 	int error;
628 
629 	error = copyin(uap->mac_p, &mac, sizeof(mac));
630 	if (error)
631 		return (error);
632 
633 	error = mac_check_structmac_consistent(&mac);
634 	if (error)
635 		return (error);
636 
637 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
638 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
639 	if (error) {
640 		free(buffer, M_MACTEMP);
641 		return (error);
642 	}
643 
644 	intlabel = mac_cred_label_alloc();
645 	error = mac_internalize_cred_label(intlabel, buffer);
646 	free(buffer, M_MACTEMP);
647 	if (error)
648 		goto out;
649 
650 	newcred = crget();
651 
652 	p = td->td_proc;
653 	PROC_LOCK(p);
654 	oldcred = p->p_ucred;
655 
656 	error = mac_check_cred_relabel(oldcred, intlabel);
657 	if (error) {
658 		PROC_UNLOCK(p);
659 		crfree(newcred);
660 		goto out;
661 	}
662 
663 	setsugid(p);
664 	crcopy(newcred, oldcred);
665 	mac_relabel_cred(newcred, intlabel);
666 	p->p_ucred = newcred;
667 
668 	/*
669 	 * Grab additional reference for use while revoking mmaps, prior
670 	 * to releasing the proc lock and sharing the cred.
671 	 */
672 	crhold(newcred);
673 	PROC_UNLOCK(p);
674 
675 	if (mac_enforce_vm) {
676 		mtx_lock(&Giant);
677 		mac_cred_mmapped_drop_perms(td, newcred);
678 		mtx_unlock(&Giant);
679 	}
680 
681 	crfree(newcred);	/* Free revocation reference. */
682 	crfree(oldcred);
683 
684 out:
685 	mac_cred_label_free(intlabel);
686 	return (error);
687 }
688 
689 /*
690  * MPSAFE
691  */
692 int
693 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
694 {
695 	char *elements, *buffer;
696 	struct label *intlabel;
697 	struct file *fp;
698 	struct mac mac;
699 	struct vnode *vp;
700 	struct pipe *pipe;
701 	short label_type;
702 	int error;
703 
704 	error = copyin(uap->mac_p, &mac, sizeof(mac));
705 	if (error)
706 		return (error);
707 
708 	error = mac_check_structmac_consistent(&mac);
709 	if (error)
710 		return (error);
711 
712 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
713 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
714 	if (error) {
715 		free(elements, M_MACTEMP);
716 		return (error);
717 	}
718 
719 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
720 	mtx_lock(&Giant);				/* VFS */
721 	error = fget(td, uap->fd, &fp);
722 	if (error)
723 		goto out;
724 
725 	label_type = fp->f_type;
726 	switch (fp->f_type) {
727 	case DTYPE_FIFO:
728 	case DTYPE_VNODE:
729 		vp = fp->f_vnode;
730 
731 		intlabel = mac_vnode_label_alloc();
732 
733 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
734 		mac_copy_vnode_label(vp->v_label, intlabel);
735 		VOP_UNLOCK(vp, 0, td);
736 
737 		break;
738 	case DTYPE_PIPE:
739 		pipe = fp->f_data;
740 
741 		intlabel = mac_pipe_label_alloc();
742 
743 		PIPE_LOCK(pipe);
744 		mac_copy_pipe_label(pipe->pipe_label, intlabel);
745 		PIPE_UNLOCK(pipe);
746 		break;
747 	default:
748 		error = EINVAL;
749 		fdrop(fp, td);
750 		goto out;
751 	}
752 	fdrop(fp, td);
753 
754 	switch (label_type) {
755 	case DTYPE_FIFO:
756 	case DTYPE_VNODE:
757 		if (error == 0)
758 			error = mac_externalize_vnode_label(intlabel,
759 			    elements, buffer, mac.m_buflen);
760 		mac_vnode_label_free(intlabel);
761 		break;
762 	case DTYPE_PIPE:
763 		error = mac_externalize_pipe_label(intlabel, elements,
764 		    buffer, mac.m_buflen);
765 		mac_pipe_label_free(intlabel);
766 		break;
767 	default:
768 		panic("__mac_get_fd: corrupted label_type");
769 	}
770 
771 	if (error == 0)
772 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
773 
774 out:
775 	mtx_unlock(&Giant);				/* VFS */
776 	free(buffer, M_MACTEMP);
777 	free(elements, M_MACTEMP);
778 
779 	return (error);
780 }
781 
782 /*
783  * MPSAFE
784  */
785 int
786 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
787 {
788 	char *elements, *buffer;
789 	struct nameidata nd;
790 	struct label *intlabel;
791 	struct mac mac;
792 	int error;
793 
794 	error = copyin(uap->mac_p, &mac, sizeof(mac));
795 	if (error)
796 		return (error);
797 
798 	error = mac_check_structmac_consistent(&mac);
799 	if (error)
800 		return (error);
801 
802 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
803 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
804 	if (error) {
805 		free(elements, M_MACTEMP);
806 		return (error);
807 	}
808 
809 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
810 	mtx_lock(&Giant);				/* VFS */
811 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
812 	    td);
813 	error = namei(&nd);
814 	if (error)
815 		goto out;
816 
817 	intlabel = mac_vnode_label_alloc();
818 	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
819 	error = mac_externalize_vnode_label(intlabel, elements, buffer,
820 	    mac.m_buflen);
821 
822 	NDFREE(&nd, 0);
823 	mac_vnode_label_free(intlabel);
824 
825 	if (error == 0)
826 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
827 
828 out:
829 	mtx_unlock(&Giant);				/* VFS */
830 
831 	free(buffer, M_MACTEMP);
832 	free(elements, M_MACTEMP);
833 
834 	return (error);
835 }
836 
837 /*
838  * MPSAFE
839  */
840 int
841 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
842 {
843 	char *elements, *buffer;
844 	struct nameidata nd;
845 	struct label *intlabel;
846 	struct mac mac;
847 	int error;
848 
849 	error = copyin(uap->mac_p, &mac, sizeof(mac));
850 	if (error)
851 		return (error);
852 
853 	error = mac_check_structmac_consistent(&mac);
854 	if (error)
855 		return (error);
856 
857 	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
858 	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
859 	if (error) {
860 		free(elements, M_MACTEMP);
861 		return (error);
862 	}
863 
864 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
865 	mtx_lock(&Giant);				/* VFS */
866 	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
867 	    td);
868 	error = namei(&nd);
869 	if (error)
870 		goto out;
871 
872 	intlabel = mac_vnode_label_alloc();
873 	mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
874 	error = mac_externalize_vnode_label(intlabel, elements, buffer,
875 	    mac.m_buflen);
876 	NDFREE(&nd, 0);
877 	mac_vnode_label_free(intlabel);
878 
879 	if (error == 0)
880 		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
881 
882 out:
883 	mtx_unlock(&Giant);				/* VFS */
884 
885 	free(buffer, M_MACTEMP);
886 	free(elements, M_MACTEMP);
887 
888 	return (error);
889 }
890 
891 /*
892  * MPSAFE
893  */
894 int
895 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
896 {
897 	struct label *intlabel;
898 	struct pipe *pipe;
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 	mtx_lock(&Giant);				/* VFS */
922 
923 	error = fget(td, uap->fd, &fp);
924 	if (error)
925 		goto out;
926 
927 	switch (fp->f_type) {
928 	case DTYPE_FIFO:
929 	case DTYPE_VNODE:
930 		intlabel = mac_vnode_label_alloc();
931 		error = mac_internalize_vnode_label(intlabel, buffer);
932 		if (error) {
933 			mac_vnode_label_free(intlabel);
934 			break;
935 		}
936 
937 		vp = fp->f_vnode;
938 		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
939 		if (error != 0) {
940 			mac_vnode_label_free(intlabel);
941 			break;
942 		}
943 
944 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
945 		error = vn_setlabel(vp, intlabel, td->td_ucred);
946 		VOP_UNLOCK(vp, 0, td);
947 		vn_finished_write(mp);
948 
949 		mac_vnode_label_free(intlabel);
950 		break;
951 
952 	case DTYPE_PIPE:
953 		intlabel = mac_pipe_label_alloc();
954 		error = mac_internalize_pipe_label(intlabel, buffer);
955 		if (error == 0) {
956 			pipe = fp->f_data;
957 			PIPE_LOCK(pipe);
958 			error = mac_pipe_label_set(td->td_ucred, pipe,
959 			    intlabel);
960 			PIPE_UNLOCK(pipe);
961 		}
962 
963 		mac_pipe_label_free(intlabel);
964 		break;
965 
966 	default:
967 		error = EINVAL;
968 	}
969 
970 	fdrop(fp, td);
971 out:
972 	mtx_unlock(&Giant);				/* VFS */
973 
974 	free(buffer, M_MACTEMP);
975 
976 	return (error);
977 }
978 
979 /*
980  * MPSAFE
981  */
982 int
983 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
984 {
985 	struct label *intlabel;
986 	struct nameidata nd;
987 	struct mount *mp;
988 	struct mac mac;
989 	char *buffer;
990 	int error;
991 
992 	error = copyin(uap->mac_p, &mac, sizeof(mac));
993 	if (error)
994 		return (error);
995 
996 	error = mac_check_structmac_consistent(&mac);
997 	if (error)
998 		return (error);
999 
1000 	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1001 	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1002 	if (error) {
1003 		free(buffer, M_MACTEMP);
1004 		return (error);
1005 	}
1006 
1007 	intlabel = mac_vnode_label_alloc();
1008 	error = mac_internalize_vnode_label(intlabel, buffer);
1009 	free(buffer, M_MACTEMP);
1010 	if (error)
1011 		goto out;
1012 
1013 	mtx_lock(&Giant);				/* VFS */
1014 
1015 	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
1016 	    td);
1017 	error = namei(&nd);
1018 	if (error == 0) {
1019 		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1020 		if (error == 0)
1021 			error = vn_setlabel(nd.ni_vp, intlabel,
1022 			    td->td_ucred);
1023 		vn_finished_write(mp);
1024 	}
1025 
1026 	NDFREE(&nd, 0);
1027 	mtx_unlock(&Giant);				/* VFS */
1028 out:
1029 	mac_vnode_label_free(intlabel);
1030 	return (error);
1031 }
1032 
1033 /*
1034  * MPSAFE
1035  */
1036 int
1037 __mac_set_link(struct thread *td, struct __mac_set_link_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 | NOFOLLOW, 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_syscall(struct thread *td, struct mac_syscall_args *uap)
1092 {
1093 	struct mac_policy_conf *mpc;
1094 	char target[MAC_MAX_POLICY_NAME];
1095 	int entrycount, error;
1096 
1097 	error = copyinstr(uap->policy, target, sizeof(target), NULL);
1098 	if (error)
1099 		return (error);
1100 
1101 	error = ENOSYS;
1102 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
1103 		if (strcmp(mpc->mpc_name, target) == 0 &&
1104 		    mpc->mpc_ops->mpo_syscall != NULL) {
1105 			error = mpc->mpc_ops->mpo_syscall(td,
1106 			    uap->call, uap->arg);
1107 			goto out;
1108 		}
1109 	}
1110 
1111 	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
1112 		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
1113 			if (strcmp(mpc->mpc_name, target) == 0 &&
1114 			    mpc->mpc_ops->mpo_syscall != NULL) {
1115 				error = mpc->mpc_ops->mpo_syscall(td,
1116 				    uap->call, uap->arg);
1117 				break;
1118 			}
1119 		}
1120 		mac_policy_list_unbusy();
1121 	}
1122 out:
1123 	return (error);
1124 }
1125 
1126 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
1127 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
1128 
1129 #else /* !MAC */
1130 
1131 int
1132 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1133 {
1134 
1135 	return (ENOSYS);
1136 }
1137 
1138 int
1139 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
1140 {
1141 
1142 	return (ENOSYS);
1143 }
1144 
1145 int
1146 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
1147 {
1148 
1149 	return (ENOSYS);
1150 }
1151 
1152 int
1153 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
1154 {
1155 
1156 	return (ENOSYS);
1157 }
1158 
1159 int
1160 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
1161 {
1162 
1163 	return (ENOSYS);
1164 }
1165 
1166 int
1167 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1168 {
1169 
1170 	return (ENOSYS);
1171 }
1172 
1173 int
1174 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
1175 {
1176 
1177 	return (ENOSYS);
1178 }
1179 
1180 int
1181 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1182 {
1183 
1184 	return (ENOSYS);
1185 }
1186 
1187 int
1188 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1189 {
1190 
1191 	return (ENOSYS);
1192 }
1193 
1194 int
1195 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1196 {
1197 
1198 	return (ENOSYS);
1199 }
1200 
1201 #endif
1202