xref: /xnu-10002.41.9/security/mac_process.c (revision 699cd48037512bf4380799317ca44ca453c82f57)
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 	kauth_cred_t cred;
379 	int error;
380 
381 #if SECURITY_MAC_CHECK_ENFORCE
382 	/* 21167099 - only check if we allow write */
383 	if (!mac_proc_enforce) {
384 		return 0;
385 	}
386 #endif
387 	if (!mac_proc_check_enforce(curp)) {
388 		return 0;
389 	}
390 
391 	proc = proc_find(task_pid(task));
392 	if (proc == PROC_NULL) {
393 		return ESRCH;
394 	}
395 
396 	cred = kauth_cred_proc_ref(curp);
397 	MAC_CHECK(proc_check_remote_thread_create, cred, proc, flavor, new_state, new_state_count);
398 	kauth_cred_unref(&cred);
399 	proc_rele(proc);
400 
401 	return error;
402 }
403 
404 void
mac_proc_notify_service_port_derive(struct mach_service_port_info * sp_info)405 mac_proc_notify_service_port_derive(struct mach_service_port_info *sp_info)
406 {
407 	proc_t curp = current_proc();
408 	kauth_cred_t cred = kauth_cred_proc_ref(curp);
409 	MAC_PERFORM(proc_notify_service_port_derive, cred, sp_info);
410 	kauth_cred_unref(&cred);
411 }
412 
413 int
mac_proc_check_fork(proc_t curp)414 mac_proc_check_fork(proc_t curp)
415 {
416 	kauth_cred_t cred;
417 	int error;
418 
419 #if SECURITY_MAC_CHECK_ENFORCE
420 	/* 21167099 - only check if we allow write */
421 	if (!mac_proc_enforce) {
422 		return 0;
423 	}
424 #endif
425 	if (!mac_proc_check_enforce(curp)) {
426 		return 0;
427 	}
428 
429 	cred = kauth_cred_proc_ref(curp);
430 	MAC_CHECK(proc_check_fork, cred, curp);
431 	kauth_cred_unref(&cred);
432 
433 	return error;
434 }
435 
436 int
mac_proc_check_get_task(struct ucred * cred,proc_ident_t pident,mach_task_flavor_t flavor)437 mac_proc_check_get_task(struct ucred *cred, proc_ident_t pident, mach_task_flavor_t flavor)
438 {
439 	int error;
440 
441 	assert(flavor <= TASK_FLAVOR_NAME);
442 
443 	MAC_CHECK(proc_check_get_task_with_flavor, cred, pident, flavor);
444 
445 	return error;
446 }
447 
448 int
mac_proc_check_expose_task(struct ucred * cred,proc_ident_t pident,mach_task_flavor_t flavor)449 mac_proc_check_expose_task(struct ucred *cred, proc_ident_t pident, mach_task_flavor_t flavor)
450 {
451 	int error;
452 
453 	assert(flavor <= TASK_FLAVOR_NAME);
454 
455 	MAC_CHECK(proc_check_expose_task_with_flavor, cred, pident, flavor);
456 
457 	return error;
458 }
459 
460 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)461 mac_proc_check_inherit_ipc_ports(
462 	struct proc *p,
463 	struct vnode *cur_vp,
464 	off_t cur_offset,
465 	struct vnode *img_vp,
466 	off_t img_offset,
467 	struct vnode *scriptvp)
468 {
469 	int error;
470 
471 	MAC_CHECK(proc_check_inherit_ipc_ports, p, cur_vp, cur_offset, img_vp, img_offset, scriptvp);
472 
473 	return error;
474 }
475 
476 /*
477  * The type of maxprot in proc_check_map_anon must be equivalent to vm_prot_t
478  * (defined in <mach/vm_prot.h>). mac_policy.h does not include any header
479  * files, so cannot use the typedef itself.
480  */
481 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)482 mac_proc_check_map_anon(proc_t proc, user_addr_t u_addr,
483     user_size_t u_size, int prot, int flags, int *maxprot)
484 {
485 	kauth_cred_t cred;
486 	int error;
487 
488 #if SECURITY_MAC_CHECK_ENFORCE
489 	/* 21167099 - only check if we allow write */
490 	if (!mac_vm_enforce) {
491 		return 0;
492 	}
493 #endif
494 	if (!mac_proc_check_enforce(proc)) {
495 		return 0;
496 	}
497 
498 	cred = kauth_cred_proc_ref(proc);
499 	MAC_CHECK(proc_check_map_anon, proc, cred, u_addr, u_size, prot, flags, maxprot);
500 	kauth_cred_unref(&cred);
501 
502 	return error;
503 }
504 
505 
506 int
mac_proc_check_memorystatus_control(proc_t proc,uint32_t command,pid_t pid)507 mac_proc_check_memorystatus_control(proc_t proc, uint32_t command, pid_t pid)
508 {
509 	kauth_cred_t cred;
510 	int error;
511 
512 #if SECURITY_MAC_CHECK_ENFORCE
513 	/* 21167099 - only check if we allow write */
514 	if (!mac_proc_enforce) {
515 		return 0;
516 	}
517 #endif
518 	if (!mac_proc_check_enforce(proc)) {
519 		return 0;
520 	}
521 
522 	cred = kauth_cred_proc_ref(proc);
523 	MAC_CHECK(proc_check_memorystatus_control, cred, command, pid);
524 	kauth_cred_unref(&cred);
525 
526 	return error;
527 }
528 
529 int
mac_proc_check_mprotect(proc_t proc,user_addr_t addr,user_size_t size,int prot)530 mac_proc_check_mprotect(proc_t proc,
531     user_addr_t addr, user_size_t size, int prot)
532 {
533 	kauth_cred_t cred;
534 	int error;
535 
536 #if SECURITY_MAC_CHECK_ENFORCE
537 	/* 21167099 - only check if we allow write */
538 	if (!mac_vm_enforce) {
539 		return 0;
540 	}
541 #endif
542 	if (!mac_proc_check_enforce(proc)) {
543 		return 0;
544 	}
545 
546 	cred = kauth_cred_proc_ref(proc);
547 	MAC_CHECK(proc_check_mprotect, cred, proc, addr, size, prot);
548 	kauth_cred_unref(&cred);
549 
550 	return error;
551 }
552 
553 int
mac_proc_check_run_cs_invalid(proc_t proc)554 mac_proc_check_run_cs_invalid(proc_t proc)
555 {
556 	int error;
557 
558 #if SECURITY_MAC_CHECK_ENFORCE
559 	/* 21167099 - only check if we allow write */
560 	if (!mac_vm_enforce) {
561 		return 0;
562 	}
563 #endif
564 
565 	MAC_CHECK(proc_check_run_cs_invalid, proc);
566 
567 	return error;
568 }
569 
570 void
mac_proc_notify_cs_invalidated(proc_t proc)571 mac_proc_notify_cs_invalidated(proc_t proc)
572 {
573 	MAC_PERFORM(proc_notify_cs_invalidated, proc);
574 }
575 
576 int
mac_proc_check_sched(proc_t curp,struct proc * proc)577 mac_proc_check_sched(proc_t curp, struct proc *proc)
578 {
579 	kauth_cred_t cred;
580 	int error;
581 
582 #if SECURITY_MAC_CHECK_ENFORCE
583 	/* 21167099 - only check if we allow write */
584 	if (!mac_proc_enforce) {
585 		return 0;
586 	}
587 #endif
588 	if (!mac_proc_check_enforce(curp)) {
589 		return 0;
590 	}
591 
592 	cred = kauth_cred_proc_ref(curp);
593 	MAC_CHECK(proc_check_sched, cred, proc);
594 	kauth_cred_unref(&cred);
595 
596 	return error;
597 }
598 
599 int
mac_proc_check_signal(proc_t curp,struct proc * proc,int signum)600 mac_proc_check_signal(proc_t curp, struct proc *proc, int signum)
601 {
602 	kauth_cred_t cred;
603 	int error;
604 
605 #if SECURITY_MAC_CHECK_ENFORCE
606 	/* 21167099 - only check if we allow write */
607 	if (!mac_proc_enforce) {
608 		return 0;
609 	}
610 #endif
611 	if (!mac_proc_check_enforce(curp)) {
612 		return 0;
613 	}
614 
615 	cred = kauth_cred_proc_ref(curp);
616 	MAC_CHECK(proc_check_signal, cred, proc, signum);
617 	kauth_cred_unref(&cred);
618 
619 	return error;
620 }
621 
622 int
mac_proc_check_syscall_unix(proc_t curp,int scnum)623 mac_proc_check_syscall_unix(proc_t curp, int scnum)
624 {
625 	int error;
626 
627 #if SECURITY_MAC_CHECK_ENFORCE
628 	/* 21167099 - only check if we allow write */
629 	if (!mac_proc_enforce) {
630 		return 0;
631 	}
632 #endif
633 	if (!mac_proc_check_enforce(curp)) {
634 		return 0;
635 	}
636 
637 	MAC_CHECK(proc_check_syscall_unix, curp, scnum);
638 
639 	return error;
640 }
641 
642 int
mac_proc_check_wait(proc_t curp,struct proc * proc)643 mac_proc_check_wait(proc_t curp, struct proc *proc)
644 {
645 	kauth_cred_t cred;
646 	int error;
647 
648 #if SECURITY_MAC_CHECK_ENFORCE
649 	/* 21167099 - only check if we allow write */
650 	if (!mac_proc_enforce) {
651 		return 0;
652 	}
653 #endif
654 	if (!mac_proc_check_enforce(curp)) {
655 		return 0;
656 	}
657 
658 	cred = kauth_cred_proc_ref(curp);
659 	MAC_CHECK(proc_check_wait, cred, proc);
660 	kauth_cred_unref(&cred);
661 
662 	return error;
663 }
664 
665 void
mac_proc_notify_exit(struct proc * proc)666 mac_proc_notify_exit(struct proc *proc)
667 {
668 	MAC_PERFORM(proc_notify_exit, proc);
669 }
670 
671 int
mac_proc_check_suspend_resume(proc_t proc,int sr)672 mac_proc_check_suspend_resume(proc_t proc, int sr)
673 {
674 	kauth_cred_t cred;
675 	int error;
676 
677 #if SECURITY_MAC_CHECK_ENFORCE
678 	/* 21167099 - only check if we allow write */
679 	if (!mac_proc_enforce) {
680 		return 0;
681 	}
682 #endif
683 	if (!mac_proc_check_enforce(current_proc())) {
684 		return 0;
685 	}
686 
687 	cred = kauth_cred_proc_ref(current_proc());
688 	MAC_CHECK(proc_check_suspend_resume, cred, proc, sr);
689 	kauth_cred_unref(&cred);
690 
691 	return error;
692 }
693 
694 int
mac_proc_check_ledger(proc_t curp,proc_t proc,int ledger_op)695 mac_proc_check_ledger(proc_t curp, proc_t proc, int ledger_op)
696 {
697 	kauth_cred_t cred;
698 	int error = 0;
699 
700 #if SECURITY_MAC_CHECK_ENFORCE
701 	/* 21167099 - only check if we allow write */
702 	if (!mac_proc_enforce) {
703 		return 0;
704 	}
705 #endif
706 	if (!mac_proc_check_enforce(curp)) {
707 		return 0;
708 	}
709 
710 	cred = kauth_cred_proc_ref(curp);
711 	MAC_CHECK(proc_check_ledger, cred, proc, ledger_op);
712 	kauth_cred_unref(&cred);
713 
714 	return error;
715 }
716 
717 int
mac_proc_check_proc_info(proc_t curp,proc_t target,int callnum,int flavor)718 mac_proc_check_proc_info(proc_t curp, proc_t target, int callnum, int flavor)
719 {
720 	kauth_cred_t cred;
721 	int error = 0;
722 
723 #if SECURITY_MAC_CHECK_ENFORCE
724 	/* 21167099 - only check if we allow write */
725 	if (!mac_proc_enforce) {
726 		return 0;
727 	}
728 #endif
729 	if (!mac_proc_check_enforce(curp)) {
730 		return 0;
731 	}
732 
733 	cred = kauth_cred_proc_ref(curp);
734 	MAC_CHECK(proc_check_proc_info, cred, target, callnum, flavor);
735 	kauth_cred_unref(&cred);
736 
737 	return error;
738 }
739 
740 int
mac_proc_check_get_cs_info(proc_t curp,proc_t target,unsigned int op)741 mac_proc_check_get_cs_info(proc_t curp, proc_t target, unsigned int op)
742 {
743 	kauth_cred_t cred;
744 	int error = 0;
745 
746 #if SECURITY_MAC_CHECK_ENFORCE
747 	/* 21167099 - only check if we allow write */
748 	if (!mac_proc_enforce) {
749 		return 0;
750 	}
751 #endif
752 	if (!mac_proc_check_enforce(curp)) {
753 		return 0;
754 	}
755 
756 	cred = kauth_cred_proc_ref(curp);
757 	MAC_CHECK(proc_check_get_cs_info, cred, target, op);
758 	kauth_cred_unref(&cred);
759 
760 	return error;
761 }
762 
763 int
mac_proc_check_set_cs_info(proc_t curp,proc_t target,unsigned int op)764 mac_proc_check_set_cs_info(proc_t curp, proc_t target, unsigned int op)
765 {
766 	kauth_cred_t cred;
767 	int error = 0;
768 
769 #if SECURITY_MAC_CHECK_ENFORCE
770 	/* 21167099 - only check if we allow write */
771 	if (!mac_proc_enforce) {
772 		return 0;
773 	}
774 #endif
775 	if (!mac_proc_check_enforce(curp)) {
776 		return 0;
777 	}
778 
779 	cred = kauth_cred_proc_ref(curp);
780 	MAC_CHECK(proc_check_set_cs_info, cred, target, op);
781 	kauth_cred_unref(&cred);
782 
783 	return error;
784 }
785 
786 int
mac_proc_check_setuid(proc_t curp,kauth_cred_t cred,uid_t uid)787 mac_proc_check_setuid(proc_t curp, kauth_cred_t cred, uid_t uid)
788 {
789 	int error = 0;
790 
791 #if SECURITY_MAC_CHECK_ENFORCE
792 	/* 21167099 - only check if we allow write */
793 	if (!mac_proc_enforce) {
794 		return 0;
795 	}
796 #endif
797 	if (!mac_proc_check_enforce(curp)) {
798 		return 0;
799 	}
800 
801 	MAC_CHECK(proc_check_setuid, cred, uid);
802 
803 	return error;
804 }
805 
806 int
mac_proc_check_seteuid(proc_t curp,kauth_cred_t cred,uid_t euid)807 mac_proc_check_seteuid(proc_t curp, kauth_cred_t cred, uid_t euid)
808 {
809 	int error = 0;
810 
811 #if SECURITY_MAC_CHECK_ENFORCE
812 	/* 21167099 - only check if we allow write */
813 	if (!mac_proc_enforce) {
814 		return 0;
815 	}
816 #endif
817 	if (!mac_proc_check_enforce(curp)) {
818 		return 0;
819 	}
820 
821 	MAC_CHECK(proc_check_seteuid, cred, euid);
822 
823 	return error;
824 }
825 
826 int
mac_proc_check_setreuid(proc_t curp,kauth_cred_t cred,uid_t ruid,uid_t euid)827 mac_proc_check_setreuid(proc_t curp, kauth_cred_t cred, uid_t ruid, uid_t euid)
828 {
829 	int error = 0;
830 
831 #if SECURITY_MAC_CHECK_ENFORCE
832 	/* 21167099 - only check if we allow write */
833 	if (!mac_proc_enforce) {
834 		return 0;
835 	}
836 #endif
837 	if (!mac_proc_check_enforce(curp)) {
838 		return 0;
839 	}
840 
841 	MAC_CHECK(proc_check_setreuid, cred, ruid, euid);
842 
843 	return error;
844 }
845 
846 int
mac_proc_check_setgid(proc_t curp,kauth_cred_t cred,gid_t gid)847 mac_proc_check_setgid(proc_t curp, kauth_cred_t cred, gid_t gid)
848 {
849 	int error = 0;
850 
851 #if SECURITY_MAC_CHECK_ENFORCE
852 	/* 21167099 - only check if we allow write */
853 	if (!mac_proc_enforce) {
854 		return 0;
855 	}
856 #endif
857 	if (!mac_proc_check_enforce(curp)) {
858 		return 0;
859 	}
860 
861 	MAC_CHECK(proc_check_setgid, cred, gid);
862 
863 	return error;
864 }
865 
866 int
mac_proc_check_setegid(proc_t curp,kauth_cred_t cred,gid_t egid)867 mac_proc_check_setegid(proc_t curp, kauth_cred_t cred, gid_t egid)
868 {
869 	int error = 0;
870 
871 #if SECURITY_MAC_CHECK_ENFORCE
872 	/* 21167099 - only check if we allow write */
873 	if (!mac_proc_enforce) {
874 		return 0;
875 	}
876 #endif
877 	if (!mac_proc_check_enforce(curp)) {
878 		return 0;
879 	}
880 
881 	MAC_CHECK(proc_check_setegid, cred, egid);
882 
883 	return error;
884 }
885 
886 int
mac_proc_check_setregid(proc_t curp,kauth_cred_t cred,gid_t rgid,gid_t egid)887 mac_proc_check_setregid(proc_t curp, kauth_cred_t cred, gid_t rgid, gid_t egid)
888 {
889 	int error = 0;
890 
891 #if SECURITY_MAC_CHECK_ENFORCE
892 	/* 21167099 - only check if we allow write */
893 	if (!mac_proc_enforce) {
894 		return 0;
895 	}
896 #endif
897 	if (!mac_proc_check_enforce(curp)) {
898 		return 0;
899 	}
900 
901 	MAC_CHECK(proc_check_setregid, cred, rgid, egid);
902 
903 	return error;
904 }
905 
906 int
mac_proc_check_settid(proc_t curp,uid_t uid,gid_t gid)907 mac_proc_check_settid(proc_t curp, uid_t uid, gid_t gid)
908 {
909 	kauth_cred_t pcred, tcred;
910 	int error = 0;
911 
912 #if SECURITY_MAC_CHECK_ENFORCE
913 	/* 21167099 - only check if we allow write */
914 	if (!mac_proc_enforce) {
915 		return 0;
916 	}
917 #endif
918 	if (!mac_proc_check_enforce(curp)) {
919 		return 0;
920 	}
921 
922 	pcred = kauth_cred_proc_ref(curp);
923 	tcred = kauth_cred_get_with_ref();
924 	MAC_CHECK(proc_check_settid, pcred, tcred, uid, gid);
925 	kauth_cred_unref(&tcred);
926 	kauth_cred_unref(&pcred);
927 
928 	return error;
929 }
930 
931 int
mac_proc_check_launch_constraints(proc_t curp,struct image_params * imgp,os_reason_t * reasonp)932 mac_proc_check_launch_constraints(proc_t curp, struct image_params *imgp, os_reason_t *reasonp)
933 {
934 	char *fatal_failure_desc = NULL;
935 	size_t fatal_failure_desc_len = 0;
936 
937 	pid_t original_parent_id = proc_original_ppid(curp);
938 
939 	pid_t responsible_pid = curp->p_responsible_pid;
940 
941 	int error = 0;
942 
943 	/* Vnode of the file */
944 	struct vnode *vp = imgp->ip_vp;
945 
946 	char *vn_path = NULL;
947 	vm_size_t vn_pathlen = MAXPATHLEN;
948 #if SECURITY_MAC_CHECK_ENFORCE
949 	/* 21167099 - only check if we allow write */
950 	if (!mac_proc_enforce || !mac_vnode_enforce) {
951 		return 0;
952 	}
953 #endif
954 
955 	MAC_POLICY_ITERATE({
956 		mpo_proc_check_launch_constraints_t *hook = mpc->mpc_ops->mpo_proc_check_launch_constraints;
957 		if (hook == NULL) {
958 		        continue;
959 		}
960 
961 		size_t spawnattrlen = 0;
962 		void *spawnattr = exec_spawnattr_getmacpolicyinfo(&imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
963 		struct _posix_spawnattr *psa = (struct _posix_spawnattr *) imgp->ip_px_sa;
964 		struct launch_constraint_data lcd;
965 		lcd.launch_type = CS_LAUNCH_TYPE_NONE;
966 
967 		/* Check to see if psa_launch_type was initalized */
968 		if (psa != (struct _posix_spawnattr*)NULL) {
969 		        lcd.launch_type = psa->psa_launch_type;
970 		}
971 
972 		error = mac_error_select(
973 			hook(curp, original_parent_id, responsible_pid,
974 			spawnattr, spawnattrlen, &lcd, &fatal_failure_desc, &fatal_failure_desc_len), error);
975 
976 		/*
977 		 * Early exit in case of failure in case we have multiple registered callers.
978 		 * This is to avoid other MACF policies from stomping on each other's failure description
979 		 */
980 		if (fatal_failure_desc_len) {
981 		        goto policy_fail;
982 		}
983 	});
984 
985 policy_fail:
986 	if (fatal_failure_desc_len) {
987 		/*
988 		 * A fatal code signature validation failure occured, formulate a crash
989 		 * reason.
990 		 */
991 
992 		char const *path = NULL;
993 
994 		vn_path = zalloc(ZV_NAMEI);
995 		if (vn_getpath(vp, vn_path, (int*)&vn_pathlen) == 0) {
996 			path = vn_path;
997 		} else {
998 			path = "(get vnode path failed)";
999 		}
1000 
1001 		if (error == 0) {
1002 			panic("%s: MAC hook returned no error, but status is claimed to be fatal? "
1003 			    "path: '%s', fatal_failure_desc_len: %ld, fatal_failure_desc:\n%s\n",
1004 			    __func__, path, fatal_failure_desc_len, fatal_failure_desc);
1005 		}
1006 
1007 		os_reason_t reason = os_reason_create(OS_REASON_CODESIGNING,
1008 		    CODESIGNING_EXIT_REASON_LAUNCH_CONSTRAINT_VIOLATION);
1009 
1010 		*reasonp = reason;
1011 
1012 		reason->osr_flags = (OS_REASON_FLAG_GENERATE_CRASH_REPORT |
1013 		    OS_REASON_FLAG_CONSISTENT_FAILURE);
1014 
1015 		if (fatal_failure_desc != NULL) {
1016 			mach_vm_address_t data_addr = 0;
1017 
1018 			int reason_error = 0;
1019 			int kcdata_error = 0;
1020 
1021 			if ((reason_error = os_reason_alloc_buffer_noblock(reason,
1022 			    kcdata_estimate_required_buffer_size(1,
1023 			    (uint32_t)fatal_failure_desc_len))) == 0) {
1024 				if ((kcdata_error = kcdata_get_memory_addr(&reason->osr_kcd_descriptor,
1025 				    EXIT_REASON_USER_DESC, (uint32_t)fatal_failure_desc_len,
1026 				    &data_addr)) == KERN_SUCCESS) {
1027 					kcdata_memcpy(&reason->osr_kcd_descriptor, (mach_vm_address_t)data_addr,
1028 					    fatal_failure_desc, (uint32_t)fatal_failure_desc_len);
1029 				}
1030 			}
1031 		}
1032 	}
1033 
1034 	if (vn_path) {
1035 		zfree(ZV_NAMEI, vn_path);
1036 	}
1037 
1038 	if (fatal_failure_desc_len > 0 && fatal_failure_desc != NULL) {
1039 		kfree_data(fatal_failure_desc, fatal_failure_desc_len);
1040 	}
1041 
1042 	return error;
1043 }
1044