1 /*
2 * Copyright (c) 2007-2010 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 /*-
30 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
31 * Copyright (c) 2001 Ilmar S. Habibulin
32 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, 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 #include <string.h>
66 #include <sys/param.h>
67 #include <sys/ucred.h>
68 #include <sys/malloc.h>
69 #include <sys/sbuf.h>
70 #include <sys/vnode.h>
71 #include <sys/proc.h>
72 #include <sys/proc_internal.h>
73 #include <sys/kauth.h>
74 #include <sys/imgact.h>
75 #include <sys/reason.h>
76 #include <sys/vnode_internal.h>
77 #include <mach/mach_types.h>
78 #include <kern/task.h>
79 #include <kern/zalloc.h>
80
81 #include <os/hash.h>
82
83 #include <security/mac_internal.h>
84 #include <security/mac_mach_internal.h>
85
86 #include <bsd/security/audit/audit.h>
87
88 #include <os/log.h>
89 #include <kern/cs_blobs.h>
90 #include <sys/spawn.h>
91 #include <sys/spawn_internal.h>
92
93 struct label *
mac_cred_label_alloc(void)94 mac_cred_label_alloc(void)
95 {
96 struct label *label;
97
98 label = mac_labelzone_alloc(MAC_WAITOK);
99 if (label == NULL) {
100 return NULL;
101 }
102 MAC_PERFORM(cred_label_init, label);
103 return label;
104 }
105
106 void
mac_cred_label_init(struct ucred * cred)107 mac_cred_label_init(struct ucred *cred)
108 {
109 cred->cr_label = mac_cred_label_alloc();
110 }
111
112 void
mac_cred_label_free(struct label * label)113 mac_cred_label_free(struct label *label)
114 {
115 MAC_PERFORM(cred_label_destroy, label);
116 mac_labelzone_free(label);
117 }
118
119 struct label *
mac_cred_label(struct ucred * cred)120 mac_cred_label(struct ucred *cred)
121 {
122 return cred->cr_label;
123 }
124
125 bool
mac_cred_label_is_equal(const struct label * a,const struct label * b)126 mac_cred_label_is_equal(const struct label *a, const struct label *b)
127 {
128 return memcmp(a->l_perpolicy, b->l_perpolicy, sizeof(a->l_perpolicy)) == 0;
129 }
130
131 uint32_t
mac_cred_label_hash_update(const struct label * a,uint32_t hash)132 mac_cred_label_hash_update(const struct label *a, uint32_t hash)
133 {
134 return os_hash_jenkins_update(a->l_perpolicy, sizeof(a->l_perpolicy), hash);
135 }
136
137 int
mac_cred_label_externalize_audit(struct proc * p,struct mac * mac)138 mac_cred_label_externalize_audit(struct proc *p, struct mac *mac)
139 {
140 kauth_cred_t cr;
141 int error;
142
143 cr = kauth_cred_proc_ref(p);
144
145 error = MAC_EXTERNALIZE_AUDIT(cred, mac_cred_label(cr),
146 mac->m_string, mac->m_buflen);
147
148 kauth_cred_unref(&cr);
149 return error;
150 }
151
152 void
mac_cred_label_destroy(kauth_cred_t cred)153 mac_cred_label_destroy(kauth_cred_t cred)
154 {
155 struct label *label = mac_cred_label(cred);
156 cred->cr_label = NULL;
157 mac_cred_label_free(label);
158 }
159
160 int
mac_cred_label_externalize(struct label * label,char * elements,char * outbuf,size_t outbuflen,int flags __unused)161 mac_cred_label_externalize(struct label *label, char *elements,
162 char *outbuf, size_t outbuflen, int flags __unused)
163 {
164 int error = 0;
165
166 error = MAC_EXTERNALIZE(cred, label, elements, outbuf, outbuflen);
167
168 return error;
169 }
170
171 int
mac_cred_label_internalize(struct label * label,char * string)172 mac_cred_label_internalize(struct label *label, char *string)
173 {
174 int error;
175
176 error = MAC_INTERNALIZE(cred, label, string);
177
178 return error;
179 }
180
181 /*
182 * By default, fork just adds a reference to the parent
183 * credential. Policies may need to know about this reference
184 * if they are tracking exit calls to know when to free the
185 * label.
186 */
187 void
mac_cred_label_associate_fork(kauth_cred_t cred,proc_t proc)188 mac_cred_label_associate_fork(kauth_cred_t cred, proc_t proc)
189 {
190 MAC_PERFORM(cred_label_associate_fork, cred, proc);
191 }
192
193 /*
194 * Initialize MAC label for the first kernel process, from which other
195 * kernel processes and threads are spawned.
196 */
197 void
mac_cred_label_associate_kernel(kauth_cred_t cred)198 mac_cred_label_associate_kernel(kauth_cred_t cred)
199 {
200 MAC_PERFORM(cred_label_associate_kernel, cred);
201 }
202
203 /*
204 * Initialize MAC label for the first userland process, from which other
205 * userland processes and threads are spawned.
206 */
207 void
mac_cred_label_associate_user(kauth_cred_t cred)208 mac_cred_label_associate_user(kauth_cred_t cred)
209 {
210 MAC_PERFORM(cred_label_associate_user, cred);
211 }
212
213 /*
214 * When a new process is created, its label must be initialized. Generally,
215 * this involves inheritence from the parent process, modulo possible
216 * deltas. This function allows that processing to take place.
217 */
218 void
mac_cred_label_associate(struct ucred * parent_cred,struct ucred * child_cred)219 mac_cred_label_associate(struct ucred *parent_cred, struct ucred *child_cred)
220 {
221 MAC_PERFORM(cred_label_associate, parent_cred, child_cred);
222 }
223
224 int
mac_execve_enter(user_addr_t mac_p,struct image_params * imgp)225 mac_execve_enter(user_addr_t mac_p, struct image_params *imgp)
226 {
227 if (mac_p == USER_ADDR_NULL) {
228 return 0;
229 }
230
231 return mac_do_set(current_proc(), mac_p,
232 ^(char *input, __unused size_t len) {
233 struct label *execlabel;
234 int error;
235
236 execlabel = mac_cred_label_alloc();
237 if ((error = mac_cred_label_internalize(execlabel, input))) {
238 mac_cred_label_free(execlabel);
239 execlabel = NULL;
240 }
241
242 imgp->ip_execlabelp = execlabel;
243 return error;
244 });
245 }
246
247 /*
248 * When the subject's label changes, it may require revocation of privilege
249 * to mapped objects. This can't be done on-the-fly later with a unified
250 * buffer cache.
251 *
252 * XXX: CRF_MAC_ENFORCE should be in a kauth_cred_t field, rather
253 * XXX: than a posix_cred_t field.
254 */
255 void
mac_cred_label_update(kauth_cred_t cred,struct label * newlabel)256 mac_cred_label_update(kauth_cred_t cred, struct label *newlabel)
257 {
258 posix_cred_t pcred = posix_cred_get(cred);
259
260 /* force label to be part of "matching" for credential */
261 pcred->cr_flags |= CRF_MAC_ENFORCE;
262
263 /* inform the policies of the update */
264 MAC_PERFORM(cred_label_update, cred, newlabel);
265 }
266
267 int
mac_cred_check_label_update(kauth_cred_t cred,struct label * newlabel)268 mac_cred_check_label_update(kauth_cred_t cred, struct label *newlabel)
269 {
270 int error;
271
272 #if SECURITY_MAC_CHECK_ENFORCE
273 /* 21167099 - only check if we allow write */
274 if (!mac_proc_enforce) {
275 return 0;
276 }
277 #endif
278
279 MAC_CHECK(cred_check_label_update, cred, newlabel);
280
281 return error;
282 }
283
284 int
mac_cred_check_visible(kauth_cred_t u1,kauth_cred_t u2)285 mac_cred_check_visible(kauth_cred_t u1, kauth_cred_t u2)
286 {
287 int error;
288
289 #if SECURITY_MAC_CHECK_ENFORCE
290 /* 21167099 - only check if we allow write */
291 if (!mac_proc_enforce) {
292 return 0;
293 }
294 #endif
295
296 MAC_CHECK(cred_check_visible, u1, u2);
297
298 return error;
299 }
300
301 int
mac_proc_check_debug(proc_ident_t tracing_ident,kauth_cred_t tracing_cred,proc_ident_t traced_ident)302 mac_proc_check_debug(proc_ident_t tracing_ident, kauth_cred_t tracing_cred, proc_ident_t traced_ident)
303 {
304 int error;
305 bool enforce;
306 proc_t tracingp;
307
308 #if SECURITY_MAC_CHECK_ENFORCE
309 /* 21167099 - only check if we allow write */
310 if (!mac_proc_enforce) {
311 return 0;
312 }
313 #endif
314 /*
315 * Once all mac hooks adopt proc_ident_t, finding proc_t and releasing
316 * it below should go to mac_proc_check_enforce().
317 */
318 if ((tracingp = proc_find_ident(tracing_ident)) == PROC_NULL) {
319 return ESRCH;
320 }
321 enforce = mac_proc_check_enforce(tracingp);
322 proc_rele(tracingp);
323
324 if (!enforce) {
325 return 0;
326 }
327 MAC_CHECK(proc_check_debug, tracing_cred, traced_ident);
328
329 return error;
330 }
331
332 int
mac_proc_check_dump_core(struct proc * proc)333 mac_proc_check_dump_core(struct proc *proc)
334 {
335 int error;
336
337 #if SECURITY_MAC_CHECK_ENFORCE
338 /* 21167099 - only check if we allow write */
339 if (!mac_proc_enforce) {
340 return 0;
341 }
342 #endif
343 if (!mac_proc_check_enforce(proc)) {
344 return 0;
345 }
346
347 MAC_CHECK(proc_check_dump_core, proc);
348
349 return error;
350 }
351
352 int
mac_proc_check_remote_thread_create(struct task * task,int flavor,thread_state_t new_state,mach_msg_type_number_t new_state_count)353 mac_proc_check_remote_thread_create(struct task *task, int flavor, thread_state_t new_state, mach_msg_type_number_t new_state_count)
354 {
355 proc_t curp = current_proc();
356 proc_t proc;
357 kauth_cred_t cred;
358 int error;
359
360 #if SECURITY_MAC_CHECK_ENFORCE
361 /* 21167099 - only check if we allow write */
362 if (!mac_proc_enforce) {
363 return 0;
364 }
365 #endif
366 if (!mac_proc_check_enforce(curp)) {
367 return 0;
368 }
369
370 proc = proc_find(task_pid(task));
371 if (proc == PROC_NULL) {
372 return ESRCH;
373 }
374
375 cred = kauth_cred_proc_ref(curp);
376 MAC_CHECK(proc_check_remote_thread_create, cred, proc, flavor, new_state, new_state_count);
377 kauth_cred_unref(&cred);
378 proc_rele(proc);
379
380 return error;
381 }
382
383 int
mac_proc_check_fork(proc_t curp)384 mac_proc_check_fork(proc_t curp)
385 {
386 kauth_cred_t cred;
387 int error;
388
389 #if SECURITY_MAC_CHECK_ENFORCE
390 /* 21167099 - only check if we allow write */
391 if (!mac_proc_enforce) {
392 return 0;
393 }
394 #endif
395 if (!mac_proc_check_enforce(curp)) {
396 return 0;
397 }
398
399 cred = kauth_cred_proc_ref(curp);
400 MAC_CHECK(proc_check_fork, cred, curp);
401 kauth_cred_unref(&cred);
402
403 return error;
404 }
405
406 int
mac_proc_check_get_task(struct ucred * cred,proc_ident_t pident,mach_task_flavor_t flavor)407 mac_proc_check_get_task(struct ucred *cred, proc_ident_t pident, mach_task_flavor_t flavor)
408 {
409 int error;
410
411 assert(flavor <= TASK_FLAVOR_NAME);
412
413 MAC_CHECK(proc_check_get_task_with_flavor, cred, pident, flavor);
414
415 return error;
416 }
417
418 int
mac_proc_check_expose_task(struct ucred * cred,proc_ident_t pident,mach_task_flavor_t flavor)419 mac_proc_check_expose_task(struct ucred *cred, proc_ident_t pident, mach_task_flavor_t flavor)
420 {
421 int error;
422
423 assert(flavor <= TASK_FLAVOR_NAME);
424
425 MAC_CHECK(proc_check_expose_task_with_flavor, cred, pident, flavor);
426
427 return error;
428 }
429
430 int
mac_proc_check_inherit_ipc_ports(struct proc * p,struct vnode * cur_vp,off_t cur_offset,struct vnode * img_vp,off_t img_offset,struct vnode * scriptvp)431 mac_proc_check_inherit_ipc_ports(
432 struct proc *p,
433 struct vnode *cur_vp,
434 off_t cur_offset,
435 struct vnode *img_vp,
436 off_t img_offset,
437 struct vnode *scriptvp)
438 {
439 int error;
440
441 MAC_CHECK(proc_check_inherit_ipc_ports, p, cur_vp, cur_offset, img_vp, img_offset, scriptvp);
442
443 return error;
444 }
445
446 /*
447 * The type of maxprot in proc_check_map_anon must be equivalent to vm_prot_t
448 * (defined in <mach/vm_prot.h>). mac_policy.h does not include any header
449 * files, so cannot use the typedef itself.
450 */
451 int
mac_proc_check_map_anon(proc_t proc,user_addr_t u_addr,user_size_t u_size,int prot,int flags,int * maxprot)452 mac_proc_check_map_anon(proc_t proc, user_addr_t u_addr,
453 user_size_t u_size, int prot, int flags, int *maxprot)
454 {
455 kauth_cred_t cred;
456 int error;
457
458 #if SECURITY_MAC_CHECK_ENFORCE
459 /* 21167099 - only check if we allow write */
460 if (!mac_vm_enforce) {
461 return 0;
462 }
463 #endif
464 if (!mac_proc_check_enforce(proc)) {
465 return 0;
466 }
467
468 cred = kauth_cred_proc_ref(proc);
469 MAC_CHECK(proc_check_map_anon, proc, cred, u_addr, u_size, prot, flags, maxprot);
470 kauth_cred_unref(&cred);
471
472 return error;
473 }
474
475
476 int
mac_proc_check_memorystatus_control(proc_t proc,uint32_t command,pid_t pid)477 mac_proc_check_memorystatus_control(proc_t proc, uint32_t command, pid_t pid)
478 {
479 kauth_cred_t cred;
480 int error;
481
482 #if SECURITY_MAC_CHECK_ENFORCE
483 /* 21167099 - only check if we allow write */
484 if (!mac_proc_enforce) {
485 return 0;
486 }
487 #endif
488 if (!mac_proc_check_enforce(proc)) {
489 return 0;
490 }
491
492 cred = kauth_cred_proc_ref(proc);
493 MAC_CHECK(proc_check_memorystatus_control, cred, command, pid);
494 kauth_cred_unref(&cred);
495
496 return error;
497 }
498
499 int
mac_proc_check_mprotect(proc_t proc,user_addr_t addr,user_size_t size,int prot)500 mac_proc_check_mprotect(proc_t proc,
501 user_addr_t addr, user_size_t size, int prot)
502 {
503 kauth_cred_t cred;
504 int error;
505
506 #if SECURITY_MAC_CHECK_ENFORCE
507 /* 21167099 - only check if we allow write */
508 if (!mac_vm_enforce) {
509 return 0;
510 }
511 #endif
512 if (!mac_proc_check_enforce(proc)) {
513 return 0;
514 }
515
516 cred = kauth_cred_proc_ref(proc);
517 MAC_CHECK(proc_check_mprotect, cred, proc, addr, size, prot);
518 kauth_cred_unref(&cred);
519
520 return error;
521 }
522
523 int
mac_proc_check_run_cs_invalid(proc_t proc)524 mac_proc_check_run_cs_invalid(proc_t proc)
525 {
526 int error;
527
528 #if SECURITY_MAC_CHECK_ENFORCE
529 /* 21167099 - only check if we allow write */
530 if (!mac_vm_enforce) {
531 return 0;
532 }
533 #endif
534
535 MAC_CHECK(proc_check_run_cs_invalid, proc);
536
537 return error;
538 }
539
540 void
mac_proc_notify_cs_invalidated(proc_t proc)541 mac_proc_notify_cs_invalidated(proc_t proc)
542 {
543 MAC_PERFORM(proc_notify_cs_invalidated, proc);
544 }
545
546 int
mac_proc_check_sched(proc_t curp,struct proc * proc)547 mac_proc_check_sched(proc_t curp, struct proc *proc)
548 {
549 kauth_cred_t cred;
550 int error;
551
552 #if SECURITY_MAC_CHECK_ENFORCE
553 /* 21167099 - only check if we allow write */
554 if (!mac_proc_enforce) {
555 return 0;
556 }
557 #endif
558 if (!mac_proc_check_enforce(curp)) {
559 return 0;
560 }
561
562 cred = kauth_cred_proc_ref(curp);
563 MAC_CHECK(proc_check_sched, cred, proc);
564 kauth_cred_unref(&cred);
565
566 return error;
567 }
568
569 int
mac_proc_check_signal(proc_t curp,struct proc * proc,int signum)570 mac_proc_check_signal(proc_t curp, struct proc *proc, int signum)
571 {
572 kauth_cred_t cred;
573 int error;
574
575 #if SECURITY_MAC_CHECK_ENFORCE
576 /* 21167099 - only check if we allow write */
577 if (!mac_proc_enforce) {
578 return 0;
579 }
580 #endif
581 if (!mac_proc_check_enforce(curp)) {
582 return 0;
583 }
584
585 cred = kauth_cred_proc_ref(curp);
586 MAC_CHECK(proc_check_signal, cred, proc, signum);
587 kauth_cred_unref(&cred);
588
589 return error;
590 }
591
592 int
mac_proc_check_syscall_unix(proc_t curp,int scnum)593 mac_proc_check_syscall_unix(proc_t curp, int scnum)
594 {
595 int error;
596
597 #if SECURITY_MAC_CHECK_ENFORCE
598 /* 21167099 - only check if we allow write */
599 if (!mac_proc_enforce) {
600 return 0;
601 }
602 #endif
603 if (!mac_proc_check_enforce(curp)) {
604 return 0;
605 }
606
607 MAC_CHECK(proc_check_syscall_unix, curp, scnum);
608
609 return error;
610 }
611
612 int
mac_proc_check_wait(proc_t curp,struct proc * proc)613 mac_proc_check_wait(proc_t curp, struct proc *proc)
614 {
615 kauth_cred_t cred;
616 int error;
617
618 #if SECURITY_MAC_CHECK_ENFORCE
619 /* 21167099 - only check if we allow write */
620 if (!mac_proc_enforce) {
621 return 0;
622 }
623 #endif
624 if (!mac_proc_check_enforce(curp)) {
625 return 0;
626 }
627
628 cred = kauth_cred_proc_ref(curp);
629 MAC_CHECK(proc_check_wait, cred, proc);
630 kauth_cred_unref(&cred);
631
632 return error;
633 }
634
635 void
mac_proc_notify_exit(struct proc * proc)636 mac_proc_notify_exit(struct proc *proc)
637 {
638 MAC_PERFORM(proc_notify_exit, proc);
639 }
640
641 int
mac_proc_check_suspend_resume(proc_t proc,int sr)642 mac_proc_check_suspend_resume(proc_t proc, int sr)
643 {
644 kauth_cred_t cred;
645 int error;
646
647 #if SECURITY_MAC_CHECK_ENFORCE
648 /* 21167099 - only check if we allow write */
649 if (!mac_proc_enforce) {
650 return 0;
651 }
652 #endif
653 if (!mac_proc_check_enforce(current_proc())) {
654 return 0;
655 }
656
657 cred = kauth_cred_proc_ref(current_proc());
658 MAC_CHECK(proc_check_suspend_resume, cred, proc, sr);
659 kauth_cred_unref(&cred);
660
661 return error;
662 }
663
664 int
mac_proc_check_ledger(proc_t curp,proc_t proc,int ledger_op)665 mac_proc_check_ledger(proc_t curp, proc_t proc, int ledger_op)
666 {
667 kauth_cred_t cred;
668 int error = 0;
669
670 #if SECURITY_MAC_CHECK_ENFORCE
671 /* 21167099 - only check if we allow write */
672 if (!mac_proc_enforce) {
673 return 0;
674 }
675 #endif
676 if (!mac_proc_check_enforce(curp)) {
677 return 0;
678 }
679
680 cred = kauth_cred_proc_ref(curp);
681 MAC_CHECK(proc_check_ledger, cred, proc, ledger_op);
682 kauth_cred_unref(&cred);
683
684 return error;
685 }
686
687 int
mac_proc_check_proc_info(proc_t curp,proc_t target,int callnum,int flavor)688 mac_proc_check_proc_info(proc_t curp, proc_t target, int callnum, int flavor)
689 {
690 kauth_cred_t cred;
691 int error = 0;
692
693 #if SECURITY_MAC_CHECK_ENFORCE
694 /* 21167099 - only check if we allow write */
695 if (!mac_proc_enforce) {
696 return 0;
697 }
698 #endif
699 if (!mac_proc_check_enforce(curp)) {
700 return 0;
701 }
702
703 cred = kauth_cred_proc_ref(curp);
704 MAC_CHECK(proc_check_proc_info, cred, target, callnum, flavor);
705 kauth_cred_unref(&cred);
706
707 return error;
708 }
709
710 int
mac_proc_check_get_cs_info(proc_t curp,proc_t target,unsigned int op)711 mac_proc_check_get_cs_info(proc_t curp, proc_t target, unsigned int op)
712 {
713 kauth_cred_t cred;
714 int error = 0;
715
716 #if SECURITY_MAC_CHECK_ENFORCE
717 /* 21167099 - only check if we allow write */
718 if (!mac_proc_enforce) {
719 return 0;
720 }
721 #endif
722 if (!mac_proc_check_enforce(curp)) {
723 return 0;
724 }
725
726 cred = kauth_cred_proc_ref(curp);
727 MAC_CHECK(proc_check_get_cs_info, cred, target, op);
728 kauth_cred_unref(&cred);
729
730 return error;
731 }
732
733 int
mac_proc_check_set_cs_info(proc_t curp,proc_t target,unsigned int op)734 mac_proc_check_set_cs_info(proc_t curp, proc_t target, unsigned int op)
735 {
736 kauth_cred_t cred;
737 int error = 0;
738
739 #if SECURITY_MAC_CHECK_ENFORCE
740 /* 21167099 - only check if we allow write */
741 if (!mac_proc_enforce) {
742 return 0;
743 }
744 #endif
745 if (!mac_proc_check_enforce(curp)) {
746 return 0;
747 }
748
749 cred = kauth_cred_proc_ref(curp);
750 MAC_CHECK(proc_check_set_cs_info, cred, target, op);
751 kauth_cred_unref(&cred);
752
753 return error;
754 }
755
756 int
mac_proc_check_setuid(proc_t curp,kauth_cred_t cred,uid_t uid)757 mac_proc_check_setuid(proc_t curp, kauth_cred_t cred, uid_t uid)
758 {
759 int error = 0;
760
761 #if SECURITY_MAC_CHECK_ENFORCE
762 /* 21167099 - only check if we allow write */
763 if (!mac_proc_enforce) {
764 return 0;
765 }
766 #endif
767 if (!mac_proc_check_enforce(curp)) {
768 return 0;
769 }
770
771 MAC_CHECK(proc_check_setuid, cred, uid);
772
773 return error;
774 }
775
776 int
mac_proc_check_seteuid(proc_t curp,kauth_cred_t cred,uid_t euid)777 mac_proc_check_seteuid(proc_t curp, kauth_cred_t cred, uid_t euid)
778 {
779 int error = 0;
780
781 #if SECURITY_MAC_CHECK_ENFORCE
782 /* 21167099 - only check if we allow write */
783 if (!mac_proc_enforce) {
784 return 0;
785 }
786 #endif
787 if (!mac_proc_check_enforce(curp)) {
788 return 0;
789 }
790
791 MAC_CHECK(proc_check_seteuid, cred, euid);
792
793 return error;
794 }
795
796 int
mac_proc_check_setreuid(proc_t curp,kauth_cred_t cred,uid_t ruid,uid_t euid)797 mac_proc_check_setreuid(proc_t curp, kauth_cred_t cred, uid_t ruid, uid_t euid)
798 {
799 int error = 0;
800
801 #if SECURITY_MAC_CHECK_ENFORCE
802 /* 21167099 - only check if we allow write */
803 if (!mac_proc_enforce) {
804 return 0;
805 }
806 #endif
807 if (!mac_proc_check_enforce(curp)) {
808 return 0;
809 }
810
811 MAC_CHECK(proc_check_setreuid, cred, ruid, euid);
812
813 return error;
814 }
815
816 int
mac_proc_check_setgid(proc_t curp,kauth_cred_t cred,gid_t gid)817 mac_proc_check_setgid(proc_t curp, kauth_cred_t cred, gid_t gid)
818 {
819 int error = 0;
820
821 #if SECURITY_MAC_CHECK_ENFORCE
822 /* 21167099 - only check if we allow write */
823 if (!mac_proc_enforce) {
824 return 0;
825 }
826 #endif
827 if (!mac_proc_check_enforce(curp)) {
828 return 0;
829 }
830
831 MAC_CHECK(proc_check_setgid, cred, gid);
832
833 return error;
834 }
835
836 int
mac_proc_check_setegid(proc_t curp,kauth_cred_t cred,gid_t egid)837 mac_proc_check_setegid(proc_t curp, kauth_cred_t cred, gid_t egid)
838 {
839 int error = 0;
840
841 #if SECURITY_MAC_CHECK_ENFORCE
842 /* 21167099 - only check if we allow write */
843 if (!mac_proc_enforce) {
844 return 0;
845 }
846 #endif
847 if (!mac_proc_check_enforce(curp)) {
848 return 0;
849 }
850
851 MAC_CHECK(proc_check_setegid, cred, egid);
852
853 return error;
854 }
855
856 int
mac_proc_check_setregid(proc_t curp,kauth_cred_t cred,gid_t rgid,gid_t egid)857 mac_proc_check_setregid(proc_t curp, kauth_cred_t cred, gid_t rgid, gid_t egid)
858 {
859 int error = 0;
860
861 #if SECURITY_MAC_CHECK_ENFORCE
862 /* 21167099 - only check if we allow write */
863 if (!mac_proc_enforce) {
864 return 0;
865 }
866 #endif
867 if (!mac_proc_check_enforce(curp)) {
868 return 0;
869 }
870
871 MAC_CHECK(proc_check_setregid, cred, rgid, egid);
872
873 return error;
874 }
875
876 int
mac_proc_check_settid(proc_t curp,uid_t uid,gid_t gid)877 mac_proc_check_settid(proc_t curp, uid_t uid, gid_t gid)
878 {
879 kauth_cred_t pcred, tcred;
880 int error = 0;
881
882 #if SECURITY_MAC_CHECK_ENFORCE
883 /* 21167099 - only check if we allow write */
884 if (!mac_proc_enforce) {
885 return 0;
886 }
887 #endif
888 if (!mac_proc_check_enforce(curp)) {
889 return 0;
890 }
891
892 pcred = kauth_cred_proc_ref(curp);
893 tcred = kauth_cred_get_with_ref();
894 MAC_CHECK(proc_check_settid, pcred, tcred, uid, gid);
895 kauth_cred_unref(&tcred);
896 kauth_cred_unref(&pcred);
897
898 return error;
899 }
900
901 int
mac_proc_check_launch_constraints(proc_t curp,struct image_params * imgp,os_reason_t * reasonp)902 mac_proc_check_launch_constraints(proc_t curp, struct image_params *imgp, os_reason_t *reasonp)
903 {
904 char *fatal_failure_desc = NULL;
905 size_t fatal_failure_desc_len = 0;
906
907 pid_t original_parent_id = proc_original_ppid(curp);
908
909 pid_t responsible_pid = curp->p_responsible_pid;
910
911 int error = 0;
912
913 /* Vnode of the file */
914 struct vnode *vp = imgp->ip_vp;
915
916 char *vn_path = NULL;
917 vm_size_t vn_pathlen = MAXPATHLEN;
918 #if SECURITY_MAC_CHECK_ENFORCE
919 /* 21167099 - only check if we allow write */
920 if (!mac_proc_enforce || !mac_vnode_enforce) {
921 return 0;
922 }
923 #endif
924
925 MAC_POLICY_ITERATE({
926 mpo_proc_check_launch_constraints_t *hook = mpc->mpc_ops->mpo_proc_check_launch_constraints;
927 if (hook == NULL) {
928 continue;
929 }
930
931 size_t spawnattrlen = 0;
932 void *spawnattr = exec_spawnattr_getmacpolicyinfo(&imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
933 struct _posix_spawnattr *psa = (struct _posix_spawnattr *) imgp->ip_px_sa;
934 struct launch_constraint_data lcd;
935 lcd.launch_type = CS_LAUNCH_TYPE_NONE;
936
937 /* Check to see if psa_launch_type was initalized */
938 if (psa != (struct _posix_spawnattr*)NULL) {
939 lcd.launch_type = psa->psa_launch_type;
940 }
941
942 error = mac_error_select(
943 hook(curp, original_parent_id, responsible_pid,
944 spawnattr, spawnattrlen, &lcd, &fatal_failure_desc, &fatal_failure_desc_len), error);
945
946 /*
947 * Early exit in case of failure in case we have multiple registered callers.
948 * This is to avoid other MACF policies from stomping on each other's failure description
949 */
950 if (fatal_failure_desc_len) {
951 goto policy_fail;
952 }
953 });
954
955 policy_fail:
956 if (fatal_failure_desc_len) {
957 /*
958 * A fatal code signature validation failure occured, formulate a crash
959 * reason.
960 */
961
962 char const *path = NULL;
963
964 vn_path = zalloc(ZV_NAMEI);
965 if (vn_getpath(vp, vn_path, (int*)&vn_pathlen) == 0) {
966 path = vn_path;
967 } else {
968 path = "(get vnode path failed)";
969 }
970
971 if (error == 0) {
972 panic("%s: MAC hook returned no error, but status is claimed to be fatal? "
973 "path: '%s', fatal_failure_desc_len: %ld, fatal_failure_desc:\n%s\n",
974 __func__, path, fatal_failure_desc_len, fatal_failure_desc);
975 }
976
977 os_reason_t reason = os_reason_create(OS_REASON_CODESIGNING,
978 CODESIGNING_EXIT_REASON_LAUNCH_CONSTRAINT_VIOLATION);
979
980 *reasonp = reason;
981
982 reason->osr_flags = (OS_REASON_FLAG_GENERATE_CRASH_REPORT |
983 OS_REASON_FLAG_CONSISTENT_FAILURE);
984
985 if (fatal_failure_desc != NULL) {
986 mach_vm_address_t data_addr = 0;
987
988 int reason_error = 0;
989 int kcdata_error = 0;
990
991 if ((reason_error = os_reason_alloc_buffer_noblock(reason,
992 kcdata_estimate_required_buffer_size(1,
993 (uint32_t)fatal_failure_desc_len))) == 0) {
994 if ((kcdata_error = kcdata_get_memory_addr(&reason->osr_kcd_descriptor,
995 EXIT_REASON_USER_DESC, (uint32_t)fatal_failure_desc_len,
996 &data_addr)) == KERN_SUCCESS) {
997 kcdata_memcpy(&reason->osr_kcd_descriptor, (mach_vm_address_t)data_addr,
998 fatal_failure_desc, (uint32_t)fatal_failure_desc_len);
999 }
1000 }
1001 }
1002 }
1003
1004 if (vn_path) {
1005 zfree(ZV_NAMEI, vn_path);
1006 }
1007
1008 if (fatal_failure_desc_len > 0 && fatal_failure_desc != NULL) {
1009 kfree_data(fatal_failure_desc, fatal_failure_desc_len);
1010 }
1011
1012 return error;
1013 }
1014