Skip to content

Uninitialized stack variable infoleak

Bir kernel fonksiyonu, stack üzerindeki bir local'i (ya da struct padding'ini) initialize etmeden userspace'e kopyalar ve önceki bir call frame'in bıraktığı artık byte'ları — çoğu zaman kernel pointer'larını ya da bir stack canary'sini — açığa çıkarır.

Mechanism

Kernel stack'i çağrılar arasında yeniden kullanılır. Bir syscall handler bir local değişken ya da struct tanımlayıp onu her byte'ı yazmayan bir yol boyunca copy_to_user()/put_user() ile userspace'e kopyaladığında, yazılmamış byte'lar hâlâ önceki fonksiyonun orada bıraktığı her ne ise onu tutar.

Note

Aynı invariant'ın iki çeşidi — "tam olarak initialize etmediğin belleği asla dışarı kopyalama":

  • Yazılmamış local'ler / error path'leri: bir alan yalnızca başarı durumunda doldurulur, ama struct koşulsuz olarak (ya da erken bir return/goto'da) dışarı kopyalanır.
  • Struct padding boşlukları: compiler alanlar arasına alignment padding ekler. memcpy/alan-alan kopyalar boşluğa hiç dokunmaz, dolayısıyla her isimli alan set edilse bile boşluk eski stack byte'larını leak'ler.

Açığa çıkan veri "bedava"dır, ama değeri önceki frame'in ne bıraktığına bağlıdır. WOOT'20 sonucu (Cho et al.) şudur: bu düşük riskli değildir: targeted stack-spraying ile saldırgan önce derin call chain'i tam olarak vulnerable fonksiyonun daha sonra initialize edilmemiş okuduğu stack slot'una bir kernel function pointer'ı ya da kernel-stack pointer'ı bırakan bir syscall çağırır — bir "çöp byte" leak'ini güvenilir bir KASLR-bozan kernel-pointer leak'ine çevirir.

Kanonik örnekler: VMware DRM vmw_gb_surface_define_ioctl (initialize edilmemiş backup_handle), Xen blkif make_response padding'i (XSA-216) ve birçok compat-ioctl handler'ı (bkz. cciss_ioctl32_passthru, atyfb ioctl padding).

Walkthrough

Minimal bir vulnerable handler ve saldırgan iş akışı:

struct leak { u32 a; /* 4 bytes padding here */ u64 b; };

long vuln_ioctl(unsigned long uarg) {
    struct leak out;          // NOT zeroed
    out.a = 0x1337;           // 'a' set; padding + 'b' may stay stale
    return copy_to_user((void __user *)uarg, &out, sizeof(out));
}
  1. Stack'i hazırla (targeted spray). Call chain'i aynı stack bölgesiyle örtüşecek kadar derin olan ve oraya bir kernel pointer bırakan ilgisiz bir syscall çağır. "Priming" syscall'unun seçimi, leak'i rastgele yerine deterministik yapan şeydir.

  2. Leak'i tetikle. Aynı thread'den derhal vulnerable handler'ı çağır (slot'u yeniden ezecek araya giren derin bir çağrı olmadan):

struct leak out;
ioctl(fd, VULN_CMD, &out);
printf("padding/uninit = %#llx\n", out.b);   // stale kernel pointer
  1. KASLR'ı boz. Leak'lenen değeri bir kernel sembolünün bilinen low bit'lerine maskele ve KASLR slide'ını geri elde etmek için sembolün statik offset'ini çıkar:
unsigned long kbase = out.b - KNOWN_SYM_STATIC_OFFSET;
Expected output
padding/uninit = 0xffffffff8108c4a0
[*] leaked kernel text pointer, KASLR slide = 0x1e000000

Aynı desen, leak'lenen slot bir saved-canary konumuyla alias olduğunda bir stack canary verir ve downstream'de stack-smash exploitation'ı mümkün kılar.

Detection

  • Compile-time: -Wuninitialized, -Wmaybe-uninitialized ve kernel'in stack-init hardening'i (CONFIG_INIT_STACK_ALL_ZERO, CONFIG_INIT_STACK_ALL_PATTERN) local'leri zero/poison yapar, böylece leak'ler secret yerine zero/poison olarak yüzeye çıkar.
  • Dynamic: KMSAN (CONFIG_KMSAN) initialize edilmemiş belleği izler ve poison'lanmış byte'ların userspace'e kopyalarını raporlar; syzbot onu sürekli çalıştırır.
  • Multi-variant execution (kMVX) ve stack-leak dedektörleri, yazılmamış boşluklarla dışarı kopyalanan struct'ları işaretler.

Mitigation

  • Doldurmadan önce memset(&out, 0, sizeof(out)) yap, ya da designated-initializer = {0} / = {} kullan.
  • CONFIG_INIT_STACK_ALL_ZERO=y (modern hardened build'lerde default-on) stack local'lerini otomatik sıfırlar ve padding dahil tüm sınıfı etkisizleştirir.
  • CONFIG_GCC_PLUGIN_STRUCTLEAK / __user-copy padding-temizleyen helper'lar; kptr_restrict ve KASLR, kalan herhangi bir leak'in değerini artırır.

References