SPARC Application Data Integrity¶
SPARC M7+ üzerinde her 64-byte block'u ve ona ulaşmak için kullanılan pointer'ları tag'leyen, bir load/store'un pointer version'ı target memory'nin version'ı ile uyuşmadığında trap üreten hardware memory-versioning.
Mechanism¶
Note
Kavramsal: NEDEN çalışır, invariant/teori.
Silicon Secured Memory olarak da pazarlanan Application Data Integrity (ADI), SPARC M7, M8, S7, T7 ve T8 processor'larında implemente edilmiştir. Aynı anda iki şeye küçük bir version number iliştirir: physical memory'ye (her 64-byte ADI block başına — bir cacheline ile aynı boyut) ve o memory'ye ulaşmak için kullanılan virtual address'in üst bitlerine. Her load ve store'da MMU, pointer'da encode edilen version'ı target block için saklanan version ile karşılaştırır; uyuşmazlıkta bir exception üretir.
Invariant şudur: "memory'yi yalnızca doğru color'ı taşıyan bir pointer üzerinden dereference edebilirsin." Bu, çoğu memory-corruption exploit'inin altında yatan iki bug sınıfını doğrudan yakalar:
- Linear buffer overflow'lar: bitişik allocation'lar farklı version'larla color'lanır, böylece bir buffer'ın sonunu aşıp bir sonrakine giren bir write yanlış version ile dereference edilir ve trap'ler.
- Stray / dangling pointer dereference (use-after-free): memory free edilip yeniden color'landığında, bayat bir pointer hâlâ eski version'ı taşır ve kullanımda trap'ler.
SPARC M7'de version tag, virtual address'in bit 63-60'ını işgal eder
(4 bit → 16 değer). İki değer reserve'dür: 0x0 ve 0xf herhangi bir
target version ile eşleşir ve bu yüzden asla bir uyuşmazlık üretmez —
herhangi-color'lı memory'ye meşru şekilde dokunabilen bir "wildcard" pointer
için kullanışlı. Bir task açıkça opt-in yapmalıdır: kernel, versioning etkili
olmadan önce task için PSTATE.mcde'yi (MCD enable) ve ilgili TLB entry'lerinde
TTE.mcd'yi set eder.
İki trap çeşidi vardır. Bir precise exception (MCDPERR=1) senkron olarak
ateşlenir ve si_code = SEGV_ADIPERR ile SIGSEGV teslim eder; bir
disrupting exception asenkrondur (suçlu erişimden biraz sonra ortaya
çıkabilir) ve si_code = SEGV_ADIDERR ile SIGSEGV teslim eder.
Walkthrough¶
Linux kernel'i ADI parametrelerini auxiliary vector'lar üzerinden sunar, böylece bir program granule ve tag width'ini hardcode etmek yerine runtime'da keşfedebilir:
#include <sys/auxv.h>
#include <stdio.h>
int main(void) {
unsigned long blksz = getauxval(AT_ADI_BLKSZ); /* ADI block size, bytes */
unsigned long nbits = getauxval(AT_ADI_NBITS); /* number of version bits */
printf("ADI block size = %lu bytes, version bits = %lu\n", blksz, nbits);
return 0;
}
ADI-capable bir M7-sınıfı makinede beklenen:
Bir bölgeyi enable etme ve tag'leme (Linux modeli):
- Mapping'i
mprotect(addr, len, PROT_READ | PROT_WRITE | PROT_ADI)ile ADI-capable işaretleyin. Kernel, task içinPSTATE.mcde'yi ve TLB entry'lerindeTTE.mcd'yi set eder. - Aralıktaki her ADI block üzerinde iterate ederek, ASI
ASI_MCD_PRIMARY(veyaASI_MCD_ST_BLKINIT_PRIMARY) ilestxastore'unu kullanarak her 64-byte block'u seçilen bir version ile damgalayın. - Memory'ye, bit 63-60'ı o aynı version'ı encode eden bir virtual address
üzerinden erişin (ör. version
0xa→ top nibble'ında0xaolan adresler).
Solaris'te eşdeğer kontroller library/syscall tabanlıdır: memcntl(2) /
mmap(2) page'lerde ADI'yi enable eder, meminfo(2) ADI durumunu sorgular,
pmap(1) hangi mapping'lerin ADI açık olduğunu raporlar ve libadimalloc, her
malloc() chunk'ını otomatik olarak color'layan ADI-aware bir allocator'dır.
Data-transfer syscall'ları (read(), write(), copyin()/copyout(),
uiomove(), …) de version'ları onurlandırır ve uyuşmazlıkta hata döner.
Warning
Wildcard version'ları 0x0 ve 0xf, hassas bir pointer bir wildcard color'da
bırakılırsa korumayı yener ve 4-bit tag yalnızca 14 ayırt edilebilir
non-wildcard color demektir — bitişik allocation'lar şans eseri bir version'da
çakışabilir, bu yüzden ADI spatial safety için probabilistiktir, sert bir
bounds check değil.
Detection¶
Bir version uyuşmazlığı, process'e si_code == SEGV_ADIPERR (precise) veya
SEGV_ADIDERR (disrupting) ile SIGSEGV olarak ortaya çıkar; bir fault handler
veya fuzzer harness'i, crash'i sıradan bir page fault yerine ADI'ye atfetmek için
siginfo'yu inceleyebilir.