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_tableserişilebilirliğini kaldırır. nft_verdict_init()fix'i verdict'leriNF_ACCEPT/DROP/QUEUEile 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.