Supervisor Mode Access Prevention¶
ring-0 bir user-accessible page'i okuduğunda ya da yazdığında fault eden Intel CPU feature'ı (CR4.SMAP, bit 21); meğer ki kernel EFLAGS.AC (STAC/CLAC) üzerinden opt-in yapsın.
Mechanism¶
Neden işe yarar
CR4.SMAP = 1 olduğunda, supervisor-mode data erişimlerine user mode'da
erişilebilir (U=1 page-table entry) linear address'ler izin verilmez. Bir user
pointer'ın başıboş bir kernel dereference'ı — ders kitabı NULL-pointer ve
"kernel user memory'yi okumaya kandırıldı" bug sınıfı — attacker-controlled bir
değeri sessizce takip etmek yerine fault eder. Kernel erişimi yalnızca açık,
audit edilmiş kopyaların etrafında EFLAGS.AC = 1 set ederek yeniden etkinleştirir
(CPL < 3 olduğunda); Intel bunun için single-cycle STAC (set AC) ve CLAC
(clear AC) instruction'larını ekledi. Kritik olarak, user page'lere implicit
supervisor erişimleri (descriptor-table load'ları vb.) AC'den bağımsız olarak fault eder.
SMAP, "kernel yanlışlıkla user-controlled bir pointer'a güveniyor"u bir fault'a çevirir. Klasik ret2usr-tarzı data payload'larının (userland'e yerleştirilen fake structure'lar) tam da dayandığı şey budur, dolayısıyla SMAP saldırganları payload'larını kernel-accessible memory içinde tutmaya zorlar.
Walkthrough¶
Linux'ta feature'ı kontrol et:
grep -o '\bsmap\b' /proc/cpuinfo | head -1
# smap (present => CPU supports SMAP; introduced with Intel Broadwell)
Linux her legitimate user erişimini AC dansıyla sarar. User-access helper'ları
(copy_to_user(), copy_from_user(), get_user(), put_user()),
STAC/CLAC ile parantezlenir:
stac ; EFLAGS.AC = 1 -> SMAP temporarily off for this access
... rep movsb ... ; the audited copy to/from the user page
clac ; EFLAGS.AC = 0 -> SMAP back on
Kernel patch serisi (H. Peter Anvin)
Mainline etkinleştirme (Ingo Molnar, Thomas Gleixner ile) şunları ekledi:
x86, smap: Add CR4 bit for SMAPx86, smap: Add STAC and CLAC instructions to control user space accesscopy_user_64.S,getuser.S,putuser.S,uaccess.h'in sarılması
"When SMAP is active, the kernel cannot normally access pages that are user space (U=1)." … "the kernel can access user space pages if EFLAGS.AC=1."
AC dengeli olmalıdır
AC=1 bırakan herhangi bir kernel path'i (CLAC olmayan dengesiz bir STAC
ya da AC'yi çeviren bir gadget) tüm address space'i ring-0 data erişimlerine
yeniden açar — aşağıdaki residual risk'lere bak.
Detection¶
Eksik ya da başıboş bir user dereference artık, oops'ta görünen SMAP ihlaliyle
birlikte bir page fault üretir (faulting address, ring 0'dan AC=0 ile erişilen
bir user address'idir). Geliştirme sırasında bu, latent bug'ları "kötü code bir
mainline kernel'de shipping olmadan önce" yüzeye çıkarır.
Mitigation¶
SMAP bir savunmadır; residual risk yüzeyi:
- Kernel-resident payload — fake struct'ları/shellcode'u kernel-accessible memory'ye yerleştir ki hiçbir user page'e dokunulmasın. Bkz. SMAP bypass via kernel-resident payload ve ret2dir-tarzı direct-map yeniden kullanımı.
- AC-flag manipulation — exploit süresince SMAP'i devre dışı bırakmak için bir
stac/popfgadget'ı ROP'la (ya da başka türlüEFLAGS.AC=1set et). - CR4 bit'ini temizleme — bkz. Disable SMEP/SMAP via CR4 ROP; modern CR4 pinning bunu bir no-op yapar.
SMEP (execution) ile eşleşir ve PaX'in daha eski UDEREF'i tarafından tamamlanır.