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