2 * Copyright (c) 2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
30 * Copyright (c) 2001 Ilmar S. Habibulin
31 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc.
32 * Copyright (c) 2005-2006 SPARTA, Inc.
34 * This software was developed by Robert Watson and Ilmar Habibulin for the
37 * This software was developed for the FreeBSD Project in part by Network
38 * Associates Laboratories, the Security Research Division of Network
39 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
40 * as part of the DARPA CHATS research program.
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * Framework for extensible kernel access control. This file contains
67 * Kernel and userland interface to the framework, policy registration
68 * and composition. Per-object interfaces, controls, and labeling may be
69 * found in src/sys/mac/. Sample policies may be found in src/sys/mac*.
74 #include <security/mac_internal.h>
75 #include <security/mac_mach_internal.h>
76 #include <sys/param.h>
77 #include <sys/vnode.h>
78 #include <sys/vnode_internal.h>
79 #include <sys/vfs_context.h>
80 #include <sys/namei.h>
81 #include <bsd/bsm/audit.h>
82 #include <bsd/bsm/audit_kernel.h>
84 #include <sys/file_internal.h>
85 #include <sys/filedesc.h>
87 #include <sys/proc_internal.h>
88 #include <sys/kauth.h>
89 #include <sys/sysproto.h>
91 #include <mach/vm_types.h>
92 #include <mach/vm_prot.h>
94 #include <kern/zalloc.h>
95 #include <kern/sched_prim.h>
96 #include <osfmk/kern/task.h>
97 #include <osfmk/kern/kalloc.h>
98 #include <libsa/libsa/kext.h>
101 #include <security/mac.h>
102 #include <security/mac_policy.h>
103 #include <security/mac_framework.h>
104 #include <security/mac_internal.h>
105 #include <security/mac_mach_internal.h>
109 * define MB_DEBUG to display run-time debugging information
114 #define DPRINTF(x) printf x
121 SYSCTL_NODE(, OID_AUTO
, security
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0,
122 "Security Controls");
123 SYSCTL_NODE(_security
, OID_AUTO
, mac
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0,
124 "TrustedBSD MAC policy controls");
129 * Declare that the kernel provides MAC support, version 1. This permits
130 * modules to refuse to be loaded if the necessary support isn't present,
131 * even if it's pre-boot.
134 MODULE_VERSION(kernel_mac_support
, 1);
137 #if MAC_MAX_SLOTS > 32
138 #error "MAC_MAX_SLOTS too large"
141 static unsigned int mac_max_slots
= MAC_MAX_SLOTS
;
142 static unsigned int mac_slot_offsets_free
= (1 << MAC_MAX_SLOTS
) - 1;
143 SYSCTL_UINT(_security_mac
, OID_AUTO
, max_slots
, CTLFLAG_RD
,
144 &mac_max_slots
, 0, "");
147 * Has the kernel started generating labeled objects yet? All read/write
148 * access to this variable is serialized during the boot process. Following
149 * the end of serialization, we don't update this flag; no locking.
154 * Flag to indicate whether or not we should allocate label storage for
155 * new mbufs. Since most dynamic policies we currently work with don't
156 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
157 * unless specifically notified of interest. One result of this is
158 * that if a dynamically loaded policy requests mbuf labels, it must
159 * be able to deal with a NULL label being returned on any mbufs that
160 * were already in flight when the policy was loaded. Since the policy
161 * already has to deal with uninitialized labels, this probably won't
162 * be a problem. Note: currently no locking. Will this be a problem?
164 #if !defined(CONFIG_MACF_ALWAYS_LABEL_MBUF) && 0
165 static int mac_labelmbufs
= 0;
168 unsigned int mac_mmap_revocation
= 0;
169 SYSCTL_UINT(_security_mac
, OID_AUTO
, mmap_revocation
, CTLFLAG_RW
,
170 &mac_mmap_revocation
, 0, "Revoke mmap access to files on subject "
173 unsigned int mac_mmap_revocation_via_cow
= 0;
174 SYSCTL_UINT(_security_mac
, OID_AUTO
, mmap_revocation_via_cow
, CTLFLAG_RW
,
175 &mac_mmap_revocation_via_cow
, 0, "Revoke mmap access to files via "
176 "copy-on-write semantics, or by removing all write access");
178 unsigned int mac_device_enforce
= 1;
179 SYSCTL_UINT(_security_mac
, OID_AUTO
, device_enforce
, CTLFLAG_RW
,
180 &mac_device_enforce
, 0, "Enforce MAC policy on device operations");
182 unsigned int mac_file_enforce
= 0;
183 SYSCTL_UINT(_security_mac
, OID_AUTO
, file_enforce
, CTLFLAG_RW
,
184 &mac_file_enforce
, 0, "Enforce MAC policy on file operations");
186 unsigned int mac_iokit_enforce
= 0;
187 SYSCTL_UINT(_security_mac
, OID_AUTO
, iokit_enforce
, CTLFLAG_RW
,
188 &mac_file_enforce
, 0, "Enforce MAC policy on IOKit operations");
190 unsigned int mac_pipe_enforce
= 1;
191 SYSCTL_UINT(_security_mac
, OID_AUTO
, pipe_enforce
, CTLFLAG_RW
,
192 &mac_pipe_enforce
, 0, "Enforce MAC policy on pipe operations");
194 unsigned int mac_posixsem_enforce
= 1;
195 SYSCTL_UINT(_security_mac
, OID_AUTO
, posixsem_enforce
, CTLFLAG_RW
,
196 &mac_posixsem_enforce
, 0, "Enforce MAC policy on POSIX semaphores");
198 unsigned int mac_posixshm_enforce
= 1;
199 SYSCTL_UINT(_security_mac
, OID_AUTO
, posixshm_enforce
, CTLFLAG_RW
,
200 &mac_posixshm_enforce
, 0, "Enforce MAC policy on Posix Shared Memory");
202 unsigned int mac_proc_enforce
= 1;
203 SYSCTL_UINT(_security_mac
, OID_AUTO
, proc_enforce
, CTLFLAG_RW
,
204 &mac_proc_enforce
, 0, "Enforce MAC policy on process operations");
206 unsigned int mac_socket_enforce
= 1;
207 SYSCTL_UINT(_security_mac
, OID_AUTO
, socket_enforce
, CTLFLAG_RW
,
208 &mac_socket_enforce
, 0, "Enforce MAC policy on socket operations");
210 unsigned int mac_system_enforce
= 1;
211 SYSCTL_UINT(_security_mac
, OID_AUTO
, system_enforce
, CTLFLAG_RW
,
212 &mac_system_enforce
, 0, "Enforce MAC policy on system-wide interfaces");
214 unsigned int mac_sysvmsg_enforce
= 1;
215 SYSCTL_UINT(_security_mac
, OID_AUTO
, sysvmsg_enforce
, CTLFLAG_RW
,
216 &mac_sysvmsg_enforce
, 0, "Enforce MAC policy on System V IPC message queues");
218 unsigned int mac_sysvsem_enforce
= 1;
219 SYSCTL_UINT(_security_mac
, OID_AUTO
, sysvsem_enforce
, CTLFLAG_RW
,
220 &mac_sysvsem_enforce
, 0, "Enforce MAC policy on System V IPC semaphores");
222 unsigned int mac_sysvshm_enforce
= 1;
223 SYSCTL_INT(_security_mac
, OID_AUTO
, sysvshm_enforce
, CTLFLAG_RW
,
224 &mac_sysvshm_enforce
, 0, "Enforce MAC policy on System V Shared Memory");
226 unsigned int mac_vm_enforce
= 1;
227 SYSCTL_INT(_security_mac
, OID_AUTO
, vm_enforce
, CTLFLAG_RW
,
228 &mac_vm_enforce
, 0, "Enforce MAC policy on VM operations");
230 unsigned int mac_vnode_enforce
= 1;
231 SYSCTL_UINT(_security_mac
, OID_AUTO
, vnode_enforce
, CTLFLAG_RW
,
232 &mac_vnode_enforce
, 0, "Enforce MAC policy on vnode operations");
236 unsigned int mac_port_enforce
= 0;
237 SYSCTL_UINT(_security_mac
, OID_AUTO
, port_enforce
, CTLFLAG_RW
,
238 &mac_port_enforce
, 0, "Enforce MAC policy on Mach port operations");
240 unsigned int mac_task_enforce
= 0;
241 SYSCTL_UINT(_security_mac
, OID_AUTO
, task_enforce
, CTLFLAG_RW
,
242 &mac_task_enforce
, 0, "Enforce MAC policy on Mach task operations");
246 unsigned int mac_label_mbufs
= 1;
247 SYSCTL_UINT(_security_mac
, OID_AUTO
, label_mbufs
, CTLFLAG_RW
,
248 &mac_label_mbufs
, 0, "Label all MBUFs");
253 * mac_audit_data_zone is the zone used for data pushed into the audit
254 * record by policies. Using a zone simplifies memory management of this
255 * data, and allows tracking of the amount of data in flight.
257 extern zone_t mac_audit_data_zone
;
261 * mac_policy_list holds the list of policy modules. Modules with a
262 * handle lower than staticmax are considered "static" and cannot be
263 * unloaded. Such policies can be invoked without holding the busy count.
265 * Modules with a handle at or above the staticmax high water mark
266 * are considered to be "dynamic" policies. A busy count is maintained
267 * for the list, stored in mac_policy_busy. The busy count is protected
268 * by mac_policy_mtx; the list may be modified only while the busy
269 * count is 0, requiring that the lock be held to prevent new references
270 * to the list from being acquired. For almost all operations,
271 * incrementing the busy count is sufficient to guarantee consistency,
272 * as the list cannot be modified while the busy count is elevated.
273 * For a few special operations involving a change to the list of
274 * active policies, the mtx itself must be held.
276 static lck_mtx_t
*mac_policy_mtx
;
279 * Policy list array allocation chunk size. Trying to set this so that we
280 * allocate a page at a time.
282 #define MAC_POLICY_LIST_CHUNKSIZE 512
284 static int mac_policy_busy
;
286 mac_policy_list_t mac_policy_list
;
289 * mac_label_element_list holds the master list of label namespaces for
290 * all the policies. When a policy is loaded, each of it's label namespace
291 * elements is added to the master list if not already present. When a
292 * policy is unloaded, the namespace elements are removed if no other
293 * policy is interested in that namespace element.
295 struct mac_label_element_list_t mac_label_element_list
;
296 struct mac_label_element_list_t mac_static_label_element_list
;
299 * Journal of label operations that occur before policies are loaded.
301 struct mac_label_journal_list_t mac_label_journal_list
;
304 mac_label_journal_add (struct label
*l
, int type
)
306 struct mac_label_journal
*mlj
;
308 if (mac_label_journal_find(l
))
311 MALLOC(mlj
, struct mac_label_journal
*,
312 sizeof(struct mac_label_journal
), M_MACTEMP
, M_WAITOK
);
315 TAILQ_INSERT_TAIL(&mac_label_journal_list
, mlj
, link
);
321 mac_label_journal_remove (struct label
*l
)
323 struct mac_label_journal
*mlj
;
325 mlj
= mac_label_journal_find(l
);
329 TAILQ_REMOVE(&mac_label_journal_list
, mlj
, link
);
330 FREE(mlj
, M_MACTEMP
);
334 struct mac_label_journal
*
335 mac_label_journal_find (struct label
*l
)
337 struct mac_label_journal
*mlj
;
339 TAILQ_FOREACH(mlj
, &mac_label_journal_list
, link
) {
348 mac_label_journal (struct label
*l
, int op
, ...)
350 struct mac_label_journal
*mlj
;
353 mlj
= mac_label_journal_find(l
);
355 printf("%s(): Label not in list!\n", __func__
);
359 if (op
== MLJ_PORT_OP_UPDATE
) {
361 mlj
->kotype
= va_arg(ap
, int);
370 * The assumption during replay is that the system is totally
371 * serialized and no additional tasks/ports will be created.
374 mac_label_journal_replay (void)
376 struct mac_label_journal
*mlj
;
378 TAILQ_FOREACH(mlj
, &mac_label_journal_list
, link
) {
381 if (mlj
->ops
& MLJ_PORT_OP_INIT
)
382 MAC_PERFORM(port_label_init
, mlj
->l
);
383 if (mlj
->ops
& MLJ_PORT_OP_CREATE_K
)
384 MAC_PERFORM(port_label_associate_kernel
, mlj
->l
, 0);
385 if (mlj
->ops
& MLJ_PORT_OP_UPDATE
)
386 MAC_PERFORM(port_label_update_kobject
, mlj
->l
,
390 if (mlj
->ops
& MLJ_TASK_OP_INIT
)
391 MAC_PERFORM(task_label_init
, mlj
->l
);
393 /* Not enough context to replay. */
394 if (mlj
->ops
& MLJ_TASK_OP_CREATE_K
)
404 while (!TAILQ_EMPTY(&mac_label_journal_list
)) {
405 mlj
= TAILQ_FIRST(&mac_label_journal_list
);
406 TAILQ_REMOVE(&mac_label_journal_list
, mlj
, link
);
407 FREE(mlj
, M_MACTEMP
);
413 mac_policy_grab_exclusive(void)
415 lck_mtx_lock(mac_policy_mtx
);
416 while (mac_policy_busy
!= 0) {
417 lck_mtx_sleep(mac_policy_mtx
, LCK_SLEEP_UNLOCK
,
418 (event_t
)&mac_policy_busy
, THREAD_UNINT
);
419 lck_mtx_lock(mac_policy_mtx
);
424 mac_policy_assert_exclusive(void)
426 lck_mtx_assert(mac_policy_mtx
, LCK_MTX_ASSERT_OWNED
);
427 KASSERT(mac_policy_busy
== 0,
428 ("mac_policy_assert_exclusive(): not exclusive"));
432 mac_policy_release_exclusive(void)
435 KASSERT(mac_policy_busy
== 0,
436 ("mac_policy_release_exclusive(): not exclusive"));
437 lck_mtx_unlock(mac_policy_mtx
);
438 thread_wakeup((event_t
) &mac_policy_busy
);
442 mac_policy_list_busy(void)
444 lck_mtx_lock(mac_policy_mtx
);
446 lck_mtx_unlock(mac_policy_mtx
);
450 mac_policy_list_conditional_busy(void)
454 if (mac_policy_list
.numloaded
<= mac_policy_list
.staticmax
)
457 lck_mtx_lock(mac_policy_mtx
);
458 if (mac_policy_list
.numloaded
> mac_policy_list
.staticmax
) {
463 lck_mtx_unlock(mac_policy_mtx
);
468 mac_policy_list_unbusy(void)
470 lck_mtx_lock(mac_policy_mtx
);
472 KASSERT(mac_policy_busy
>= 0, ("MAC_POLICY_LIST_LOCK"));
473 if (mac_policy_busy
== 0)
474 thread_wakeup(&mac_policy_busy
);
475 lck_mtx_unlock(mac_policy_mtx
);
479 * Early pre-malloc MAC initialization, including appropriate SMP locks.
482 mac_policy_init(void)
484 lck_grp_attr_t
*mac_lck_grp_attr
;
485 lck_attr_t
*mac_lck_attr
;
486 lck_grp_t
*mac_lck_grp
;
488 mac_policy_list
.numloaded
= 0;
489 mac_policy_list
.max
= MAC_POLICY_LIST_CHUNKSIZE
;
490 mac_policy_list
.maxindex
= 0;
491 mac_policy_list
.staticmax
= 0;
492 mac_policy_list
.freehint
= 0;
493 mac_policy_list
.chunks
= 1;
495 mac_policy_list
.entries
= kalloc(sizeof(struct mac_policy_list_element
) * MAC_POLICY_LIST_CHUNKSIZE
);
496 bzero(mac_policy_list
.entries
, sizeof(struct mac_policy_list_element
) * MAC_POLICY_LIST_CHUNKSIZE
);
498 LIST_INIT(&mac_label_element_list
);
499 LIST_INIT(&mac_static_label_element_list
);
500 TAILQ_INIT(&mac_label_journal_list
);
502 mac_lck_grp_attr
= lck_grp_attr_alloc_init();
503 lck_grp_attr_setstat(mac_lck_grp_attr
);
504 mac_lck_grp
= lck_grp_alloc_init("MAC lock", mac_lck_grp_attr
);
505 mac_lck_attr
= lck_attr_alloc_init();
506 lck_attr_setdefault(mac_lck_attr
);
507 mac_policy_mtx
= lck_mtx_alloc_init(mac_lck_grp
, mac_lck_attr
);
508 lck_attr_free(mac_lck_attr
);
509 lck_grp_attr_free(mac_lck_grp_attr
);
510 lck_grp_free(mac_lck_grp
);
512 mac_labelzone_init();
516 * Init after early Mach startup, but before BSD
519 mac_policy_initmach(void)
523 * For the purposes of modules that want to know if they were
524 * loaded "early", set the mac_late flag once we've processed
525 * modules either linked into the kernel, or loaded before the
529 load_security_extensions();
532 mac_label_journal_replay();
540 mac_policy_initbsd(void)
542 struct mac_policy_conf
*mpc
;
546 mac_audit_data_zone
= zinit(MAC_AUDIT_DATA_LIMIT
,
547 AQ_HIWATER
* MAC_AUDIT_DATA_LIMIT
,
548 8192, "mac_audit_data_zone");
551 printf("MAC Framework successfully initialized\n");
553 /* Call bsd init functions of already loaded policies */
556 * Using the exclusive lock means no other framework entry
557 * points can proceed while initializations are running.
558 * This may not be necessary.
560 mac_policy_grab_exclusive();
562 for (i
= 0; i
<= mac_policy_list
.maxindex
; i
++) {
563 mpc
= mac_get_mpc(i
);
564 if ((mpc
!= NULL
) && (mpc
->mpc_ops
->mpo_policy_initbsd
!= NULL
))
565 (*(mpc
->mpc_ops
->mpo_policy_initbsd
))(mpc
);
568 mac_policy_release_exclusive();
572 * After a policy has been loaded, add the label namespaces managed by the
573 * policy to either the static or non-static label namespace list.
574 * A namespace is added to the the list only if it is not already on one of
578 mac_policy_addto_labellist(mac_policy_handle_t handle
, int static_entry
)
580 struct mac_label_listener
**new_mlls
;
581 struct mac_label_element
*mle
, **new_mles
;
582 struct mac_label_element_list_t
*list
;
583 struct mac_policy_conf
*mpc
;
584 const char *name
, *name2
;
585 u_int idx
, mle_free
, mll_free
;
587 mpc
= mac_get_mpc(handle
);
589 if (mpc
->mpc_labelnames
== NULL
)
592 if (mpc
->mpc_labelname_count
== 0)
596 list
= &mac_static_label_element_list
;
598 list
= &mac_label_element_list
;
601 * Before we grab the policy list lock, allocate enough memory
602 * to contain the potential new elements so we don't have to
603 * give up the lock, or allocate with the lock held.
605 MALLOC(new_mles
, struct mac_label_element
**,
606 sizeof(struct mac_label_element
*) *
607 mpc
->mpc_labelname_count
, M_MACTEMP
, M_WAITOK
| M_ZERO
);
608 for (idx
= 0; idx
< mpc
->mpc_labelname_count
; idx
++)
609 MALLOC(new_mles
[idx
], struct mac_label_element
*,
610 sizeof(struct mac_label_element
),
611 M_MACTEMP
, M_WAITOK
);
613 MALLOC(new_mlls
, struct mac_label_listener
**,
614 sizeof(struct mac_label_listener
*) *
615 mpc
->mpc_labelname_count
, M_MACTEMP
, M_WAITOK
);
616 for (idx
= 0; idx
< mpc
->mpc_labelname_count
; idx
++)
617 MALLOC(new_mlls
[idx
], struct mac_label_listener
*,
618 sizeof(struct mac_label_listener
), M_MACTEMP
, M_WAITOK
);
622 mac_policy_grab_exclusive();
623 for (idx
= 0; idx
< mpc
->mpc_labelname_count
; idx
++) {
625 if (*(name
= mpc
->mpc_labelnames
[idx
]) == '?')
628 * Check both label element lists and add to the
629 * appropriate list only if not already on a list.
631 LIST_FOREACH(mle
, &mac_static_label_element_list
, mle_list
) {
632 if (*(name2
= mle
->mle_name
) == '?')
634 if (strcmp(name
, name2
) == 0)
638 LIST_FOREACH(mle
, &mac_label_element_list
, mle_list
) {
639 if (*(name2
= mle
->mle_name
) == '?')
641 if (strcmp(name
, name2
) == 0)
646 mle
= new_mles
[mle_free
];
647 strlcpy(mle
->mle_name
, mpc
->mpc_labelnames
[idx
],
648 MAC_MAX_LABEL_ELEMENT_NAME
);
649 LIST_INIT(&mle
->mle_listeners
);
650 LIST_INSERT_HEAD(list
, mle
, mle_list
);
653 /* Add policy handler as a listener. */
654 new_mlls
[mll_free
]->mll_handle
= handle
;
655 LIST_INSERT_HEAD(&mle
->mle_listeners
, new_mlls
[mll_free
],
660 mac_policy_release_exclusive();
662 /* Free up any unused label elements and listeners */
663 for (idx
= mle_free
; idx
< mpc
->mpc_labelname_count
; idx
++)
664 FREE(new_mles
[idx
], M_MACTEMP
);
665 FREE(new_mles
, M_MACTEMP
);
666 for (idx
= mll_free
; idx
< mpc
->mpc_labelname_count
; idx
++)
667 FREE(new_mlls
[idx
], M_MACTEMP
);
668 FREE(new_mlls
, M_MACTEMP
);
672 * After a policy has been unloaded, remove the label namespaces that the
673 * the policy manages from the non-static list of namespaces.
674 * The removal only takes place when no other policy is interested in the
677 * Must be called with the policy exclusive lock held.
680 mac_policy_removefrom_labellist(mac_policy_handle_t handle
)
682 struct mac_label_listener
*mll
;
683 struct mac_label_element
*mle
;
684 struct mac_policy_conf
*mpc
;
686 mpc
= mac_get_mpc(handle
);
688 if (mpc
->mpc_labelnames
== NULL
)
691 if (mpc
->mpc_labelname_count
== 0)
695 * Unregister policy as being interested in any label
696 * namespaces. If no other policy is listening, remove
697 * that label element from the list. Note that we only
698 * have to worry about the non-static list.
700 LIST_FOREACH(mle
, &mac_label_element_list
, mle_list
) {
701 LIST_FOREACH(mll
, &mle
->mle_listeners
, mll_list
) {
702 if (mll
->mll_handle
== handle
) {
703 LIST_REMOVE(mll
, mll_list
);
704 FREE(mll
, M_MACTEMP
);
705 if (LIST_EMPTY(&mle
->mle_listeners
)) {
706 LIST_REMOVE(mle
, mle_list
);
707 FREE(mle
, M_MACTEMP
);
716 * After the policy list has changed, walk the list to update any global
720 mac_policy_updateflags(void)
722 #if !defined(CONFIG_MACF_ALWAYS_LABEL_MBUF) && 0 /* port to new list style */
724 struct mac_policy_conf
*tmpc
;
727 mac_policy_assert_exclusive();
731 /* XXX - convert to new list structure */
732 LIST_FOREACH(tmpc
, &mac_static_policy_list
, mpc_list
) {
733 if (tmpc
->mpc_loadtime_flags
& MPC_LOADTIME_FLAG_LABELMBUFS
)
736 LIST_FOREACH(tmpc
, &mac_policy_list
, mpc_list
) {
737 if (tmpc
->mpc_loadtime_flags
& MPC_LOADTIME_FLAG_LABELMBUFS
)
740 mac_labelmbufs
= (labelmbufs
!= 0);
745 mac_policy_fixup_mmd_list(struct mac_module_data
*new)
747 struct mac_module_data
*old
;
748 struct mac_module_data_element
*ele
, *aele
;
749 struct mac_module_data_list
*arr
, *dict
;
750 unsigned int i
, j
, k
;
752 old
= new->base_addr
;
753 DPRINTF(("fixup_mmd: old %p new %p\n", old
, new));
754 for (i
= 0; i
< new->count
; i
++) {
755 ele
= &(new->data
[i
]);
756 DPRINTF(("fixup_mmd: ele %p\n", ele
));
757 DPRINTF((" key %p value %p\n", ele
->key
, ele
->value
));
758 mmd_fixup_ele(old
, new, ele
); /* Fix up key/value ptrs. */
759 DPRINTF((" key %p value %p\n", ele
->key
, ele
->value
));
760 if (ele
->value_type
== MAC_DATA_TYPE_ARRAY
) {
761 arr
= (struct mac_module_data_list
*)ele
->value
;
762 DPRINTF(("fixup_mmd: array @%p\n", arr
));
763 for (j
= 0; j
< arr
->count
; j
++) {
764 aele
= &(arr
->list
[j
]);
765 DPRINTF(("fixup_mmd: aele %p\n", aele
));
766 DPRINTF((" key %p value %p\n", aele
->key
, aele
->value
));
767 mmd_fixup_ele(old
, new, aele
);
768 DPRINTF((" key %p value %p\n", aele
->key
, aele
->value
));
769 if (arr
->type
== MAC_DATA_TYPE_DICT
) {
770 dict
= (struct mac_module_data_list
*)aele
->value
;
771 DPRINTF(("fixup_mmd: dict @%p\n", dict
));
772 for (k
= 0; k
< dict
->count
; k
++)
773 mmd_fixup_ele(old
, new,
779 new->base_addr
= new;
783 mac_policy_register(struct mac_policy_conf
*mpc
, mac_policy_handle_t
*handlep
,
786 struct mac_policy_list_element
*tmac_policy_list_element
;
787 int error
, slot
, static_entry
= 0;
791 * Some preliminary checks to make sure the policy's conf structure
792 * contains the required fields.
794 if (mpc
->mpc_name
== NULL
)
795 panic("policy's name is not set\n");
797 if (mpc
->mpc_fullname
== NULL
)
798 panic("policy's full name is not set\n");
800 if (mpc
->mpc_labelname_count
> MAC_MAX_MANAGED_NAMESPACES
)
801 panic("policy's managed label namespaces exceeds maximum\n");
803 if (mpc
->mpc_ops
== NULL
)
804 panic("policy's OPs field is NULL\n");
809 if (mpc
->mpc_loadtime_flags
& MPC_LOADTIME_FLAG_NOTLATE
) {
810 printf("Module %s does not support late loading.\n",
814 mac_policy_grab_exclusive();
817 if (mac_policy_list
.numloaded
>= mac_policy_list
.max
) {
818 /* allocate new policy list array, zero new chunk */
819 tmac_policy_list_element
=
820 kalloc((sizeof(struct mac_policy_list_element
) *
821 MAC_POLICY_LIST_CHUNKSIZE
) * (mac_policy_list
.chunks
+ 1));
822 bzero(&tmac_policy_list_element
[mac_policy_list
.max
],
823 sizeof(struct mac_policy_list_element
) *
824 MAC_POLICY_LIST_CHUNKSIZE
);
826 /* copy old entries into new list */
827 memcpy(tmac_policy_list_element
, mac_policy_list
.entries
,
828 sizeof(struct mac_policy_list_element
) *
829 MAC_POLICY_LIST_CHUNKSIZE
* mac_policy_list
.chunks
);
832 kfree(mac_policy_list
.entries
,
833 sizeof(struct mac_policy_list_element
) *
834 MAC_POLICY_LIST_CHUNKSIZE
* mac_policy_list
.chunks
);
836 mac_policy_list
.entries
= tmac_policy_list_element
;
838 /* Update maximums, etc */
839 mac_policy_list
.max
+= MAC_POLICY_LIST_CHUNKSIZE
;
840 mac_policy_list
.chunks
++;
843 /* Check for policy with same name already loaded */
844 for (i
= 0; i
<= mac_policy_list
.maxindex
; i
++) {
845 if (mac_policy_list
.entries
[i
].mpc
== NULL
)
848 if (strcmp(mac_policy_list
.entries
[i
].mpc
->mpc_name
,
849 mpc
->mpc_name
) == 0) {
855 if (mpc
->mpc_field_off
!= NULL
) {
856 slot
= ffs(mac_slot_offsets_free
);
862 mac_slot_offsets_free
&= ~(1 << slot
);
863 *mpc
->mpc_field_off
= slot
;
865 mpc
->mpc_runtime_flags
|= MPC_RUNTIME_FLAG_REGISTERED
;
868 struct mac_module_data
*mmd
= xd
; /* module data from plist */
870 /* Make a copy of the data. */
871 mpc
->mpc_data
= (void *)kalloc(mmd
->size
);
872 if (mpc
->mpc_data
!= NULL
) {
873 memcpy(mpc
->mpc_data
, mmd
, mmd
->size
);
875 /* Fix up pointers after copy. */
876 mac_policy_fixup_mmd_list(mpc
->mpc_data
);
880 /* Find the first free handle in the list (using our hint). */
881 for (i
= mac_policy_list
.freehint
; i
< mac_policy_list
.max
; i
++) {
882 if (mac_policy_list
.entries
[i
].mpc
== NULL
) {
884 mac_policy_list
.freehint
= ++i
;
890 * If we are loading a MAC module before the framework has
891 * finished initializing or the module is not unloadable and
892 * we can place its handle adjacent to the last static entry,
893 * bump the static policy high water mark.
894 * Static policies can get by with weaker locking requirements.
897 ((mpc
->mpc_loadtime_flags
& MPC_LOADTIME_FLAG_UNLOADOK
) == 0 &&
898 *handlep
== mac_policy_list
.staticmax
)) {
900 mac_policy_list
.staticmax
++;
903 mac_policy_list
.entries
[*handlep
].mpc
= mpc
;
905 /* Update counters, etc */
906 if (*handlep
> mac_policy_list
.maxindex
)
907 mac_policy_list
.maxindex
= *handlep
;
908 mac_policy_list
.numloaded
++;
910 /* Per-policy initialization. */
911 printf ("calling mpo_policy_init for %s\n", mpc
->mpc_name
);
912 if (mpc
->mpc_ops
->mpo_policy_init
!= NULL
)
913 (*(mpc
->mpc_ops
->mpo_policy_init
))(mpc
);
915 if (mac_late
&& mpc
->mpc_ops
->mpo_policy_initbsd
!= NULL
) {
916 printf ("calling mpo_policy_initbsd for %s\n", mpc
->mpc_name
);
917 (*(mpc
->mpc_ops
->mpo_policy_initbsd
))(mpc
);
920 mac_policy_updateflags();
923 mac_policy_release_exclusive();
925 mac_policy_addto_labellist(*handlep
, static_entry
);
927 printf("Security policy loaded: %s (%s)\n", mpc
->mpc_fullname
,
934 mac_policy_release_exclusive();
940 mac_policy_unregister(mac_policy_handle_t handle
)
942 struct mac_policy_conf
*mpc
;
945 * If we fail the load, we may get a request to unload. Check
946 * to see if we did the run-time registration, and if not,
949 mac_policy_grab_exclusive();
950 mpc
= mac_get_mpc(handle
);
951 if ((mpc
->mpc_runtime_flags
& MPC_RUNTIME_FLAG_REGISTERED
) == 0) {
952 mac_policy_release_exclusive();
958 * Don't allow unloading modules with private data.
960 if (mpc
->mpc_field_off
!= NULL
) {
961 MAC_POLICY_LIST_UNLOCK();
966 * Only allow the unload to proceed if the module is unloadable
967 * by its own definition.
969 if ((mpc
->mpc_loadtime_flags
& MPC_LOADTIME_FLAG_UNLOADOK
) == 0) {
970 mac_policy_release_exclusive();
974 mac_policy_removefrom_labellist(handle
);
976 mac_get_mpc(handle
) = NULL
;
977 if (handle
< mac_policy_list
.freehint
&&
978 handle
>= mac_policy_list
.staticmax
)
979 mac_policy_list
.freehint
= handle
;
981 if (handle
== mac_policy_list
.maxindex
)
982 mac_policy_list
.maxindex
--;
984 mac_policy_list
.numloaded
--;
985 if (mpc
->mpc_field_off
!= NULL
) {
986 mac_slot_offsets_free
|= (1 << *mpc
->mpc_field_off
);
989 if (mpc
->mpc_ops
->mpo_policy_destroy
!= NULL
)
990 (*(mpc
->mpc_ops
->mpo_policy_destroy
))(mpc
);
992 mpc
->mpc_runtime_flags
&= ~MPC_RUNTIME_FLAG_REGISTERED
;
993 mac_policy_updateflags();
995 mac_policy_release_exclusive();
998 struct mac_module_data
*mmd
= mpc
->mpc_data
;
999 kfree(mmd
, mmd
->size
);
1000 mpc
->mpc_data
= NULL
;
1003 printf("Security policy unload: %s (%s)\n", mpc
->mpc_fullname
,
1010 * Define an error value precedence, and given two arguments, selects the
1011 * value with the higher precedence.
1014 mac_error_select(int error1
, int error2
)
1017 /* Certain decision-making errors take top priority. */
1018 if (error1
== EDEADLK
|| error2
== EDEADLK
)
1021 /* Invalid arguments should be reported where possible. */
1022 if (error1
== EINVAL
|| error2
== EINVAL
)
1025 /* Precedence goes to "visibility", with both process and file. */
1026 if (error1
== ESRCH
|| error2
== ESRCH
)
1029 if (error1
== ENOENT
|| error2
== ENOENT
)
1032 /* Precedence goes to DAC/MAC protections. */
1033 if (error1
== EACCES
|| error2
== EACCES
)
1036 /* Precedence goes to privilege. */
1037 if (error1
== EPERM
|| error2
== EPERM
)
1040 /* Precedence goes to error over success; otherwise, arbitrary. */
1047 mac_label_init(struct label
*label
)
1050 bzero(label
, sizeof(*label
));
1051 label
->l_flags
= MAC_FLAG_INITIALIZED
;
1055 mac_label_destroy(struct label
*label
)
1058 KASSERT(label
->l_flags
& MAC_FLAG_INITIALIZED
,
1059 ("destroying uninitialized label"));
1061 bzero(label
, sizeof(*label
));
1062 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1066 mac_port_check_service (struct label
*subj
, struct label
*obj
,
1067 const char *s
, const char *p
)
1071 MAC_CHECK(port_check_service
, subj
, obj
, s
, p
);
1076 mac_port_label_compute(struct label
*subj
, struct label
*obj
,
1077 const char *s
, struct label
*out
)
1081 MAC_CHECK(port_label_compute
, subj
, obj
, s
, out
);
1086 mac_check_structmac_consistent(struct user_mac
*mac
)
1089 if (mac
->m_buflen
> MAC_MAX_LABEL_BUF_LEN
|| mac
->m_buflen
== 0)
1096 * Get the external forms of labels from all policies, for a single
1097 * label namespace or "*" for all namespaces. Returns ENOENT if no policy
1098 * is registered for the namespace, unless the namespace begins with a '?'.
1101 mac_label_externalize(size_t mpo_externalize_off
, struct label
*label
,
1102 const char *element
, struct sbuf
*sb
)
1104 struct mac_policy_conf
*mpc
;
1105 struct mac_label_listener
*mll
;
1106 struct mac_label_element
*mle
;
1107 struct mac_label_element_list_t
*element_list
;
1109 int (*mpo_externalize
)(struct label
*, char *, struct sbuf
*);
1110 int all_labels
= 0, ignorenotfound
= 0, error
= 0, busy
= FALSE
;
1111 unsigned int count
= 0;
1113 if (element
[0] == '?') {
1116 } else if (element
[0] == '*' && element
[1] == '\0')
1119 element_list
= &mac_static_label_element_list
;
1121 LIST_FOREACH(mle
, element_list
, mle_list
) {
1122 name
= mle
->mle_name
;
1129 if (strcmp(name
, element
) != 0)
1132 LIST_FOREACH(mll
, &mle
->mle_listeners
, mll_list
) {
1133 mpc
= mac_policy_list
.entries
[mll
->mll_handle
].mpc
;
1136 mpo_externalize
= *(typeof(mpo_externalize
) *)
1137 ((char *)mpc
->mpc_ops
+ mpo_externalize_off
);
1138 if (mpo_externalize
== NULL
)
1140 error
= sbuf_printf(sb
, "%s/", name
);
1143 error
= mpo_externalize(label
, mle
->mle_name
, sb
);
1145 if (error
!= ENOENT
)
1148 * If a policy doesn't have a label to
1149 * externalize it returns ENOENT. This
1150 * may occur for policies that support
1151 * multiple label elements for some
1152 * (but not all) object types.
1154 sbuf_setpos(sb
, sbuf_len(sb
) -
1155 (strlen(name
) + 1));
1159 error
= sbuf_putc(sb
, ',');
1165 /* If there are dynamic policies present, check their elements too. */
1166 if (!busy
&& mac_policy_list_conditional_busy() == 1) {
1167 element_list
= &mac_label_element_list
;
1173 mac_policy_list_unbusy();
1174 if (!error
&& count
== 0) {
1175 if (!all_labels
&& !ignorenotfound
)
1176 error
= ENOENT
; /* XXX: ENOLABEL? */
1182 * Get the external forms of labels from all policies, for all label
1183 * namespaces contained in a list.
1186 mac_externalize(size_t mpo_externalize_off
, struct label
*label
,
1187 const char *elementlist
, char *outbuf
, size_t outbuflen
)
1193 sbuf_new(&sb
, outbuf
, outbuflen
, SBUF_FIXEDLEN
);
1194 while ((element
= strsep(&elementlist
, ",")) != NULL
) {
1195 error
= mac_label_externalize(mpo_externalize_off
, label
,
1200 if ((len
= sbuf_len(&sb
)) > 0)
1201 sbuf_setpos(&sb
, len
- 1); /* trim trailing comma */
1207 * Have all policies set the internal form of a label, for a single
1211 mac_label_internalize(size_t mpo_internalize_off
, struct label
*label
,
1212 char *element_name
, char *element_data
)
1214 struct mac_policy_conf
*mpc
;
1215 struct mac_label_listener
*mll
;
1216 struct mac_label_element
*mle
;
1217 struct mac_label_element_list_t
*element_list
;
1218 int (*mpo_internalize
)(struct label
*, char *, char *);
1219 int error
= 0, busy
= FALSE
;
1220 unsigned int count
= 0;
1223 element_list
= &mac_static_label_element_list
;
1225 LIST_FOREACH(mle
, element_list
, mle_list
) {
1226 if (*(name
= mle
->mle_name
) == '?')
1228 if (strcmp(element_name
, name
) != 0)
1230 LIST_FOREACH(mll
, &mle
->mle_listeners
, mll_list
) {
1231 mpc
= mac_policy_list
.entries
[mll
->mll_handle
].mpc
;
1234 mpo_internalize
= *(typeof(mpo_internalize
) *)
1235 ((char *)mpc
->mpc_ops
+ mpo_internalize_off
);
1236 if (mpo_internalize
== NULL
)
1238 error
= mpo_internalize(label
, element_name
,
1245 /* If there are dynamic policies present, check their elements too. */
1246 if (!busy
&& mac_policy_list_conditional_busy() == 1) {
1247 element_list
= &mac_label_element_list
;
1253 mac_policy_list_unbusy();
1254 if (!error
&& count
== 0)
1260 mac_internalize(size_t mpo_internalize_off
, struct label
*label
,
1263 char *element_name
, *element_data
;
1266 while (!error
&& (element_name
= strsep(&textlabels
, ",")) != NULL
) {
1267 element_data
= strchr(element_name
, '/');
1268 if (element_data
== NULL
) {
1272 *element_data
++ = '\0';
1273 error
= mac_label_internalize(mpo_internalize_off
, label
,
1274 element_name
, element_data
);
1282 __mac_get_pid(struct proc
*p
, struct __mac_get_pid_args
*uap
, register_t
*ret __unused
)
1284 char *elements
, *buffer
;
1285 struct user_mac mac
;
1287 struct ucred
*tcred
;
1291 AUDIT_ARG(pid
, uap
->pid
);
1292 if (IS_64BIT_PROCESS(p
)) {
1293 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1296 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1297 mac
.m_buflen
= mac32
.m_buflen
;
1298 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1303 error
= mac_check_structmac_consistent(&mac
);
1307 tproc
= proc_find(uap
->pid
);
1310 tcred
= kauth_cred_proc_ref(tproc
);
1313 MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1314 error
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
);
1316 FREE(elements
, M_MACTEMP
);
1317 kauth_cred_unref(&tcred
);
1320 AUDIT_ARG(mac_string
, elements
);
1322 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
| M_ZERO
);
1323 error
= mac_cred_label_externalize(tcred
->cr_label
, elements
,
1324 buffer
, mac
.m_buflen
, M_WAITOK
);
1326 error
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1);
1328 FREE(buffer
, M_MACTEMP
);
1329 FREE(elements
, M_MACTEMP
);
1330 kauth_cred_unref(&tcred
);
1335 __mac_get_proc(proc_t p
, struct __mac_get_proc_args
*uap
, register_t
*ret __unused
)
1337 char *elements
, *buffer
;
1338 struct user_mac mac
;
1343 if (IS_64BIT_PROCESS(p
)) {
1344 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1347 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1348 mac
.m_buflen
= mac32
.m_buflen
;
1349 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1354 error
= mac_check_structmac_consistent(&mac
);
1358 MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1359 error
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
);
1361 FREE(elements
, M_MACTEMP
);
1364 AUDIT_ARG(mac_string
, elements
);
1366 cr
= kauth_cred_proc_ref(p
);
1368 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
| M_ZERO
);
1369 error
= mac_cred_label_externalize(cr
->cr_label
,
1370 elements
, buffer
, mac
.m_buflen
, M_WAITOK
);
1372 error
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1);
1374 FREE(buffer
, M_MACTEMP
);
1375 FREE(elements
, M_MACTEMP
);
1376 kauth_cred_unref(&cr
);
1385 __mac_set_proc(proc_t p
, struct __mac_set_proc_args
*uap
, register_t
*ret __unused
)
1387 kauth_cred_t newcred
, oldcred
;
1388 struct label
*intlabel
;
1389 struct user_mac mac
;
1394 if (IS_64BIT_PROCESS(p
)) {
1395 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1398 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1399 mac
.m_buflen
= mac32
.m_buflen
;
1400 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1405 error
= mac_check_structmac_consistent(&mac
);
1409 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1410 error
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
);
1412 FREE(buffer
, M_MACTEMP
);
1415 AUDIT_ARG(mac_string
, buffer
);
1417 intlabel
= mac_cred_label_alloc();
1418 error
= mac_cred_label_internalize(intlabel
, buffer
);
1419 FREE(buffer
, M_MACTEMP
);
1423 error
= mac_cred_check_label_update(kauth_cred_get(), intlabel
);
1428 error
= kauth_proc_label_update(p
, intlabel
);
1432 newcred
= kauth_cred_proc_ref(p
);
1433 mac_task_label_update_cred(newcred
, p
->task
);
1436 if (mac_vm_enforce
) {
1437 mutex_lock(Giant
); /* XXX FUNNEL? */
1438 mac_cred_mmapped_drop_perms(p
, newcred
);
1439 mutex_unlock(Giant
); /* XXX FUNNEL? */
1443 kauth_cred_unref(&newcred
);
1445 mac_cred_label_free(intlabel
);
1451 __mac_get_lcid(proc_t p
, struct __mac_get_lcid_args
*uap
, register_t
*ret __unused
)
1453 char *elements
, *buffer
;
1454 struct user_mac mac
;
1459 AUDIT_ARG(value
, uap
->lcid
);
1460 if (IS_64BIT_PROCESS(p
)) {
1461 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1464 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1465 mac
.m_buflen
= mac32
.m_buflen
;
1466 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1472 error
= mac_check_structmac_consistent(&mac
);
1476 l
= lcfind(uap
->lcid
);
1480 MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1481 error
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
);
1484 FREE(elements
, M_MACTEMP
);
1487 AUDIT_ARG(mac_string
, elements
);
1488 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1489 error
= mac_lctx_label_externalize(l
->lc_label
, elements
,
1490 buffer
, mac
.m_buflen
);
1492 error
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1);
1495 FREE(buffer
, M_MACTEMP
);
1496 FREE(elements
, M_MACTEMP
);
1501 __mac_get_lctx(proc_t p
, struct __mac_get_lctx_args
*uap
, register_t
*ret __unused
)
1503 char *elements
, *buffer
;
1504 struct user_mac mac
;
1508 if (IS_64BIT_PROCESS(p
)) {
1509 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1512 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1513 mac
.m_buflen
= mac32
.m_buflen
;
1514 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1520 error
= mac_check_structmac_consistent(&mac
);
1524 MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1525 error
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
);
1527 FREE(elements
, M_MACTEMP
);
1530 AUDIT_ARG(mac_string
, elements
);
1531 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1534 if (p
->p_lctx
== NULL
) {
1540 error
= mac_lctx_label_externalize(p
->p_lctx
->lc_label
,
1541 elements
, buffer
, mac
.m_buflen
);
1544 error
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1);
1547 FREE(buffer
, M_MACTEMP
);
1548 FREE(elements
, M_MACTEMP
);
1553 __mac_set_lctx(proc_t p
, struct __mac_set_lctx_args
*uap
, register_t
*ret __unused
)
1555 struct user_mac mac
;
1556 struct label
*intlabel
;
1561 if (IS_64BIT_PROCESS(p
)) {
1562 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1565 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1566 mac
.m_buflen
= mac32
.m_buflen
;
1567 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1572 error
= mac_check_structmac_consistent(&mac
);
1576 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1577 error
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
);
1579 FREE(buffer
, M_MACTEMP
);
1582 AUDIT_ARG(mac_string
, buffer
);
1584 intlabel
= mac_lctx_label_alloc();
1585 error
= mac_lctx_label_internalize(intlabel
, buffer
);
1586 FREE(buffer
, M_MACTEMP
);
1591 if (p
->p_lctx
== NULL
) {
1597 error
= mac_lctx_check_label_update(p
->p_lctx
, intlabel
);
1602 mac_lctx_label_update(p
->p_lctx
, intlabel
);
1605 mac_lctx_label_free(intlabel
);
1612 __mac_get_lcid(proc_t p __unused
, struct __mac_get_lcid_args
*uap __unused
, register_t
*ret __unused
)
1619 __mac_get_lctx(proc_t p __unused
, struct __mac_get_lctx_args
*uap __unused
, register_t
*ret __unused
)
1626 __mac_set_lctx(proc_t p __unused
, struct __mac_set_lctx_args
*uap __unused
, register_t
*ret __unused
)
1634 __mac_get_fd(proc_t p
, struct __mac_get_fd_args
*uap
, register_t
*ret __unused
)
1636 struct fileproc
*fp
;
1638 struct user_mac mac
;
1639 char *elements
, *buffer
;
1642 kauth_cred_t my_cred
;
1643 #if CONFIG_MACF_SOCKET
1645 #endif /* MAC_SOCKET */
1646 struct label
*intlabel
;
1648 AUDIT_ARG(fd
, uap
->fd
);
1650 if (IS_64BIT_PROCESS(p
)) {
1651 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1654 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1655 mac
.m_buflen
= mac32
.m_buflen
;
1656 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1662 error
= mac_check_structmac_consistent(&mac
);
1666 MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1667 error
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
);
1669 FREE(elements
, M_MACTEMP
);
1672 AUDIT_ARG(mac_string
, elements
);
1674 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1675 error
= fp_lookup(p
, uap
->fd
, &fp
, 0);
1677 FREE(buffer
, M_MACTEMP
);
1678 FREE(elements
, M_MACTEMP
);
1682 my_cred
= kauth_cred_proc_ref(p
);
1683 error
= mac_file_check_get(my_cred
, fp
->f_fglob
, elements
, mac
.m_buflen
);
1684 kauth_cred_unref(&my_cred
);
1686 fp_drop(p
, uap
->fd
, fp
, 0);
1687 FREE(buffer
, M_MACTEMP
);
1688 FREE(elements
, M_MACTEMP
);
1692 switch (fp
->f_fglob
->fg_type
) {
1695 intlabel
= mac_vnode_label_alloc();
1696 vp
= (struct vnode
*)fp
->f_fglob
->fg_data
;
1698 error
= vnode_getwithref(vp
);
1700 mac_vnode_label_copy(vp
->v_label
, intlabel
);
1701 error
= mac_vnode_label_externalize(intlabel
,
1703 mac
.m_buflen
, M_WAITOK
);
1706 mac_vnode_label_free(intlabel
);
1709 #if CONFIG_MACF_SOCKET
1710 so
= (struct socket
*) fp
->f_fglob
->fg_data
;
1711 intlabel
= mac_socket_label_alloc(MAC_WAITOK
);
1713 mac_socket_label_copy(so
->so_label
, intlabel
);
1715 error
= mac_socket_label_externalize(intlabel
, elements
, buffer
, mac
.m_buflen
);
1716 mac_socket_label_free(intlabel
);
1723 case DTYPE_FSEVENTS
:
1725 error
= ENOSYS
; // only sockets/vnodes so far
1728 fp_drop(p
, uap
->fd
, fp
, 0);
1731 error
= copyout(buffer
, mac
.m_string
, strlen(buffer
)+1);
1733 FREE(buffer
, M_MACTEMP
);
1734 FREE(elements
, M_MACTEMP
);
1742 mac_get_filelink(proc_t p
, user_addr_t mac_p
, user_addr_t path_p
, int follow
)
1746 char *elements
, *buffer
;
1747 struct nameidata nd
;
1748 struct label
*intlabel
;
1749 struct user_mac mac
;
1753 if (IS_64BIT_PROCESS(p
)) {
1754 error
= copyin(mac_p
, &mac
, sizeof(mac
));
1757 error
= copyin(mac_p
, &mac32
, sizeof(mac32
));
1758 mac
.m_buflen
= mac32
.m_buflen
;
1759 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1765 error
= mac_check_structmac_consistent(&mac
);
1769 MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1770 error
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
);
1772 FREE(elements
, M_MACTEMP
);
1775 AUDIT_ARG(mac_string
, elements
);
1777 ctx
= vfs_context_current();
1780 LOCKLEAF
| (follow
? FOLLOW
: NOFOLLOW
) | AUDITVNPATH1
,
1781 UIO_USERSPACE
, path_p
, ctx
);
1784 FREE(elements
, M_MACTEMP
);
1791 intlabel
= mac_vnode_label_alloc();
1792 mac_vnode_label_copy(vp
->v_label
, intlabel
);
1794 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
| M_ZERO
);
1795 error
= mac_vnode_label_externalize(intlabel
, elements
, buffer
,
1796 mac
.m_buflen
, M_WAITOK
);
1797 FREE(elements
, M_MACTEMP
);
1800 error
= copyout(buffer
, mac
.m_string
, strlen(buffer
) + 1);
1801 FREE(buffer
, M_MACTEMP
);
1804 mac_vnode_label_free(intlabel
);
1810 __mac_get_file(proc_t p
, struct __mac_get_file_args
*uap
,
1811 register_t
*ret __unused
)
1814 return (mac_get_filelink(p
, uap
->mac_p
, uap
->path_p
, 1));
1818 __mac_get_link(proc_t p
, struct __mac_get_link_args
*uap
,
1819 register_t
*ret __unused
)
1822 return (mac_get_filelink(p
, uap
->mac_p
, uap
->path_p
, 0));
1826 __mac_set_fd(proc_t p
, struct __mac_set_fd_args
*uap
, register_t
*ret __unused
)
1829 struct fileproc
*fp
;
1830 struct user_mac mac
;
1831 struct vfs_context
*ctx
= vfs_context_current();
1835 struct label
*intlabel
;
1836 #if CONFIG_MACF_SOCKET
1841 AUDIT_ARG(fd
, uap
->fd
);
1843 if (IS_64BIT_PROCESS(p
)) {
1844 error
= copyin(uap
->mac_p
, &mac
, sizeof(mac
));
1847 error
= copyin(uap
->mac_p
, &mac32
, sizeof(mac32
));
1848 mac
.m_buflen
= mac32
.m_buflen
;
1849 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1854 error
= mac_check_structmac_consistent(&mac
);
1858 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1859 error
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
);
1861 FREE(buffer
, M_MACTEMP
);
1864 AUDIT_ARG(mac_string
, buffer
);
1866 error
= fp_lookup(p
, uap
->fd
, &fp
, 0);
1868 FREE(buffer
, M_MACTEMP
);
1873 error
= mac_file_check_set(vfs_context_ucred(ctx
), fp
->f_fglob
, buffer
, mac
.m_buflen
);
1875 fp_drop(p
, uap
->fd
, fp
, 0);
1876 FREE(buffer
, M_MACTEMP
);
1880 switch (fp
->f_fglob
->fg_type
) {
1883 intlabel
= mac_vnode_label_alloc();
1885 error
= mac_vnode_label_internalize(intlabel
, buffer
);
1887 mac_vnode_label_free(intlabel
);
1892 vp
= (struct vnode
*)fp
->f_fglob
->fg_data
;
1894 error
= vnode_getwithref(vp
);
1896 error
= vn_setlabel(vp
, intlabel
, ctx
);
1899 mac_vnode_label_free(intlabel
);
1903 #if CONFIG_MACF_SOCKET
1904 intlabel
= mac_socket_label_alloc(MAC_WAITOK
);
1905 error
= mac_socket_label_internalize(intlabel
, buffer
);
1907 so
= (struct socket
*) fp
->f_fglob
->fg_data
;
1909 error
= mac_socket_label_update(vfs_context_ucred(ctx
), so
, intlabel
);
1912 mac_socket_label_free(intlabel
);
1919 case DTYPE_FSEVENTS
:
1921 error
= ENOSYS
; // only sockets/vnodes so far
1925 fp_drop(p
, uap
->fd
, fp
, 0);
1926 FREE(buffer
, M_MACTEMP
);
1934 mac_set_filelink(proc_t p
, user_addr_t mac_p
, user_addr_t path_p
,
1937 register struct vnode
*vp
;
1938 struct vfs_context
*ctx
= vfs_context_current();
1939 struct label
*intlabel
;
1940 struct nameidata nd
;
1941 struct user_mac mac
;
1946 if (IS_64BIT_PROCESS(p
)) {
1947 error
= copyin(mac_p
, &mac
, sizeof(mac
));
1950 error
= copyin(mac_p
, &mac32
, sizeof(mac32
));
1951 mac
.m_buflen
= mac32
.m_buflen
;
1952 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
1957 error
= mac_check_structmac_consistent(&mac
);
1959 printf("mac_set_file: failed structure consistency check\n");
1963 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
1964 error
= copyinstr(mac
.m_string
, buffer
, mac
.m_buflen
, &ulen
);
1966 FREE(buffer
, M_MACTEMP
);
1969 AUDIT_ARG(mac_string
, buffer
);
1971 intlabel
= mac_vnode_label_alloc();
1972 error
= mac_vnode_label_internalize(intlabel
, buffer
);
1973 FREE(buffer
, M_MACTEMP
);
1975 mac_vnode_label_free(intlabel
);
1980 LOCKLEAF
| (follow
? FOLLOW
: NOFOLLOW
) | AUDITVNPATH1
,
1981 UIO_USERSPACE
, path_p
, ctx
);
1984 mac_vnode_label_free(intlabel
);
1991 error
= vn_setlabel(vp
, intlabel
, ctx
);
1993 mac_vnode_label_free(intlabel
);
1999 __mac_set_file(proc_t p
, struct __mac_set_file_args
*uap
,
2000 register_t
*ret __unused
)
2003 return (mac_set_filelink(p
, uap
->mac_p
, uap
->path_p
, 1));
2007 __mac_set_link(proc_t p
, struct __mac_set_link_args
*uap
,
2008 register_t
*ret __unused
)
2011 return (mac_set_filelink(p
, uap
->mac_p
, uap
->path_p
, 0));
2019 __mac_syscall(proc_t p
, struct __mac_syscall_args
*uap
, register_t
*retv __unused
)
2021 struct mac_policy_conf
*mpc
;
2022 char target
[MAC_MAX_POLICY_NAME
];
2027 error
= copyinstr(uap
->policy
, target
, sizeof(target
), &ulen
);
2030 AUDIT_ARG(value
, uap
->call
);
2031 AUDIT_ARG(mac_string
, target
);
2035 for (i
= 0; i
< mac_policy_list
.staticmax
; i
++) {
2036 mpc
= mac_policy_list
.entries
[i
].mpc
;
2040 if (strcmp(mpc
->mpc_name
, target
) == 0 &&
2041 mpc
->mpc_ops
->mpo_policy_syscall
!= NULL
) {
2042 error
= mpc
->mpc_ops
->mpo_policy_syscall(p
,
2043 uap
->call
, uap
->arg
);
2047 if (mac_policy_list_conditional_busy() != 0) {
2048 for (; i
<= mac_policy_list
.maxindex
; i
++) {
2049 mpc
= mac_policy_list
.entries
[i
].mpc
;
2053 if (strcmp(mpc
->mpc_name
, target
) == 0 &&
2054 mpc
->mpc_ops
->mpo_policy_syscall
!= NULL
) {
2055 error
= mpc
->mpc_ops
->mpo_policy_syscall(p
,
2056 uap
->call
, uap
->arg
);
2060 mac_policy_list_unbusy();
2068 mac_mount_label_get(struct mount
*mp
, user_addr_t mac_p
)
2070 char *elements
, *buffer
;
2071 struct label
*label
;
2072 struct user_mac mac
;
2076 if (IS_64BIT_PROCESS(current_proc())) {
2077 error
= copyin(mac_p
, &mac
, sizeof(mac
));
2080 error
= copyin(mac_p
, &mac32
, sizeof(mac32
));
2081 mac
.m_buflen
= mac32
.m_buflen
;
2082 mac
.m_string
= CAST_USER_ADDR_T(mac32
.m_string
);
2087 error
= mac_check_structmac_consistent(&mac
);
2091 MALLOC(elements
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
);
2092 error
= copyinstr(mac
.m_string
, elements
, mac
.m_buflen
, &ulen
);
2094 FREE(elements
, M_MACTEMP
);
2097 AUDIT_ARG(mac_string
, elements
);
2099 label
= mp
->mnt_mntlabel
;
2100 MALLOC(buffer
, char *, mac
.m_buflen
, M_MACTEMP
, M_WAITOK
| M_ZERO
);
2101 error
= mac_mount_label_externalize(label
, elements
, buffer
,
2103 FREE(elements
, M_MACTEMP
);
2106 error
= copyout(buffer
, mac
.m_string
, strlen(buffer
) + 1);
2107 FREE(buffer
, M_MACTEMP
);
2113 __mac_get_mount(proc_t p __unused
, struct __mac_get_mount_args
*uap
,
2114 register_t
*ret __unused
)
2116 struct nameidata nd
;
2117 struct vfs_context
*ctx
= vfs_context_current();
2121 NDINIT(&nd
, LOOKUP
, FOLLOW
| AUDITVNPATH1
,
2122 UIO_USERSPACE
, uap
->path
, ctx
);
2127 mp
= nd
.ni_vp
->v_mount
;
2130 return mac_mount_label_get(mp
, uap
->mac_p
);
2136 mac_policy_register(struct mac_policy_conf
*mpc __unused
,
2137 mac_policy_handle_t
*handlep __unused
, void *xd __unused
)
2144 mac_policy_unregister(mac_policy_handle_t handle __unused
)
2151 mac_audit_text(char *text __unused
, mac_policy_handle_t handle __unused
)
2158 mac_mount_label_get(struct mount
*mp __unused
, user_addr_t mac_p __unused
)
2164 mac_vnop_setxattr(struct vnode
*vp __unused
, const char *name __unused
, char *buf __unused
, size_t len __unused
)
2171 mac_vnop_getxattr(struct vnode
*vp __unused
, const char *name __unused
,
2172 char *buf __unused
, size_t len __unused
, size_t *attrlen __unused
)
2179 mac_vnop_removexattr(struct vnode
*vp __unused
, const char *name __unused
)
2186 __mac_get_pid(proc_t p __unused
, struct __mac_get_pid_args
*uap __unused
, register_t
*ret __unused
)
2193 __mac_get_proc(proc_t p __unused
, struct __mac_get_proc_args
*uap __unused
, register_t
*ret __unused
)
2200 __mac_set_proc(proc_t p __unused
, struct __mac_set_proc_args
*uap __unused
, register_t
*ret __unused
)
2207 __mac_get_file(proc_t p __unused
, struct __mac_get_file_args
*uap __unused
, register_t
*ret __unused
)
2214 __mac_get_link(proc_t p __unused
, struct __mac_get_link_args
*uap __unused
, register_t
*ret __unused
)
2221 __mac_set_file(proc_t p __unused
, struct __mac_set_file_args
*uap __unused
, register_t
*ret __unused
)
2228 __mac_set_link(proc_t p __unused
, struct __mac_set_link_args
*uap __unused
, register_t
*ret __unused
)
2235 __mac_get_fd(proc_t p __unused
, struct __mac_get_fd_args
*uap __unused
, register_t
*ret __unused
)
2242 __mac_set_fd(proc_t p __unused
, struct __mac_set_fd_args
*uap __unused
, register_t
*ret __unused
)
2249 __mac_syscall(proc_t p __unused
, struct __mac_syscall_args
*uap __unused
, register_t
*ret __unused
)
2256 __mac_get_lcid(proc_t p __unused
, struct __mac_get_lcid_args
*uap __unused
, register_t
*ret __unused
)
2263 __mac_get_lctx(proc_t p __unused
, struct __mac_get_lctx_args
*uap __unused
, register_t
*ret __unused
)
2270 __mac_set_lctx(proc_t p __unused
, struct __mac_set_lctx_args
*uap __unused
, register_t
*ret __unused
)
2277 __mac_get_mount(proc_t p __unused
,
2278 struct __mac_get_mount_args
*uap __unused
, register_t
*ret __unused
)