Skip to content

Page-level cross-cache attack

Page-allocator granülaritesinde çalışan bir cross-cache varyantı: bir slab page'i buddy allocator'a geri free et ve onu farklı türde bir page olarak (başka bir slab veya bir hardware page table) reclaim et; yalnızca slab cache'ler yerine object type'ları arasında geçiş yap.

Mechanism

Note

Klasik bir cross-cache attack, page'i buddy allocator'a dönsün diye tüm bir slab'i free eder, sonra o page'i farklı bir kmem_cache'e yeniden allocate eder — orijinal cache'in isolation'ından kaçar. Page-level varyant aynı invariant'ı daha ileri iter: geri dönüştürülen page hiç başka bir slab olmak zorunda değildir. Buddy allocator page'leri her tüketiciye servis ettiği için — SLUB refill, pipe buffer'lar ve page table'lar — free edilen page, raw page-table memory olarak reclaim edilebilir. Geçiş birimi cache değil page'dir, bu yüzden bug'ın orijinal size class'ı önemsiz hale gelir ve attacker, sonra ne allocate edeceğine karar vererek victim type'ını seçer.

Walkthrough

Flipping Pages exploit'i (CVE-2024-1086) kanonik page-level cross-cache'tir: nft_verdict_init() / nf_hook_slow() içindeki bir double-free, 0xffff0000 verdict'i NF_DROP olarak okunacak (kfree_skb_reason()'ı çağırarak) ama yine de NF_ACCEPT döndürecek şekilde yönlendirilir; bu da ikinci bir free üretir.

/* Force the buggy allocation OUT of the slab and into the page allocator:
   sk_buff->head over KMALLOC_MAX_CACHE_SIZE (PAGE_SIZE*2) uses the buddy
   allocator. A ~64KB packet forces an order-4 (16-page) allocation. */
send_oversized_packet(sock, 64 * 1024);

Refcount juggling, double-free'nin underflow etmesini engeller:

/* First free drops the page refcount to 0; a reallocation reincarnates
   the page before the second free, so put_page_testzero() doesn't trip:
   "When we free the page for the 2nd time, the refcount will be
    decremented to -1 and it will not be freed" without that intervening
   allocation. */

PCP draining üzerinden slab page'den page-table page'e geçiş:

/* Order >=4 lives in the buddy global pool; order 0-3 are cached in
   per-CPU (PCP) freelists. Drain PCP by mass order-0 allocations so the
   freed order-4 region is split and refilled via rmqueue_bulk(). */

/* Spray ~16,000 PTEs (order-0). Allocating PMDs also pulls child PTE +
   userland pages from the same freelist -> ~50% PMD / 50% PTE, giving
   deterministic page-table placement onto the freed region. */
Overlap'ten arbitrary read/write'a (Dirty Pagedirectory)

Bir PTE page ve bir PMD page aynı physical frame'e double-allocate edildiğinde, bir userland address'ine (örn. 0x40000000) yapılan bir write aynı anda PTE word'ünü de düzenler (ikisi de aynı physical memory'yi alias'lar). Child'da fork() + munmap(), TLB'yi flush eder ki forge edilmiş translation etkili olsun; eşleşen higher-level address'i okumak sonra arbitrary physical memory'yi dereference eder. Exploit, physical kernel memory'yi modprobe_path için tarar ve onu bir memfd privesc script'ine işaret eden /proc/self/fd/<fd> ile overwrite eder. Bkz. page table manipulation attack.

Warning

Page order ve zone hizalanmalıdır. Order ≤1 slab allocator'da kalır; order 0–3 PCP'de cache'lenir; order ≥4 buddy global pool'dan gelir. CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y, allocation'da page'leri sıfırlar ve v6.4+'ta bad_page() detection'ını tetikleyebilir, bu yüzden reclaim path'i ve hedef kernel config'i tam olarak eşleştirilmelidir.

Detection

Buddy-order allocation'ları süren oversized network packet'leri, PCP list'leri drain eden mass PTE/PMD allocation fırtınaları ve post-exploit artifact'lar (overwrite edilmiş modprobe_path, userspace'e map'lenmiş kernel-physical frame'ler) gözlemlenebilir.

Mitigation

  • SLAB_VIRTUAL / page isolation, free edilen slab page'lerin foreign-type page'ler (page table'lar dahil) olarak yeniden verilmesini engeller ve cross'u yener.
  • Unprivileged userns'i kısıtlamak, exploit'in dayandığı nf_tables erişilebilirliğini kaldırır.
  • nft_verdict_init() fix'i verdict'leri NF_ACCEPT/DROP/QUEUE ile kısıtlar ve bu belirli zinciri bootstrap eden bug'ı kapatır.

Ayrıca bkz. cross-cache attack, nf_tables Flipping Pages double-free, Dirty Pagetable.

References