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