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
)) {
208 if(cs_debug
) printf("CODE SIGNING: cs_allow_invalid() "
209 "not allowed: pid %d\n",
213 if(cs_debug
) printf("CODE SIGNING: cs_allow_invalid() "
217 p
->p_csflags
&= ~(CS_KILL
| CS_HARD
);
218 if (p
->p_csflags
& CS_VALID
)
220 p
->p_csflags
|= CS_DEBUGGED
;
225 vm_map_switch_protect(get_task_map(p
->task
), FALSE
);
227 return (p
->p_csflags
& (CS_KILL
| CS_HARD
)) == 0;
231 cs_invalid_page(addr64_t vaddr
, boolean_t
*cs_killed
)
234 int send_kill
= 0, retval
= 0, verbose
= cs_debug
;
240 printf("CODE SIGNING: cs_invalid_page(0x%llx): p=%d[%s]\n",
241 vaddr
, p
->p_pid
, p
->p_comm
);
245 /* XXX for testing */
247 p
->p_csflags
|= CS_KILL
;
249 p
->p_csflags
|= CS_HARD
;
251 /* CS_KILL triggers a kill signal, and no you can't have the page. Nothing else. */
252 if (p
->p_csflags
& CS_KILL
) {
253 p
->p_csflags
|= CS_KILLED
;
259 /* CS_HARD means fail the mapping operation so the process stays valid. */
260 if (p
->p_csflags
& CS_HARD
) {
263 if (p
->p_csflags
& CS_VALID
) {
264 p
->p_csflags
&= ~CS_VALID
;
265 cs_procs_invalidated
++;
269 csflags
= p
->p_csflags
;
273 printf("CODE SIGNING: cs_invalid_page(0x%llx): "
274 "p=%d[%s] final status 0x%x, %s page%s\n",
275 vaddr
, p
->p_pid
, p
->p_comm
, p
->p_csflags
,
276 retval
? "denying" : "allowing (remove VALID)",
277 send_kill
? " sending SIGKILL" : "");
280 /* We will set the exit reason for the thread later */
281 threadsignal(current_thread(), SIGKILL
, EXC_BAD_ACCESS
, FALSE
);
285 } else if (cs_killed
) {
294 * Assumes p (if passed in) is locked with proc_lock().
298 cs_process_enforcement(struct proc
*p
)
301 if (cs_process_enforcement_enable
)
307 if (p
!= NULL
&& (p
->p_csflags
& CS_ENFORCEMENT
))
314 cs_process_global_enforcement(void)
316 return cs_process_enforcement_enable
? 1 : 0;
320 cs_system_enforcement(void)
322 return cs_system_enforcement_enable
? 1 : 0;
326 * Returns whether a given process is still valid.
329 cs_valid(struct proc
*p
)
335 if (p
!= NULL
&& (p
->p_csflags
& CS_VALID
))
342 * Library validation functions
345 cs_require_lv(struct proc
*p
)
348 if (cs_library_val_enable
)
354 if (p
!= NULL
&& (p
->p_csflags
& CS_REQUIRE_LV
))
361 csproc_forced_lv(struct proc
* p
)
366 if (p
!= NULL
&& (p
->p_csflags
& CS_FORCED_LV
)) {
373 * <rdar://problem/24634089> added to allow system level library
374 * validation check at mac_cred_label_update_execve time
377 cs_system_require_lv(void)
379 return cs_library_val_enable
? 1 : 0;
383 * Function: csblob_get_base_offset
385 * Description: This function returns the base offset into the (possibly universal) binary
390 csblob_get_base_offset(struct cs_blob
*blob
)
392 return blob
->csb_base_offset
;
396 * Function: csblob_get_size
398 * Description: This function returns the size of a given blob.
402 csblob_get_size(struct cs_blob
*blob
)
404 return blob
->csb_mem_size
;
408 * Function: csblob_get_addr
410 * Description: This function returns the address of a given blob.
414 csblob_get_addr(struct cs_blob
*blob
)
416 return blob
->csb_mem_kaddr
;
420 * Function: csblob_get_platform_binary
422 * Description: This function returns true if the binary is
423 * in the trust cache.
427 csblob_get_platform_binary(struct cs_blob
*blob
)
429 if (blob
&& blob
->csb_platform_binary
)
435 * Function: csblob_get_flags
437 * Description: This function returns the flags for a given blob
441 csblob_get_flags(struct cs_blob
*blob
)
443 return blob
->csb_flags
;
447 * Function: csblob_get_hashtype
449 * Description: This function returns the hash type for a given blob
453 csblob_get_hashtype(struct cs_blob
const * const blob
)
455 return blob
->csb_hashtype
!= NULL
? cs_hash_type(blob
->csb_hashtype
) : 0;
459 * Function: csproc_get_blob
461 * Description: This function returns the cs_blob
465 csproc_get_blob(struct proc
*p
)
470 if (NULL
== p
->p_textvp
)
473 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
477 return ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
);
481 * Function: csvnode_get_blob
483 * Description: This function returns the cs_blob
487 csvnode_get_blob(struct vnode
*vp
, off_t offset
)
489 return ubc_cs_blob_get(vp
, -1, offset
);
493 * Function: csblob_get_teamid
495 * Description: This function returns a pointer to the
499 csblob_get_teamid(struct cs_blob
*csblob
)
501 return csblob
->csb_teamid
;
505 * Function: csblob_get_identity
507 * Description: This function returns a pointer to the
511 csblob_get_identity(struct cs_blob
*csblob
)
513 const CS_CodeDirectory
*cd
;
515 cd
= (const CS_CodeDirectory
*)csblob_find_blob(csblob
, CSSLOT_CODEDIRECTORY
, CSMAGIC_CODEDIRECTORY
);
519 if (cd
->identOffset
== 0)
522 return ((const char *)cd
) + ntohl(cd
->identOffset
);
526 * Function: csblob_get_cdhash
528 * Description: This function returns a pointer to the
529 * cdhash of csblob (20 byte array)
532 csblob_get_cdhash(struct cs_blob
*csblob
)
534 return csblob
->csb_cdhash
;
538 * Function: csblob_get_signer_type
540 * Description: This function returns the signer type
544 csblob_get_signer_type(struct cs_blob
*csblob
)
546 return csblob
->csb_signer_type
;
550 csblob_entitlements_dictionary_copy(struct cs_blob
*csblob
)
552 if (!csblob
->csb_entitlements
) return NULL
;
553 osobject_retain(csblob
->csb_entitlements
);
554 return csblob
->csb_entitlements
;
558 csblob_entitlements_dictionary_set(struct cs_blob
*csblob
, void * entitlements
)
560 assert(csblob
->csb_entitlements
== NULL
);
561 if (entitlements
) osobject_retain(entitlements
);
562 csblob
->csb_entitlements
= entitlements
;
566 * Function: csproc_get_teamid
568 * Description: This function returns a pointer to the
569 * team id of the process p
572 csproc_get_teamid(struct proc
*p
)
574 struct cs_blob
*csblob
;
576 csblob
= csproc_get_blob(p
);
580 return csblob_get_teamid(csblob
);
584 * Function: csproc_get_signer_type
586 * Description: This function returns the signer type
590 csproc_get_signer_type(struct proc
*p
)
592 struct cs_blob
*csblob
;
594 csblob
= csproc_get_blob(p
);
596 return CS_SIGNER_TYPE_UNKNOWN
;
598 return csblob_get_signer_type(csblob
);
602 * Function: csvnode_get_teamid
604 * Description: This function returns a pointer to the
605 * team id of the binary at the given offset in vnode vp
608 csvnode_get_teamid(struct vnode
*vp
, off_t offset
)
610 struct cs_blob
*csblob
;
615 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
619 return csblob_get_teamid(csblob
);
623 * Function: csproc_get_platform_binary
625 * Description: This function returns the value
626 * of the platform_binary field for proc p
629 csproc_get_platform_binary(struct proc
*p
)
631 struct cs_blob
*csblob
;
633 csblob
= csproc_get_blob(p
);
635 /* If there is no csblob this returns 0 because
636 it is true that it is not a platform binary */
637 return (csblob
== NULL
) ? 0 : csblob
->csb_platform_binary
;
641 csproc_get_platform_path(struct proc
*p
)
643 struct cs_blob
*csblob
;
645 csblob
= csproc_get_blob(p
);
647 return (csblob
== NULL
) ? 0 : csblob
->csb_platform_path
;
650 #if DEVELOPMENT || DEBUG
652 csproc_clear_platform_binary(struct proc
*p
)
654 struct cs_blob
*csblob
= csproc_get_blob(p
);
656 if (csblob
== NULL
) {
661 printf("clearing platform binary on proc/task: pid = %d\n", p
->p_pid
);
664 csblob
->csb_platform_binary
= 0;
665 csblob
->csb_platform_path
= 0;
666 task_set_platform_binary(proc_task(p
), FALSE
);
671 csproc_disable_enforcement(struct proc
* __unused p
)
673 #if !CONFIG_ENFORCE_SIGNED_CODE
676 p
->p_csflags
&= (~CS_ENFORCEMENT
);
682 /* Function: csproc_mark_invalid_allowed
684 * Description: Mark the process as being allowed to go invalid. Called as part of
685 * task_for_pid and ptrace policy. Note CS_INVALID_ALLOWED only matters for
686 * processes that have been opted into CS_ENFORCEMENT.
689 csproc_mark_invalid_allowed(struct proc
* __unused p
)
691 #if !CONFIG_ENFORCE_SIGNED_CODE
694 p
->p_csflags
|= CS_INVALID_ALLOWED
;
701 * Function: csproc_check_invalid_allowed
703 * Description: Returns 1 if the process has been marked as allowed to go invalid
704 * because it gave its task port to an allowed process.
707 csproc_check_invalid_allowed(struct proc
* __unused p
)
709 #if !CONFIG_ENFORCE_SIGNED_CODE
714 if (p
!= NULL
&& (p
->p_csflags
& CS_INVALID_ALLOWED
))
721 * Function: csproc_get_prod_signed
723 * Description: Returns 1 if process is not signed with a developer identity.
724 * Note the inverted meaning from the cs_flag to make the error case safer.
725 * Will go away with rdar://problem/28322552.
728 csproc_get_prod_signed(struct proc
*p
)
730 return ((p
->p_csflags
& CS_DEV_CODE
) == 0);
735 * Function: csfg_get_platform_binary
737 * Description: This function returns the
738 * platform binary field for the
742 csfg_get_platform_binary(struct fileglob
*fg
)
744 int platform_binary
= 0;
745 struct ubc_info
*uip
;
748 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
751 vp
= (struct vnode
*)fg
->fg_data
;
756 if (!UBCINFOEXISTS(vp
))
763 if (uip
->cs_blobs
== NULL
)
766 /* It is OK to extract the teamid from the first blob
767 because all blobs of a vnode must have the same teamid */
768 platform_binary
= uip
->cs_blobs
->csb_platform_binary
;
772 return platform_binary
;
776 csfg_get_cdhash(struct fileglob
*fg
, uint64_t offset
, size_t *cdhash_size
)
780 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
783 vp
= (struct vnode
*)fg
->fg_data
;
787 struct cs_blob
*csblob
= NULL
;
788 if ((csblob
= ubc_cs_blob_get(vp
, -1, offset
)) == NULL
)
792 *cdhash_size
= CS_CDHASH_LEN
;
794 return csblob
->csb_cdhash
;
798 * Function: csfg_get_signer_type
800 * Description: This returns the signer type
801 * for the fileglob fg
804 csfg_get_signer_type(struct fileglob
*fg
)
806 struct ubc_info
*uip
;
807 unsigned int signer_type
= CS_SIGNER_TYPE_UNKNOWN
;
810 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
811 return CS_SIGNER_TYPE_UNKNOWN
;
813 vp
= (struct vnode
*)fg
->fg_data
;
815 return CS_SIGNER_TYPE_UNKNOWN
;
818 if (!UBCINFOEXISTS(vp
))
825 if (uip
->cs_blobs
== NULL
)
828 /* It is OK to extract the signer type from the first blob,
829 because all blobs of a vnode must have the same signer type. */
830 signer_type
= uip
->cs_blobs
->csb_signer_type
;
838 * Function: csfg_get_teamid
840 * Description: This returns a pointer to
841 * the teamid for the fileglob fg
844 csfg_get_teamid(struct fileglob
*fg
)
846 struct ubc_info
*uip
;
847 const char *str
= NULL
;
850 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
853 vp
= (struct vnode
*)fg
->fg_data
;
858 if (!UBCINFOEXISTS(vp
))
865 if (uip
->cs_blobs
== NULL
)
868 /* It is OK to extract the teamid from the first blob
869 because all blobs of a vnode must have the same teamid */
870 str
= uip
->cs_blobs
->csb_teamid
;
878 * Function: csfg_get_prod_signed
880 * Description: Returns 1 if code is not signed with a developer identity.
881 * Note the inverted meaning from the cs_flag to make the error case safer.
882 * Will go away with rdar://problem/28322552.
885 csfg_get_prod_signed(struct fileglob
*fg
)
887 struct ubc_info
*uip
;
891 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
894 vp
= (struct vnode
*)fg
->fg_data
;
899 if (!UBCINFOEXISTS(vp
))
906 if (uip
->cs_blobs
== NULL
)
909 /* It is OK to extract the flag from the first blob
910 because all blobs of a vnode must have the same cs_flags */
911 prod_signed
= (uip
->cs_blobs
->csb_flags
& CS_DEV_CODE
) == 0;
919 * Function: csfg_get_identity
921 * Description: This function returns the codesign identity
925 csfg_get_identity(struct fileglob
*fg
, off_t offset
)
928 struct cs_blob
*csblob
= NULL
;
930 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
933 vp
= (struct vnode
*)fg
->fg_data
;
937 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
941 return csblob_get_identity(csblob
);
945 * Function: csfg_get_platform_identifier
947 * Description: This function returns the codesign platform
948 * identifier for the fileglob. Assumes the fileproc
949 * is being held busy to keep the fileglob consistent.
952 csfg_get_platform_identifier(struct fileglob
*fg
, off_t offset
)
956 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
959 vp
= (struct vnode
*)fg
->fg_data
;
963 return csvnode_get_platform_identifier(vp
, offset
);
967 * Function: csvnode_get_platform_identifier
969 * Description: This function returns the codesign platform
970 * identifier for the vnode. Assumes a vnode reference
974 csvnode_get_platform_identifier(struct vnode
*vp
, off_t offset
)
976 struct cs_blob
*csblob
;
977 const CS_CodeDirectory
*code_dir
;
979 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
983 code_dir
= csblob
->csb_cd
;
984 if (code_dir
== NULL
|| ntohl(code_dir
->length
) < 8)
987 return code_dir
->platform
;
991 * Function: csproc_get_platform_identifier
993 * Description: This function returns the codesign platform
994 * identifier for the proc. Assumes proc will remain
995 * valid through call.
998 csproc_get_platform_identifier(struct proc
*p
)
1000 if (NULL
== p
->p_textvp
)
1003 return csvnode_get_platform_identifier(p
->p_textvp
, p
->p_textoff
);
1007 cs_entitlement_flags(struct proc
*p
)
1009 return (p
->p_csflags
& CS_ENTITLEMENT_FLAGS
);
1013 cs_restricted(struct proc
*p
)
1015 return (p
->p_csflags
& CS_RESTRICT
) ? 1 : 0;
1019 csproc_hardened_runtime(struct proc
* p
)
1021 return (p
->p_csflags
& CS_RUNTIME
) ? 1 : 0;
1025 * Function: csfg_get_path
1027 * Description: This populates the buffer passed in
1028 * with the path of the vnode
1029 * When calling this, the fileglob
1030 * cannot go away. The caller must have a
1031 * a reference on the fileglob or fileproc
1034 csfg_get_path(struct fileglob
*fg
, char *path
, int *len
)
1038 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
)
1041 vp
= (struct vnode
*)fg
->fg_data
;
1043 /* vn_getpath returns 0 for success,
1045 return vn_getpath(vp
, path
, len
);
1048 /* Retrieve the entitlements blob for a process.
1050 * EINVAL no text vnode associated with the process
1051 * EBADEXEC invalid code signing data
1052 * 0 no error occurred
1054 * On success, out_start and out_length will point to the
1055 * entitlements blob if found; or will be set to NULL/zero
1056 * if there were no entitlements.
1060 cs_entitlements_blob_get(proc_t p
, void **out_start
, size_t *out_length
)
1062 struct cs_blob
*csblob
;
1067 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1071 if (NULL
== p
->p_textvp
)
1074 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
)
1077 return csblob_get_entitlements(csblob
, out_start
, out_length
);
1080 /* Retrieve the codesign identity for a process.
1082 * NULL an error occured
1083 * string the cs_identity
1087 cs_identity_get(proc_t p
)
1089 struct cs_blob
*csblob
;
1091 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1095 if (NULL
== p
->p_textvp
)
1098 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
)
1101 return csblob_get_identity(csblob
);
1105 * DO NOT USE THIS FUNCTION!
1106 * Use the properly guarded csproc_get_blob instead.
1108 * This is currently here to allow detached signatures to work
1109 * properly. The only user of this function is also checking
1114 cs_blob_get(proc_t p
, void **out_start
, size_t *out_length
)
1116 struct cs_blob
*csblob
;
1121 if (NULL
== p
->p_textvp
)
1124 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
)
1127 *out_start
= (void *)csblob
->csb_mem_kaddr
;
1128 *out_length
= csblob
->csb_mem_size
;
1134 * return cshash of a process, cdhash is of size CS_CDHASH_LEN
1138 cs_get_cdhash(struct proc
*p
)
1140 struct cs_blob
*csblob
;
1142 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1146 if (NULL
== p
->p_textvp
)
1149 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
)
1152 return csblob
->csb_cdhash
;