2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/proc_internal.h>
34 #include <sys/sysctl.h>
35 #include <sys/signal.h>
36 #include <sys/signalvar.h>
37 #include <sys/codesign.h>
39 #include <sys/fcntl.h>
41 #include <sys/file_internal.h>
42 #include <sys/kauth.h>
43 #include <sys/mount.h>
46 #include <sys/socketvar.h>
47 #include <sys/vnode.h>
48 #include <sys/vnode_internal.h>
51 #include <sys/ubc_internal.h>
53 #include <security/mac.h>
54 #include <security/mac_policy.h>
55 #include <security/mac_framework.h>
57 #include <mach/mach_types.h>
58 #include <mach/vm_map.h>
59 #include <mach/mach_vm.h>
61 #include <kern/kern_types.h>
62 #include <kern/task.h>
64 #include <vm/vm_map.h>
65 #include <vm/vm_kern.h>
68 #include <kern/assert.h>
70 #include <pexpert/pexpert.h>
72 #include <mach/shared_region.h>
74 #include <libkern/section_keywords.h>
76 unsigned long cs_procs_killed
= 0;
77 unsigned long cs_procs_invalidated
= 0;
79 int cs_force_kill
= 0;
80 int cs_force_hard
= 0;
82 // If set, AMFI will error out early on unsigned code, before evaluation the normal policy.
83 int cs_debug_fail_on_unsigned_code
= 0;
84 // If the previous mode is enabled, we count the resulting failures here.
85 unsigned int cs_debug_unsigned_exec_failures
= 0;
86 unsigned int cs_debug_unsigned_mmap_failures
= 0;
90 * Here we split cs_enforcement_enable into cs_system_enforcement_enable and cs_process_enforcement_enable
92 * cs_system_enforcement_enable governs whether or not system level code signing enforcement mechanisms
93 * are applied on the system. Today, the only such mechanism is code signing enforcement of the dyld shared
96 * cs_process_enforcement_enable governs whether code signing enforcement mechanisms are applied to all
97 * processes or only those that opt into such enforcement.
99 * (On iOS and related, both of these are set by default. On macOS, only cs_system_enforcement_enable
100 * is set by default. Processes can then be opted into code signing enforcement on a case by case basis.)
102 const int cs_system_enforcement_enable
= 1;
103 const int cs_process_enforcement_enable
= 1;
104 const int cs_library_val_enable
= 1;
105 #else /* !SECURE_KERNEL */
106 int cs_enforcement_panic
= 0;
107 int cs_relax_platform_task_ports
= 0;
109 #if CONFIG_ENFORCE_SIGNED_CODE
110 #define DEFAULT_CS_SYSTEM_ENFORCEMENT_ENABLE 1
111 #define DEFAULT_CS_PROCESS_ENFORCEMENT_ENABLE 1
113 #define DEFAULT_CS_SYSTEM_ENFORCEMENT_ENABLE 1
114 #define DEFAULT_CS_PROCESS_ENFORCEMENT_ENABLE 0
116 SECURITY_READ_ONLY_LATE(int) cs_system_enforcement_enable
= DEFAULT_CS_SYSTEM_ENFORCEMENT_ENABLE
;
117 SECURITY_READ_ONLY_LATE(int) cs_process_enforcement_enable
= DEFAULT_CS_PROCESS_ENFORCEMENT_ENABLE
;
119 #if CONFIG_ENFORCE_LIBRARY_VALIDATION
120 #define DEFAULT_CS_LIBRARY_VA_ENABLE 1
122 #define DEFAULT_CS_LIBRARY_VA_ENABLE 0
124 SECURITY_READ_ONLY_LATE(int) cs_library_val_enable
= DEFAULT_CS_LIBRARY_VA_ENABLE
;
126 #endif /* !SECURE_KERNEL */
127 int cs_all_vnodes
= 0;
129 static lck_grp_t
*cs_lockgrp
;
131 SYSCTL_INT(_vm
, OID_AUTO
, cs_force_kill
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &cs_force_kill
, 0, "");
132 SYSCTL_INT(_vm
, OID_AUTO
, cs_force_hard
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &cs_force_hard
, 0, "");
133 SYSCTL_INT(_vm
, OID_AUTO
, cs_debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &cs_debug
, 0, "");
134 SYSCTL_INT(_vm
, OID_AUTO
, cs_debug_fail_on_unsigned_code
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
135 &cs_debug_fail_on_unsigned_code
, 0, "");
136 SYSCTL_UINT(_vm
, OID_AUTO
, cs_debug_unsigned_exec_failures
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
137 &cs_debug_unsigned_exec_failures
, 0, "");
138 SYSCTL_UINT(_vm
, OID_AUTO
, cs_debug_unsigned_mmap_failures
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
139 &cs_debug_unsigned_mmap_failures
, 0, "");
141 SYSCTL_INT(_vm
, OID_AUTO
, cs_all_vnodes
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &cs_all_vnodes
, 0, "");
144 SYSCTL_INT(_vm
, OID_AUTO
, cs_system_enforcement
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_system_enforcement_enable
, 0, "");
145 SYSCTL_INT(_vm
, OID_AUTO
, cs_process_enforcement
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &cs_process_enforcement_enable
, 0, "");
146 SYSCTL_INT(_vm
, OID_AUTO
, cs_enforcement_panic
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &cs_enforcement_panic
, 0, "");
148 #if !CONFIG_ENFORCE_LIBRARY_VALIDATION
149 SYSCTL_INT(_vm
, OID_AUTO
, cs_library_validation
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_library_val_enable
, 0, "");
151 #endif /* !SECURE_KERNEL */
153 int panic_on_cs_killed
= 0;
159 #if PLATFORM_WatchOS || __x86_64__
160 panic_on_cs_killed
= 1;
161 #endif /* watchos || x86_64 */
162 #endif /* MACH_ASSERT */
163 PE_parse_boot_argn("panic_on_cs_killed", &panic_on_cs_killed
,
164 sizeof(panic_on_cs_killed
));
166 int disable_cs_enforcement
= 0;
167 PE_parse_boot_argn("cs_enforcement_disable", &disable_cs_enforcement
,
168 sizeof(disable_cs_enforcement
));
169 if (disable_cs_enforcement
&& PE_i_can_has_debugger(NULL
) != 0) {
170 cs_system_enforcement_enable
= 0;
171 cs_process_enforcement_enable
= 0;
174 PE_parse_boot_argn("cs_enforcement_panic", &panic
, sizeof(panic
));
175 cs_enforcement_panic
= (panic
!= 0);
178 PE_parse_boot_argn("cs_relax_platform_task_ports",
179 &cs_relax_platform_task_ports
,
180 sizeof(cs_relax_platform_task_ports
));
182 PE_parse_boot_argn("cs_debug", &cs_debug
, sizeof(cs_debug
));
184 #if !CONFIG_ENFORCE_LIBRARY_VALIDATION
185 PE_parse_boot_argn("cs_library_val_enable", &cs_library_val_enable
,
186 sizeof(cs_library_val_enable
));
188 #endif /* !SECURE_KERNEL */
190 lck_grp_attr_t
*attr
= lck_grp_attr_alloc_init();
191 cs_lockgrp
= lck_grp_alloc_init("KERNCS", attr
);
192 lck_grp_attr_free(attr
);
196 cs_allow_invalid(struct proc
*p
)
199 lck_mtx_assert(&p
->p_mlock
, LCK_MTX_ASSERT_NOTOWNED
);
202 /* There needs to be a MAC policy to implement this hook, or else the
203 * kill bits will be cleared here every time. If we have
204 * CONFIG_ENFORCE_SIGNED_CODE, we can assume there is a policy
205 * implementing the hook.
207 if (0 != mac_proc_check_run_cs_invalid(p
)) {
209 printf("CODE SIGNING: cs_allow_invalid() "
210 "not allowed: pid %d\n",
216 printf("CODE SIGNING: cs_allow_invalid() "
221 p
->p_csflags
&= ~(CS_KILL
| CS_HARD
);
222 if (p
->p_csflags
& CS_VALID
) {
223 p
->p_csflags
|= CS_DEBUGGED
;
227 vm_map_switch_protect(get_task_map(p
->task
), FALSE
);
229 return (p
->p_csflags
& (CS_KILL
| CS_HARD
)) == 0;
233 cs_invalid_page(addr64_t vaddr
, boolean_t
*cs_killed
)
236 int send_kill
= 0, retval
= 0, verbose
= cs_debug
;
242 printf("CODE SIGNING: cs_invalid_page(0x%llx): p=%d[%s]\n",
243 vaddr
, p
->p_pid
, p
->p_comm
);
248 /* XXX for testing */
250 p
->p_csflags
|= CS_KILL
;
253 p
->p_csflags
|= CS_HARD
;
256 /* CS_KILL triggers a kill signal, and no you can't have the page. Nothing else. */
257 if (p
->p_csflags
& CS_KILL
) {
258 p
->p_csflags
|= CS_KILLED
;
264 /* CS_HARD means fail the mapping operation so the process stays valid. */
265 if (p
->p_csflags
& CS_HARD
) {
268 if (p
->p_csflags
& CS_VALID
) {
269 p
->p_csflags
&= ~CS_VALID
;
270 cs_procs_invalidated
++;
274 csflags
= p
->p_csflags
;
278 printf("CODE SIGNING: cs_invalid_page(0x%llx): "
279 "p=%d[%s] final status 0x%x, %s page%s\n",
280 vaddr
, p
->p_pid
, p
->p_comm
, p
->p_csflags
,
281 retval
? "denying" : "allowing (remove VALID)",
282 send_kill
? " sending SIGKILL" : "");
286 /* We will set the exit reason for the thread later */
287 threadsignal(current_thread(), SIGKILL
, EXC_BAD_ACCESS
, FALSE
);
291 } else if (cs_killed
) {
300 * Assumes p (if passed in) is locked with proc_lock().
304 cs_process_enforcement(struct proc
*p
)
306 if (cs_process_enforcement_enable
) {
314 if (p
!= NULL
&& (p
->p_csflags
& CS_ENFORCEMENT
)) {
322 cs_process_global_enforcement(void)
324 return cs_process_enforcement_enable
? 1 : 0;
328 cs_system_enforcement(void)
330 return cs_system_enforcement_enable
? 1 : 0;
334 * Returns whether a given process is still valid.
337 cs_valid(struct proc
*p
)
343 if (p
!= NULL
&& (p
->p_csflags
& CS_VALID
)) {
351 * Library validation functions
354 cs_require_lv(struct proc
*p
)
356 if (cs_library_val_enable
) {
364 if (p
!= NULL
&& (p
->p_csflags
& CS_REQUIRE_LV
)) {
372 csproc_forced_lv(struct proc
* p
)
377 if (p
!= NULL
&& (p
->p_csflags
& CS_FORCED_LV
)) {
384 * <rdar://problem/24634089> added to allow system level library
385 * validation check at mac_cred_label_update_execve time
388 cs_system_require_lv(void)
390 return cs_library_val_enable
? 1 : 0;
394 * Function: csblob_get_base_offset
396 * Description: This function returns the base offset into the (possibly universal) binary
401 csblob_get_base_offset(struct cs_blob
*blob
)
403 return blob
->csb_base_offset
;
407 * Function: csblob_get_size
409 * Description: This function returns the size of a given blob.
413 csblob_get_size(struct cs_blob
*blob
)
415 return blob
->csb_mem_size
;
419 * Function: csblob_get_addr
421 * Description: This function returns the address of a given blob.
425 csblob_get_addr(struct cs_blob
*blob
)
427 return blob
->csb_mem_kaddr
;
431 * Function: csblob_get_platform_binary
433 * Description: This function returns true if the binary is
434 * in the trust cache.
438 csblob_get_platform_binary(struct cs_blob
*blob
)
440 if (blob
&& blob
->csb_platform_binary
) {
447 * Function: csblob_get_flags
449 * Description: This function returns the flags for a given blob
453 csblob_get_flags(struct cs_blob
*blob
)
455 return blob
->csb_flags
;
459 * Function: csblob_get_hashtype
461 * Description: This function returns the hash type for a given blob
465 csblob_get_hashtype(struct cs_blob
const * const blob
)
467 return blob
->csb_hashtype
!= NULL
? cs_hash_type(blob
->csb_hashtype
) : 0;
471 * Function: csproc_get_blob
473 * Description: This function returns the cs_blob
477 csproc_get_blob(struct proc
*p
)
483 if (NULL
== p
->p_textvp
) {
487 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
491 return ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
);
495 * Function: csvnode_get_blob
497 * Description: This function returns the cs_blob
501 csvnode_get_blob(struct vnode
*vp
, off_t offset
)
503 return ubc_cs_blob_get(vp
, -1, offset
);
507 * Function: csblob_get_teamid
509 * Description: This function returns a pointer to the
513 csblob_get_teamid(struct cs_blob
*csblob
)
515 return csblob
->csb_teamid
;
519 * Function: csblob_get_identity
521 * Description: This function returns a pointer to the
525 csblob_get_identity(struct cs_blob
*csblob
)
527 const CS_CodeDirectory
*cd
;
529 cd
= (const CS_CodeDirectory
*)csblob_find_blob(csblob
, CSSLOT_CODEDIRECTORY
, CSMAGIC_CODEDIRECTORY
);
534 if (cd
->identOffset
== 0) {
538 return ((const char *)cd
) + ntohl(cd
->identOffset
);
542 * Function: csblob_get_cdhash
544 * Description: This function returns a pointer to the
545 * cdhash of csblob (20 byte array)
548 csblob_get_cdhash(struct cs_blob
*csblob
)
550 return csblob
->csb_cdhash
;
554 * Function: csblob_get_signer_type
556 * Description: This function returns the signer type
560 csblob_get_signer_type(struct cs_blob
*csblob
)
562 return csblob
->csb_signer_type
;
566 csblob_entitlements_dictionary_copy(struct cs_blob
*csblob
)
568 if (!csblob
->csb_entitlements
) {
571 osobject_retain(csblob
->csb_entitlements
);
572 return csblob
->csb_entitlements
;
576 csblob_entitlements_dictionary_set(struct cs_blob
*csblob
, void * entitlements
)
578 assert(csblob
->csb_entitlements
== NULL
);
580 osobject_retain(entitlements
);
582 csblob
->csb_entitlements
= entitlements
;
586 * Function: csproc_get_teamid
588 * Description: This function returns a pointer to the
589 * team id of the process p
592 csproc_get_teamid(struct proc
*p
)
594 struct cs_blob
*csblob
;
596 csblob
= csproc_get_blob(p
);
597 if (csblob
== NULL
) {
601 return csblob_get_teamid(csblob
);
605 * Function: csproc_get_signer_type
607 * Description: This function returns the signer type
611 csproc_get_signer_type(struct proc
*p
)
613 struct cs_blob
*csblob
;
615 csblob
= csproc_get_blob(p
);
616 if (csblob
== NULL
) {
617 return CS_SIGNER_TYPE_UNKNOWN
;
620 return csblob_get_signer_type(csblob
);
624 * Function: csvnode_get_teamid
626 * Description: This function returns a pointer to the
627 * team id of the binary at the given offset in vnode vp
630 csvnode_get_teamid(struct vnode
*vp
, off_t offset
)
632 struct cs_blob
*csblob
;
638 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
639 if (csblob
== NULL
) {
643 return csblob_get_teamid(csblob
);
647 * Function: csproc_get_platform_binary
649 * Description: This function returns the value
650 * of the platform_binary field for proc p
653 csproc_get_platform_binary(struct proc
*p
)
655 struct cs_blob
*csblob
;
657 csblob
= csproc_get_blob(p
);
659 /* If there is no csblob this returns 0 because
660 * it is true that it is not a platform binary */
661 return (csblob
== NULL
) ? 0 : csblob
->csb_platform_binary
;
665 csproc_get_platform_path(struct proc
*p
)
667 struct cs_blob
*csblob
;
669 csblob
= csproc_get_blob(p
);
671 return (csblob
== NULL
) ? 0 : csblob
->csb_platform_path
;
674 #if DEVELOPMENT || DEBUG
676 csproc_clear_platform_binary(struct proc
*p
)
678 struct cs_blob
*csblob
= csproc_get_blob(p
);
680 if (csblob
== NULL
) {
685 printf("clearing platform binary on proc/task: pid = %d\n", p
->p_pid
);
688 csblob
->csb_platform_binary
= 0;
689 csblob
->csb_platform_path
= 0;
690 task_set_platform_binary(proc_task(p
), FALSE
);
695 csproc_disable_enforcement(struct proc
* __unused p
)
697 #if !CONFIG_ENFORCE_SIGNED_CODE
700 p
->p_csflags
&= (~CS_ENFORCEMENT
);
706 /* Function: csproc_mark_invalid_allowed
708 * Description: Mark the process as being allowed to go invalid. Called as part of
709 * task_for_pid and ptrace policy. Note CS_INVALID_ALLOWED only matters for
710 * processes that have been opted into CS_ENFORCEMENT.
713 csproc_mark_invalid_allowed(struct proc
* __unused p
)
715 #if !CONFIG_ENFORCE_SIGNED_CODE
718 p
->p_csflags
|= CS_INVALID_ALLOWED
;
725 * Function: csproc_check_invalid_allowed
727 * Description: Returns 1 if the process has been marked as allowed to go invalid
728 * because it gave its task port to an allowed process.
731 csproc_check_invalid_allowed(struct proc
* __unused p
)
733 #if !CONFIG_ENFORCE_SIGNED_CODE
738 if (p
!= NULL
&& (p
->p_csflags
& CS_INVALID_ALLOWED
)) {
746 * Function: csproc_get_prod_signed
748 * Description: Returns 1 if process is not signed with a developer identity.
749 * Note the inverted meaning from the cs_flag to make the error case safer.
750 * Will go away with rdar://problem/28322552.
753 csproc_get_prod_signed(struct proc
*p
)
755 return (p
->p_csflags
& CS_DEV_CODE
) == 0;
760 * Function: csfg_get_platform_binary
762 * Description: This function returns the
763 * platform binary field for the
767 csfg_get_platform_binary(struct fileglob
*fg
)
769 int platform_binary
= 0;
770 struct ubc_info
*uip
;
773 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
777 vp
= (struct vnode
*)fg
->fg_data
;
783 if (!UBCINFOEXISTS(vp
)) {
792 if (uip
->cs_blobs
== NULL
) {
796 /* It is OK to extract the teamid from the first blob
797 * because all blobs of a vnode must have the same teamid */
798 platform_binary
= uip
->cs_blobs
->csb_platform_binary
;
802 return platform_binary
;
806 csfg_get_cdhash(struct fileglob
*fg
, uint64_t offset
, size_t *cdhash_size
)
810 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
814 vp
= (struct vnode
*)fg
->fg_data
;
819 struct cs_blob
*csblob
= NULL
;
820 if ((csblob
= ubc_cs_blob_get(vp
, -1, offset
)) == NULL
) {
825 *cdhash_size
= CS_CDHASH_LEN
;
828 return csblob
->csb_cdhash
;
832 * Function: csfg_get_signer_type
834 * Description: This returns the signer type
835 * for the fileglob fg
838 csfg_get_signer_type(struct fileglob
*fg
)
840 struct ubc_info
*uip
;
841 unsigned int signer_type
= CS_SIGNER_TYPE_UNKNOWN
;
844 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
845 return CS_SIGNER_TYPE_UNKNOWN
;
848 vp
= (struct vnode
*)fg
->fg_data
;
850 return CS_SIGNER_TYPE_UNKNOWN
;
854 if (!UBCINFOEXISTS(vp
)) {
863 if (uip
->cs_blobs
== NULL
) {
867 /* It is OK to extract the signer type from the first blob,
868 * because all blobs of a vnode must have the same signer type. */
869 signer_type
= uip
->cs_blobs
->csb_signer_type
;
877 * Function: csfg_get_teamid
879 * Description: This returns a pointer to
880 * the teamid for the fileglob fg
883 csfg_get_teamid(struct fileglob
*fg
)
885 struct ubc_info
*uip
;
886 const char *str
= NULL
;
889 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
893 vp
= (struct vnode
*)fg
->fg_data
;
899 if (!UBCINFOEXISTS(vp
)) {
908 if (uip
->cs_blobs
== NULL
) {
912 /* It is OK to extract the teamid from the first blob
913 * because all blobs of a vnode must have the same teamid */
914 str
= uip
->cs_blobs
->csb_teamid
;
922 * Function: csfg_get_prod_signed
924 * Description: Returns 1 if code is not signed with a developer identity.
925 * Note the inverted meaning from the cs_flag to make the error case safer.
926 * Will go away with rdar://problem/28322552.
929 csfg_get_prod_signed(struct fileglob
*fg
)
931 struct ubc_info
*uip
;
935 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
939 vp
= (struct vnode
*)fg
->fg_data
;
945 if (!UBCINFOEXISTS(vp
)) {
954 if (uip
->cs_blobs
== NULL
) {
958 /* It is OK to extract the flag from the first blob
959 * because all blobs of a vnode must have the same cs_flags */
960 prod_signed
= (uip
->cs_blobs
->csb_flags
& CS_DEV_CODE
) == 0;
968 * Function: csfg_get_identity
970 * Description: This function returns the codesign identity
974 csfg_get_identity(struct fileglob
*fg
, off_t offset
)
977 struct cs_blob
*csblob
= NULL
;
979 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
983 vp
= (struct vnode
*)fg
->fg_data
;
988 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
989 if (csblob
== NULL
) {
993 return csblob_get_identity(csblob
);
997 * Function: csfg_get_platform_identifier
999 * Description: This function returns the codesign platform
1000 * identifier for the fileglob. Assumes the fileproc
1001 * is being held busy to keep the fileglob consistent.
1004 csfg_get_platform_identifier(struct fileglob
*fg
, off_t offset
)
1008 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
1012 vp
= (struct vnode
*)fg
->fg_data
;
1017 return csvnode_get_platform_identifier(vp
, offset
);
1021 * Function: csvnode_get_platform_identifier
1023 * Description: This function returns the codesign platform
1024 * identifier for the vnode. Assumes a vnode reference
1028 csvnode_get_platform_identifier(struct vnode
*vp
, off_t offset
)
1030 struct cs_blob
*csblob
;
1031 const CS_CodeDirectory
*code_dir
;
1033 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
1034 if (csblob
== NULL
) {
1038 code_dir
= csblob
->csb_cd
;
1039 if (code_dir
== NULL
|| ntohl(code_dir
->length
) < 8) {
1043 return code_dir
->platform
;
1047 * Function: csproc_get_platform_identifier
1049 * Description: This function returns the codesign platform
1050 * identifier for the proc. Assumes proc will remain
1051 * valid through call.
1054 csproc_get_platform_identifier(struct proc
*p
)
1056 if (NULL
== p
->p_textvp
) {
1060 return csvnode_get_platform_identifier(p
->p_textvp
, p
->p_textoff
);
1064 cs_entitlement_flags(struct proc
*p
)
1066 return p
->p_csflags
& CS_ENTITLEMENT_FLAGS
;
1070 cs_restricted(struct proc
*p
)
1072 return (p
->p_csflags
& CS_RESTRICT
) ? 1 : 0;
1076 csproc_hardened_runtime(struct proc
* p
)
1078 return (p
->p_csflags
& CS_RUNTIME
) ? 1 : 0;
1082 * Function: csfg_get_path
1084 * Description: This populates the buffer passed in
1085 * with the path of the vnode
1086 * When calling this, the fileglob
1087 * cannot go away. The caller must have a
1088 * a reference on the fileglob or fileproc
1091 csfg_get_path(struct fileglob
*fg
, char *path
, int *len
)
1095 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
1099 vp
= (struct vnode
*)fg
->fg_data
;
1101 /* vn_getpath returns 0 for success,
1102 * or an error code */
1103 return vn_getpath(vp
, path
, len
);
1106 /* Retrieve the entitlements blob for a process.
1108 * EINVAL no text vnode associated with the process
1109 * EBADEXEC invalid code signing data
1110 * 0 no error occurred
1112 * On success, out_start and out_length will point to the
1113 * entitlements blob if found; or will be set to NULL/zero
1114 * if there were no entitlements.
1118 cs_entitlements_blob_get(proc_t p
, void **out_start
, size_t *out_length
)
1120 struct cs_blob
*csblob
;
1125 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1129 if (NULL
== p
->p_textvp
) {
1133 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1137 return csblob_get_entitlements(csblob
, out_start
, out_length
);
1140 /* Retrieve the codesign identity for a process.
1142 * NULL an error occured
1143 * string the cs_identity
1147 cs_identity_get(proc_t p
)
1149 struct cs_blob
*csblob
;
1151 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1155 if (NULL
== p
->p_textvp
) {
1159 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1163 return csblob_get_identity(csblob
);
1167 * DO NOT USE THIS FUNCTION!
1168 * Use the properly guarded csproc_get_blob instead.
1170 * This is currently here to allow detached signatures to work
1171 * properly. The only user of this function is also checking
1176 cs_blob_get(proc_t p
, void **out_start
, size_t *out_length
)
1178 struct cs_blob
*csblob
;
1183 if (NULL
== p
->p_textvp
) {
1187 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1191 *out_start
= (void *)csblob
->csb_mem_kaddr
;
1192 *out_length
= csblob
->csb_mem_size
;
1198 * return cshash of a process, cdhash is of size CS_CDHASH_LEN
1202 cs_get_cdhash(struct proc
*p
)
1204 struct cs_blob
*csblob
;
1206 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1210 if (NULL
== p
->p_textvp
) {
1214 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1218 return csblob
->csb_cdhash
;