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 /* allow a debugged process to hide some (debug-only!) memory */
228 task_set_memory_ownership_transfer(p
->task
, TRUE
);
230 vm_map_switch_protect(get_task_map(p
->task
), FALSE
);
232 return (p
->p_csflags
& (CS_KILL
| CS_HARD
)) == 0;
236 cs_invalid_page(addr64_t vaddr
, boolean_t
*cs_killed
)
239 int send_kill
= 0, retval
= 0, verbose
= cs_debug
;
245 printf("CODE SIGNING: cs_invalid_page(0x%llx): p=%d[%s]\n",
246 vaddr
, p
->p_pid
, p
->p_comm
);
251 /* XXX for testing */
253 p
->p_csflags
|= CS_KILL
;
256 p
->p_csflags
|= CS_HARD
;
259 /* CS_KILL triggers a kill signal, and no you can't have the page. Nothing else. */
260 if (p
->p_csflags
& CS_KILL
) {
261 p
->p_csflags
|= CS_KILLED
;
267 /* CS_HARD means fail the mapping operation so the process stays valid. */
268 if (p
->p_csflags
& CS_HARD
) {
271 if (p
->p_csflags
& CS_VALID
) {
272 p
->p_csflags
&= ~CS_VALID
;
273 cs_procs_invalidated
++;
277 csflags
= p
->p_csflags
;
281 printf("CODE SIGNING: cs_invalid_page(0x%llx): "
282 "p=%d[%s] final status 0x%x, %s page%s\n",
283 vaddr
, p
->p_pid
, p
->p_comm
, p
->p_csflags
,
284 retval
? "denying" : "allowing (remove VALID)",
285 send_kill
? " sending SIGKILL" : "");
289 /* We will set the exit reason for the thread later */
290 threadsignal(current_thread(), SIGKILL
, EXC_BAD_ACCESS
, FALSE
);
294 } else if (cs_killed
) {
303 * Assumes p (if passed in) is locked with proc_lock().
307 cs_process_enforcement(struct proc
*p
)
309 if (cs_process_enforcement_enable
) {
317 if (p
!= NULL
&& (p
->p_csflags
& CS_ENFORCEMENT
)) {
325 cs_process_global_enforcement(void)
327 return cs_process_enforcement_enable
? 1 : 0;
331 cs_system_enforcement(void)
333 return cs_system_enforcement_enable
? 1 : 0;
337 * Returns whether a given process is still valid.
340 cs_valid(struct proc
*p
)
346 if (p
!= NULL
&& (p
->p_csflags
& CS_VALID
)) {
354 * Library validation functions
357 cs_require_lv(struct proc
*p
)
359 if (cs_library_val_enable
) {
367 if (p
!= NULL
&& (p
->p_csflags
& CS_REQUIRE_LV
)) {
375 csproc_forced_lv(struct proc
* p
)
380 if (p
!= NULL
&& (p
->p_csflags
& CS_FORCED_LV
)) {
387 * <rdar://problem/24634089> added to allow system level library
388 * validation check at mac_cred_label_update_execve time
391 cs_system_require_lv(void)
393 return cs_library_val_enable
? 1 : 0;
397 * Function: csblob_get_base_offset
399 * Description: This function returns the base offset into the (possibly universal) binary
404 csblob_get_base_offset(struct cs_blob
*blob
)
406 return blob
->csb_base_offset
;
410 * Function: csblob_get_size
412 * Description: This function returns the size of a given blob.
416 csblob_get_size(struct cs_blob
*blob
)
418 return blob
->csb_mem_size
;
422 * Function: csblob_get_addr
424 * Description: This function returns the address of a given blob.
428 csblob_get_addr(struct cs_blob
*blob
)
430 return blob
->csb_mem_kaddr
;
434 * Function: csblob_get_platform_binary
436 * Description: This function returns true if the binary is
437 * in the trust cache.
441 csblob_get_platform_binary(struct cs_blob
*blob
)
443 if (blob
&& blob
->csb_platform_binary
) {
450 * Function: csblob_get_flags
452 * Description: This function returns the flags for a given blob
456 csblob_get_flags(struct cs_blob
*blob
)
458 return blob
->csb_flags
;
462 * Function: csblob_get_hashtype
464 * Description: This function returns the hash type for a given blob
468 csblob_get_hashtype(struct cs_blob
const * const blob
)
470 return blob
->csb_hashtype
!= NULL
? cs_hash_type(blob
->csb_hashtype
) : 0;
474 * Function: csproc_get_blob
476 * Description: This function returns the cs_blob
480 csproc_get_blob(struct proc
*p
)
486 if (NULL
== p
->p_textvp
) {
490 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
494 return ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
);
498 * Function: csvnode_get_blob
500 * Description: This function returns the cs_blob
504 csvnode_get_blob(struct vnode
*vp
, off_t offset
)
506 return ubc_cs_blob_get(vp
, -1, offset
);
510 * Function: csblob_get_teamid
512 * Description: This function returns a pointer to the
516 csblob_get_teamid(struct cs_blob
*csblob
)
518 return csblob
->csb_teamid
;
522 * Function: csblob_get_identity
524 * Description: This function returns a pointer to the
528 csblob_get_identity(struct cs_blob
*csblob
)
530 const CS_CodeDirectory
*cd
;
532 cd
= (const CS_CodeDirectory
*)csblob_find_blob(csblob
, CSSLOT_CODEDIRECTORY
, CSMAGIC_CODEDIRECTORY
);
537 if (cd
->identOffset
== 0) {
541 return ((const char *)cd
) + ntohl(cd
->identOffset
);
545 * Function: csblob_get_cdhash
547 * Description: This function returns a pointer to the
548 * cdhash of csblob (20 byte array)
551 csblob_get_cdhash(struct cs_blob
*csblob
)
553 return csblob
->csb_cdhash
;
557 * Function: csblob_get_signer_type
559 * Description: This function returns the signer type
563 csblob_get_signer_type(struct cs_blob
*csblob
)
565 return csblob
->csb_signer_type
;
569 csblob_entitlements_dictionary_copy(struct cs_blob
*csblob
)
571 if (!csblob
->csb_entitlements
) {
574 osobject_retain(csblob
->csb_entitlements
);
575 return csblob
->csb_entitlements
;
579 csblob_entitlements_dictionary_set(struct cs_blob
*csblob
, void * entitlements
)
581 assert(csblob
->csb_entitlements
== NULL
);
583 osobject_retain(entitlements
);
585 csblob
->csb_entitlements
= entitlements
;
589 * Function: csproc_get_teamid
591 * Description: This function returns a pointer to the
592 * team id of the process p
595 csproc_get_teamid(struct proc
*p
)
597 struct cs_blob
*csblob
;
599 csblob
= csproc_get_blob(p
);
600 if (csblob
== NULL
) {
604 return csblob_get_teamid(csblob
);
608 * Function: csproc_get_signer_type
610 * Description: This function returns the signer type
614 csproc_get_signer_type(struct proc
*p
)
616 struct cs_blob
*csblob
;
618 csblob
= csproc_get_blob(p
);
619 if (csblob
== NULL
) {
620 return CS_SIGNER_TYPE_UNKNOWN
;
623 return csblob_get_signer_type(csblob
);
627 * Function: csvnode_get_teamid
629 * Description: This function returns a pointer to the
630 * team id of the binary at the given offset in vnode vp
633 csvnode_get_teamid(struct vnode
*vp
, off_t offset
)
635 struct cs_blob
*csblob
;
641 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
642 if (csblob
== NULL
) {
646 return csblob_get_teamid(csblob
);
650 * Function: csproc_get_platform_binary
652 * Description: This function returns the value
653 * of the platform_binary field for proc p
656 csproc_get_platform_binary(struct proc
*p
)
658 struct cs_blob
*csblob
;
660 csblob
= csproc_get_blob(p
);
662 /* If there is no csblob this returns 0 because
663 * it is true that it is not a platform binary */
664 return (csblob
== NULL
) ? 0 : csblob
->csb_platform_binary
;
668 csproc_get_platform_path(struct proc
*p
)
670 struct cs_blob
*csblob
;
672 csblob
= csproc_get_blob(p
);
674 return (csblob
== NULL
) ? 0 : csblob
->csb_platform_path
;
677 #if DEVELOPMENT || DEBUG
679 csproc_clear_platform_binary(struct proc
*p
)
681 struct cs_blob
*csblob
= csproc_get_blob(p
);
683 if (csblob
== NULL
) {
688 printf("clearing platform binary on proc/task: pid = %d\n", p
->p_pid
);
691 csblob
->csb_platform_binary
= 0;
692 csblob
->csb_platform_path
= 0;
693 task_set_platform_binary(proc_task(p
), FALSE
);
698 csproc_disable_enforcement(struct proc
* __unused p
)
700 #if !CONFIG_ENFORCE_SIGNED_CODE
703 p
->p_csflags
&= (~CS_ENFORCEMENT
);
709 /* Function: csproc_mark_invalid_allowed
711 * Description: Mark the process as being allowed to go invalid. Called as part of
712 * task_for_pid and ptrace policy. Note CS_INVALID_ALLOWED only matters for
713 * processes that have been opted into CS_ENFORCEMENT.
716 csproc_mark_invalid_allowed(struct proc
* __unused p
)
718 #if !CONFIG_ENFORCE_SIGNED_CODE
721 p
->p_csflags
|= CS_INVALID_ALLOWED
;
728 * Function: csproc_check_invalid_allowed
730 * Description: Returns 1 if the process has been marked as allowed to go invalid
731 * because it gave its task port to an allowed process.
734 csproc_check_invalid_allowed(struct proc
* __unused p
)
736 #if !CONFIG_ENFORCE_SIGNED_CODE
741 if (p
!= NULL
&& (p
->p_csflags
& CS_INVALID_ALLOWED
)) {
749 * Function: csproc_get_prod_signed
751 * Description: Returns 1 if process is not signed with a developer identity.
752 * Note the inverted meaning from the cs_flag to make the error case safer.
753 * Will go away with rdar://problem/28322552.
756 csproc_get_prod_signed(struct proc
*p
)
758 return (p
->p_csflags
& CS_DEV_CODE
) == 0;
763 * Function: csfg_get_platform_binary
765 * Description: This function returns the
766 * platform binary field for the
770 csfg_get_platform_binary(struct fileglob
*fg
)
772 int platform_binary
= 0;
773 struct ubc_info
*uip
;
776 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
780 vp
= (struct vnode
*)fg
->fg_data
;
786 if (!UBCINFOEXISTS(vp
)) {
795 if (uip
->cs_blobs
== NULL
) {
799 /* It is OK to extract the teamid from the first blob
800 * because all blobs of a vnode must have the same teamid */
801 platform_binary
= uip
->cs_blobs
->csb_platform_binary
;
805 return platform_binary
;
809 csfg_get_cdhash(struct fileglob
*fg
, uint64_t offset
, size_t *cdhash_size
)
813 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
817 vp
= (struct vnode
*)fg
->fg_data
;
822 struct cs_blob
*csblob
= NULL
;
823 if ((csblob
= ubc_cs_blob_get(vp
, -1, offset
)) == NULL
) {
828 *cdhash_size
= CS_CDHASH_LEN
;
831 return csblob
->csb_cdhash
;
835 * Function: csfg_get_signer_type
837 * Description: This returns the signer type
838 * for the fileglob fg
841 csfg_get_signer_type(struct fileglob
*fg
)
843 struct ubc_info
*uip
;
844 unsigned int signer_type
= CS_SIGNER_TYPE_UNKNOWN
;
847 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
848 return CS_SIGNER_TYPE_UNKNOWN
;
851 vp
= (struct vnode
*)fg
->fg_data
;
853 return CS_SIGNER_TYPE_UNKNOWN
;
857 if (!UBCINFOEXISTS(vp
)) {
866 if (uip
->cs_blobs
== NULL
) {
870 /* It is OK to extract the signer type from the first blob,
871 * because all blobs of a vnode must have the same signer type. */
872 signer_type
= uip
->cs_blobs
->csb_signer_type
;
880 * Function: csfg_get_teamid
882 * Description: This returns a pointer to
883 * the teamid for the fileglob fg
886 csfg_get_teamid(struct fileglob
*fg
)
888 struct ubc_info
*uip
;
889 const char *str
= NULL
;
892 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
896 vp
= (struct vnode
*)fg
->fg_data
;
902 if (!UBCINFOEXISTS(vp
)) {
911 if (uip
->cs_blobs
== NULL
) {
915 /* It is OK to extract the teamid from the first blob
916 * because all blobs of a vnode must have the same teamid */
917 str
= uip
->cs_blobs
->csb_teamid
;
925 * Function: csfg_get_prod_signed
927 * Description: Returns 1 if code is not signed with a developer identity.
928 * Note the inverted meaning from the cs_flag to make the error case safer.
929 * Will go away with rdar://problem/28322552.
932 csfg_get_prod_signed(struct fileglob
*fg
)
934 struct ubc_info
*uip
;
938 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
942 vp
= (struct vnode
*)fg
->fg_data
;
948 if (!UBCINFOEXISTS(vp
)) {
957 if (uip
->cs_blobs
== NULL
) {
961 /* It is OK to extract the flag from the first blob
962 * because all blobs of a vnode must have the same cs_flags */
963 prod_signed
= (uip
->cs_blobs
->csb_flags
& CS_DEV_CODE
) == 0;
971 * Function: csfg_get_identity
973 * Description: This function returns the codesign identity
977 csfg_get_identity(struct fileglob
*fg
, off_t offset
)
980 struct cs_blob
*csblob
= NULL
;
982 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
986 vp
= (struct vnode
*)fg
->fg_data
;
991 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
992 if (csblob
== NULL
) {
996 return csblob_get_identity(csblob
);
1000 * Function: csfg_get_platform_identifier
1002 * Description: This function returns the codesign platform
1003 * identifier for the fileglob. Assumes the fileproc
1004 * is being held busy to keep the fileglob consistent.
1007 csfg_get_platform_identifier(struct fileglob
*fg
, off_t offset
)
1011 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
1015 vp
= (struct vnode
*)fg
->fg_data
;
1020 return csvnode_get_platform_identifier(vp
, offset
);
1024 * Function: csvnode_get_platform_identifier
1026 * Description: This function returns the codesign platform
1027 * identifier for the vnode. Assumes a vnode reference
1031 csvnode_get_platform_identifier(struct vnode
*vp
, off_t offset
)
1033 struct cs_blob
*csblob
;
1034 const CS_CodeDirectory
*code_dir
;
1036 csblob
= ubc_cs_blob_get(vp
, -1, offset
);
1037 if (csblob
== NULL
) {
1041 code_dir
= csblob
->csb_cd
;
1042 if (code_dir
== NULL
|| ntohl(code_dir
->length
) < 8) {
1046 return code_dir
->platform
;
1050 * Function: csproc_get_platform_identifier
1052 * Description: This function returns the codesign platform
1053 * identifier for the proc. Assumes proc will remain
1054 * valid through call.
1057 csproc_get_platform_identifier(struct proc
*p
)
1059 if (NULL
== p
->p_textvp
) {
1063 return csvnode_get_platform_identifier(p
->p_textvp
, p
->p_textoff
);
1067 cs_entitlement_flags(struct proc
*p
)
1069 return p
->p_csflags
& CS_ENTITLEMENT_FLAGS
;
1073 cs_restricted(struct proc
*p
)
1075 return (p
->p_csflags
& CS_RESTRICT
) ? 1 : 0;
1079 csproc_hardened_runtime(struct proc
* p
)
1081 return (p
->p_csflags
& CS_RUNTIME
) ? 1 : 0;
1085 * Function: csfg_get_path
1087 * Description: This populates the buffer passed in
1088 * with the path of the vnode
1089 * When calling this, the fileglob
1090 * cannot go away. The caller must have a
1091 * a reference on the fileglob or fileproc
1094 csfg_get_path(struct fileglob
*fg
, char *path
, int *len
)
1098 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
1102 vp
= (struct vnode
*)fg
->fg_data
;
1104 /* vn_getpath returns 0 for success,
1105 * or an error code */
1106 return vn_getpath(vp
, path
, len
);
1109 /* Retrieve the entitlements blob for a process.
1111 * EINVAL no text vnode associated with the process
1112 * EBADEXEC invalid code signing data
1113 * 0 no error occurred
1115 * On success, out_start and out_length will point to the
1116 * entitlements blob if found; or will be set to NULL/zero
1117 * if there were no entitlements.
1121 cs_entitlements_blob_get(proc_t p
, void **out_start
, size_t *out_length
)
1123 struct cs_blob
*csblob
;
1128 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1132 if (NULL
== p
->p_textvp
) {
1136 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1140 return csblob_get_entitlements(csblob
, out_start
, out_length
);
1144 /* Retrieve the cached entitlements for a process
1146 * EINVAL no text vnode associated with the process
1147 * EBADEXEC invalid code signing data
1148 * 0 no error occurred
1150 * Note: the entitlements may be NULL if there is nothing cached.
1154 cs_entitlements_dictionary_copy(proc_t p
, void **entitlements
)
1156 struct cs_blob
*csblob
;
1158 *entitlements
= NULL
;
1160 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1164 if (NULL
== p
->p_textvp
) {
1168 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1172 *entitlements
= csblob_entitlements_dictionary_copy(csblob
);
1176 /* Retrieve the codesign identity for a process.
1178 * NULL an error occured
1179 * string the cs_identity
1183 cs_identity_get(proc_t p
)
1185 struct cs_blob
*csblob
;
1187 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1191 if (NULL
== p
->p_textvp
) {
1195 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1199 return csblob_get_identity(csblob
);
1203 * DO NOT USE THIS FUNCTION!
1204 * Use the properly guarded csproc_get_blob instead.
1206 * This is currently here to allow detached signatures to work
1207 * properly. The only user of this function is also checking
1212 cs_blob_get(proc_t p
, void **out_start
, size_t *out_length
)
1214 struct cs_blob
*csblob
;
1219 if (NULL
== p
->p_textvp
) {
1223 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1227 *out_start
= (void *)csblob
->csb_mem_kaddr
;
1228 *out_length
= csblob
->csb_mem_size
;
1234 * return cshash of a process, cdhash is of size CS_CDHASH_LEN
1238 cs_get_cdhash(struct proc
*p
)
1240 struct cs_blob
*csblob
;
1242 if ((p
->p_csflags
& CS_SIGNED
) == 0) {
1246 if (NULL
== p
->p_textvp
) {
1250 if ((csblob
= ubc_cs_blob_get(p
->p_textvp
, -1, p
->p_textoff
)) == NULL
) {
1254 return csblob
->csb_cdhash
;