Skip to content

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:

  1. 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.
  2. 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.
  3. 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 bir malloc() 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_t invariant'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.

References