Skip to content

Page table manipulation attack (PTMA)

Attacker-controlled byte'ları bir hardware page-table page'iyle overlap ettiren, sonra arbitrary bir physical mapping forge etmek için bir Page Table Entry (PTE)'yi düzenleyen data-only bir attack — herhangi bir code execution olmadan DEP/NX, SMEP, SMAP ve CFI'yi bypass eder.

Mechanism

Note

Bir hardware page table yalnızca bellektir: her PTE, bir physical frame number (PFN) artı permission/status flag'leri tutan 64-bit'lik bir word'dür. CPU bu entry'leri her erişimde walk eder, bu yüzden bir PTE yazabilirsen, bir virtual page'i seçtiğin herhangi bir physical frame'e remap edebilirsin. PTMA bu invariant'ı istismar eder: kernel, MMU'nun zaten güvendiği bir PTE'yi asla yeniden doğrulamaz, bu yüzden tek bir forge edilmiş entry sana arbitrary physical memory üzerinde read/write verir — kernel text ve struct cred dahil. Hiçbir instruction pointer hijack edilmez, bu yüzden DEP/NX, SMEP/SMAP, KASLR ve CFI'nin hepsi ilgisizdir; attack tamamen data-only'dir. Zor kısım, controlled byte'larını canlı bir page table ile physically çakıştırmaktır; bu, free edilmiş bir object ile taze allocate edilmiş bir PTE page'i aynı physical page'i paylaşacak şekilde bir cross-cache / page-spray reclaim ile çözülür.

Walkthrough

x86-64'te bir PTE, PFN'i 12–51 bit'lerinde ve flag'leri low/high bit'lerde encode eder:

PTE = 0xe800098952ff43        (example from the Dirty Pagetable writeup)
       |          |  |
       NX/PKey   PFN  flags (_PAGE_PRESENT=bit0, _PAGE_RW=bit1, _PAGE_USER=bit2 ...)

Adımlar (Dirty Pagetable kurgusunu izleyerek):

/* 1. Trigger heap bug (UAF / double-free / OOB) on a victim object. */
/* 2. Cross-cache reclaim: free the victim slab so its page returns to the
      page allocator, then spray user page tables so a PT page reuses it.
      "The single sharing page and page table are allocated from the same
       migrate free_cache with the same order." */
/* 3. The freed object now physically overlaps a live PTE array. A write
      primitive through the dangling object becomes a PTE write. */

uint64_t *evil_pte = victim_write_window;   /* aliases real page-table memory */
*evil_pte = (target_phys & PFN_MASK) | _PAGE_PRESENT | _PAGE_RW;   /* forge mapping */

Entry'yi kullanılabilir bir primitive'e dönüştürmek:

/* 4. Point the forged PTE at kernel physical memory, then dereference the
      corresponding userspace virtual address to read/write kernel data. */
char *win = mmap_addr_covered_by(evil_pte);
/* reads/writes now hit target_phys: patch modprobe_path, cred.uid, SELinux state, ... */
Writeup'ta belirtilen kısıtlar

PTE'nin physical-address field'ı tamamen serbest değildir: writeup şunu gözlemler: "bit18 is located in the physical address of the PTE, which means that if we don't bypass the limitation, we can only patch the kernel where the bit18 of the physical address is 1." Flag bit'leri (örn. bit 8 / bit 18 üzerinde sigdelsetmask() etkileşimleri üzerinden), ek bir bypass olmadan hangi physical hedeflerin erişilebilir olduğunu kısıtlar, bu yüzden hedef seçimi serbest bir değişken değil, exploit'in parçasıdır.

Bir 2024 varyantı ("Flipping Pages", CVE-2024-1086), PTMA'yı page-table hiyerarşisinde bir seviye yukarı taşır: bir PMD page'i ve bir PTE page'i aynı physical frame'e double-allocate ederek, bir userland address'ine (0x40000000) yapılan bir write doğrudan PTE word'ünü düzenler. Bir fork() + munmap(), TLB'yi flush eder ki forge edilmiş translation etkili olsun, sonra eşleşen higher-level address'in bir read'i arbitrary physical memory'yi dereference eder — orada modprobe_path'i bulup overwrite etmek için kullanıldı.

Warning

Reclaim adımı kırılgan kısımdır. PTE page'leri page allocator'ın order-0 PCP list'lerinden gelir; victim slab page'i, spray'den önce aynı migrate type ve order'a zorlanmalıdır, aksi halde forge-edilmiş-PTE alias'ı asla materyalize olmaz. Eşleşmeyen order/zone basitçe iyi huylu bir page verir.

Detection

Bir heap free'sinin hemen ardından gelen anomalili page-table allocation churn'ü (mmap/fault fırtınaları üzerinden mass PTE/PMD allocation) ve overwrite edilmiş bir modprobe_path veya kernel-physical frame'lerin bir user address space'ine beklenmedik mapping'leri gibi post-exploit imzaları.

Mitigation

  • PT-Rand ve ilgili savunmalar, page-table memory'sini randomize/izole eder ki attacker byte'ları canlı bir PTE array ile güvenilir şekilde co-locate edilemesin.
  • Page/slab isolation (örn. SLAB_VIRTUAL, slab page'leri page-allocator page'lerinden ayırmak), PTMA'nın dayandığı cross-cache reclaim'i kırar.
  • CONFIG_INIT_ON_ALLOC_DEFAULT_ON, allocation'da page'leri sıfırlar; bazı forge-edilmiş-PTE reuse path'lerini bozar (ve belirli v6.4+ akışlarında bad_page() detection'ını tetikler).

Ayrıca bkz. Dirty Pagetable (data-only page-table attack), page-level cross-cache attack.

References