]> git.saurik.com Git - apple/xnu.git/blob - security/mac_base.c
xnu-6153.101.6.tar.gz
[apple/xnu.git] / security / mac_base.c
1 /*
2 * Copyright (c) 2007-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*-
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.
33 *
34 * This software was developed by Robert Watson and Ilmar Habibulin for the
35 * TrustedBSD Project.
36 *
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.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
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.
50 *
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
61 * SUCH DAMAGE.
62 *
63 */
64
65 /*-
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*.
70 */
71
72 #include <stdarg.h>
73 #include <string.h>
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/security/audit/audit.h>
83 #include <sys/file.h>
84 #include <sys/file_internal.h>
85 #include <sys/filedesc.h>
86 #include <sys/proc.h>
87 #include <sys/proc_internal.h>
88 #include <sys/kauth.h>
89 #include <sys/sysproto.h>
90
91 #include <mach/exception_types.h>
92 #include <mach/vm_types.h>
93 #include <mach/vm_prot.h>
94
95 #include <kern/zalloc.h>
96 #include <kern/sched_prim.h>
97 #include <osfmk/kern/task.h>
98 #include <osfmk/kern/kalloc.h>
99
100 #if CONFIG_MACF
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>
106 #endif
107
108 #if CONFIG_EMBEDDED
109 #include <libkern/section_keywords.h>
110 #endif
111
112 /*
113 * define MB_DEBUG to display run-time debugging information
114 * #define MB_DEBUG 1
115 */
116
117 #ifdef MB_DEBUG
118 #define DPRINTF(x) printf x
119 #else
120 #define MB_DEBUG
121 #define DPRINTF(x)
122 #endif
123
124 #if CONFIG_MACF
125 SYSCTL_NODE(, OID_AUTO, security, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
126 "Security Controls");
127 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
128 "TrustedBSD MAC policy controls");
129
130 /*
131 * Declare that the kernel provides MAC support, version 1. This permits
132 * modules to refuse to be loaded if the necessary support isn't present,
133 * even if it's pre-boot.
134 */
135 #if 0
136 MODULE_VERSION(kernel_mac_support, 1);
137 #endif
138
139 #if MAC_MAX_SLOTS > 32
140 #error "MAC_MAX_SLOTS too large"
141 #endif
142
143 static unsigned int mac_max_slots = MAC_MAX_SLOTS;
144 static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
145 SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD | CTLFLAG_LOCKED,
146 &mac_max_slots, 0, "");
147
148 /*
149 * Has the kernel started generating labeled objects yet? All read/write
150 * access to this variable is serialized during the boot process. Following
151 * the end of serialization, we don't update this flag; no locking.
152 */
153 int mac_late = 0;
154
155 /*
156 * Flag to indicate whether or not we should allocate label storage for
157 * new mbufs. Since most dynamic policies we currently work with don't
158 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
159 * unless specifically notified of interest. One result of this is
160 * that if a dynamically loaded policy requests mbuf labels, it must
161 * be able to deal with a NULL label being returned on any mbufs that
162 * were already in flight when the policy was loaded. Since the policy
163 * already has to deal with uninitialized labels, this probably won't
164 * be a problem. Note: currently no locking. Will this be a problem?
165 */
166 #if CONFIG_MACF_NET
167 unsigned int mac_label_mbufs = 1;
168 SYSCTL_UINT(_security_mac, OID_AUTO, label_mbufs, SECURITY_MAC_CTLFLAGS,
169 &mac_label_mbufs, 0, "Label all MBUFs");
170 #endif
171
172
173 /*
174 * Flag to indicate whether or not we should allocate label storage for
175 * new vnodes. Since most dynamic policies we currently work with don't
176 * rely on vnode labeling, try to avoid paying the cost of mtag allocation
177 * unless specifically notified of interest. One result of this is
178 * that if a dynamically loaded policy requests vnode labels, it must
179 * be able to deal with a NULL label being returned on any vnodes that
180 * were already in flight when the policy was loaded. Since the policy
181 * already has to deal with uninitialized labels, this probably won't
182 * be a problem.
183 */
184 #if CONFIG_MACF_LAZY_VNODE_LABELS
185 unsigned int mac_label_vnodes = 1;
186 #else
187 unsigned int mac_label_vnodes = 0;
188 #endif /* CONFIG_MACF_LAZY_VNODE_LABELS */
189 SYSCTL_UINT(_security_mac, OID_AUTO, labelvnodes, SECURITY_MAC_CTLFLAGS
190 #if CONFIG_MACF_LAZY_VNODE_LABELS
191 | CTLFLAG_RD
192 #endif
193 , &mac_label_vnodes, 0, "Label all vnodes");
194
195 unsigned int mac_vnode_label_count = 0;
196 SYSCTL_UINT(_security_mac, OID_AUTO, vnode_label_count, SECURITY_MAC_CTLFLAGS | CTLFLAG_RD,
197 &mac_vnode_label_count, 0, "Count of vnode labels");
198
199 unsigned int mac_device_enforce = 1;
200 SYSCTL_UINT(_security_mac, OID_AUTO, device_enforce, SECURITY_MAC_CTLFLAGS,
201 &mac_device_enforce, 0, "Enforce MAC policy on device operations");
202
203 unsigned int mac_pipe_enforce = 1;
204 SYSCTL_UINT(_security_mac, OID_AUTO, pipe_enforce, SECURITY_MAC_CTLFLAGS,
205 &mac_pipe_enforce, 0, "Enforce MAC policy on pipe operations");
206
207 unsigned int mac_posixsem_enforce = 1;
208 SYSCTL_UINT(_security_mac, OID_AUTO, posixsem_enforce, SECURITY_MAC_CTLFLAGS,
209 &mac_posixsem_enforce, 0, "Enforce MAC policy on POSIX semaphores");
210
211 unsigned int mac_posixshm_enforce = 1;
212 SYSCTL_UINT(_security_mac, OID_AUTO, posixshm_enforce, SECURITY_MAC_CTLFLAGS,
213 &mac_posixshm_enforce, 0, "Enforce MAC policy on Posix Shared Memory");
214
215 unsigned int mac_proc_enforce = 1;
216 SYSCTL_UINT(_security_mac, OID_AUTO, proc_enforce, SECURITY_MAC_CTLFLAGS,
217 &mac_proc_enforce, 0, "Enforce MAC policy on process operations");
218
219 unsigned int mac_socket_enforce = 1;
220 SYSCTL_UINT(_security_mac, OID_AUTO, socket_enforce, SECURITY_MAC_CTLFLAGS,
221 &mac_socket_enforce, 0, "Enforce MAC policy on socket operations");
222
223 unsigned int mac_system_enforce = 1;
224 SYSCTL_UINT(_security_mac, OID_AUTO, system_enforce, SECURITY_MAC_CTLFLAGS,
225 &mac_system_enforce, 0, "Enforce MAC policy on system-wide interfaces");
226
227 unsigned int mac_sysvmsg_enforce = 1;
228 SYSCTL_UINT(_security_mac, OID_AUTO, sysvmsg_enforce, SECURITY_MAC_CTLFLAGS,
229 &mac_sysvmsg_enforce, 0, "Enforce MAC policy on System V IPC message queues");
230
231 unsigned int mac_sysvsem_enforce = 1;
232 SYSCTL_UINT(_security_mac, OID_AUTO, sysvsem_enforce, SECURITY_MAC_CTLFLAGS,
233 &mac_sysvsem_enforce, 0, "Enforce MAC policy on System V IPC semaphores");
234
235 unsigned int mac_sysvshm_enforce = 1;
236 SYSCTL_INT(_security_mac, OID_AUTO, sysvshm_enforce, SECURITY_MAC_CTLFLAGS,
237 &mac_sysvshm_enforce, 0, "Enforce MAC policy on System V Shared Memory");
238
239 unsigned int mac_vm_enforce = 1;
240 SYSCTL_INT(_security_mac, OID_AUTO, vm_enforce, SECURITY_MAC_CTLFLAGS,
241 &mac_vm_enforce, 0, "Enforce MAC policy on VM operations");
242
243 unsigned int mac_vnode_enforce = 1;
244 SYSCTL_UINT(_security_mac, OID_AUTO, vnode_enforce, SECURITY_MAC_CTLFLAGS,
245 &mac_vnode_enforce, 0, "Enforce MAC policy on vnode operations");
246
247 #if CONFIG_AUDIT
248 /*
249 * mac_audit_data_zone is the zone used for data pushed into the audit
250 * record by policies. Using a zone simplifies memory management of this
251 * data, and allows tracking of the amount of data in flight.
252 */
253 extern zone_t mac_audit_data_zone;
254 #endif
255
256 /*
257 * mac_policy_list holds the list of policy modules. Modules with a
258 * handle lower than staticmax are considered "static" and cannot be
259 * unloaded. Such policies can be invoked without holding the busy count.
260 *
261 * Modules with a handle at or above the staticmax high water mark
262 * are considered to be "dynamic" policies. A busy count is maintained
263 * for the list, stored in mac_policy_busy. The busy count is protected
264 * by mac_policy_mtx; the list may be modified only while the busy
265 * count is 0, requiring that the lock be held to prevent new references
266 * to the list from being acquired. For almost all operations,
267 * incrementing the busy count is sufficient to guarantee consistency,
268 * as the list cannot be modified while the busy count is elevated.
269 * For a few special operations involving a change to the list of
270 * active policies, the mtx itself must be held.
271 */
272 static lck_mtx_t *mac_policy_mtx;
273
274 /*
275 * Policy list array allocation chunk size. Trying to set this so that we
276 * allocate a page at a time.
277 */
278 #define MAC_POLICY_LIST_CHUNKSIZE 512
279
280 static int mac_policy_busy;
281
282 #if CONFIG_EMBEDDED
283 SECURITY_READ_ONLY_LATE(mac_policy_list_t) mac_policy_list;
284 SECURITY_READ_ONLY_LATE(static struct mac_policy_list_element) mac_policy_static_entries[MAC_POLICY_LIST_CHUNKSIZE];
285 #else
286 mac_policy_list_t mac_policy_list;
287 #endif
288
289 /*
290 * mac_label_element_list holds the master list of label namespaces for
291 * all the policies. When a policy is loaded, each of it's label namespace
292 * elements is added to the master list if not already present. When a
293 * policy is unloaded, the namespace elements are removed if no other
294 * policy is interested in that namespace element.
295 */
296 struct mac_label_element_list_t mac_label_element_list;
297 struct mac_label_element_list_t mac_static_label_element_list;
298
299 static __inline void
300 mac_policy_grab_exclusive(void)
301 {
302 lck_mtx_lock(mac_policy_mtx);
303 while (mac_policy_busy != 0) {
304 lck_mtx_sleep(mac_policy_mtx, LCK_SLEEP_UNLOCK,
305 (event_t)&mac_policy_busy, THREAD_UNINT);
306 lck_mtx_lock(mac_policy_mtx);
307 }
308 }
309
310 static __inline void
311 mac_policy_release_exclusive(void)
312 {
313 KASSERT(mac_policy_busy == 0,
314 ("mac_policy_release_exclusive(): not exclusive"));
315 lck_mtx_unlock(mac_policy_mtx);
316 thread_wakeup((event_t) &mac_policy_busy);
317 }
318
319 void
320 mac_policy_list_busy(void)
321 {
322 lck_mtx_lock(mac_policy_mtx);
323 mac_policy_busy++;
324 lck_mtx_unlock(mac_policy_mtx);
325 }
326
327 int
328 mac_policy_list_conditional_busy(void)
329 {
330 int ret;
331
332 if (mac_policy_list.numloaded <= mac_policy_list.staticmax) {
333 return 0;
334 }
335
336 lck_mtx_lock(mac_policy_mtx);
337 if (mac_policy_list.numloaded > mac_policy_list.staticmax) {
338 mac_policy_busy++;
339 ret = 1;
340 } else {
341 ret = 0;
342 }
343 lck_mtx_unlock(mac_policy_mtx);
344 return ret;
345 }
346
347 void
348 mac_policy_list_unbusy(void)
349 {
350 lck_mtx_lock(mac_policy_mtx);
351 mac_policy_busy--;
352 KASSERT(mac_policy_busy >= 0, ("MAC_POLICY_LIST_LOCK"));
353 if (mac_policy_busy == 0) {
354 thread_wakeup(&mac_policy_busy);
355 }
356 lck_mtx_unlock(mac_policy_mtx);
357 }
358
359 /*
360 * Early pre-malloc MAC initialization, including appropriate SMP locks.
361 */
362 void
363 mac_policy_init(void)
364 {
365 lck_grp_attr_t *mac_lck_grp_attr;
366 lck_attr_t *mac_lck_attr;
367 lck_grp_t *mac_lck_grp;
368
369 mac_policy_list.numloaded = 0;
370 mac_policy_list.max = MAC_POLICY_LIST_CHUNKSIZE;
371 mac_policy_list.maxindex = 0;
372 mac_policy_list.staticmax = 0;
373 mac_policy_list.freehint = 0;
374 mac_policy_list.chunks = 1;
375
376 #if CONFIG_EMBEDDED
377 mac_policy_list.entries = mac_policy_static_entries;
378 #else
379 mac_policy_list.entries = kalloc(sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE);
380 #endif
381
382 bzero(mac_policy_list.entries, sizeof(struct mac_policy_list_element) * MAC_POLICY_LIST_CHUNKSIZE);
383
384 LIST_INIT(&mac_label_element_list);
385 LIST_INIT(&mac_static_label_element_list);
386
387 mac_lck_grp_attr = lck_grp_attr_alloc_init();
388 mac_lck_grp = lck_grp_alloc_init("MAC lock", mac_lck_grp_attr);
389 mac_lck_attr = lck_attr_alloc_init();
390 lck_attr_setdefault(mac_lck_attr);
391 mac_policy_mtx = lck_mtx_alloc_init(mac_lck_grp, mac_lck_attr);
392 lck_attr_free(mac_lck_attr);
393 lck_grp_attr_free(mac_lck_grp_attr);
394 lck_grp_free(mac_lck_grp);
395
396 mac_labelzone_init();
397 }
398
399 /* Function pointer set up for loading security extensions.
400 * It is set to an actual function after OSlibkernInit()
401 * has been called, and is set back to 0 by OSKextRemoveKextBootstrap()
402 * after bsd_init().
403 */
404 void (*load_security_extensions_function)(void) = 0;
405
406 /*
407 * Init after early Mach startup, but before BSD
408 */
409 void
410 mac_policy_initmach(void)
411 {
412 /*
413 * For the purposes of modules that want to know if they were
414 * loaded "early", set the mac_late flag once we've processed
415 * modules either linked into the kernel, or loaded before the
416 * kernel startup.
417 */
418
419 if (load_security_extensions_function) {
420 load_security_extensions_function();
421 }
422 mac_late = 1;
423 }
424
425 /*
426 * BSD startup.
427 */
428 void
429 mac_policy_initbsd(void)
430 {
431 struct mac_policy_conf *mpc;
432 u_int i;
433
434 #if CONFIG_AUDIT
435 mac_audit_data_zone = zinit(MAC_AUDIT_DATA_LIMIT,
436 AQ_HIWATER * MAC_AUDIT_DATA_LIMIT,
437 8192, "mac_audit_data_zone");
438 #endif
439
440 printf("MAC Framework successfully initialized\n");
441
442 /* Call bsd init functions of already loaded policies */
443
444 /*
445 * Using the exclusive lock means no other framework entry
446 * points can proceed while initializations are running.
447 * This may not be necessary.
448 */
449 mac_policy_grab_exclusive();
450
451 for (i = 0; i <= mac_policy_list.maxindex; i++) {
452 mpc = mac_get_mpc(i);
453 if ((mpc != NULL) && (mpc->mpc_ops->mpo_policy_initbsd != NULL)) {
454 (*(mpc->mpc_ops->mpo_policy_initbsd))(mpc);
455 }
456 }
457
458 mac_policy_release_exclusive();
459 }
460
461 /*
462 * After a policy has been loaded, add the label namespaces managed by the
463 * policy to either the static or non-static label namespace list.
464 * A namespace is added to the the list only if it is not already on one of
465 * the lists.
466 */
467 void
468 mac_policy_addto_labellist(mac_policy_handle_t handle, int static_entry)
469 {
470 struct mac_label_listener **new_mlls;
471 struct mac_label_element *mle, **new_mles;
472 struct mac_label_element_list_t *list;
473 struct mac_policy_conf *mpc;
474 const char *name, *name2;
475 u_int idx, mle_free, mll_free;
476
477 mpc = mac_get_mpc(handle);
478
479 if (mpc->mpc_labelnames == NULL) {
480 return;
481 }
482
483 if (mpc->mpc_labelname_count == 0) {
484 return;
485 }
486
487 if (static_entry) {
488 list = &mac_static_label_element_list;
489 } else {
490 list = &mac_label_element_list;
491 }
492
493 /*
494 * Before we grab the policy list lock, allocate enough memory
495 * to contain the potential new elements so we don't have to
496 * give up the lock, or allocate with the lock held.
497 */
498 MALLOC(new_mles, struct mac_label_element **,
499 sizeof(struct mac_label_element *) *
500 mpc->mpc_labelname_count, M_MACTEMP, M_WAITOK | M_ZERO);
501 for (idx = 0; idx < mpc->mpc_labelname_count; idx++) {
502 MALLOC(new_mles[idx], struct mac_label_element *,
503 sizeof(struct mac_label_element),
504 M_MACTEMP, M_WAITOK);
505 }
506 mle_free = 0;
507 MALLOC(new_mlls, struct mac_label_listener **,
508 sizeof(struct mac_label_listener *) *
509 mpc->mpc_labelname_count, M_MACTEMP, M_WAITOK);
510 for (idx = 0; idx < mpc->mpc_labelname_count; idx++) {
511 MALLOC(new_mlls[idx], struct mac_label_listener *,
512 sizeof(struct mac_label_listener), M_MACTEMP, M_WAITOK);
513 }
514 mll_free = 0;
515
516 if (mac_late) {
517 mac_policy_grab_exclusive();
518 }
519 for (idx = 0; idx < mpc->mpc_labelname_count; idx++) {
520 if (*(name = mpc->mpc_labelnames[idx]) == '?') {
521 name++;
522 }
523 /*
524 * Check both label element lists and add to the
525 * appropriate list only if not already on a list.
526 */
527 LIST_FOREACH(mle, &mac_static_label_element_list, mle_list) {
528 if (*(name2 = mle->mle_name) == '?') {
529 name2++;
530 }
531 if (strcmp(name, name2) == 0) {
532 break;
533 }
534 }
535 if (mle == NULL) {
536 LIST_FOREACH(mle, &mac_label_element_list, mle_list) {
537 if (*(name2 = mle->mle_name) == '?') {
538 name2++;
539 }
540 if (strcmp(name, name2) == 0) {
541 break;
542 }
543 }
544 }
545 if (mle == NULL) {
546 mle = new_mles[mle_free];
547 strlcpy(mle->mle_name, mpc->mpc_labelnames[idx],
548 MAC_MAX_LABEL_ELEMENT_NAME);
549 LIST_INIT(&mle->mle_listeners);
550 LIST_INSERT_HEAD(list, mle, mle_list);
551 mle_free++;
552 }
553 /* Add policy handler as a listener. */
554 new_mlls[mll_free]->mll_handle = handle;
555 LIST_INSERT_HEAD(&mle->mle_listeners, new_mlls[mll_free],
556 mll_list);
557 mll_free++;
558 }
559 if (mac_late) {
560 mac_policy_release_exclusive();
561 }
562
563 /* Free up any unused label elements and listeners */
564 for (idx = mle_free; idx < mpc->mpc_labelname_count; idx++) {
565 FREE(new_mles[idx], M_MACTEMP);
566 }
567 FREE(new_mles, M_MACTEMP);
568 for (idx = mll_free; idx < mpc->mpc_labelname_count; idx++) {
569 FREE(new_mlls[idx], M_MACTEMP);
570 }
571 FREE(new_mlls, M_MACTEMP);
572 }
573
574 /*
575 * After a policy has been unloaded, remove the label namespaces that the
576 * the policy manages from the non-static list of namespaces.
577 * The removal only takes place when no other policy is interested in the
578 * namespace.
579 *
580 * Must be called with the policy exclusive lock held.
581 */
582 void
583 mac_policy_removefrom_labellist(mac_policy_handle_t handle)
584 {
585 struct mac_label_listener *mll;
586 struct mac_label_element *mle;
587 struct mac_policy_conf *mpc;
588
589 mpc = mac_get_mpc(handle);
590
591 if (mpc->mpc_labelnames == NULL) {
592 return;
593 }
594
595 if (mpc->mpc_labelname_count == 0) {
596 return;
597 }
598
599 /*
600 * Unregister policy as being interested in any label
601 * namespaces. If no other policy is listening, remove
602 * that label element from the list. Note that we only
603 * have to worry about the non-static list.
604 */
605 LIST_FOREACH(mle, &mac_label_element_list, mle_list) {
606 LIST_FOREACH(mll, &mle->mle_listeners, mll_list) {
607 if (mll->mll_handle == handle) {
608 LIST_REMOVE(mll, mll_list);
609 FREE(mll, M_MACTEMP);
610 if (LIST_EMPTY(&mle->mle_listeners)) {
611 LIST_REMOVE(mle, mle_list);
612 FREE(mle, M_MACTEMP);
613 }
614 return;
615 }
616 }
617 }
618 }
619
620 /*
621 * After the policy list has changed, walk the list to update any global
622 * flags.
623 */
624 static void
625 mac_policy_updateflags(void)
626 {
627 }
628
629 static __inline void
630 mac_policy_fixup_mmd_list(struct mac_module_data *new)
631 {
632 struct mac_module_data *old;
633 struct mac_module_data_element *ele, *aele;
634 struct mac_module_data_list *arr, *dict;
635 unsigned int i, j, k;
636
637 old = new->base_addr;
638 DPRINTF(("fixup_mmd: old %p new %p\n", old, new));
639 for (i = 0; i < new->count; i++) {
640 ele = &(new->data[i]);
641 DPRINTF(("fixup_mmd: ele %p\n", ele));
642 DPRINTF((" key %p value %p\n", ele->key, ele->value));
643 mmd_fixup_ele(old, new, ele); /* Fix up key/value ptrs. */
644 DPRINTF((" key %p value %p\n", ele->key, ele->value));
645 if (ele->value_type == MAC_DATA_TYPE_ARRAY) {
646 arr = (struct mac_module_data_list *)ele->value;
647 DPRINTF(("fixup_mmd: array @%p\n", arr));
648 for (j = 0; j < arr->count; j++) {
649 aele = &(arr->list[j]);
650 DPRINTF(("fixup_mmd: aele %p\n", aele));
651 DPRINTF((" key %p value %p\n", aele->key, aele->value));
652 mmd_fixup_ele(old, new, aele);
653 DPRINTF((" key %p value %p\n", aele->key, aele->value));
654 if (arr->type == MAC_DATA_TYPE_DICT) {
655 dict = (struct mac_module_data_list *)aele->value;
656 DPRINTF(("fixup_mmd: dict @%p\n", dict));
657 for (k = 0; k < dict->count; k++) {
658 mmd_fixup_ele(old, new,
659 &(dict->list[k]));
660 }
661 }
662 }
663 }
664 }
665 new->base_addr = new;
666 }
667
668 int
669 mac_policy_register(struct mac_policy_conf *mpc, mac_policy_handle_t *handlep,
670 void *xd)
671 {
672 #if !CONFIG_EMBEDDED
673 struct mac_policy_list_element *tmac_policy_list_element;
674 #endif
675 int error, slot, static_entry = 0;
676 u_int i;
677
678 /*
679 * Some preliminary checks to make sure the policy's conf structure
680 * contains the required fields.
681 */
682 if (mpc->mpc_name == NULL) {
683 panic("policy's name is not set\n");
684 }
685
686 if (mpc->mpc_fullname == NULL) {
687 panic("policy's full name is not set\n");
688 }
689
690 if (mpc->mpc_labelname_count > MAC_MAX_MANAGED_NAMESPACES) {
691 panic("policy's managed label namespaces exceeds maximum\n");
692 }
693
694 if (mpc->mpc_ops == NULL) {
695 panic("policy's OPs field is NULL\n");
696 }
697
698 error = 0;
699
700 if (mac_late) {
701 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE) {
702 printf("Module %s does not support late loading.\n",
703 mpc->mpc_name);
704 return EPERM;
705 }
706 mac_policy_grab_exclusive();
707 }
708
709 if (mac_policy_list.numloaded >= mac_policy_list.max) {
710 #if !CONFIG_EMBEDDED
711 /* allocate new policy list array, zero new chunk */
712 tmac_policy_list_element =
713 kalloc((sizeof(struct mac_policy_list_element) *
714 MAC_POLICY_LIST_CHUNKSIZE) * (mac_policy_list.chunks + 1));
715 bzero(&tmac_policy_list_element[mac_policy_list.max],
716 sizeof(struct mac_policy_list_element) *
717 MAC_POLICY_LIST_CHUNKSIZE);
718
719 /* copy old entries into new list */
720 memcpy(tmac_policy_list_element, mac_policy_list.entries,
721 sizeof(struct mac_policy_list_element) *
722 MAC_POLICY_LIST_CHUNKSIZE * mac_policy_list.chunks);
723
724 /* free old array */
725 kfree(mac_policy_list.entries,
726 sizeof(struct mac_policy_list_element) *
727 MAC_POLICY_LIST_CHUNKSIZE * mac_policy_list.chunks);
728
729 mac_policy_list.entries = tmac_policy_list_element;
730
731 /* Update maximums, etc */
732 mac_policy_list.max += MAC_POLICY_LIST_CHUNKSIZE;
733 mac_policy_list.chunks++;
734 #else
735 printf("out of space in mac_policy_list.\n");
736 return ENOMEM;
737 #endif /* CONFIG_EMBEDDED */
738 }
739
740 /* Check for policy with same name already loaded */
741 for (i = 0; i <= mac_policy_list.maxindex; i++) {
742 if (mac_policy_list.entries[i].mpc == NULL) {
743 continue;
744 }
745
746 if (strcmp(mac_policy_list.entries[i].mpc->mpc_name,
747 mpc->mpc_name) == 0) {
748 error = EEXIST;
749 goto out;
750 }
751 }
752
753 if (mpc->mpc_field_off != NULL) {
754 slot = ffs(mac_slot_offsets_free);
755 if (slot == 0) {
756 error = ENOMEM;
757 goto out;
758 }
759 slot--;
760 mac_slot_offsets_free &= ~(1 << slot);
761 *mpc->mpc_field_off = slot;
762 }
763 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
764
765 if (xd) {
766 struct mac_module_data *mmd = xd; /* module data from plist */
767
768 /* Make a copy of the data. */
769 mpc->mpc_data = (void *)kalloc(mmd->size);
770 if (mpc->mpc_data != NULL) {
771 memcpy(mpc->mpc_data, mmd, mmd->size);
772
773 /* Fix up pointers after copy. */
774 mac_policy_fixup_mmd_list(mpc->mpc_data);
775 }
776 }
777
778 /* Find the first free handle in the list (using our hint). */
779 for (i = mac_policy_list.freehint; i < mac_policy_list.max; i++) {
780 if (mac_policy_list.entries[i].mpc == NULL) {
781 *handlep = i;
782 mac_policy_list.freehint = ++i;
783 break;
784 }
785 }
786
787 /*
788 * If we are loading a MAC module before the framework has
789 * finished initializing or the module is not unloadable and
790 * we can place its handle adjacent to the last static entry,
791 * bump the static policy high water mark.
792 * Static policies can get by with weaker locking requirements.
793 */
794 if (!mac_late ||
795 ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0 &&
796 *handlep == mac_policy_list.staticmax)) {
797 static_entry = 1;
798 mac_policy_list.staticmax++;
799 }
800
801 mac_policy_list.entries[*handlep].mpc = mpc;
802
803 /* Update counters, etc */
804 if (*handlep > mac_policy_list.maxindex) {
805 mac_policy_list.maxindex = *handlep;
806 }
807 mac_policy_list.numloaded++;
808
809 /* Per-policy initialization. */
810 printf("calling mpo_policy_init for %s\n", mpc->mpc_name);
811 if (mpc->mpc_ops->mpo_policy_init != NULL) {
812 (*(mpc->mpc_ops->mpo_policy_init))(mpc);
813 }
814
815 if (mac_late && mpc->mpc_ops->mpo_policy_initbsd != NULL) {
816 printf("calling mpo_policy_initbsd for %s\n", mpc->mpc_name);
817 (*(mpc->mpc_ops->mpo_policy_initbsd))(mpc);
818 }
819
820 mac_policy_updateflags();
821
822 if (mac_late) {
823 mac_policy_release_exclusive();
824 }
825
826 mac_policy_addto_labellist(*handlep, static_entry);
827
828 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
829 mpc->mpc_name);
830
831 return 0;
832
833 out:
834 if (mac_late) {
835 mac_policy_release_exclusive();
836 }
837
838 return error;
839 }
840
841 int
842 mac_policy_unregister(mac_policy_handle_t handle)
843 {
844 struct mac_policy_conf *mpc;
845
846 /*
847 * If we fail the load, we may get a request to unload. Check
848 * to see if we did the run-time registration, and if not,
849 * silently succeed.
850 */
851 mac_policy_grab_exclusive();
852 mpc = mac_get_mpc(handle);
853 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
854 mac_policy_release_exclusive();
855 return 0;
856 }
857
858 #if 0
859 /*
860 * Don't allow unloading modules with private data.
861 */
862 if (mpc->mpc_field_off != NULL) {
863 MAC_POLICY_LIST_UNLOCK();
864 return EBUSY;
865 }
866 #endif
867 /*
868 * Only allow the unload to proceed if the module is unloadable
869 * by its own definition.
870 */
871 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
872 mac_policy_release_exclusive();
873 return EBUSY;
874 }
875
876 mac_policy_removefrom_labellist(handle);
877
878 mac_get_mpc(handle) = NULL;
879 if (handle < mac_policy_list.freehint &&
880 handle >= mac_policy_list.staticmax) {
881 mac_policy_list.freehint = handle;
882 }
883
884 if (handle == mac_policy_list.maxindex) {
885 mac_policy_list.maxindex--;
886 }
887
888 mac_policy_list.numloaded--;
889 if (mpc->mpc_field_off != NULL) {
890 mac_slot_offsets_free |= (1 << *mpc->mpc_field_off);
891 }
892
893 if (mpc->mpc_ops->mpo_policy_destroy != NULL) {
894 (*(mpc->mpc_ops->mpo_policy_destroy))(mpc);
895 }
896
897 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
898 mac_policy_updateflags();
899
900 mac_policy_release_exclusive();
901
902 if (mpc->mpc_data) {
903 struct mac_module_data *mmd = mpc->mpc_data;
904 kfree(mmd, mmd->size);
905 mpc->mpc_data = NULL;
906 }
907
908 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
909 mpc->mpc_name);
910
911 return 0;
912 }
913
914 /*
915 * Define an error value precedence, and given two arguments, selects the
916 * value with the higher precedence.
917 */
918 int
919 mac_error_select(int error1, int error2)
920 {
921 /* Certain decision-making errors take top priority. */
922 if (error1 == EDEADLK || error2 == EDEADLK) {
923 return EDEADLK;
924 }
925
926 /* Invalid arguments should be reported where possible. */
927 if (error1 == EINVAL || error2 == EINVAL) {
928 return EINVAL;
929 }
930
931 /* Precedence goes to "visibility", with both process and file. */
932 if (error1 == ESRCH || error2 == ESRCH) {
933 return ESRCH;
934 }
935
936 if (error1 == ENOENT || error2 == ENOENT) {
937 return ENOENT;
938 }
939
940 /* Precedence goes to DAC/MAC protections. */
941 if (error1 == EACCES || error2 == EACCES) {
942 return EACCES;
943 }
944
945 /* Precedence goes to privilege. */
946 if (error1 == EPERM || error2 == EPERM) {
947 return EPERM;
948 }
949
950 /* Precedence goes to error over success; otherwise, arbitrary. */
951 if (error1 != 0) {
952 return error1;
953 }
954 return error2;
955 }
956
957 void
958 mac_label_init(struct label *label)
959 {
960 bzero(label, sizeof(*label));
961 label->l_flags = MAC_FLAG_INITIALIZED;
962 }
963
964 void
965 mac_label_destroy(struct label *label)
966 {
967 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
968 ("destroying uninitialized label"));
969
970 bzero(label, sizeof(*label));
971 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
972 }
973
974 int
975 mac_check_structmac_consistent(struct user_mac *mac)
976 {
977 if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN || mac->m_buflen == 0) {
978 return EINVAL;
979 }
980
981 return 0;
982 }
983
984 /*
985 * Get the external forms of labels from all policies, for a single
986 * label namespace or "*" for all namespaces. Returns ENOENT if no policy
987 * is registered for the namespace, unless the namespace begins with a '?'.
988 */
989 static int
990 mac_label_externalize(size_t mpo_externalize_off, struct label *label,
991 const char *element, struct sbuf *sb)
992 {
993 struct mac_policy_conf *mpc;
994 struct mac_label_listener *mll;
995 struct mac_label_element *mle;
996 struct mac_label_element_list_t *element_list;
997 const char *name;
998 int (*mpo_externalize)(struct label *, char *, struct sbuf *);
999 int all_labels = 0, ignorenotfound = 0, error = 0, busy = FALSE;
1000 unsigned int count = 0;
1001
1002 if (element[0] == '?') {
1003 element++;
1004 ignorenotfound = 1;
1005 } else if (element[0] == '*' && element[1] == '\0') {
1006 all_labels = 1;
1007 }
1008
1009 element_list = &mac_static_label_element_list;
1010 element_loop:
1011 LIST_FOREACH(mle, element_list, mle_list) {
1012 name = mle->mle_name;
1013 if (all_labels) {
1014 if (*name == '?') {
1015 continue;
1016 }
1017 } else {
1018 if (*name == '?') {
1019 name++;
1020 }
1021 if (strcmp(name, element) != 0) {
1022 continue;
1023 }
1024 }
1025 LIST_FOREACH(mll, &mle->mle_listeners, mll_list) {
1026 mpc = mac_policy_list.entries[mll->mll_handle].mpc;
1027 if (mpc == NULL) {
1028 continue;
1029 }
1030 mpo_externalize = *(const typeof(mpo_externalize) *)
1031 ((const char *)mpc->mpc_ops + mpo_externalize_off);
1032 if (mpo_externalize == NULL) {
1033 continue;
1034 }
1035 error = sbuf_printf(sb, "%s/", name);
1036 if (error) {
1037 goto done;
1038 }
1039 error = mpo_externalize(label, mle->mle_name, sb);
1040 if (error) {
1041 if (error != ENOENT) {
1042 goto done;
1043 }
1044 /*
1045 * If a policy doesn't have a label to
1046 * externalize it returns ENOENT. This
1047 * may occur for policies that support
1048 * multiple label elements for some
1049 * (but not all) object types.
1050 */
1051 sbuf_setpos(sb, sbuf_len(sb) -
1052 (strlen(name) + 1));
1053 error = 0;
1054 continue;
1055 }
1056 error = sbuf_putc(sb, ',');
1057 if (error) {
1058 goto done;
1059 }
1060 count++;
1061 }
1062 }
1063 /* If there are dynamic policies present, check their elements too. */
1064 if (!busy && mac_policy_list_conditional_busy() == 1) {
1065 element_list = &mac_label_element_list;
1066 busy = TRUE;
1067 goto element_loop;
1068 }
1069 done:
1070 if (busy) {
1071 mac_policy_list_unbusy();
1072 }
1073 if (!error && count == 0) {
1074 if (!all_labels && !ignorenotfound) {
1075 error = ENOENT; /* XXX: ENOLABEL? */
1076 }
1077 }
1078 return error;
1079 }
1080
1081 /*
1082 * Get the external forms of labels from all policies, for all label
1083 * namespaces contained in a list.
1084 *
1085 * XXX This may be leaking an sbuf.
1086 */
1087 int
1088 mac_externalize(size_t mpo_externalize_off, struct label *label,
1089 const char *elementlist, char *outbuf, size_t outbuflen)
1090 {
1091 char *element;
1092 char *scratch_base;
1093 char *scratch;
1094 struct sbuf sb;
1095 int error = 0, len;
1096
1097 /* allocate a scratch buffer the size of the string */
1098 MALLOC(scratch_base, char *, strlen(elementlist) + 1, M_MACTEMP, M_WAITOK);
1099 if (scratch_base == NULL) {
1100 error = ENOMEM;
1101 goto out;
1102 }
1103
1104 /* copy the elementlist to the scratch buffer */
1105 strlcpy(scratch_base, elementlist, strlen(elementlist) + 1);
1106
1107 /*
1108 * set up a temporary pointer that can be used to iterate the
1109 * scratch buffer without losing the allocation address
1110 */
1111 scratch = scratch_base;
1112
1113 /* get an sbuf */
1114 if (sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN) == NULL) {
1115 /* could not allocate interior buffer */
1116 error = ENOMEM;
1117 goto out;
1118 }
1119 /* iterate the scratch buffer; NOTE: buffer contents modified! */
1120 while ((element = strsep(&scratch, ",")) != NULL) {
1121 error = mac_label_externalize(mpo_externalize_off, label,
1122 element, &sb);
1123 if (error) {
1124 break;
1125 }
1126 }
1127 if ((len = sbuf_len(&sb)) > 0) {
1128 sbuf_setpos(&sb, len - 1); /* trim trailing comma */
1129 }
1130 sbuf_finish(&sb);
1131
1132 out:
1133 if (scratch_base != NULL) {
1134 FREE(scratch_base, M_MACTEMP);
1135 }
1136
1137 return error;
1138 }
1139
1140 /*
1141 * Have all policies set the internal form of a label, for a single
1142 * label namespace.
1143 */
1144 static int
1145 mac_label_internalize(size_t mpo_internalize_off, struct label *label,
1146 char *element_name, char *element_data)
1147 {
1148 struct mac_policy_conf *mpc;
1149 struct mac_label_listener *mll;
1150 struct mac_label_element *mle;
1151 struct mac_label_element_list_t *element_list;
1152 int (*mpo_internalize)(struct label *, char *, char *);
1153 int error = 0, busy = FALSE;
1154 unsigned int count = 0;
1155 const char *name;
1156
1157 element_list = &mac_static_label_element_list;
1158 element_loop:
1159 LIST_FOREACH(mle, element_list, mle_list) {
1160 if (*(name = mle->mle_name) == '?') {
1161 name++;
1162 }
1163 if (strcmp(element_name, name) != 0) {
1164 continue;
1165 }
1166 LIST_FOREACH(mll, &mle->mle_listeners, mll_list) {
1167 mpc = mac_policy_list.entries[mll->mll_handle].mpc;
1168 if (mpc == NULL) {
1169 continue;
1170 }
1171 mpo_internalize = *(const typeof(mpo_internalize) *)
1172 ((const char *)mpc->mpc_ops + mpo_internalize_off);
1173 if (mpo_internalize == NULL) {
1174 continue;
1175 }
1176 error = mpo_internalize(label, element_name,
1177 element_data);
1178 if (error) {
1179 goto done;
1180 }
1181 count++;
1182 }
1183 }
1184 /* If there are dynamic policies present, check their elements too. */
1185 if (!busy && mac_policy_list_conditional_busy() == 1) {
1186 element_list = &mac_label_element_list;
1187 busy = TRUE;
1188 goto element_loop;
1189 }
1190 done:
1191 if (busy) {
1192 mac_policy_list_unbusy();
1193 }
1194 if (!error && count == 0) {
1195 error = ENOPOLICY;
1196 }
1197 return error;
1198 }
1199
1200 int
1201 mac_internalize(size_t mpo_internalize_off, struct label *label,
1202 char *textlabels)
1203 {
1204 char *element_name, *element_data;
1205 int error = 0;
1206
1207 while (!error && (element_name = strsep(&textlabels, ",")) != NULL) {
1208 element_data = strchr(element_name, '/');
1209 if (element_data == NULL) {
1210 error = EINVAL;
1211 break;
1212 }
1213 *element_data++ = '\0';
1214 error = mac_label_internalize(mpo_internalize_off, label,
1215 element_name, element_data);
1216 }
1217 return error;
1218 }
1219
1220 /* system calls */
1221
1222 int
1223 __mac_get_pid(struct proc *p, struct __mac_get_pid_args *uap, int *ret __unused)
1224 {
1225 char *elements, *buffer;
1226 struct user_mac mac;
1227 struct proc *tproc;
1228 struct ucred *tcred;
1229 int error;
1230 size_t ulen;
1231
1232 AUDIT_ARG(pid, uap->pid);
1233 if (IS_64BIT_PROCESS(p)) {
1234 struct user64_mac mac64;
1235 error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1236 mac.m_buflen = mac64.m_buflen;
1237 mac.m_string = mac64.m_string;
1238 } else {
1239 struct user32_mac mac32;
1240 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1241 mac.m_buflen = mac32.m_buflen;
1242 mac.m_string = mac32.m_string;
1243 }
1244 if (error) {
1245 return error;
1246 }
1247
1248 error = mac_check_structmac_consistent(&mac);
1249 if (error) {
1250 return error;
1251 }
1252
1253 tproc = proc_find(uap->pid);
1254 if (tproc == NULL) {
1255 return ESRCH;
1256 }
1257 tcred = kauth_cred_proc_ref(tproc);
1258 proc_rele(tproc);
1259
1260 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1261 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1262 if (error) {
1263 FREE(elements, M_MACTEMP);
1264 kauth_cred_unref(&tcred);
1265 return error;
1266 }
1267 AUDIT_ARG(mac_string, elements);
1268
1269 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1270 error = mac_cred_label_externalize(tcred->cr_label, elements,
1271 buffer, mac.m_buflen, M_WAITOK);
1272 if (error == 0) {
1273 error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
1274 }
1275
1276 FREE(buffer, M_MACTEMP);
1277 FREE(elements, M_MACTEMP);
1278 kauth_cred_unref(&tcred);
1279 return error;
1280 }
1281
1282 int
1283 __mac_get_proc(proc_t p, struct __mac_get_proc_args *uap, int *ret __unused)
1284 {
1285 char *elements, *buffer;
1286 struct user_mac mac;
1287 kauth_cred_t cr;
1288 int error;
1289 size_t ulen;
1290
1291 if (IS_64BIT_PROCESS(p)) {
1292 struct user64_mac mac64;
1293 error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1294 mac.m_buflen = mac64.m_buflen;
1295 mac.m_string = mac64.m_string;
1296 } else {
1297 struct user32_mac mac32;
1298 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1299 mac.m_buflen = mac32.m_buflen;
1300 mac.m_string = mac32.m_string;
1301 }
1302 if (error) {
1303 return error;
1304 }
1305
1306 error = mac_check_structmac_consistent(&mac);
1307 if (error) {
1308 return error;
1309 }
1310
1311 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1312 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1313 if (error) {
1314 FREE(elements, M_MACTEMP);
1315 return error;
1316 }
1317 AUDIT_ARG(mac_string, elements);
1318
1319 cr = kauth_cred_proc_ref(p);
1320
1321 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1322 error = mac_cred_label_externalize(cr->cr_label,
1323 elements, buffer, mac.m_buflen, M_WAITOK);
1324 if (error == 0) {
1325 error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
1326 }
1327
1328 FREE(buffer, M_MACTEMP);
1329 FREE(elements, M_MACTEMP);
1330 kauth_cred_unref(&cr);
1331 return error;
1332 }
1333
1334 int
1335 __mac_set_proc(proc_t p, struct __mac_set_proc_args *uap, int *ret __unused)
1336 {
1337 struct label *intlabel;
1338 struct user_mac mac;
1339 char *buffer;
1340 int error;
1341 size_t ulen;
1342
1343 if (IS_64BIT_PROCESS(p)) {
1344 struct user64_mac mac64;
1345 error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1346 mac.m_buflen = mac64.m_buflen;
1347 mac.m_string = mac64.m_string;
1348 } else {
1349 struct user32_mac mac32;
1350 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1351 mac.m_buflen = mac32.m_buflen;
1352 mac.m_string = mac32.m_string;
1353 }
1354 if (error) {
1355 return error;
1356 }
1357
1358 error = mac_check_structmac_consistent(&mac);
1359 if (error) {
1360 return error;
1361 }
1362
1363 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1364 error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
1365 if (error) {
1366 FREE(buffer, M_MACTEMP);
1367 return error;
1368 }
1369 AUDIT_ARG(mac_string, buffer);
1370
1371 intlabel = mac_cred_label_alloc();
1372 error = mac_cred_label_internalize(intlabel, buffer);
1373 FREE(buffer, M_MACTEMP);
1374 if (error) {
1375 goto out;
1376 }
1377
1378 error = mac_cred_check_label_update(kauth_cred_get(), intlabel);
1379 if (error) {
1380 goto out;
1381 }
1382
1383 error = kauth_proc_label_update(p, intlabel);
1384 if (error) {
1385 goto out;
1386 }
1387
1388 out:
1389 mac_cred_label_free(intlabel);
1390 return error;
1391 }
1392
1393 int
1394 __mac_get_fd(proc_t p, struct __mac_get_fd_args *uap, int *ret __unused)
1395 {
1396 struct fileproc *fp;
1397 struct vnode *vp;
1398 struct user_mac mac;
1399 char *elements, *buffer;
1400 int error;
1401 size_t ulen;
1402 kauth_cred_t my_cred;
1403 #if CONFIG_MACF_SOCKET
1404 struct socket *so;
1405 #endif /* MAC_SOCKET */
1406 struct label *intlabel;
1407
1408 AUDIT_ARG(fd, uap->fd);
1409
1410 if (IS_64BIT_PROCESS(p)) {
1411 struct user64_mac mac64;
1412 error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1413 mac.m_buflen = mac64.m_buflen;
1414 mac.m_string = mac64.m_string;
1415 } else {
1416 struct user32_mac mac32;
1417 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1418 mac.m_buflen = mac32.m_buflen;
1419 mac.m_string = mac32.m_string;
1420 }
1421
1422 if (error) {
1423 return error;
1424 }
1425
1426 error = mac_check_structmac_consistent(&mac);
1427 if (error) {
1428 return error;
1429 }
1430
1431 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1432 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1433 if (error) {
1434 FREE(elements, M_MACTEMP);
1435 return error;
1436 }
1437 AUDIT_ARG(mac_string, elements);
1438
1439 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1440 error = fp_lookup(p, uap->fd, &fp, 0);
1441 if (error) {
1442 FREE(buffer, M_MACTEMP);
1443 FREE(elements, M_MACTEMP);
1444 return error;
1445 }
1446
1447 my_cred = kauth_cred_proc_ref(p);
1448 error = mac_file_check_get(my_cred, fp->f_fglob, elements, mac.m_buflen);
1449 kauth_cred_unref(&my_cred);
1450 if (error) {
1451 fp_drop(p, uap->fd, fp, 0);
1452 FREE(buffer, M_MACTEMP);
1453 FREE(elements, M_MACTEMP);
1454 return error;
1455 }
1456
1457 switch (FILEGLOB_DTYPE(fp->f_fglob)) {
1458 case DTYPE_VNODE:
1459 intlabel = mac_vnode_label_alloc();
1460 if (intlabel == NULL) {
1461 error = ENOMEM;
1462 break;
1463 }
1464 vp = (struct vnode *)fp->f_fglob->fg_data;
1465 error = vnode_getwithref(vp);
1466 if (error == 0) {
1467 mac_vnode_label_copy(vp->v_label, intlabel);
1468 error = mac_vnode_label_externalize(intlabel,
1469 elements, buffer,
1470 mac.m_buflen, M_WAITOK);
1471 vnode_put(vp);
1472 }
1473 mac_vnode_label_free(intlabel);
1474 break;
1475 case DTYPE_SOCKET:
1476 #if CONFIG_MACF_SOCKET
1477 so = (struct socket *) fp->f_fglob->fg_data;
1478 intlabel = mac_socket_label_alloc(MAC_WAITOK);
1479 sock_lock(so, 1);
1480 mac_socket_label_copy(so->so_label, intlabel);
1481 sock_unlock(so, 1);
1482 error = mac_socket_label_externalize(intlabel, elements, buffer, mac.m_buflen);
1483 mac_socket_label_free(intlabel);
1484 break;
1485 #endif
1486 case DTYPE_PSXSHM:
1487 case DTYPE_PSXSEM:
1488 case DTYPE_PIPE:
1489 case DTYPE_KQUEUE:
1490 case DTYPE_FSEVENTS:
1491 case DTYPE_ATALK:
1492 case DTYPE_NETPOLICY:
1493 default:
1494 error = ENOSYS; // only sockets/vnodes so far
1495 break;
1496 }
1497 fp_drop(p, uap->fd, fp, 0);
1498
1499 if (error == 0) {
1500 error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
1501 }
1502
1503 FREE(buffer, M_MACTEMP);
1504 FREE(elements, M_MACTEMP);
1505 return error;
1506 }
1507
1508 static int
1509 mac_get_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p, int follow)
1510 {
1511 struct vnode *vp;
1512 vfs_context_t ctx;
1513 char *elements, *buffer;
1514 struct nameidata nd;
1515 struct label *intlabel;
1516 struct user_mac mac;
1517 int error;
1518 size_t ulen;
1519
1520 if (IS_64BIT_PROCESS(p)) {
1521 struct user64_mac mac64;
1522 error = copyin(mac_p, &mac64, sizeof(mac64));
1523 mac.m_buflen = mac64.m_buflen;
1524 mac.m_string = mac64.m_string;
1525 } else {
1526 struct user32_mac mac32;
1527 error = copyin(mac_p, &mac32, sizeof(mac32));
1528 mac.m_buflen = mac32.m_buflen;
1529 mac.m_string = mac32.m_string;
1530 }
1531
1532 if (error) {
1533 return error;
1534 }
1535
1536 error = mac_check_structmac_consistent(&mac);
1537 if (error) {
1538 return error;
1539 }
1540
1541 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1542 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1543
1544 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1545 if (error) {
1546 FREE(buffer, M_MACTEMP);
1547 FREE(elements, M_MACTEMP);
1548 return error;
1549 }
1550 AUDIT_ARG(mac_string, elements);
1551
1552 ctx = vfs_context_current();
1553
1554 NDINIT(&nd, LOOKUP, OP_LOOKUP,
1555 LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1,
1556 UIO_USERSPACE, path_p, ctx);
1557 error = namei(&nd);
1558 if (error) {
1559 FREE(buffer, M_MACTEMP);
1560 FREE(elements, M_MACTEMP);
1561 return error;
1562 }
1563 vp = nd.ni_vp;
1564
1565 nameidone(&nd);
1566
1567 intlabel = mac_vnode_label_alloc();
1568 mac_vnode_label_copy(vp->v_label, intlabel);
1569 error = mac_vnode_label_externalize(intlabel, elements, buffer,
1570 mac.m_buflen, M_WAITOK);
1571 mac_vnode_label_free(intlabel);
1572 if (error == 0) {
1573 error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
1574 }
1575
1576 vnode_put(vp);
1577
1578 FREE(buffer, M_MACTEMP);
1579 FREE(elements, M_MACTEMP);
1580
1581 return error;
1582 }
1583
1584 int
1585 __mac_get_file(proc_t p, struct __mac_get_file_args *uap,
1586 int *ret __unused)
1587 {
1588 return mac_get_filelink(p, uap->mac_p, uap->path_p, 1);
1589 }
1590
1591 int
1592 __mac_get_link(proc_t p, struct __mac_get_link_args *uap,
1593 int *ret __unused)
1594 {
1595 return mac_get_filelink(p, uap->mac_p, uap->path_p, 0);
1596 }
1597
1598 int
1599 __mac_set_fd(proc_t p, struct __mac_set_fd_args *uap, int *ret __unused)
1600 {
1601 struct fileproc *fp;
1602 struct user_mac mac;
1603 struct vfs_context *ctx = vfs_context_current();
1604 int error;
1605 size_t ulen;
1606 char *buffer;
1607 struct label *intlabel;
1608 #if CONFIG_MACF_SOCKET
1609 struct socket *so;
1610 #endif
1611 struct vnode *vp;
1612
1613 AUDIT_ARG(fd, uap->fd);
1614
1615 if (IS_64BIT_PROCESS(p)) {
1616 struct user64_mac mac64;
1617 error = copyin(uap->mac_p, &mac64, sizeof(mac64));
1618 mac.m_buflen = mac64.m_buflen;
1619 mac.m_string = mac64.m_string;
1620 } else {
1621 struct user32_mac mac32;
1622 error = copyin(uap->mac_p, &mac32, sizeof(mac32));
1623 mac.m_buflen = mac32.m_buflen;
1624 mac.m_string = mac32.m_string;
1625 }
1626 if (error) {
1627 return error;
1628 }
1629
1630 error = mac_check_structmac_consistent(&mac);
1631 if (error) {
1632 return error;
1633 }
1634
1635 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1636 error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
1637 if (error) {
1638 FREE(buffer, M_MACTEMP);
1639 return error;
1640 }
1641 AUDIT_ARG(mac_string, buffer);
1642
1643 error = fp_lookup(p, uap->fd, &fp, 0);
1644 if (error) {
1645 FREE(buffer, M_MACTEMP);
1646 return error;
1647 }
1648
1649
1650 error = mac_file_check_set(vfs_context_ucred(ctx), fp->f_fglob, buffer, mac.m_buflen);
1651 if (error) {
1652 fp_drop(p, uap->fd, fp, 0);
1653 FREE(buffer, M_MACTEMP);
1654 return error;
1655 }
1656
1657 switch (FILEGLOB_DTYPE(fp->f_fglob)) {
1658 case DTYPE_VNODE:
1659 if (mac_label_vnodes == 0) {
1660 error = ENOSYS;
1661 break;
1662 }
1663
1664 intlabel = mac_vnode_label_alloc();
1665
1666 error = mac_vnode_label_internalize(intlabel, buffer);
1667 if (error) {
1668 mac_vnode_label_free(intlabel);
1669 break;
1670 }
1671
1672
1673 vp = (struct vnode *)fp->f_fglob->fg_data;
1674
1675 error = vnode_getwithref(vp);
1676 if (error == 0) {
1677 error = vn_setlabel(vp, intlabel, ctx);
1678 vnode_put(vp);
1679 }
1680 mac_vnode_label_free(intlabel);
1681 break;
1682
1683 case DTYPE_SOCKET:
1684 #if CONFIG_MACF_SOCKET
1685 intlabel = mac_socket_label_alloc(MAC_WAITOK);
1686 error = mac_socket_label_internalize(intlabel, buffer);
1687 if (error == 0) {
1688 so = (struct socket *) fp->f_fglob->fg_data;
1689 SOCK_LOCK(so);
1690 error = mac_socket_label_update(vfs_context_ucred(ctx), so, intlabel);
1691 SOCK_UNLOCK(so);
1692 }
1693 mac_socket_label_free(intlabel);
1694 break;
1695 #endif
1696 case DTYPE_PSXSHM:
1697 case DTYPE_PSXSEM:
1698 case DTYPE_PIPE:
1699 case DTYPE_KQUEUE:
1700 case DTYPE_FSEVENTS:
1701 case DTYPE_ATALK:
1702 case DTYPE_NETPOLICY:
1703 default:
1704 error = ENOSYS; // only sockets/vnodes so far
1705 break;
1706 }
1707
1708 fp_drop(p, uap->fd, fp, 0);
1709 FREE(buffer, M_MACTEMP);
1710 return error;
1711 }
1712
1713 static int
1714 mac_set_filelink(proc_t p, user_addr_t mac_p, user_addr_t path_p,
1715 int follow)
1716 {
1717 struct vnode *vp;
1718 struct vfs_context *ctx = vfs_context_current();
1719 struct label *intlabel;
1720 struct nameidata nd;
1721 struct user_mac mac;
1722 char *buffer;
1723 int error;
1724 size_t ulen;
1725
1726 if (mac_label_vnodes == 0) {
1727 return ENOSYS;
1728 }
1729
1730 if (IS_64BIT_PROCESS(p)) {
1731 struct user64_mac mac64;
1732 error = copyin(mac_p, &mac64, sizeof(mac64));
1733 mac.m_buflen = mac64.m_buflen;
1734 mac.m_string = mac64.m_string;
1735 } else {
1736 struct user32_mac mac32;
1737 error = copyin(mac_p, &mac32, sizeof(mac32));
1738 mac.m_buflen = mac32.m_buflen;
1739 mac.m_string = mac32.m_string;
1740 }
1741 if (error) {
1742 return error;
1743 }
1744
1745 error = mac_check_structmac_consistent(&mac);
1746 if (error) {
1747 printf("mac_set_file: failed structure consistency check\n");
1748 return error;
1749 }
1750
1751 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1752 error = copyinstr(mac.m_string, buffer, mac.m_buflen, &ulen);
1753 if (error) {
1754 FREE(buffer, M_MACTEMP);
1755 return error;
1756 }
1757 AUDIT_ARG(mac_string, buffer);
1758
1759 intlabel = mac_vnode_label_alloc();
1760 error = mac_vnode_label_internalize(intlabel, buffer);
1761 FREE(buffer, M_MACTEMP);
1762 if (error) {
1763 mac_vnode_label_free(intlabel);
1764 return error;
1765 }
1766
1767 NDINIT(&nd, LOOKUP, OP_LOOKUP,
1768 LOCKLEAF | (follow ? FOLLOW : NOFOLLOW) | AUDITVNPATH1,
1769 UIO_USERSPACE, path_p, ctx);
1770 error = namei(&nd);
1771 if (error) {
1772 mac_vnode_label_free(intlabel);
1773 return error;
1774 }
1775 vp = nd.ni_vp;
1776
1777 nameidone(&nd);
1778
1779 error = vn_setlabel(vp, intlabel, ctx);
1780 vnode_put(vp);
1781 mac_vnode_label_free(intlabel);
1782
1783 return error;
1784 }
1785
1786 int
1787 __mac_set_file(proc_t p, struct __mac_set_file_args *uap,
1788 int *ret __unused)
1789 {
1790 return mac_set_filelink(p, uap->mac_p, uap->path_p, 1);
1791 }
1792
1793 int
1794 __mac_set_link(proc_t p, struct __mac_set_link_args *uap,
1795 int *ret __unused)
1796 {
1797 return mac_set_filelink(p, uap->mac_p, uap->path_p, 0);
1798 }
1799
1800 /*
1801 * __mac_syscall: Perform a MAC policy system call
1802 *
1803 * Parameters: p Process calling this routine
1804 * uap User argument descriptor (see below)
1805 * retv (Unused)
1806 *
1807 * Indirect: uap->policy Name of target MAC policy
1808 * uap->call MAC policy-specific system call to perform
1809 * uap->arg MAC policy-specific system call arguments
1810 *
1811 * Returns: 0 Success
1812 * !0 Not success
1813 *
1814 */
1815 int
1816 __mac_syscall(proc_t p, struct __mac_syscall_args *uap, int *retv __unused)
1817 {
1818 struct mac_policy_conf *mpc;
1819 char target[MAC_MAX_POLICY_NAME];
1820 int error;
1821 u_int i;
1822 size_t ulen;
1823
1824 error = copyinstr(uap->policy, target, sizeof(target), &ulen);
1825 if (error) {
1826 return error;
1827 }
1828 AUDIT_ARG(value32, uap->call);
1829 AUDIT_ARG(mac_string, target);
1830
1831 error = ENOPOLICY;
1832
1833 for (i = 0; i < mac_policy_list.staticmax; i++) {
1834 mpc = mac_policy_list.entries[i].mpc;
1835 if (mpc == NULL) {
1836 continue;
1837 }
1838
1839 if (strcmp(mpc->mpc_name, target) == 0 &&
1840 mpc->mpc_ops->mpo_policy_syscall != NULL) {
1841 error = mpc->mpc_ops->mpo_policy_syscall(p,
1842 uap->call, uap->arg);
1843 goto done;
1844 }
1845 }
1846 if (mac_policy_list_conditional_busy() != 0) {
1847 for (; i <= mac_policy_list.maxindex; i++) {
1848 mpc = mac_policy_list.entries[i].mpc;
1849 if (mpc == NULL) {
1850 continue;
1851 }
1852
1853 if (strcmp(mpc->mpc_name, target) == 0 &&
1854 mpc->mpc_ops->mpo_policy_syscall != NULL) {
1855 error = mpc->mpc_ops->mpo_policy_syscall(p,
1856 uap->call, uap->arg);
1857 break;
1858 }
1859 }
1860 mac_policy_list_unbusy();
1861 }
1862
1863 done:
1864 return error;
1865 }
1866
1867 int
1868 mac_mount_label_get(struct mount *mp, user_addr_t mac_p)
1869 {
1870 char *elements, *buffer;
1871 struct label *label;
1872 struct user_mac mac;
1873 int error;
1874 size_t ulen;
1875
1876 if (IS_64BIT_PROCESS(current_proc())) {
1877 struct user64_mac mac64;
1878 error = copyin(mac_p, &mac64, sizeof(mac64));
1879 mac.m_buflen = mac64.m_buflen;
1880 mac.m_string = mac64.m_string;
1881 } else {
1882 struct user32_mac mac32;
1883 error = copyin(mac_p, &mac32, sizeof(mac32));
1884 mac.m_buflen = mac32.m_buflen;
1885 mac.m_string = mac32.m_string;
1886 }
1887 if (error) {
1888 return error;
1889 }
1890
1891 error = mac_check_structmac_consistent(&mac);
1892 if (error) {
1893 return error;
1894 }
1895
1896 MALLOC(elements, char *, mac.m_buflen, M_MACTEMP, M_WAITOK);
1897 error = copyinstr(mac.m_string, elements, mac.m_buflen, &ulen);
1898 if (error) {
1899 FREE(elements, M_MACTEMP);
1900 return error;
1901 }
1902 AUDIT_ARG(mac_string, elements);
1903
1904 label = mp->mnt_mntlabel;
1905 MALLOC(buffer, char *, mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1906 error = mac_mount_label_externalize(label, elements, buffer,
1907 mac.m_buflen);
1908 FREE(elements, M_MACTEMP);
1909
1910 if (error == 0) {
1911 error = copyout(buffer, mac.m_string, strlen(buffer) + 1);
1912 }
1913 FREE(buffer, M_MACTEMP);
1914
1915 return error;
1916 }
1917
1918 /*
1919 * __mac_get_mount: Get mount point label information for a given pathname
1920 *
1921 * Parameters: p (ignored)
1922 * uap User argument descriptor (see below)
1923 * ret (ignored)
1924 *
1925 * Indirect: uap->path Pathname
1926 * uap->mac_p MAC info
1927 *
1928 * Returns: 0 Success
1929 * !0 Not success
1930 */
1931 int
1932 __mac_get_mount(proc_t p __unused, struct __mac_get_mount_args *uap,
1933 int *ret __unused)
1934 {
1935 struct nameidata nd;
1936 struct vfs_context *ctx = vfs_context_current();
1937 struct mount *mp;
1938 int error;
1939
1940 NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | AUDITVNPATH1,
1941 UIO_USERSPACE, uap->path, ctx);
1942 error = namei(&nd);
1943 if (error) {
1944 return error;
1945 }
1946 mp = nd.ni_vp->v_mount;
1947 vnode_put(nd.ni_vp);
1948 nameidone(&nd);
1949
1950 return mac_mount_label_get(mp, uap->mac_p);
1951 }
1952
1953 /*
1954 * mac_schedule_userret()
1955 *
1956 * Schedule a callback to the mpo_thread_userret hook. The mpo_thread_userret
1957 * hook is called just before the thread exit from the kernel in ast_taken().
1958 *
1959 * Returns: 0 Success
1960 * !0 Not successful
1961 */
1962 int
1963 mac_schedule_userret(void)
1964 {
1965 act_set_astmacf(current_thread());
1966 return 0;
1967 }
1968
1969 /*
1970 * mac_do_machexc()
1971 *
1972 * Do a Mach exception. This should only be done in the mpo_thread_userret
1973 * callback.
1974 *
1975 * params: code exception code
1976 * subcode exception subcode
1977 * flags flags:
1978 * MAC_DOEXCF_TRACED Only do exception if being
1979 * ptrace()'ed.
1980 *
1981 *
1982 * Returns: 0 Success
1983 * !0 Not successful
1984 */
1985 int
1986 mac_do_machexc(int64_t code, int64_t subcode, uint32_t flags)
1987 {
1988 mach_exception_data_type_t codes[EXCEPTION_CODE_MAX];
1989 proc_t p = current_proc();
1990
1991 /* Only allow execption codes in MACF's reserved range. */
1992 if ((code < EXC_MACF_MIN) || (code > EXC_MACF_MAX)) {
1993 return 1;
1994 }
1995
1996 if (flags & MAC_DOEXCF_TRACED &&
1997 !(p->p_lflag & P_LTRACED && (p->p_lflag & P_LPPWAIT) == 0)) {
1998 return 0;
1999 }
2000
2001
2002 /* Send the Mach exception */
2003 codes[0] = (mach_exception_data_type_t)code;
2004 codes[1] = (mach_exception_data_type_t)subcode;
2005
2006 return bsd_exception(EXC_SOFTWARE, codes, 2) != KERN_SUCCESS;
2007 }
2008
2009 #else /* MAC */
2010
2011 void (*load_security_extensions_function)(void) = 0;
2012
2013 struct sysctl_oid_list sysctl__security_mac_children;
2014
2015 int
2016 mac_policy_register(struct mac_policy_conf *mpc __unused,
2017 mac_policy_handle_t *handlep __unused, void *xd __unused)
2018 {
2019 return 0;
2020 }
2021
2022 int
2023 mac_policy_unregister(mac_policy_handle_t handle __unused)
2024 {
2025 return 0;
2026 }
2027
2028 int
2029 mac_audit_text(char *text __unused, mac_policy_handle_t handle __unused)
2030 {
2031 return 0;
2032 }
2033
2034 int
2035 mac_vnop_setxattr(struct vnode *vp __unused, const char *name __unused, char *buf __unused, size_t len __unused)
2036 {
2037 return ENOENT;
2038 }
2039
2040 int
2041 mac_vnop_getxattr(struct vnode *vp __unused, const char *name __unused,
2042 char *buf __unused, size_t len __unused, size_t *attrlen __unused)
2043 {
2044 return ENOENT;
2045 }
2046
2047 int
2048 mac_vnop_removexattr(struct vnode *vp __unused, const char *name __unused)
2049 {
2050 return ENOENT;
2051 }
2052
2053 int
2054 mac_file_setxattr(struct fileglob *fg __unused, const char *name __unused, char *buf __unused, size_t len __unused)
2055 {
2056 return ENOENT;
2057 }
2058
2059 int
2060 mac_file_getxattr(struct fileglob *fg __unused, const char *name __unused,
2061 char *buf __unused, size_t len __unused, size_t *attrlen __unused)
2062 {
2063 return ENOENT;
2064 }
2065
2066 int
2067 mac_file_removexattr(struct fileglob *fg __unused, const char *name __unused)
2068 {
2069 return ENOENT;
2070 }
2071
2072 intptr_t
2073 mac_label_get(struct label *l __unused, int slot __unused)
2074 {
2075 return 0;
2076 }
2077
2078 void
2079 mac_label_set(struct label *l __unused, int slot __unused, intptr_t v __unused)
2080 {
2081 return;
2082 }
2083
2084 int mac_iokit_check_hid_control(kauth_cred_t cred __unused);
2085 int
2086 mac_iokit_check_hid_control(kauth_cred_t cred __unused)
2087 {
2088 return 0;
2089 }
2090
2091 int mac_mount_check_snapshot_mount(vfs_context_t ctx, struct vnode *rvp, struct vnode *vp, struct componentname *cnp,
2092 const char *name, const char *vfc_name);
2093 int
2094 mac_mount_check_snapshot_mount(vfs_context_t ctx __unused, struct vnode *rvp __unused, struct vnode *vp __unused,
2095 struct componentname *cnp __unused, const char *name __unused, const char *vfc_name __unused)
2096 {
2097 return 0;
2098 }
2099
2100 int mac_vnode_check_trigger_resolve(vfs_context_t ctx __unused, struct vnode *dvp __unused, struct componentname *cnp __unused);
2101 int
2102 mac_vnode_check_trigger_resolve(vfs_context_t ctx __unused, struct vnode *dvp __unused, struct componentname *cnp __unused)
2103 {
2104 return 0;
2105 }
2106
2107 #endif /* !MAC */