Intel Memory Protection Extensions (historical)¶
Kullanımdan kaldırılmış Skylake dönemi hardware bounds checking'i: dört
BND0-BND3register'ı artı pointer dereference'lerinin etrafına yerleştirilenbndcl/bndcukontrolleri; zayıf performans ve benimsenme sonrası GCC 9'dan, Linux kernel'inden (5.6) ve glibc'den (2.35) kaldırıldı.
Mechanism¶
Neden çalışır
MPX, spatial memory safety'ye — out-of-bounds read'ler ve write'lar — her pointer'a açık lower/upper bound'lar ilişkilendirerek ve her dereference'i hardware'de bunlara karşı kontrol ederek saldırdı; böylece bir buffer overflow komşu belleği bozmak yerine fault verir.
- Dört 128-bit bounds register'ı
BND0-BND3'ün her biri bir çift 64-bit değer tutar: pointer'ın içinde kalması gereken nesnenin bir lower bound'u (LB) ve bir upper bound'u (UB). - Compiler kodu instrumente eder, böylece bir pointer üzerinden her load veya
store'dan önce bir bounds check emit eder:
bndcl(lower bound'u kontrol et) vebndcu/bndcn(upper bound'u kontrol et), bir GPR'daki pointer'ı birBNDregister'ındaki bound'larla karşılaştırır; bir ihlal bir #BR bound-range-exceeded exception'ı doğurur.bndmkyeni bound'lar yaratır,bndmovbound'ları register'dan register'a veya belleğe taşır. - Yalnızca dört BND register'ı ama sınırsız sayıda canlı pointer olduğundan,
bound'lar pointer'ın kendi konumuyla adreslenen bir iki seviyeli Bounds
Directory / Bounds Table yapısı aracılığıyla belleğe spill olur:
bndstxbir pointer'ın bound'larını table'a depolar vebndldxonları geri yükler, böylece bound'lar bir pointer'ı bellek boyunca "takip eder". - Configuration ve status özel register'larda durur:
BNDCFGU(user-mode config) /IA32_BNDCFGS(supervisor) feature'ı etkinleştirir ve bound directory base'ini tutar,BNDSTATUSise bir #BR fault'unun nedenini kaydeder. Legacy prefix encoding'i, BND instruction'larının MPX'siz CPU'larda NOP olarak decode edilmesi anlamına gelir, dolayısıyla tek bir binary her ikisinde de çalışabilir.
Invariant: her instrumente edilmiş dereference, pointer'la birlikte gezinen bound'lara karşı kontrol edilir. Pratikte bu invariant pahalı ve eksikti — MPX'in şimdi tarih olmasının nedeni budur.
Walkthrough¶
1. MPX instrumentation'ı ile derle (onu destekleyecek kadar eski bir toolchain'de).
GCC < 9 ve ICC -fcheck-pointer-bounds -mmpx'i kabul ediyordu:
2. Emit edilen kontrolleri incele. Bir pointer store'unun etrafında compiler erişimi bounds instruction'larıyla parantezler:
bndmk (%rdi,%rsi,1), %bnd0 ; make bounds [rdi .. rdi+rsi] for buffer
bndcl (%rax), %bnd0 ; check rax >= lower bound
bndcu 7(%rax), %bnd0 ; check rax+7 <= upper bound (#BR on violation)
mov %rcx, (%rax) ; the now-checked store
Not: bndcl/bndcu'daki (%rax) bir memory load değildir — MPX bu operand'ın
effective address'ini lea gibi hesaplar (bellek okunmaz) ve bu adres değerini
bound'a karşı kontrol eder; dolayısıyla (%rax) adres rax'i, 7(%rax) ise rax+7'yi
denetler.
3. Register'lardan daha uzun yaşayan bound'lar table aracılığıyla spill olur:
bndstx %bnd0, (%rbx,%rax,1) ; store bounds for pointer at [rbx+rax]
; ... later ...
bndldx (%rbx,%rax,1), %bnd0 ; reload them before dereference
4. Modern bir stack'te gittiğini doğrula. Güncel compiler'lar flag'leri reddeder — feature kaldırıldı:
$ gcc -fcheck-pointer-bounds -mmpx -c demo.c
cc1: error: '-fcheck-pointer-bounds' is not supported with MPX disabled/removed
MPX neden terk edildi
MPX kötü ölçüm verdi ve az şeyi kapsadı: çalışmalar en kötü durumda ~4x'e kadar yavaşlama (~%50 ortalama) bildirdi, yalnızca spatial safety'yi korudu (use-after-free / temporal koruma yok), bounds-table güncellemelerinde thread-safety tehlikeleri vardı ve diğer extension'larla çakışıyordu. Kaldırma hızla geldi: GCC 9.1 onu düşürdü, Linux kernel MPX'i 5.6'da kaldırdı, glibc 2.35 MPX desteğini kaldırdı ve Intel MPX'i deprecate etti, sonraki CPU'larda yokluğunu bıraktı. Yerini bunun yerine software bounds checker'lar (AddressSanitizer) ve ARM MTE / pointer şemaları doldurdu.
References¶
- Wikipedia. Intel MPX. — https://en.wikipedia.org/wiki/Intel_MPX
- Oleksii Oleksenko et al. Intel MPX Explained. (arXiv) — https://arxiv.org/pdf/1702.00719
- Phoronix. Glibc 2.35 Removes The Long-Deprecated Intel MPX Support. — https://www.phoronix.com/news/Glibc-2.35-Removes-Intel-MPX