Deleted Added
full compact
mac_framework.c (125293) mac_framework.c (126097)
1/*-
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
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>
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: head/sys/security/mac/mac_framework.c 125293 2004-02-01 05:56:51Z rwatson $");
45__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 126097 2004-02-22 00:33:12Z rwatson $");
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 */
99MODULE_VERSION(kernel_mac_support, 1);
100
101SYSCTL_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
108static unsigned int mac_max_slots = MAC_MAX_SLOTS;
109static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
110SYSCTL_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 */
118int 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
132int mac_labelmbufs = 0;
133#endif
134
135#ifdef MAC_DEBUG
136SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
137 "TrustedBSD MAC debug info");
138SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
139 "TrustedBSD MAC object counters");
140
141static unsigned int nmactemp;
142SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
143 &nmactemp, 0, "number of temporary labels in use");
144#endif
145
146static int mac_policy_register(struct mac_policy_conf *mpc);
147static int mac_policy_unregister(struct mac_policy_conf *mpc);
148
149MALLOC_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 */
169static struct mtx mac_policy_mtx;
170static struct cv mac_policy_cv;
171static int mac_policy_count;
172struct mac_policy_list_head mac_policy_list;
173struct 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 */
184void
185mac_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
195void
196mac_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
204void
205mac_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
214void
215mac_policy_list_busy(void)
216{
217
218 mtx_lock(&mac_policy_mtx);
219 mac_policy_count++;
220 mtx_unlock(&mac_policy_mtx);
221}
222
223int
224mac_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
238void
239mac_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 */
253static void
254mac_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 */
270static void
271mac_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 */
283static void
284mac_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 */
308int
309mac_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
343static int
344mac_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
413out:
414 mac_policy_release_exclusive();
415 return (error);
416}
417
418static int
419mac_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 */
468int
469mac_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
501void
502mac_init_label(struct label *label)
503{
504
505 bzero(label, sizeof(*label));
506 label->l_flags = MAC_FLAG_INITIALIZED;
507}
508
509void
510mac_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
520int
521mac_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 */
534int
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 */
586int
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 */
622int
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
687out:
688 mac_cred_label_free(intlabel);
689 return (error);
690}
691
692/*
693 * MPSAFE
694 */
695int
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
775out:
776 free(buffer, M_MACTEMP);
777 free(elements, M_MACTEMP);
778 return (error);
779}
780
781/*
782 * MPSAFE
783 */
784int
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
827out:
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 */
839int
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
881out:
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 */
893int
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);
982out:
983 free(buffer, M_MACTEMP);
984 return (error);
985}
986
987/*
988 * MPSAFE
989 */
990int
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 */
1036out:
1037 mac_vnode_label_free(intlabel);
1038 return (error);
1039}
1040
1041/*
1042 * MPSAFE
1043 */
1044int
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 */
1090out:
1091 mac_vnode_label_free(intlabel);
1092 return (error);
1093}
1094
1095/*
1096 * MPSAFE
1097 */
1098int
1099mac_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 }
1130out:
1131 return (error);
1132}
1133
1134SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
1135SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
1136
1137#else /* !MAC */
1138
1139int
1140__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1141{
1142
1143 return (ENOSYS);
1144}
1145
1146int
1147__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
1148{
1149
1150 return (ENOSYS);
1151}
1152
1153int
1154__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
1155{
1156
1157 return (ENOSYS);
1158}
1159
1160int
1161__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
1162{
1163
1164 return (ENOSYS);
1165}
1166
1167int
1168__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
1169{
1170
1171 return (ENOSYS);
1172}
1173
1174int
1175__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1176{
1177
1178 return (ENOSYS);
1179}
1180
1181int
1182__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
1183{
1184
1185 return (ENOSYS);
1186}
1187
1188int
1189__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1190{
1191
1192 return (ENOSYS);
1193}
1194
1195int
1196__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1197{
1198
1199 return (ENOSYS);
1200}
1201
1202int
1203mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1204{
1205
1206 return (ENOSYS);
1207}
1208
1209#endif
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 */
99MODULE_VERSION(kernel_mac_support, 1);
100
101SYSCTL_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
108static unsigned int mac_max_slots = MAC_MAX_SLOTS;
109static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
110SYSCTL_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 */
118int 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
132int mac_labelmbufs = 0;
133#endif
134
135#ifdef MAC_DEBUG
136SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
137 "TrustedBSD MAC debug info");
138SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
139 "TrustedBSD MAC object counters");
140
141static unsigned int nmactemp;
142SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
143 &nmactemp, 0, "number of temporary labels in use");
144#endif
145
146static int mac_policy_register(struct mac_policy_conf *mpc);
147static int mac_policy_unregister(struct mac_policy_conf *mpc);
148
149MALLOC_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 */
169static struct mtx mac_policy_mtx;
170static struct cv mac_policy_cv;
171static int mac_policy_count;
172struct mac_policy_list_head mac_policy_list;
173struct 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 */
184void
185mac_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
195void
196mac_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
204void
205mac_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
214void
215mac_policy_list_busy(void)
216{
217
218 mtx_lock(&mac_policy_mtx);
219 mac_policy_count++;
220 mtx_unlock(&mac_policy_mtx);
221}
222
223int
224mac_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
238void
239mac_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 */
253static void
254mac_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 */
270static void
271mac_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 */
283static void
284mac_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 */
308int
309mac_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
343static int
344mac_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
413out:
414 mac_policy_release_exclusive();
415 return (error);
416}
417
418static int
419mac_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 */
468int
469mac_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
501void
502mac_init_label(struct label *label)
503{
504
505 bzero(label, sizeof(*label));
506 label->l_flags = MAC_FLAG_INITIALIZED;
507}
508
509void
510mac_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
520int
521mac_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 */
534int
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 */
586int
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 */
622int
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
687out:
688 mac_cred_label_free(intlabel);
689 return (error);
690}
691
692/*
693 * MPSAFE
694 */
695int
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
775out:
776 free(buffer, M_MACTEMP);
777 free(elements, M_MACTEMP);
778 return (error);
779}
780
781/*
782 * MPSAFE
783 */
784int
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
827out:
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 */
839int
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
881out:
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 */
893int
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);
982out:
983 free(buffer, M_MACTEMP);
984 return (error);
985}
986
987/*
988 * MPSAFE
989 */
990int
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 */
1036out:
1037 mac_vnode_label_free(intlabel);
1038 return (error);
1039}
1040
1041/*
1042 * MPSAFE
1043 */
1044int
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 */
1090out:
1091 mac_vnode_label_free(intlabel);
1092 return (error);
1093}
1094
1095/*
1096 * MPSAFE
1097 */
1098int
1099mac_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 }
1130out:
1131 return (error);
1132}
1133
1134SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
1135SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
1136
1137#else /* !MAC */
1138
1139int
1140__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1141{
1142
1143 return (ENOSYS);
1144}
1145
1146int
1147__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
1148{
1149
1150 return (ENOSYS);
1151}
1152
1153int
1154__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
1155{
1156
1157 return (ENOSYS);
1158}
1159
1160int
1161__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
1162{
1163
1164 return (ENOSYS);
1165}
1166
1167int
1168__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
1169{
1170
1171 return (ENOSYS);
1172}
1173
1174int
1175__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1176{
1177
1178 return (ENOSYS);
1179}
1180
1181int
1182__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
1183{
1184
1185 return (ENOSYS);
1186}
1187
1188int
1189__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1190{
1191
1192 return (ENOSYS);
1193}
1194
1195int
1196__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1197{
1198
1199 return (ENOSYS);
1200}
1201
1202int
1203mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1204{
1205
1206 return (ENOSYS);
1207}
1208
1209#endif