}
}
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,
error = EINVAL;
goto out;
}
- if (ngroups != (int)px_persona->pspi_ngroups) {
+ if (ngroups != px_persona->pspi_ngroups) {
error = EINVAL;
goto out;
}
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__
*
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);
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;
/* 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);
+ }
+
}
}