PPL is an execution context that runs at EL1 but with higher privilege than the normal kernel. PPL protects page tables and code signing verification. Present on A12 through A14 (replaced by SPTM on A15+).


Mechanism

Concept

Normal kernel code (EL1):
  ✗ Cannot modify page tables directly
  ✗ Cannot change code signing state
  ✗ Cannot map executable pages

PPL code (EL1, special mode):
  ✓ Full access to page tables
  ✓ Code signing verification
  ✓ Manage pmap structures

Transition: kernel → PPL via a gated call interface
  ppl_enter() → switch to PPL context
  PPL operation
  ppl_leave() → return to normal kernel

Implementation

PPL uses APRR (Apple Page Protection Register) to change permissions
depending on the execution context:

  Normal kernel:  page table pages = read-only
  PPL context:    page table pages = read-write

APRR remaps permission bits per-EL:
  - Kernel code reading page table → APRR says "read-only"
  - PPL code reading page table → APRR says "read-write"

Protected Operations

Through PPL:
  - pmap_enter() → create page table entries
  - pmap_remove() → remove page table entries  
  - pmap_protect() → change page permissions
  - Code signing page verification
  - Trust cache management

NOT through PPL:
  - Normal kernel memory allocation (kalloc, zalloc)
  - Process scheduling
  - File I/O
  - Networking

Why PPL Matters for Exploitation

Without PPL:
  kernel r/w → modify page table → map executable page → run arbitrary code

With PPL:
  kernel r/w → CAN READ page tables but CANNOT WRITE
  → Need PPL bypass to modify page tables
  → Need PPL bypass to inject executable code

PPL Bypass Techniques

1. Operation Triangulation (2023)

- Exploit uses UNDOCUMENTED hardware MMIO registers
- Registers allow modifying page table entries WITHOUT going through PPL
- Apple did not know these registers existed (or forgot to protect them)
- Fix: Apple removed/protected these registers

Impact: Full PPL bypass → map any physical address → code execution

2. PPL Logic Bugs

- Bugs in the PPL code itself
- PPL is C code → it can have bugs
- But the PPL codebase is small → limited attack surface

Example:
  - pmap_enter with crafted arguments → bypass checks
  - Race condition in PPL transition

3. Physical Memory Attack (Pre-SPTM)

With physrw (physical read/write):
  - PPL protects page tables via APRR (virtual permission remapping)
  - But physrw bypasses virtual permissions entirely
  - → Directly modify page table physical memory
  - → PPL protection ineffective against physical access

This is why Apple replaced PPL with SPTM:
  SPTM runs at EL2 → controls physical page types
  → Physrw via dangling user page CANNOT touch kernel/page-table pages

Dopamine PPL Bypass

Dopamine jailbreak (iOS 15-16):
  1. kfd exploit → kernel read/write
  2. PPL bypass based on the Operation Triangulation technique:
     - Use hardware MMIO registers to modify page tables
  3. Trust cache injection (now possible with page table control)
  4. Rootless jailbreak installation

Resources