Skip to content

AddressSanitizer

heap/stack/global overflow'ları ve use-after-free'i tam erişim anında yakalamak için shadow memory ve redzone'lar kullanan compiler instrumentation (-fsanitize=address).

Mechanism

Neden çalışır

Memory-safety bug'larını yakalamak zordur çünkü başıboş bir read/write genellikle hâlâ geçerli map'lenmiş memory'ye düşer — corruption sessizdir. ASan her out-of-bounds ya da free edilmiş byte'ı açıkça un-addressable yapar ve her load/store'u bu state'e göre kontrol eder.

Bir shadow memory tutar: 8 byte application memory, 1 shadow byte'a map olur (1:8 scaling). Mapping sabit bir shift + offset'tir; 64-bit'te:

Shadow = (Mem >> 3) + 0x7fff8000      # 32-bit offset is 0x20000000

0 olan bir shadow byte, 8 application byte'ın tamamının addressable olduğunu gösterir; negatif bir değer 8'inin de poisoned olduğunu gösterir; 1..7 granule'ün yalnızca ilk k byte'ının geçerli olduğunu gösterir (partial-granule, 8-aligned olmayan object'ler için). Her allocation'ın etrafına ASan poisoned redzone'lar yerleştirir; free()'de tüm region'ı poison eder ve chunk'ı bir quarantine queue'suna iter ki memory hemen yeniden kullanılmasın — işte use-after-free'i yakalayan budur.

Compiler'ın emit ettiği her memory access'in önüne bir instrumentation check konur:

shadow_address = MemToShadow(address);
if (ShadowIsPoisoned(shadow_address)) ReportError(...);

Invariant şu: poisoned bir granule'e erişim, gerçekleştiği anda raporlanır ve bu, sessiz corruption'ı deterministik, konumu belli bir abort'a dönüştürür.

Walkthrough

1. Sanitizer ile compile et. Hem compile hem de link aşamasında kullan, okunabilir raporlar için genellikle -O1 -g ile:

$ cat uaf.c
int main(int argc, char **argv) {
  int *array = new int[100];
  delete [] array;
  return array[argc];          // BOOM: use-after-free
}

$ clang++ -fsanitize=address -O1 -g uaf.c -o uaf
$ ./uaf

2. Raporu oku. ASan bug class'ını, fault'a yol açan access'i ve allocation/free stack'lerini yazdırır (clang dokümanlarından çıktı):

AddressSanitizer heap-use-after-free report
==9442== ERROR: AddressSanitizer heap-use-after-free on address 0x7f7ddab8c084
READ of size 4 at 0x7f7ddab8c084 thread T0
    #0 0x403c8c in main example_UseAfterFree.cc:4
freed by thread T0 here:
    #0 0x404704 in operator delete[](void*) ??:0
    #1 0x403c53 in main example_UseAfterFree.cc:4
previously allocated by thread T0 here:
    #0 0x404544 in operator new[](unsigned long) ??:0
    #1 0x403c43 in main example_UseAfterFree.cc:2

Aynı makine, bir access redzone shadow byte'ına düştüğünde heap-buffer-overflow, stack-buffer-overflow ve global-buffer-overflow raporlar.

Bir debugging aracı, runtime defense değil

ASan'ın ~2x yavaşlaması ve büyük memory overhead'i vardır; quarantine ve redzone'lar sonludur, dolayısıyla çok uzağa giden bir out-of-bounds ya da özenle boyutlandırılmış bir access poisoned bir region'ı atlayabilir. Fuzzing/CI için düşünülmüştür, production hardening için değil — onun için HWASan ya da ARM MTE'ye bak.

Detection

ASan'ın kendisi zaten detector'dır; bir bulgu olduğunda abort eder ve access'in etrafındaki shadow-byte map'ini yazdırır; bu da access'in bir left/right redzone'a mı, free edilmiş bir bölgeye mi, yoksa partial granule'e mi denk geldiğini kesin olarak belirler.

References