]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_cs.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / bsd / kern / kern_cs.c
index c15dd4f118ed0f1df620e90bf8b4b219b45be412..214b041b7ac4784bae5ed2ba9ded39676ecbcc11 100644 (file)
@@ -150,6 +150,7 @@ cs_init(void)
 
        lck_grp_attr_t *attr = lck_grp_attr_alloc_init();
        cs_lockgrp = lck_grp_alloc_init("KERNCS", attr);
+       lck_grp_attr_free(attr);
 }
 
 int
@@ -186,8 +187,7 @@ cs_allow_invalid(struct proc *p)
 }
 
 int
-cs_invalid_page(
-       addr64_t vaddr)
+cs_invalid_page(addr64_t vaddr, boolean_t *cs_killed)
 {
        struct proc     *p;
        int             send_kill = 0, retval = 0, verbose = cs_debug;
@@ -209,25 +209,12 @@ cs_invalid_page(
 
        /* CS_KILL triggers a kill signal, and no you can't have the page. Nothing else. */
        if (p->p_csflags & CS_KILL) {
-               if (panic_on_cs_killed &&
-                   vaddr >= SHARED_REGION_BASE &&
-                   vaddr < SHARED_REGION_BASE + SHARED_REGION_SIZE) {
-                       panic("<rdar://14393620> cs_invalid_page(va=0x%llx): killing p=%p\n", (uint64_t) vaddr, p);
-               }
                p->p_csflags |= CS_KILLED;
                cs_procs_killed++;
                send_kill = 1;
                retval = 1;
        }
        
-#if __x86_64__
-       if (panic_on_cs_killed &&
-           vaddr >= SHARED_REGION_BASE &&
-           vaddr < SHARED_REGION_BASE + SHARED_REGION_SIZE) {
-               panic("<rdar://14393620> cs_invalid_page(va=0x%llx): cs error p=%p\n", (uint64_t) vaddr, p);
-       }
-#endif /* __x86_64__ */
-
        /* CS_HARD means fail the mapping operation so the process stays valid. */
        if (p->p_csflags & CS_HARD) {
                retval = 1;
@@ -248,8 +235,15 @@ cs_invalid_page(
                       retval ? "denying" : "allowing (remove VALID)",
                       send_kill ? " sending SIGKILL" : "");
 
-       if (send_kill)
-               threadsignal(current_thread(), SIGKILL, EXC_BAD_ACCESS);
+       if (send_kill) {
+               /* We will set the exit reason for the thread later */
+               threadsignal(current_thread(), SIGKILL, EXC_BAD_ACCESS, FALSE);
+               if (cs_killed) {
+                       *cs_killed = TRUE;
+               }
+       } else if (cs_killed) {
+               *cs_killed = FALSE;
+       }
 
 
        return retval;
@@ -275,6 +269,22 @@ cs_enforcement(struct proc *p)
        return 0;
 }
 
+/*
+ * Returns whether a given process is still valid.
+ */
+int
+cs_valid(struct proc *p)
+{
+
+       if (p == NULL)
+               p = current_proc();
+
+       if (p != NULL && (p->p_csflags & CS_VALID))
+               return 1;
+
+       return 0;
+}
+
 /*
  * Library validation functions 
  */
@@ -294,6 +304,53 @@ cs_require_lv(struct proc *p)
        return 0;
 }
 
+/*
+ * <rdar://problem/24634089> added to allow system level library
+ *  validation check at mac_cred_label_update_execve time
+ */
+int
+cs_system_require_lv(void)
+{
+       return cs_library_val_enable ? 1 : 0;
+}
+
+/*
+ * Function: csblob_get_base_offset
+ *
+ * Description: This function returns the base offset into the Mach-O binary
+ *             for a given blob.
+*/
+
+off_t
+csblob_get_base_offset(struct cs_blob *blob)
+{
+    return blob->csb_base_offset;
+}
+
+/*
+ * Function: csblob_get_size
+ *
+ * Description: This function returns the size of a given blob.
+*/
+
+vm_size_t
+csblob_get_size(struct cs_blob *blob)
+{
+    return blob->csb_mem_size;
+}
+
+/*
+ * Function: csblob_get_addr
+ *
+ * Description: This function returns the address of a given blob.
+*/
+
+vm_address_t
+csblob_get_addr(struct cs_blob *blob)
+{
+    return blob->csb_mem_kaddr;
+}
+
 /*
  * Function: csblob_get_platform_binary
  *
@@ -318,9 +375,7 @@ csblob_get_platform_binary(struct cs_blob *blob)
 unsigned int
 csblob_get_flags(struct cs_blob *blob)
 {
-       if (blob)
-               return blob->csb_flags;
-       return 0;
+    return blob->csb_flags;
 }
 
 /*
@@ -398,6 +453,22 @@ csblob_get_cdhash(struct cs_blob *csblob)
        return csblob->csb_cdhash;
 }
 
+void *
+csblob_entitlements_dictionary_copy(struct cs_blob *csblob)
+{
+    if (!csblob->csb_entitlements) return NULL;
+    osobject_retain(csblob->csb_entitlements);
+    return csblob->csb_entitlements;
+}
+
+void
+csblob_entitlements_dictionary_set(struct cs_blob *csblob, void * entitlements)
+{
+    assert(csblob->csb_entitlements == NULL);
+    if (entitlements) osobject_retain(entitlements);
+    csblob->csb_entitlements = entitlements;
+}
+
 /*
  * Function: csproc_get_teamid 
  *
@@ -463,6 +534,20 @@ csproc_get_platform_path(struct proc *p)
        return (csblob == NULL) ? 0 : csblob->csb_platform_path;
 }
 
+/*
+ * Function: csproc_get_prod_signed
+ *
+ * Description: Returns 1 if process is not signed with a developer identity.
+ *             Note the inverted meaning from the cs_flag to make the error case safer.
+ *             Will go away with rdar://problem/28322552.
+ */
+int
+csproc_get_prod_signed(struct proc *p)
+{
+       return ((p->p_csflags & CS_DEV_CODE) == 0);
+}
+
+
 /*
  * Function: csfg_get_platform_binary
  *
@@ -566,6 +651,48 @@ out:
        return str;
 }
 
+/*
+ * Function: csfg_get_prod_signed
+ *
+ * Description: Returns 1 if code is not signed with a developer identity.
+ *             Note the inverted meaning from the cs_flag to make the error case safer.
+ *             Will go away with rdar://problem/28322552.
+ */
+int
+csfg_get_prod_signed(struct fileglob *fg)
+{
+       struct ubc_info *uip;
+       vnode_t vp;
+       int prod_signed = 0;
+
+       if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE)
+               return NULL;
+       
+       vp = (struct vnode *)fg->fg_data;
+       if (vp == NULL)
+               return NULL;
+
+       vnode_lock(vp);
+       if (!UBCINFOEXISTS(vp))
+               goto out;
+       
+       uip = vp->v_ubcinfo;
+       if (uip == NULL)
+               goto out;
+       
+       if (uip->cs_blobs == NULL)
+               goto out;
+
+       /* It is OK to extract the flag from the first blob
+          because all blobs of a vnode must have the same cs_flags */  
+       prod_signed = (uip->cs_blobs->csb_flags & CS_DEV_CODE) == 0;
+out:
+       vnode_unlock(vp);
+
+       return prod_signed;
+}
+
+
 uint32_t
 cs_entitlement_flags(struct proc *p)
 {