Skip to content

APRR (Access Protection Re-mapping Register)

Page-table permission bit'lerini per-core bir register üzerinden indirect ederek bütün page gruplarının permission'ları atomically flip etmesine olanak tanıyan Apple'ın özel A11+ hardware feature'ı — WebKit'in JIT region'ının hızlı W^X enforcement'ının ve kernel'ın PPL'inin temeli.

Mechanism

Invariant

Normalde bir page'in access permission'ları doğrudan kendi page-table entry'sinde (PTE) yaşar: AP[2:1] bit'leri artı PXN/UXN, read/write/execute'a karar verir. Dolayısıyla çok sayıda page'in effective permission'ını değiştirmek, çok sayıda PTE'yi walk edip yeniden yazmak ve TLB'yi shoot-down etmek demektir — yavaş ve global. APRR bir indirection katmanı ekler: A11 ve sonrasında, PTE'deki permission bit'leri, alanları gerçek permission'ları tutan bir CPU register'ına (APRR register'ı) index olarak yeniden yorumlanır. O register'da bir alanı flip et ve o index ile map'lenmiş her page bir anda permission değiştirir, atomically ve per-core, tek bir PTE'ye dokunmadan ya da TLB'yi flush etmeden. (Kavramsal olarak Intel'in Memory Protection Keys'ine yakındır: küçük bir register bir page sınıfını gate'ler.)

Bu, Apple'ın dayandığı iki şeyi sağlar:

  • JIT için hızlı per-thread / per-core W^X. WebKit'in JIT region'ı permissive PTE'lerle map'lenebilir, ama APRR onu fiilen r-x tutar; kısa, hardened bir unlock rutini, APRR alanını JIT index'i için yalnızca code emit edilirken writable'a flip eder, sonra tekrar executable'a flip eder — böylece region, thread'in bakışından asla aynı anda hem W hem X olmaz.
  • PPL için ucuz bir toggle. A12+ üzerinde Apple'ın Page Protection Layer'ı (page-table write'larını tekelleştiren software katmanı), page table'ları yalnızca PPL code içinde writable ve başka her yerde read-only yapmak için APRR-tarzı remapping kullanır.

APRR tek başına bir security boundary değildir

APRR, kısıtlaması gereken privilege level'ın aynısından konfigüre edilebilir, dolayısıyla tek başına hiçbir boundary sağlamaz. Güvenliği, KTRR ile birleştirilmiş olmasından (ki KTRR, ilgili code/register'ları lock'tan sonra immutable yapar) ve onu kimin değiştirebileceğini PPL'in gate'lemesinden gelir. KTRR backstop'tur: APRR register state'i ne olursa olsun, bir page EL1 için asla hem writable hem executable yapılamaz.

Walkthrough

APRR'a, Apple'a özgü system register'lar üzerinden erişilir (s3_* IMPLEMENTATION DEFINED encoding'leri); EL0 için bir mapping register ve EL1 için bir tane vardır, artı JIT toggle için kullanılan mask register'lar. Remapping index'i PTE bit'lerinden inşa edilir:

index = function(AP[2:1], PXN, UXN)        // 4-bit index per page
perm  = APRRx_EL1[ index ]                  // 4-bit field -> effective r/w/x

WebKit'teki JIT lifecycle'ı, kavramsal olarak:

// pseudo: emit machine code into the JIT region under W^X
jit_unlock();           // flip APRR field for JIT index -> rw-  (this core only)
memcpy(jit_ptr, code, len);
jit_lock();             // flip APRR field back            -> r-x
// the region is r-x again before it is ever executed

Unlock/lock helper'ları kasıtlı olarak ufak ve hardened'tır — yazılan register değeri sabit bir kaynaktan yeniden yüklenir ve karşılaştırılır, böylece bir attacker, region'ı writable bırakmak için control flow'u sequence'ın ortasına yönlendiremez.

Bir kernel debug context'inden APRR register okuma

Bir EL1 debug primitive ile, canlı mapping register'ını örnekleyip bir JIT operasyonu boyunca değiştiğini izleyebilirsin:

// illustrative — Apple IMPLEMENTATION DEFINED encoding
mrs  x0, s3_6_c15_c1_5      // read APRR mapping register
// ... observe the JIT-index field toggle rw- <-> r-x around code emission

Tam encoding'ler ve field layout'ları device/SoC'ye özgüdür; gözlemlenebilir invariant şudur: effective permission değişirken PTE bit'leri sabit kalır — permission'ın page table'da değil register'da yaşadığının kanıtı.

Detection

  • PTE'leri hiç değişmeyen ama effective permission'ı emit ile execute arasında flip olan bir JIT region, APRR-based W^X'in (klasik per-PTE remap'e karşı) parmak izidir.
  • A12+ üzerinde, page-table page'lerinin yalnızca PPL trampoline'leri içinde writable olması, APRR/PPL coupling'ine işaret eder.

Mitigation

APRR, W^X'i güçlendirir ama yalnızca register'larını yazmasına izin verilen code kadar güçlüdür. Public research (Project Zero'nun JITSploitation serisi, Siguza'nın APRR notları), anlamlı saldırıların register semantics'inden ziyade unlock routine'unu ya da onu çevreleyen control flow'u hedef aldığını gösteriyor. Dolayısıyla APRR, pac / pointer-authentication (toggle'a ulaşan control flow'u hardening etmek için), KTRR / amcc-rorgn (immutable kernel text) ve PPL ile birlikte deploy edilir.

References