Skip to content

Intel CET Supervisor Shadow Stack

CET shadow stack'lerinin supervisor (ring-0) tarafı: MSR'larda privilege-level başına shadow-stack pointer'ları ve bir kernel ROP girişimini control-protection (#CP) fault'una çeviren korumalı bir return-address kopyası, CR4.CET ile koşullanır.

Mechanism

Neden çalışır

Bir shadow stack, her return address'in ikinci, hardware tarafından korunan bir kopyasını tutarak ROP'u yener: CALL'da CPU return address'i hem normal stack'e hem de shadow stack'e push'lar ve RET'te onları karşılaştırır — ikisi farklıysa, processor bir control-protection (#CP) fault'u doğurur. Supervisor varyantı bu invariant'ı ring 0'a genişletir. Mekanizma user-mode shadow stack ile aynıdır; fark enablement ve scope'ta: burada IA32_S_CET + CR4.CET, per-privilege IA32_PL0..3_SSP ve supervisor busy-bit token'ları (SETSSBSY/CLRSSBSY) devreye girer, arch_prctl/glibc opt-in yerine OS/hypervisor doğrudan MSR programlar.

  • Supervisor shadow stack'leri, user-mode IA32_U_CET'in (0x6A0) ring-0 karşılığı olan IA32_S_CET MSR'ı (adres 0x6A2) aracılığıyla yapılandırılır. Düşük bit'ler (SH_STK_EN, WR_SHSTK_EN), supervisor mode için shadow-stack enforcement'ını ve WRSS instruction'ını etkinleştirir.
  • Ring 0'ın birkaç privilege level'i olduğu ve SSP'nin ring geçişlerinde değiştirilmesi gerektiği için, mimari privilege başına shadow-stack pointer MSR'ları sağlar: IA32_PL0_SSP, IA32_PL1_SSP, IA32_PL2_SSP ve IA32_PL3_SSP. CPL'yi 0'a yükselten bir geçişte, processor SSP'yi IA32_PL0_SSP'den yükler.
  • Ana etkinleştirme CR4.CET bit'idir (bit 23). CR4.CET=0 ile hiçbir CET enforcement'ı olmaz; OS bunu *_CET MSR'larını programlamadan önce set eder. Shadow-stack page'leri özel bir "shadow stack" memory type'ı taşır — sıradan MOV store'ları fault verir, onlara yalnızca call/return makinesi ve WRSS/INCSSP/RSTORSSP dokunur.
  • Supervisor shadow stack'leri, stack base'indeki bir supervisor token'ında bir busy bit kullanır: SETSSBSY bir shadow stack'i aktif işaretler (busy set eder), CLRSSBSY onu serbest bırakır ve RSTORSSP bir restore token aracılığıyla bir shadow stack'e geçer. Bu, iki logical processor'ın tek bir shadow stack'i paylaşmasını önler.

Invariant: RET'in okuduğu return hedefi, attacker'ın forge edemeyeceği bellekte yaşar — ring 0'da bile. Kaydedilmiş bir return address'i yeniden yazan bir kernel stack overflow shadow kopyasını el değmemiş bırakır, dolayısıyla uyuşmazlık kontrolü yönlendirmek yerine fault verir.

Walkthrough

1. Mimari yapı taşlarını doğrula. CET desteği CR4.CET (bit 23 / mask 0x800000) ile duyurulur; yazılım etkinleştirmeden önce bunu kontrol eder:

; pseudo-check used by an OS / hypervisor
mov  rax, cr4
test rax, 0x800000        ; CR4.CET — is CET enabled?
jz   cet_not_enabled

2. Supervisor SSP bir GPR'da değil, MSR'larda yaşar. Yazılım canlı SSP'yi RDSSPQ ile okur ve PL başına pointer'ları MSR'lar aracılığıyla programlar:

IA32_S_CET   = 0x6A2   ; supervisor CET config (SH_STK_EN, WR_SHSTK_EN, ENDBR_EN ...)
IA32_PL0_SSP = 0x6A4   ; SSP loaded on transition to CPL 0
IA32_PL1_SSP = 0x6A5
IA32_PL2_SSP = 0x6A6
IA32_PL3_SSP = 0x6A7

3. Supervisor shadow stack'leri kur ve aralarında geçiş yap, kısıtlanmış instruction'larla (hiçbir düz MOV SSP'ye yazamaz):

SETSSBSY      ; set busy bit in supervisor shadow-stack token -> activate
RSTORSSP mem  ; switch to another shadow stack via its restore token
CLRSSBSY mem  ; clear busy bit -> release the shadow stack

4. Bir kernel ROP girişiminde fault'u gözlemle. Normal kernel stack'indeki kaydedilmiş bir return address'i overwrite et; RET'te shadow kopyası hâlâ gerçek caller'ı tutar, ikisi uyuşmaz ve CPU gadget'a atlamak yerine bir control-protection (#CP) fault'u teslim eder.

Linux kernel shadow stack'i değil, kernel IBT'yi destekler

Linux 64-bit kernel'i yalnızca userspace shadow stack artı kernel IBT implemente eder: kernel belgelerine göre, "Bugün 64-bit kernel'de yalnızca userspace shadow stack ve kernel IBT destekleniyor." Supervisor shadow stack'leri en belirgin biçimde diğer OS'lerde görülür — örn. IA32_PL0_SSP'nin ring-0 shadow stack'ini tuttuğu ve supervisor token'larının geçişi koruduğu Windows kernel-mode shadow stack'leri.

Mitigation

(Artık risk / hâlâ neler geçer.) Supervisor shadow stack yalnızca backward edge'leri (kernel return'leri) korur. Forward-edge hijack'leri — bir indirect CALL/JMP hedefini bozma, JOP veya COOP tarzı data-only call-site reuse — etkilenmez ve Indirect Branch Tracking ya da FineIBT gibi daha ince CFI gerektirir. Kernel IBT sevk eden ama kernel shadow stack sevk etmeyen bir platform ring-0 return'lerini korumasız bırakır.

References