Skip to content

Cross-cache attack (slab type confusion via page reuse)

Bir slab'in tamamını free et ki page'leri buddy allocator'a dönsün, sonra o page'i farklı bir cache'e reallocate ederek başka bir type'tan bir victim object'ini bir dangling reference'ın üzerine yerleştir.

Mechanism

SLUB allocator'ında, belirli bir boyuttaki object'ler slab'lerde (bir veya daha fazla bitişik page) yaşar. Bir slab'in backing page'leri page (buddy) allocator'a yalnızca belirli koşullarda dönülür: slab aktif per-CPU slab olmamalı ve per-CPU partial slab listesi dolu olmalıdır (bir slab, zaten-dolu bir per-node partial list'te otururken son object'i free edildiğinde discard edilir).

Note

Bir target slab'deki tüm object'ler free edilip slab discard edildiğinde, page'leri buddy/PCP allocator'a geri döner. Attacker ardından aynı page order'ından çeken farklı bir victim cache'i spray eder (örn. kmalloc-32 ve freed slab her ikisi de order-0 page kullanır), böylece victim cache freed page'leri reuse eder — farklı bir type'tan bir victim object'ini, attacker'ın hâlâ bir dangling reference tuttuğu belleğin üzerine yerleştirir. Bu cross-type örtüşmesi type confusion'dır ve RANDOM_KMALLOC_CACHES gibi same-cache hardening'i by-pass eder.

Kavramsal akış (boyutlar/yerleşim kernel'e göre değişir):

1) slab fully freed            2) page → buddy/PCP            3) victim cache reuse
   cache A (vuln type)            (aynı page order)              cache B (victim type)
   +----------------------+       +-------------------+          +----------------------+
   | obj | obj | obj | obj |  ->   |   free page(s)    |   ->     | victimA | victimB |..|
   +----------------------+       +-------------------+          +----------------------+
        ^ dangling ref                                                ^ dangling ref now
        | (attacker hâlâ tutuyor)                                     | aynı belleğe denk gelir
        +-------------------------------------------------------------+
                          => cross-type overlap = type confusion

Walkthrough

Freed bir reference'ı temizlemeyen kasıtlı olarak vulnerable bir module'e karşı (r1ru):

  1. /sys/kernel/slab/<CACHE>/objs_per_slab ve cpu_partial'ı oku (örnek: 8 objs/slab, cpu_partial = 52 ⇒ doldurmak için 424 allocation).
  2. Birçok slab'e yayılmış objs_per_slab * (cpu_partial + 1) object allocate et.
  3. Yeni bir aktif slab'i zorlamak için bir object daha allocate et; böylece önceki dolu slab'ler dormant (discard'a uygun) hâle gelir.
  4. Yalnızca dönüşümlü (çift numaralı) slab'lerdeki object'leri free et — "ardışık page'ler free edilirse, buddy allocator bunları" daha yüksek order'lı page'lere "merge eder", dolayısıyla bitişik olmayan freeing bunları order-0 page olarak tutar.
  5. Reclaim: freed page'leri reuse ederek kmalloc-32'den (order-0) ~32 struct seq_operations object allocate etmek için /proc/self/stat'ı tekrar tekrar aç.
  6. Exploit: module'ün CMD_WRITEseq_operations'taki function pointer'ları overwrite eder; proc dosyasında read() çağırmak corrupt edilmiş handler'ı invoke eder → RIP control.

Mitigation

SLUB-tarafı savunmaları (RANDOM_KMALLOC_CACHES, SLAB_BUCKETS, kmalloc-cg-* ayrımı) same-cache spraying'i engeller ama cross-cache'i durdurmaz; bu yüzden başvurulan by-pass'tır. Önerilen doğrudan mitigation, slab page address space'lerini pinleyerek freed slab page'lerinin re-type edilememesini sağlayan SLAB_VIRTUAL'dır; overhead nedeniyle mainline değildir.

References