jemalloc Chunk metadata corruption¶
Bir region'ın dışına overflow yaparak chunk-level bookkeeping'i (ya da komşu bir region'ı) corrupt et ki allocator overlapping memory geri versin.
Mechanism¶
Kırılan invariant
jemalloc virtual memory'yi büyük, eşit boyutlu, aligned chunk'lara böler
(klasik olarak Firefox'un mozjemalloc'unda 1 MB, FreeBSD libc'de 2 MB, standalone
sürümde ~4 MB'a kadar). Her chunk, kendisine ait arena_t'ye bir back-pointer ve her
page boyutundaki birimin state'ini ve page'lerin run'lara nasıl gruplandığını kaydeden
bir chunk map tutan bir arena_chunk_t header ile başlar. Allocator hangi
page'lerin/run'ların free olduğuna karar vermek için bu bookkeeping'e güvenir. Geçilen
sınır user data → allocator metadata'dır: bir run'ın son region'ının dışına yapılan
linear bir overflow chunk map'e (ya da komşu bir arena'nın arena_chunk_t'sine) ulaşabilir
ve allocator'a kullanımdaki alanı free olarak tanımlatabilir.
Çok daha yaygın varyant adjacent-region overflow'dur: aynı size-class'taki region'lar bir
run içinde aralarında inline metadata olmadan contiguous şekilde durur, dolayısıyla bir
overflow doğrudan komşu bir objeye (vtable pointer, length field, function pointer) yazar.
jemalloc kasıtlı olarak dlmalloc tarzı unlink/frontlink kullanmaz, dolayısıyla freelist
cerrahisinden write-4-anywhere yoktur — amaç sonraki bir malloc()'un zaten canlı ya da
attacker-chosen memory'ye bir pointer döndürmesini sağlamaktır.
Walkthrough¶
Üst düzey, public Phrack #68 ve Black Hat USA 2012 write-up'larından:
- Groom ("Heap Feng Shui") yap ki aynı size-class'taki region'lar bir run'da komşu yerleştirilsin; seçilmiş bir victim objeyi vulnerable olanın hemen ardına konumlandır.
- Basit durum için, vulnerable region'ı victim'in içine overflow et — field'larını doğrudan corrupt ederek. Bu, baskın ve en güvenilir path'tir.
- Chunk-header path'i için: allocation'ları öyle sür ki target yeni bir arena/chunk
ayağa kaldırsın, sonra sınırdaki arena'nın son region'ını overflow ederek yeni chunk'ın
housekeeping'ini corrupt et. Whitepaper'a göre, sonraki bir
free()state'i öyle değiştirir ki sonraki birmalloc()zaten allocate edilmiş alana işaret eden bir region döndürür (bir overlapping allocation).
Kavramsal layout
[ run: regionA | regionB(victim) ] ... [ arena_chunk_t header | chunk map ]
regionA'dan gelen bir overflow regionB'ye ulaşır; daha büyük/cross-run bir overflow
header/map'e ulaşır. Sınıfı anlamak için tam offset gerekmez.
Detection¶
- Region'lar arasında ve chunk header'ların etrafında heap canary / red-zone'lar; jemalloc'un kendi debug junk-fill ve red-zone build'leri; test pipeline'larında ASan / HWASan.
- Chunk/arena sınırlarındaki guard page'ler metadata'ya yapılan overflow'u bir fault'a çevirir.
- Hardened build'lerde
arena_chunk_tinvariant'larını sanity-check et (arena back-pointer registered bir arena'ya çözülür; chunk-map index'leri legal page range içinde).
Mitigation¶
- Chunk/run metadata'sını user region'lardan uzakta out-of-line tut ki contiguous bir overflow ona ulaşamasın (modern allocator'ların tercih ettiği ayrım).
- Technique'in bağlı olduğu deterministic grooming'i yenmek için chunk base yerleşimini randomize et (ASLR).
- Per-size-class / type isolation ile attacker-controlled ve security-critical objelerin asla aynı run'ı paylaşmamasını sağla.