]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_cs.c
xnu-3789.31.2.tar.gz
[apple/xnu.git] / bsd / kern / kern_cs.c
CommitLineData
39236c6e
A
1/*
2 * Copyright (c) 2000-2012 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#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>
38
39#include <sys/fcntl.h>
40#include <sys/file.h>
fe8ab488 41#include <sys/file_internal.h>
39236c6e
A
42#include <sys/kauth.h>
43#include <sys/mount.h>
44#include <sys/msg.h>
45#include <sys/proc.h>
46#include <sys/socketvar.h>
47#include <sys/vnode.h>
48#include <sys/vnode_internal.h>
49
50#include <sys/ubc.h>
51#include <sys/ubc_internal.h>
52
53#include <security/mac.h>
54#include <security/mac_policy.h>
55#include <security/mac_framework.h>
56
57#include <mach/mach_types.h>
58#include <mach/vm_map.h>
59#include <mach/mach_vm.h>
60
61#include <kern/kern_types.h>
62#include <kern/task.h>
63
64#include <vm/vm_map.h>
65#include <vm/vm_kern.h>
66
39236c6e
A
67
68#include <kern/assert.h>
69
70#include <pexpert/pexpert.h>
71
15129b1c
A
72#include <mach/shared_region.h>
73
4bd07ac2
A
74#include <libkern/section_keywords.h>
75
39236c6e
A
76unsigned long cs_procs_killed = 0;
77unsigned long cs_procs_invalidated = 0;
78
79int cs_force_kill = 0;
80int cs_force_hard = 0;
81int cs_debug = 0;
82#if SECURE_KERNEL
3e170ce0
A
83const int cs_enforcement_enable = 1;
84const int cs_library_val_enable = 1;
85#else /* !SECURE_KERNEL */
86int cs_enforcement_panic=0;
87
39236c6e 88#if CONFIG_ENFORCE_SIGNED_CODE
4bd07ac2 89#define DEFAULT_CS_ENFORCEMENT_ENABLE 1
39236c6e 90#else
4bd07ac2 91#define DEFAULT_CS_ENFORCEMENT_ENABLE 0
3e170ce0 92#endif
4bd07ac2 93SECURITY_READ_ONLY_LATE(int) cs_enforcement_enable = DEFAULT_CS_ENFORCEMENT_ENABLE;
fe8ab488
A
94
95#if CONFIG_ENFORCE_LIBRARY_VALIDATION
4bd07ac2 96#define DEFAULT_CS_LIBRARY_VA_ENABLE 1
fe8ab488 97#else
4bd07ac2 98#define DEFAULT_CS_LIBRARY_VA_ENABLE 0
3e170ce0 99#endif
4bd07ac2 100SECURITY_READ_ONLY_LATE(int) cs_library_val_enable = DEFAULT_CS_LIBRARY_VA_ENABLE;
fe8ab488 101
3e170ce0 102#endif /* !SECURE_KERNEL */
39236c6e
A
103int cs_all_vnodes = 0;
104
105static lck_grp_t *cs_lockgrp;
39236c6e
A
106
107SYSCTL_INT(_vm, OID_AUTO, cs_force_kill, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_force_kill, 0, "");
108SYSCTL_INT(_vm, OID_AUTO, cs_force_hard, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_force_hard, 0, "");
109SYSCTL_INT(_vm, OID_AUTO, cs_debug, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_debug, 0, "");
110
111SYSCTL_INT(_vm, OID_AUTO, cs_all_vnodes, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_all_vnodes, 0, "");
112
113#if !SECURE_KERNEL
114SYSCTL_INT(_vm, OID_AUTO, cs_enforcement, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_enforcement_enable, 0, "");
115SYSCTL_INT(_vm, OID_AUTO, cs_enforcement_panic, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_enforcement_panic, 0, "");
3e170ce0
A
116
117#if !CONFIG_ENFORCE_LIBRARY_VALIDATION
118SYSCTL_INT(_vm, OID_AUTO, cs_library_validation, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_library_val_enable, 0, "");
39236c6e 119#endif
3e170ce0 120#endif /* !SECURE_KERNEL */
39236c6e 121
15129b1c 122int panic_on_cs_killed = 0;
39236c6e
A
123void
124cs_init(void)
125{
fe8ab488 126#if MACH_ASSERT && __x86_64__
15129b1c 127 panic_on_cs_killed = 1;
fe8ab488 128#endif /* MACH_ASSERT && __x86_64__ */
15129b1c
A
129 PE_parse_boot_argn("panic_on_cs_killed", &panic_on_cs_killed,
130 sizeof (panic_on_cs_killed));
39236c6e
A
131#if !SECURE_KERNEL
132 int disable_cs_enforcement = 0;
133 PE_parse_boot_argn("cs_enforcement_disable", &disable_cs_enforcement,
134 sizeof (disable_cs_enforcement));
135 if (disable_cs_enforcement) {
136 cs_enforcement_enable = 0;
137 } else {
138 int panic = 0;
139 PE_parse_boot_argn("cs_enforcement_panic", &panic, sizeof(panic));
140 cs_enforcement_panic = (panic != 0);
141 }
142
143 PE_parse_boot_argn("cs_debug", &cs_debug, sizeof (cs_debug));
3e170ce0
A
144
145#if !CONFIG_ENFORCE_LIBRARY_VALIDATION
146 PE_parse_boot_argn("cs_library_val_enable", &cs_library_val_enable,
147 sizeof (cs_library_val_enable));
39236c6e 148#endif
3e170ce0
A
149#endif /* !SECURE_KERNEL */
150
39236c6e
A
151 lck_grp_attr_t *attr = lck_grp_attr_alloc_init();
152 cs_lockgrp = lck_grp_alloc_init("KERNCS", attr);
39037602 153 lck_grp_attr_free(attr);
39236c6e
A
154}
155
156int
157cs_allow_invalid(struct proc *p)
158{
159#if MACH_ASSERT
160 lck_mtx_assert(&p->p_mlock, LCK_MTX_ASSERT_NOTOWNED);
161#endif
162#if CONFIG_MACF && CONFIG_ENFORCE_SIGNED_CODE
163 /* There needs to be a MAC policy to implement this hook, or else the
164 * kill bits will be cleared here every time. If we have
165 * CONFIG_ENFORCE_SIGNED_CODE, we can assume there is a policy
166 * implementing the hook.
167 */
168 if( 0 != mac_proc_check_run_cs_invalid(p)) {
169 if(cs_debug) printf("CODE SIGNING: cs_allow_invalid() "
170 "not allowed: pid %d\n",
171 p->p_pid);
172 return 0;
173 }
174 if(cs_debug) printf("CODE SIGNING: cs_allow_invalid() "
175 "allowed: pid %d\n",
176 p->p_pid);
177 proc_lock(p);
178 p->p_csflags &= ~(CS_KILL | CS_HARD);
490019cf
A
179 if (p->p_csflags & CS_VALID)
180 {
181 p->p_csflags |= CS_DEBUGGED;
182 }
39236c6e
A
183 proc_unlock(p);
184 vm_map_switch_protect(get_task_map(p->task), FALSE);
185#endif
186 return (p->p_csflags & (CS_KILL | CS_HARD)) == 0;
187}
188
189int
39037602 190cs_invalid_page(addr64_t vaddr, boolean_t *cs_killed)
39236c6e
A
191{
192 struct proc *p;
193 int send_kill = 0, retval = 0, verbose = cs_debug;
194 uint32_t csflags;
195
196 p = current_proc();
197
39236c6e
A
198 if (verbose)
199 printf("CODE SIGNING: cs_invalid_page(0x%llx): p=%d[%s]\n",
200 vaddr, p->p_pid, p->p_comm);
201
202 proc_lock(p);
203
204 /* XXX for testing */
205 if (cs_force_kill)
206 p->p_csflags |= CS_KILL;
207 if (cs_force_hard)
208 p->p_csflags |= CS_HARD;
209
210 /* CS_KILL triggers a kill signal, and no you can't have the page. Nothing else. */
211 if (p->p_csflags & CS_KILL) {
212 p->p_csflags |= CS_KILLED;
213 cs_procs_killed++;
214 send_kill = 1;
215 retval = 1;
216 }
217
218 /* CS_HARD means fail the mapping operation so the process stays valid. */
219 if (p->p_csflags & CS_HARD) {
220 retval = 1;
221 } else {
222 if (p->p_csflags & CS_VALID) {
223 p->p_csflags &= ~CS_VALID;
224 cs_procs_invalidated++;
225 verbose = 1;
226 }
227 }
228 csflags = p->p_csflags;
229 proc_unlock(p);
230
fe8ab488 231 if (verbose)
39236c6e 232 printf("CODE SIGNING: cs_invalid_page(0x%llx): "
15129b1c 233 "p=%d[%s] final status 0x%x, %s page%s\n",
39236c6e 234 vaddr, p->p_pid, p->p_comm, p->p_csflags,
15129b1c 235 retval ? "denying" : "allowing (remove VALID)",
39236c6e 236 send_kill ? " sending SIGKILL" : "");
39236c6e 237
39037602
A
238 if (send_kill) {
239 /* We will set the exit reason for the thread later */
240 threadsignal(current_thread(), SIGKILL, EXC_BAD_ACCESS, FALSE);
241 if (cs_killed) {
242 *cs_killed = TRUE;
243 }
244 } else if (cs_killed) {
245 *cs_killed = FALSE;
246 }
39236c6e
A
247
248
249 return retval;
250}
251
252/*
253 * Assumes p (if passed in) is locked with proc_lock().
254 */
255
256int
257cs_enforcement(struct proc *p)
258{
259
260 if (cs_enforcement_enable)
261 return 1;
262
263 if (p == NULL)
264 p = current_proc();
265
266 if (p != NULL && (p->p_csflags & CS_ENFORCEMENT))
267 return 1;
268
269 return 0;
270}
271
39037602
A
272/*
273 * Returns whether a given process is still valid.
274 */
275int
276cs_valid(struct proc *p)
277{
278
279 if (p == NULL)
280 p = current_proc();
281
282 if (p != NULL && (p->p_csflags & CS_VALID))
283 return 1;
284
285 return 0;
286}
287
fe8ab488
A
288/*
289 * Library validation functions
290 */
291int
292cs_require_lv(struct proc *p)
293{
294
295 if (cs_library_val_enable)
296 return 1;
297
298 if (p == NULL)
299 p = current_proc();
300
301 if (p != NULL && (p->p_csflags & CS_REQUIRE_LV))
302 return 1;
303
304 return 0;
305}
306
39037602
A
307/*
308 * <rdar://problem/24634089> added to allow system level library
309 * validation check at mac_cred_label_update_execve time
310 */
311int
312cs_system_require_lv(void)
313{
314 return cs_library_val_enable ? 1 : 0;
315}
316
317/*
318 * Function: csblob_get_base_offset
319 *
320 * Description: This function returns the base offset into the Mach-O binary
321 * for a given blob.
322*/
323
324off_t
325csblob_get_base_offset(struct cs_blob *blob)
326{
327 return blob->csb_base_offset;
328}
329
330/*
331 * Function: csblob_get_size
332 *
333 * Description: This function returns the size of a given blob.
334*/
335
336vm_size_t
337csblob_get_size(struct cs_blob *blob)
338{
339 return blob->csb_mem_size;
340}
341
342/*
343 * Function: csblob_get_addr
344 *
345 * Description: This function returns the address of a given blob.
346*/
347
348vm_address_t
349csblob_get_addr(struct cs_blob *blob)
350{
351 return blob->csb_mem_kaddr;
352}
353
fe8ab488 354/*
3e170ce0 355 * Function: csblob_get_platform_binary
fe8ab488 356 *
3e170ce0
A
357 * Description: This function returns true if the binary is
358 * in the trust cache.
fe8ab488 359*/
fe8ab488 360
3e170ce0
A
361int
362csblob_get_platform_binary(struct cs_blob *blob)
363{
364 if (blob && blob->csb_platform_binary)
365 return 1;
366 return 0;
367}
fe8ab488 368
3e170ce0
A
369/*
370 * Function: csblob_get_flags
371 *
372 * Description: This function returns the flags for a given blob
373*/
fe8ab488 374
3e170ce0
A
375unsigned int
376csblob_get_flags(struct cs_blob *blob)
377{
39037602 378 return blob->csb_flags;
fe8ab488
A
379}
380
381/*
382 * Function: csproc_get_blob
383 *
384 * Description: This function returns the cs_blob
385 * for the process p
386 */
3e170ce0 387struct cs_blob *
fe8ab488
A
388csproc_get_blob(struct proc *p)
389{
390 if (NULL == p)
391 return NULL;
392
393 if (NULL == p->p_textvp)
394 return NULL;
395
396 return ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff);
397}
398
3e170ce0
A
399/*
400 * Function: csproc_get_blob
401 *
402 * Description: This function returns the cs_blob
403 * for the vnode vp
404 */
405struct cs_blob *
406csvnode_get_blob(struct vnode *vp, off_t offset)
407{
408 return ubc_cs_blob_get(vp, -1, offset);
409}
410
411/*
412 * Function: csblob_get_teamid
413 *
414 * Description: This function returns a pointer to the
415 * team id of csblob
416*/
417const char *
418csblob_get_teamid(struct cs_blob *csblob)
419{
420 return csblob->csb_teamid;
421}
422
423/*
424 * Function: csblob_get_identity
425 *
426 * Description: This function returns a pointer to the
427 * identity string
428 */
429const char *
430csblob_get_identity(struct cs_blob *csblob)
431{
432 const CS_CodeDirectory *cd;
433
434 cd = (const CS_CodeDirectory *)csblob_find_blob(csblob, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY);
435 if (cd == NULL)
436 return NULL;
437
438 if (cd->identOffset == 0)
439 return NULL;
440
441 return ((const char *)cd) + ntohl(cd->identOffset);
442}
443
444/*
445 * Function: csblob_get_cdhash
446 *
447 * Description: This function returns a pointer to the
448 * cdhash of csblob (20 byte array)
449 */
450const uint8_t *
451csblob_get_cdhash(struct cs_blob *csblob)
452{
453 return csblob->csb_cdhash;
454}
455
39037602
A
456void *
457csblob_entitlements_dictionary_copy(struct cs_blob *csblob)
458{
459 if (!csblob->csb_entitlements) return NULL;
460 osobject_retain(csblob->csb_entitlements);
461 return csblob->csb_entitlements;
462}
463
464void
465csblob_entitlements_dictionary_set(struct cs_blob *csblob, void * entitlements)
466{
467 assert(csblob->csb_entitlements == NULL);
468 if (entitlements) osobject_retain(entitlements);
469 csblob->csb_entitlements = entitlements;
470}
471
fe8ab488
A
472/*
473 * Function: csproc_get_teamid
474 *
475 * Description: This function returns a pointer to the
476 * team id of the process p
477*/
478const char *
479csproc_get_teamid(struct proc *p)
480{
481 struct cs_blob *csblob;
482
483 csblob = csproc_get_blob(p);
3e170ce0
A
484 if (csblob == NULL)
485 return NULL;
fe8ab488 486
3e170ce0 487 return csblob_get_teamid(csblob);
fe8ab488
A
488}
489
490/*
491 * Function: csvnode_get_teamid
492 *
493 * Description: This function returns a pointer to the
494 * team id of the binary at the given offset in vnode vp
495*/
496const char *
497csvnode_get_teamid(struct vnode *vp, off_t offset)
498{
499 struct cs_blob *csblob;
500
501 if (vp == NULL)
502 return NULL;
503
504 csblob = ubc_cs_blob_get(vp, -1, offset);
3e170ce0
A
505 if (csblob == NULL)
506 return NULL;
fe8ab488 507
3e170ce0 508 return csblob_get_teamid(csblob);
fe8ab488
A
509}
510
511/*
512 * Function: csproc_get_platform_binary
513 *
514 * Description: This function returns the value
515 * of the platform_binary field for proc p
516 */
517int
518csproc_get_platform_binary(struct proc *p)
519{
520 struct cs_blob *csblob;
521
522 csblob = csproc_get_blob(p);
523
524 /* If there is no csblob this returns 0 because
525 it is true that it is not a platform binary */
526 return (csblob == NULL) ? 0 : csblob->csb_platform_binary;
527}
528
3e170ce0
A
529int
530csproc_get_platform_path(struct proc *p)
531{
532 struct cs_blob *csblob = csproc_get_blob(p);
533
534 return (csblob == NULL) ? 0 : csblob->csb_platform_path;
535}
536
743345f9
A
537/*
538 * Function: csproc_get_prod_signed
539 *
540 * Description: Returns 1 if process is not signed with a developer identity.
541 * Note the inverted meaning from the cs_flag to make the error case safer.
542 * Will go away with rdar://problem/28322552.
543 */
544int
545csproc_get_prod_signed(struct proc *p)
546{
547 return ((p->p_csflags & CS_DEV_CODE) == 0);
548}
549
550
fe8ab488
A
551/*
552 * Function: csfg_get_platform_binary
553 *
554 * Description: This function returns the
555 * platform binary field for the
556 * fileglob fg
557 */
558int
559csfg_get_platform_binary(struct fileglob *fg)
560{
561 int platform_binary = 0;
562 struct ubc_info *uip;
563 vnode_t vp;
564
565 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE)
566 return 0;
567
568 vp = (struct vnode *)fg->fg_data;
569 if (vp == NULL)
570 return 0;
571
572 vnode_lock(vp);
573 if (!UBCINFOEXISTS(vp))
574 goto out;
575
576 uip = vp->v_ubcinfo;
577 if (uip == NULL)
578 goto out;
579
580 if (uip->cs_blobs == NULL)
581 goto out;
582
583 /* It is OK to extract the teamid from the first blob
584 because all blobs of a vnode must have the same teamid */
585 platform_binary = uip->cs_blobs->csb_platform_binary;
586out:
587 vnode_unlock(vp);
588
589 return platform_binary;
590}
591
3e170ce0
A
592uint8_t *
593csfg_get_cdhash(struct fileglob *fg, uint64_t offset, size_t *cdhash_size)
594{
595 vnode_t vp;
596
597 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE)
598 return NULL;
599
600 vp = (struct vnode *)fg->fg_data;
601 if (vp == NULL)
602 return NULL;
603
604 struct cs_blob *csblob = NULL;
605 if ((csblob = ubc_cs_blob_get(vp, -1, offset)) == NULL)
606 return NULL;
607
608 if (cdhash_size)
609 *cdhash_size = CS_CDHASH_LEN;
610
611 return csblob->csb_cdhash;
612}
613
fe8ab488
A
614/*
615 * Function: csfg_get_teamid
616 *
617 * Description: This returns a pointer to
618 * the teamid for the fileglob fg
619 */
620const char *
621csfg_get_teamid(struct fileglob *fg)
622{
623 struct ubc_info *uip;
624 const char *str = NULL;
625 vnode_t vp;
626
627 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE)
628 return NULL;
629
630 vp = (struct vnode *)fg->fg_data;
631 if (vp == NULL)
632 return NULL;
633
634 vnode_lock(vp);
635 if (!UBCINFOEXISTS(vp))
636 goto out;
637
638 uip = vp->v_ubcinfo;
639 if (uip == NULL)
640 goto out;
641
642 if (uip->cs_blobs == NULL)
643 goto out;
644
645 /* It is OK to extract the teamid from the first blob
646 because all blobs of a vnode must have the same teamid */
647 str = uip->cs_blobs->csb_teamid;
648out:
649 vnode_unlock(vp);
650
651 return str;
652}
653
743345f9
A
654/*
655 * Function: csfg_get_prod_signed
656 *
657 * Description: Returns 1 if code is not signed with a developer identity.
658 * Note the inverted meaning from the cs_flag to make the error case safer.
659 * Will go away with rdar://problem/28322552.
660 */
661int
662csfg_get_prod_signed(struct fileglob *fg)
663{
664 struct ubc_info *uip;
665 vnode_t vp;
666 int prod_signed = 0;
667
668 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE)
669 return NULL;
670
671 vp = (struct vnode *)fg->fg_data;
672 if (vp == NULL)
673 return NULL;
674
675 vnode_lock(vp);
676 if (!UBCINFOEXISTS(vp))
677 goto out;
678
679 uip = vp->v_ubcinfo;
680 if (uip == NULL)
681 goto out;
682
683 if (uip->cs_blobs == NULL)
684 goto out;
685
686 /* It is OK to extract the flag from the first blob
687 because all blobs of a vnode must have the same cs_flags */
688 prod_signed = (uip->cs_blobs->csb_flags & CS_DEV_CODE) == 0;
689out:
690 vnode_unlock(vp);
691
692 return prod_signed;
693}
694
695
fe8ab488
A
696uint32_t
697cs_entitlement_flags(struct proc *p)
698{
699 return (p->p_csflags & CS_ENTITLEMENT_FLAGS);
700}
701
3e170ce0
A
702int
703cs_restricted(struct proc *p)
704{
705 return (p->p_csflags & CS_RESTRICT) ? 1 : 0;
706}
707
fe8ab488
A
708/*
709 * Function: csfg_get_path
710 *
711 * Description: This populates the buffer passed in
712 * with the path of the vnode
713 * When calling this, the fileglob
714 * cannot go away. The caller must have a
715 * a reference on the fileglob or fileproc
716 */
717int
718csfg_get_path(struct fileglob *fg, char *path, int *len)
719{
720 vnode_t vp = NULL;
721
722 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE)
723 return -1;
724
725 vp = (struct vnode *)fg->fg_data;
726
727 /* vn_getpath returns 0 for success,
728 or an error code */
729 return vn_getpath(vp, path, len);
730}
3e170ce0
A
731
732/* Retrieve the entitlements blob for a process.
733 * Returns:
734 * EINVAL no text vnode associated with the process
735 * EBADEXEC invalid code signing data
736 * 0 no error occurred
737 *
738 * On success, out_start and out_length will point to the
739 * entitlements blob if found; or will be set to NULL/zero
740 * if there were no entitlements.
741 */
742
743int
744cs_entitlements_blob_get(proc_t p, void **out_start, size_t *out_length)
745{
746 struct cs_blob *csblob;
747
748 *out_start = NULL;
749 *out_length = 0;
750
751 if (NULL == p->p_textvp)
752 return EINVAL;
753
754 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
755 return 0;
756
757 return csblob_get_entitlements(csblob, out_start, out_length);
758}
759
760/* Retrieve the codesign identity for a process.
761 * Returns:
762 * NULL an error occured
763 * string the cs_identity
764 */
765
766const char *
767cs_identity_get(proc_t p)
768{
769 struct cs_blob *csblob;
770
771 if (NULL == p->p_textvp)
772 return NULL;
773
774 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
775 return NULL;
776
777 return csblob_get_identity(csblob);
778}
779
780
781/* Retrieve the codesign blob for a process.
782 * Returns:
783 * EINVAL no text vnode associated with the process
784 * 0 no error occurred
785 *
786 * On success, out_start and out_length will point to the
787 * cms blob if found; or will be set to NULL/zero
788 * if there were no blob.
789 */
790
791int
792cs_blob_get(proc_t p, void **out_start, size_t *out_length)
793{
794 struct cs_blob *csblob;
795
796 *out_start = NULL;
797 *out_length = 0;
798
799 if (NULL == p->p_textvp)
800 return EINVAL;
801
802 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
803 return 0;
804
805 *out_start = (void *)csblob->csb_mem_kaddr;
806 *out_length = csblob->csb_mem_size;
807
808 return 0;
809}
810
811/*
812 * return cshash of a process, cdhash is of size CS_CDHASH_LEN
813 */
814
815uint8_t *
816cs_get_cdhash(struct proc *p)
817{
818 struct cs_blob *csblob;
819
820 if (NULL == p->p_textvp)
821 return NULL;
822
823 if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
824 return NULL;
825
826 return csblob->csb_cdhash;
827}