Spectre v1 bounds-check bypass kernel gadget¶
Syscall'dan erişilebilen bir bounds check'in ötesine speculatively execute et (Spectre-PHT / CVE-2017-5753), böylece kernel geçici olarak out-of-bounds bellek okusun ve onu bir cache side channel üzerinden sızdırsın.
Mechanism¶
Conditional branch'ler pattern-history table (PHT) tarafından predict edilir. CPU bir bounds-check branch'ini mispredict ettiğinde, misprediction tespit edilip sonuçlar squash edilmeden önce in-bounds path'i out-of-bounds bir index ile speculatively execute eder.
Note
Bir "Spectre v1 gadget", if (i < limit) y = arr2[arr1[i] * stride]; şeklindeki kernel kodudur. Önce branch predictor'ı in-bounds path'i almaya train ederek, sonra out-of-bounds bir i ile çağırarak, kernel arr1[i]'yi (out-of-bounds kernel belleği) speculatively dereference eder ve değeri arr2'yi index'lemek için kullanır, cache'te bir footprint bırakır. Architectural state geri alınsa da cache state alınmaz: attacker, arr2'nin hangi line'ının çekildiğini timing'leyerek secret byte'ı kurtarır (bir Flush+Reload / Prime+Probe covert channel). Bu, herhangi bir architectural OOB erişim olmadan syscall sınırı boyunca kernel belleğini sızdırır.
Walkthrough¶
Syscall'dan erişilebilen bir kernel gadget'ına karşı kavramsal leak loop'u:
- Train: syscall'ı in-bounds index'lerle pek çok kez çağır, böylece PHT "taken" predict etsin.
- Flush:
arr2probe array'ini cache'ten tahliye et (clflush). - Trigger: hedef kernel adresine işaret eden kötü niyetli out-of-bounds bir
iile bir kez çağır; branch mispredict eder ve gadgetarr2[secret*stride]'i speculatively load eder. - Recover:
arr2'nin her line'ını timing'le; en hızlı (cached) linesecret'ı açığa çıkarır.
// userspace side-channel probe (transient window happens kernel-side):
for (k = 0; k < 256; k++){
t = rdtscp(); volatile char v = probe[k*4096]; dt = rdtscp()-t; // Flush+Reload
if (dt < THRESHOLD) leaked = k; // cached line == speculatively accessed byte
}
Beklenen sonuç: round başına bir secret byte timing üzerinden kurtarılır; kernel belleğini dump etmek için tekrarla.
Mitigation¶
Kernel, speculative path'te index'i clamp etmek için array_index_nospec() macro'sunu (ve barrier_nospec() / LFENCE) ekler, böylece OOB load ilerleyemez. İlişkili ama ayrı bir gadget sınıfı olan SWAPGS variant'ı (CVE-2019-1125) ise entry path'lerinde FENCE_SWAPGS_* barrier'larını kullanır; bu, bu not'un kapsadığı Spectre-PHT (CVE-2017-5753) bounds-check bypass'ından farklı bir zafiyettir. Her iki mitigation da global olarak değil, denetlenmiş gadget noktalarına uygulanır.