Skip to content

VDSO KASLR oracle

vDSO, kernel image içinde sabit bir offset'te oturur, dolayısıyla runtime address'ini sızdırmak — ya da onu speculative olarak yoklamak — kernel base'i derandomize eder.

Mechanism

Neden çalışır

vDSO ("virtual dynamic shared object"), bir kernel geçişi olmadan clock_gettime() gibi hızlı syscall'lara hizmet etmek için her userspace process'ine map'lenen, kernel tarafından sağlanan küçük bir shared object'tir. Code page'i (vdso, vdso_start'tan) ve data page'i (vvar, vdso_data'dan), kernel image'ın bir parçası olarak emit edilir, dolayısıyla vdso_start, kernel TEXT içinde sabit bir offset'te yaşar.

KASLR, her boot'ta kernel TEXT base'ini randomize eder ama vDSO'yu ona göre bağımsız olarak randomize etmez. Bu yüzden, vdso_start'ın runtime address'ini bir kez bildiğinde, kernel base çıkarma ile ortaya çıkar:

kernel_base = runtime_vdso_start - compile_time_vdso_offset

İstismar edilen invariant: bilinen bir kernel-image sembolü (vDSO), randomize edilmiş base'ten sabit bir displacement korur, dolayısıyla onun için herhangi bir address oracle'ı, KASLR için bir oracle'dır. Daha eski vsyscall page'i daha da zayıftır — sabit bir virtual address'tedir (0xffffffffff600000) ve dolayısıyla kendi başına KASLR hakkında hiçbir şey sızdırmaz, ama tarihsel olarak kararlı bir execute hedefi sağlamıştır.

Walkthrough

Yalnızca yetkili test

Sahip olduğun bir kernel/VM üzerinde çalıştır. Aşağıdaki doğrudan rota yalnızca userspace vDSO address'ini sızdırır; onu kernel base'e çevirmek, o tam kernel için per-build vDSO offset'ini gerektirir.

1. Per-process vDSO mapping'ini bul (doğrudan rota). Dynamic loader, vDSO base'ini aux vector'da ve /proc/self/maps'te açığa çıkarır:

#include <sys/auxv.h>
unsigned long vdso = getauxval(AT_SYSINFO_EHDR);   // userspace vDSO base
printf("vDSO @ %lx\n", vdso);
$ cat /proc/self/maps | grep -E 'vdso|vvar'
7ffff7fc1000-7ffff7fc3000 r-xp ... [vdso]
7ffff7fbd000-7ffff7fc1000 r--p ... [vvar]

Bu sana neyi verir neyi vermez

AT_SYSINFO_EHDR, vDSO'nun userspace mapping'idir — user ASLR ile randomize edilmiş, doğrudan bir kernel-base leak'i değil. Kernel-KASLR oracle'ı, vdso_start'ın kernel address'idir. Onu, bir bug ya da side channel vDSO/vvar bölgesine bir kernel pointer'ı açığa çıkardığında elde edersin; sonra yukarıdaki çıkarmayı uygula.

2. Speculative / side-channel oracle ("oracle"ın kendisi). Bir leak doğrudan mevcut olmadığında, vDSO'nun paylaşılan physical page'i, speculative bir KASLR probe için iyi bir Flush+Reload hedefi olur. Bounds check'i speculative olarak bypass edilebilen bir syscall'a tahmin edilen kernel address'leri beslenir; doğru bir tahmin vDSO page'ine speculative olarak dokunur ve cache'i hazırlar:

for guess in candidate_kernel_bases:
    flush(vdso_shared_line)
    trigger_syscall_with_speculative_access(guess)   # mistrained branch
    t = time_reload(vdso_shared_line)
    if t < CACHE_HIT_THRESHOLD:
        kernel_base = guess                           # correct guess cached it

Beklenen etki (bir Pixel 3a üzerinde yayımlanan PoC'dan): doğru tahminler keskin biçimde daha düşük bir reload süresi gösterir (deltalar ~156–313 cycle) iken yanlış tahminler tutarlı bir sinyal göstermez; tam derandomization ~3.31 s'de tamamlandı.

3. Kurtarılan base'i kullan. Zincirin geri kalanı için KASLR'ı yenmek üzere bilinen sembol offset'lerini (commit_creds, modprobe_path vb.) kernel_base'e ekle.

Detection

  • rdtsc-stili timing ve cache flush'larıyla birleşmiş clock_gettime/vDSO-bitişik syscall'lar üzerinde sıkı döngüler, speculative bir KASLR probe'unun davranışsal imzasıdır.
  • Loglarda ya da info-leak sink'lerinde vDSO/vvar aralığına doğrudan kernel-pointer leak'leri.

Mitigation

  • vDSO'yu kernel TEXT'ten bağımsız randomize et ki sabit-offset ilişkisi artık kernel base'i vermesin (Longterm writeup'ında önerilen fix).
  • vsyscall'ı emulate ya da disabled tut (vsyscall=none) ki legacy sabit-address execute hedefi kaldırılsın.
  • Genel KASLR-side-channel hardening: KPTI user/kernel page table'larını ayırır ve birkaç speculative oracle'ı köreltir; mümkün olduğunda unprivileged timing/rdtsc'yi disable et.

References