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-xtutar; 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.