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