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