Skip to content

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 SMAP
  • x86, smap: Add STAC and CLAC instructions to control user space access
  • copy_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/popf gadget'ı ROP'la (ya da başka türlü EFLAGS.AC=1 set 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.

References