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:
İ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¶
- Longterm Security — VDSO As A Potential KASLR Oracle — https://www.longterm.io/vdso_sidechannel.html