]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_exec.c
xnu-4570.41.2.tar.gz
[apple/xnu.git] / bsd / kern / kern_exec.c
index 3ccb12119150b7bc2eab719167fca3253c62eda8..90334a7903019da29ef5749e02d163746274a0f7 100644 (file)
@@ -2082,7 +2082,7 @@ static int spawn_validate_persona(struct _posix_spawn_persona_info *px_persona)
                        }
                }
                if (px_persona->pspi_flags & POSIX_SPAWN_PERSONA_GROUPS) {
-                       int ngroups = 0;
+                       unsigned ngroups = 0;
                        gid_t groups[NGROUPS_MAX];
 
                        if (persona_get_groups(persona, &ngroups, groups,
@@ -2090,7 +2090,7 @@ static int spawn_validate_persona(struct _posix_spawn_persona_info *px_persona)
                                error = EINVAL;
                                goto out;
                        }
-                       if (ngroups != (int)px_persona->pspi_ngroups) {
+                       if (ngroups != px_persona->pspi_ngroups) {
                                error = EINVAL;
                                goto out;
                        }
@@ -5469,67 +5469,6 @@ static void cdhash_to_string(char str[CS_CDHASH_STRING_SIZE], uint8_t const * co
           str[CS_CDHASH_STRING_SIZE - 1] = 0;
 }
 
-/*
- * If the process is not signed or if it contains entitlements, we
- * need to communicate through the task_access_port to taskgated.
- *
- * taskgated will provide a detached code signature if present, and
- * will enforce any restrictions on entitlements.
- */
-
-static boolean_t
-taskgated_required(proc_t p, boolean_t *require_success)
-{
-       size_t length;
-       void *blob;
-       int error;
-
-       if (cs_debug > 2)
-               csvnode_print_debug(p->p_textvp);
-
-#if !CONFIG_EMBEDDED
-       const int can_skip_taskgated = csproc_get_platform_binary(p) && !csproc_get_platform_path(p);
-#else
-       const int can_skip_taskgated = csproc_get_platform_binary(p);
-#endif
-       if (can_skip_taskgated) {
-               if (cs_debug) printf("taskgated not required for: %s\n", p->p_name);
-               *require_success = FALSE;
-               return FALSE;
-       }
-
-       if ((p->p_csflags & CS_VALID) == 0) {
-               *require_success = FALSE;
-               return TRUE;
-       }
-
-       error = cs_entitlements_blob_get(p, &blob, &length);
-       if (error == 0 && blob != NULL) {
-#if !CONFIG_EMBEDDED
-               /*
-                * fatal on the desktop when entitlements are present,
-                * unless we started in single-user mode 
-                */
-               if ((boothowto & RB_SINGLE) == 0)
-                       *require_success = TRUE;
-               /*
-                * Allow initproc to run without causing taskgated to launch
-                */
-               if (p == initproc) {
-                       *require_success = FALSE;
-                       return FALSE;
-               }
-
-#endif
-               if (cs_debug) printf("taskgated required for: %s\n", p->p_name);
-
-               return TRUE;
-       }
-
-       *require_success = FALSE;
-       return FALSE;
-}
-
 /*
  * __EXEC_WAITING_ON_TASKGATED_CODE_SIGNATURE_UPCALL__
  * 
@@ -5550,7 +5489,7 @@ check_for_signature(proc_t p, struct image_params *imgp)
        kern_return_t kr = KERN_FAILURE;
        int error = EACCES;
        boolean_t unexpected_failure = FALSE;
-       unsigned char hash[CS_CDHASH_LEN];
+       struct cs_blob *csb;
        boolean_t require_success = FALSE;
        int spawn = (imgp->ip_flags & IMGPF_SPAWN);
        int vfexec = (imgp->ip_flags & IMGPF_VFORK_EXEC);
@@ -5592,12 +5531,17 @@ check_for_signature(proc_t p, struct image_params *imgp)
                goto done;
        }
 
-       /* check if callout to taskgated is needed */
-       if (!taskgated_required(p, &require_success)) {
+       /* If the code signature came through the image activation path, we skip the
+     * taskgated / externally attached path. */
+       if (imgp->ip_csflags & CS_SIGNED) {
                error = 0;
                goto done;
        }
 
+    /* The rest of the code is for signatures that either already have been externally
+     * attached (likely, but not necessarily by a previous run through the taskgated
+     * path), or that will now be attached by taskgated. */
+    
        kr = task_get_task_access_port(p->task, &port);
        if (KERN_SUCCESS != kr || !IPC_PORT_VALID(port)) {
                error = 0;
@@ -5642,14 +5586,42 @@ check_for_signature(proc_t p, struct image_params *imgp)
 
        /* Only do this if exec_resettextvp() did not fail */
        if (p->p_textvp != NULLVP) {
-               /*
-                * If there's a new code directory, mark this process
-                * as signed.
-                */
-               if (0 == ubc_cs_getcdhash(p->p_textvp, p->p_textoff, hash)) {
-                       proc_lock(p);
-                       p->p_csflags |= CS_VALID;
-                       proc_unlock(p);
+               csb = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff);
+
+               if (csb != NULL) {
+                       /* As the enforcement we can do here is very limited, we only allow things that
+                        * are the only reason why this code path still exists:
+                        * Adhoc signed non-platform binaries without special cs_flags and without any
+                        * entitlements (unrestricted ones still pass AMFI). */
+                       if (
+                /* Revalidate the blob if necessary through bumped generation count. */
+                (ubc_cs_generation_check(p->p_textvp) == 0 ||
+                 ubc_cs_blob_revalidate(p->p_textvp, csb, imgp, 0) == 0) &&
+                /* Only CS_ADHOC, no CS_KILL, CS_HARD etc. */
+                               (csb->csb_flags & CS_ALLOWED_MACHO) == CS_ADHOC &&
+                               /* If it has a CMS blob, it's not adhoc. The CS_ADHOC flag can lie. */
+                               csblob_find_blob_bytes((const uint8_t *)csb->csb_mem_kaddr, csb->csb_mem_size,
+                                                                          CSSLOT_SIGNATURESLOT,
+                                                                          CSMAGIC_BLOBWRAPPER) == NULL &&
+                               /* It could still be in a trust cache (unlikely with CS_ADHOC), or a magic path. */
+                               csb->csb_platform_binary == 0 &&
+                               /* No entitlements, not even unrestricted ones. */
+                csb->csb_entitlements_blob == NULL) {
+
+                               proc_lock(p);
+                               p->p_csflags |= CS_SIGNED | CS_VALID;
+                               proc_unlock(p);
+
+                       } else {
+                               uint8_t cdhash[CS_CDHASH_LEN];
+                               char cdhash_string[CS_CDHASH_STRING_SIZE];
+                               proc_getcdhash(p, cdhash);
+                               cdhash_to_string(cdhash_string, cdhash);
+                               printf("ignoring detached code signature on '%s' with cdhash '%s' "
+                                          "because it is invalid, or not a simple adhoc signature.\n", 
+                                          p->p_name, cdhash_string);
+                       }
+
                }
        }