Skip to content

tcmalloc Arbitrary Address Return

Bir tcmalloc size-class free list'indeki free edilmiş bir objenin next link'ini (overflow, UAF ya da double free üzerinden) corrupt ederek, allocator'ın sonraki bir malloc'a attacker'ın seçtiği bir adresi vermesini sağlamak — tcmalloc'un fastbin-dup / tcache poisoning analoğu.

Mechanism

Note

tcmalloc, her küçük size class'ı, head'i (thread- veya CPU-local) bir cache yapısında yaşayan ve link'leri free edilmiş objelerin kendi içinde yaşayan bir singly-linked free list'ten servis eder — bir free region'ın ilk word'ü onun next pointer'ıdır. Allocator'ın pop yolu (SLL_Pop ve arkadaşları) bu next word'ünün, kendisinin yazdığı bir list link'i olduğuna güvenir: head'i okur, head'i head->next olarak ayarlar ve eski head'i döndürür. next'in allocator'ın sahip olduğu bir span'e işaret ettiğine dair bir doğrulama yoktur, alignment kontrolü yoktur ve freed-state cookie'si yoktur.

İhlal edilen invariant şudur: "bir free objenin next word'ü allocator tarafından yazıldı ve yalnızca aynı list'teki başka bir free objeyi gösterir." Bir attacker o word'ü yazarsa — free edilmiş bir komşuya overflow ederek, bir dangling pointer'ı dereference ederek ya da aynı objeyi iki kez free ederek — list zehirlenir. ArcHeap yazarlarının ifadesiyle, free edilmiş bir chunk'ı corrupt etmek şu anlama gelir: "allocations will remove a chunk from list and set the list head, finally leading to modifying the head. Then, the next allocation will return a corrupted memory address, which is controlled by attackers." Bunun "analogous to fast-bin-dup in ptmalloc" olduğunu belirtirler. tcmalloc, ptmalloc'un sonradan eklediği freed-chunk güvenlik kontrollerini atladığından, sade bir double free bile allocation'ları doğrudan duplicate eder.

Walkthrough

Üst düzey; ArcHeap PoC'sini (§A, "arbitrary address return") yansıtır — tıpkı ../primitive/tcache-poisoning.md gibi bir free objenin ilk word'ü üzerinden link verir:

/* all same size class S, served by one singly-linked FreeList */
void *a = malloc(S);
void *b = malloc(S);

free(b);            /* FreeList head -> b -> ...        */
free(a);            /* FreeList head -> a -> b -> ...   */

/* overflow / UAF / double-free lets us rewrite the head object's next word */
*(void **)a = (void *)target;   /* a.next = target (no validation in SLL_Pop) */

malloc(S);          /* pops a                               */
void *x = malloc(S);/* pops 'target' -> attacker-chosen ptr */
/* x now aliases attacker-controlled memory -> arbitrary write */
  1. Hedef size class'ı groom et ki victim objeler onun free list'inin head'inde otursun.
  2. Bug'ı (free edilmiş komşuya overflow / UAF / double free) kullanarak head objenin ilk word'ünü target ile overwrite et.
  3. Meşru head'i geçecek kadar drain etmek için allocate et; sonraki malloc target döndürür.
  4. Döndürülen pointer üzerinden yazmak target'ta bir arbitrary write verir.
Neden hiçbir kontrol tetiklenmez

Herkese açık PoC'ler, corrupt edilmiş pointer'ın hayatta kaldığını vurgular; çünkü front-end pop yolu hiçbir span-üyeliği ya da alignment testi yapmaz. Tekniğe ait ArcHeap kaynak yorumu "tcmalloc has a next chunk address at the end of a chunk" der ve doğrudan o link'e dayanır. Corrupt edilmiş objeyi thread/CPU cache'inin içinde tutmak (objelerin index'lerini izleyen central free list'e flush olmasına izin verme) exploitation'ı güvenilir tutar.

Warning

Güvenilirlik cache locality'sine bağlıdır. Modern per-CPU tcmalloc'ta front-end çalışan CPU'ya göre anahtarlanır, dolayısıyla free'ler ve devam eden allocation'lar aynı mantıksal CPU'ya düşmelidir — thread'i sabitle (örneğin sched_setaffinity). Hardened/sanitize edilmiş build'ler, zehirlenmiş ya da double-free edilmiş bir link'te abort eden freelist integrity kontrolleri ekler.

Detection

  • ASan / allocator debug build'leri. AddressSanitizer ile ya da tcmalloc'un debug/sanitize modlarıyla derlemek, double-free'yi ve free edilmiş objeye yapılan out-of-bounds write'ı corruption anında yakalar.
  • Crash forensics. Hizasız bir pointer ya da sahip olunan herhangi bir span'in dışındaki bir pointer döndüren bir malloc, güçlü bir list-poisoning işaretidir; wild bir head pointer'ı ile front-end pop yolundaki çökmeler bu primitive'e işaret eder.
  • Allocation telemetrisi. Aynı-size-class alloc/free çiftlerinin patlamaları (grooming) ve aynı adresin tekrarlı free'leri, allocation profiler'larında gözlemlenebilir.
  • Guarded reuse. Free edilmiş bellek poison/quarantine doldurması (etkin olduğunda), bir attacker geri dönüştürülmüş bir region'ı sondaladığında fault verir.

Mitigation

  • Güncel tcmalloc / per-CPU front-end kullan. Modern release'ler, pop edilen bir objenin sahip olan span'e ait olduğunu doğrular ve per-CPU cache'i tercih eder, naif cross-span forge edilmiş pointer'ları kırar.
  • Sunan build'lerde freelist integrity / sanitizer desteğini etkinleştir ki corrupt edilmiş ya da duplicate edilmiş bir next onurlandırılmak yerine abort etsin.
  • Besleyen bug sınıfını ortadan kaldır: free edilmiş objelere ../primitive/double-free.md, ../primitive/use-after-free.md ve ../primitive/heap-buffer-overflow.md.

References