Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Log in or create an account to edit The Apple Wiki.

Dev:Launch Constraints

From The Apple Wiki

Introduced in iOS 16 / macOS Ventura (13.0), Launch Constraints are a security mitigation used to constrain how binaries can be launched.

There are three types of constraints:

  1. Self Constraints, which the launched binary itself must meet
  2. Parent Constraints, which the parent process must meet
  3. Responsible Constraints, which the “responsible process” must meet (presumably the process that asked launchd to launch it)

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

Each binary is assigned a constraint category. These define a set of launch constraints that apply to it.

In iOS 16, there are 7 documented categories (from Linus Henze), while in iOS 17 there are 18 documented categories (from Csaba Fitzl).

iOS 16

Category Self Constraint Parent Constraint Responsible Constraint
0 No Constraints N/A N/A
1 (on-authorized-authapfs-volume || on-system-volume) && launch-type == 1 && validation-category == 1 is-init-proc
2 on-authorized-authapfs-volume || on-system-volume
3 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1) && validation-category == 1
4 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1) && validation-category == 1 (on-system-volume && signing-identifier == “com.apple.mbfloagent” && validation-category == 1) || is-init-proc
5 validation-category == 1 (on-system-volume && signing-identifier == “com.apple.mbfloagent” && validation-category == 1) || is-init-proc
6 (!in-tc-with-constraint-category || is-sip-protected || on-authorized-authapfs-volume || on-system-volume) && launch-type == 1 && validation-category == 1 (apple-internal && entitlements[“com.apple.private.set-launch-type.internal”] == 1) || is-init-proc
7 validation-category == 1

iOS 17

Category Self Constraint Parent Constraint
0 N/A N/A
1 (on-authorized-authapfs-volume || on-system-volume) && launch-type == 1 && validation-category == 1 is-init-proc
2 on-authorized-authapfs-volume || on-system-volume
3 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1) && validation-category == 1
4 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1) && validation-category == 1 (on-system-volume && signing-identifier == “com.apple.mbfloagent” && validation-category == 1) || is-init-proc
5 validation-category == 1 (on-system-volume && signing-identifier == “com.apple.mbfloagent” && validation-category == 1) || is-init-proc
6 (!in-tc-with-constraint-category || is-sip-protected || on-authorized-authapfs-volume || on-system-volume) && launch-type == 1 && validation-category == 1 (apple-internal && entitlements[“com.apple.private.set-launch-type.internal”] == 1) || is-init-proc
7 validation-category == 1
8 (on-authorized-authapfs-volume || on-system-volume) && launch-type == 2 && validation-category == 1 (on-authorized-authapfs-volume || on-system-volume) && (signing-identifier == “com.apple.sysdiagnose” || signing-identifier == “com.apple.sysdiagnose”) && validation-category == 1
9 (on-authorized-authapfs-volume || on-system-volume) && apple-internal == 1 && (launch-type == 0 || launch-type == 2) && validation-category == 1
10 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 2) && validation-category == 1
11 Same as 10? Same as 10?
12 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1 || launch-type == 2) && validation-category == 1
13 (launch-type == 0 || launch-type == 2) && validation-category == 1
14 (on-authorized-authapfs-volume || on-system-volume) && launch-type == 3 && validation-category == 1 is-init-proc
15 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 3) && validation-category == 1 is-init-proc
16 launch-type == 3 && validation-category == 1 is-init-proc
17 (((is-sip-protected || on-authorized-authapfs-volume || on-system-volume) && validation-category == 1) || apple-internal == 1) && launch-type == 2
18 (on-authorized-authapfs-volume || on-system-volume) && developer-mode && validation-category == 1 ((is-init-proc || signing-identifier == “com.apple.CoreDevice.dtdebugproxyd”) && validation-category == 1) || apple-internal
19 Same as 2? Same as 2?
20 (on-authorized-authapfs-volume || on-system-volume) && (launch-type == 0 || launch-type == 1 || launch-type == 3) && validation-category == 1

Launch Type

Launch types are a type of launch constraint that are checked by AMFI on launch. They can be set via posix_spawn by calling the posix_spawnattr_set_launch_type_np function.[permanent dead link]

CS_LAUNCH_TYPE_NONE = 0

CS_LAUNCH_TYPE_SYSTEM_SERVICE = 1

CS_LAUNCH_TYPE_SYSDIAGNOSE = 2

CS_LAUNCH_TYPE_APPLICATION = 3

Validation Categories

Validation categories are a type of launch constraint that are set by AMFI during code signature validation.

There are 10 categories:

  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

< Todo: Show how TC format changed, how to reverse constraint categories from TCv2 >