Skip to content

Double free

Aynı chunk'ı iki kez free ederek allocator'ın freelist'ini corrupt etmek.

Mechanism

Aynı adres üzerinde free()'yi iki kez çağırmak allocator'ın freelist'ini öyle corrupt eder ki sonraki iki malloc() call'u aynı pointer'ı geri verebilir; bu da overlapping allocation'lar ve write-what-where'e giden bir yol sağlar. Free edilmiş chunk bir bin'in listesinde birden çok kez görünür; liste üzerindeyken object A için allocate edildiğinde, sonraki bir allocation onu tekrar object B için döndürür ve ikisini alias'lar.

Note

CWE-415. glibc'de bu, tcache-poisoning ve fastbin-dup'a giriş noktasıdır: duplicate edilmiş chunk'ın fd/next pointer'ı, sonraki allocation'ı keyfi bir adrese yönlendirmek için overwrite edilebilir.

Walkthrough

Generic CWE-415 biçimi:

char *ptr = malloc(SIZE);
if (abrt) { free(ptr); }
// ...
free(ptr);          // second free on same address -> freelist corruption

glibc 2.29+ bir tcache double-free guard'ı ekledi. Free sırasında her tcache_entry bir key saklar; eğer bu zaten tcache'e eşitse, allocator bin'i tarar ve abort eder:

typedef struct tcache_entry {
  struct tcache_entry *next;
  struct tcache_perthread_struct *key;   /* set on free */
} tcache_entry;

if (__glibc_unlikely (e->key == tcache)) {
  for (tmp = tcache->entries[tc_idx]; tmp; tmp = tmp->next)
    if (tmp == e)
      malloc_printerr ("free(): double free detected in tcache 2");
}

Bu, naif bir tekrar free'yi durdurur. Bypass: herhangi bir UAF, ikinci free'den önce e->key'i clobber etmenize izin verir ve tcache_get() hiçbir key check yapmaz — dolayısıyla tcache poisoning uygulanabilir kalır (tcache-key-bypass). glibc 2.34+, heap-pointer leak yan etkisini de gidermek için pointer key'i bir __getrandom() değeriyle değiştirdi.

Naif double-free abort
free(): double free detected in tcache 2
Aborted (core dumped)

Detection

ASan/KASAN ikinci free'de "double-free" raporlar; glibc'nin built-in tcache/fastbin kontrolleri malloc_printerr ile abort eder. glibc tunable'ları ve MALLOC_CHECK_ ekstra consistency kontrolleri ekler.

Mitigation

Free'den sonra pointer'ları null'la; glibc tcache key ve fastbin fasttop head kontrolleri; allocator quarantine ve randomized key'ler. Metadata'yı clobber eden bir UAF verildiğinde hepsi bypass edilebilir.

References