Skip to content

Instantly share code, notes, and snippets.

@LinusHenze
Created June 15, 2022 16:30
Show Gist options
  • Star 41 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save LinusHenze/4cd5d7ef057a144cda7234e2c247c056 to your computer and use it in GitHub Desktop.
Save LinusHenze/4cd5d7ef057a144cda7234e2c247c056 to your computer and use it in GitHub Desktop.
Description of the Launch Constraints introduced in iOS 16
iOS 16 introduced launch constraints, which can be used to constraint the launch of an application.
There are three types of constraints:
Self Constraints, which the launched application itself must meet
Parent Constraints, which the parent process must meet
Responsible Constraints, which the "responsible process" must meet (I assume that the responsible process is the process that asked launchd to launch a service)
Additionally, the TrustCache format was updated (see below) to support assigning each binary a "Constraint Category", which forces Self and Parent Constraints.
Note that Self, Parent and Responsible Constraints can also be set by the process performing the launch and they can be included in the code signature, in the new blob type 0xFADE8181. In both cases, the constraints are DER encoded (just like the DER entitlements).
Constraint Categories (from TrustCache, new in version 2):
Category 0:
No Constraints
Category 1:
Self Constraint: (on-authorized-authapfs-volume || on-system-volume) && launch-type == 1 && validation-category == 1
Parent Constraint: is-init-proc
Category 2:
Self Constraint: on-authorized-authapfs-volume || on-system-volume
Category 3:
Self Constraint: (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1) && validation-category == 1
Category 4:
Self Constraint: (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1) && validation-category == 1
Parent Constraint: (on-system-volume && signing-identifier == "com.apple.mbfloagent" && validation-category == 1) || is-init-proc
Category 5:
Self Constraint: validation-category == 1
Parent Constraint: (on-system-volume && signing-identifier == "com.apple.mbfloagent" && validation-category == 1) || is-init-proc
Category 6:
Self Constraint: (!in-tc-with-constraint-category || is-sip-protected || on-authorized-authapfs-volume || on-system-volume) && launch-type == 1 && validation-category == 1
Parent Constraint: (apple-internal && entitlements["com.apple.private.set-launch-type.internal"] == 1) || is-init-proc
Category 7:
Self Constraint: validation-category == 1
Validation Categories (set by AMFI during code signature validation):
1: Binary from TrustCache
2: TestFlight Development or Production signed -- Requires amfid validation
3: Signed by an Apple Developer (Production) -- Requires amfid validation
4: AppStore fast path
5: Signed with an iPhone Distribution Certificate -- Requires amfid validation
6: Signed with a trusted Certificate and not 2, 3, 5 or 10 -- Requires amfid validation
7: Locally-signed fast path (Rosetta)
8: ??? (apparently unused)
9: OOP-JIT fast path
10: From compilation service, untrusted or iPhone VPN App Production signed
Launch Types (can be set when launching an executable via posix_spawn):
0: Default, regular launch
1: System Service, AMFI will enforce that this is only used by launchd
New TrustCache Format:
typedef struct {
char cdhash[20];
uint16_t hash_type; // = 2
uint16_t category; // See Constraint Categories above
} Version2TrustCacheEntry;
typedef struct {
uint32_t version; // = 2
uuid_t uuid;
uint32_t entry_count;
Version2TrustCacheEntry entries[];
} Version2TrustCache;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment