Skip to content

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:

  1. Train: syscall'ı in-bounds index'lerle pek çok kez çağır, böylece PHT "taken" predict etsin.
  2. Flush: arr2 probe array'ini cache'ten tahliye et (clflush).
  3. Trigger: hedef kernel adresine işaret eden kötü niyetli out-of-bounds bir i ile bir kez çağır; branch mispredict eder ve gadget arr2[secret*stride]'i speculatively load eder.
  4. Recover: arr2'nin her line'ını timing'le; en hızlı (cached) line secret'ı 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.

References