Branch Target Identification (BTI)¶
Guarded page'lerdeki indirect branch'leri yalnızca bir
BTI"landing pad"e inmeye zorlayan ve jump-oriented programming'i kıran ARMv8.5-A control-flow integrity.
Mechanism¶
Note
JOP (jump-oriented programming), fonksiyonların ortasına jump etmek için
indirect branch'leri (BR, BLR) suistimal ederek gadget'lar zincirler.
BTI şu invariant'ı enforce eder: guarded bir page'e yapılan bir indirect
branch açık bir landing-pad instruction'ına inmelidir — aksi halde CPU
fault verir. Bu, legal indirect-branch target setini küçük, compiler
tarafından yerleştirilmiş bir sete daraltır.
ARMv8.5-A, 2-bit'lik bir processor-state field olan PSTATE.BTYPE'ı
(bit'ler PSTATE[11:10]) ekler. Bir indirect branch execute ettiğinde,
hardware BTYPE'ı branch türüne göre ayarlar. Page'ler translation table'da
bir Guarded Page (GP) attribute taşıyabilir (Linux'ta stage-1 descriptor'da
PTE_GP = 1 << 50). Guarded bir bölge içinde,
PSTATE.BTYPE != 0b00 iken, uyumlu bir landing pad dışında her instruction
bir Branch Target Exception üretir. Arm A64 ISA'nın Branch Target
Exception üretmediğini belgelediği instruction seti BRK, BTI, HLT,
PACIASP ve PACIBSP'dir; fakat legitimate forward-edge landing pad rolünü
yalnızca BTI (variant'ları c, j, jc) ile call-tarafında PACIASP /
PACIBSP üstlenir — BRK ve HLT bu listede yer alır çünkü kendi debug /
halt exception'larını üretirler, code-flow landing pad'i değildirler. Guarded
bir bölge dışındaki (veya BTYPE == 0b00 olan) bir BTI instruction'ı NOP
olarak execute eder.
BTI instruction'ı, hangi branch türlerini kabul ettiğini kontrol eden,
BTYPE ile eşleştirilen bir target class operand'ı alır:
| BTYPE | anlamı | izin verilen landing instruction'ları |
|---|---|---|
| 0b00 | branch değil | herhangi bir instruction |
| 0b01 | jc |
BTI jc, BTI j, BTI c, PACIxSP |
| 0b10 | c (call) |
BTI jc, BTI c, PACIxSP |
| 0b11 | j (jump) |
BTI jc, BTI j |
Uyumlu bir landing pad check'i temizler ve execution'ın devam etmesine izin
verir; başka her şey Branch Target Exception'ı tetikler. Pointer
Authentication ile birleştiğinde, PACIASP aynı zamanda bir call landing pad
görevi görür, dolayısıyla PAC+BTI birlikte return ve forward edge'leri kapsar.
Walkthrough¶
Branch protection ile derle ve üretilen landing pad'leri incele:
$ aarch64-linux-gnu-gcc -mbranch-protection=bti -c foo.c -o foo.o
$ aarch64-linux-gnu-objdump -d foo.o | head
0000000000000000 <foo>:
0: d503245f bti c # call landing pad at function entry
4: ...
-mbranch-protection=standard, bti artı PAC return-address signing'i enable
eder. Toolchain ayrıca bir ELF note (GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
üretir ki loader object'in BTI-clean olduğunu bilsin:
Linux'ta guarded page'ler map zamanında talep edilir. Kernel, bir page
PROT_BTI ile map edildiğinde GP attribute'unu ayarlar; dynamic linker bunu
BTI-marked ELF object'lerin executable segment'lerine uygular:
Bir indirect branch guarded bir page'de bir non-landing-pad instruction'ına
indiğinde, kernel Branch Target Exception'ı (Linux EC ESR_ELx_EC_BTI = 0x0D)
si_code == ILL_BTCFI ile SIGILL olarak teslim eder:
Program terminated with signal SIGILL, Illegal instruction.
# si_code = ILL_BTCFI (BTYPE mismatch on indirect branch)
Warning
BTI yalnızca guarded page'lere yapılan, valid landing pad'leri olan
indirect branch'leri kısıtlar. PROT_BTI taşımayan bir page, tesadüfen
legitimate bir BTI c entry'si olan bir JOP target'ı veya bir direct
branch üzerinden erişilebilen code kısıtlanmaz. BTI, JOP'un maliyetini
yükseltir; tam bir CFI çözümü değildir ve Pointer Authentication ile
eşleştiğinde en güçlüdür.
Detection¶
- Bir binary'nin ve library'lerinin gerçekten landing pad'lerle build edildiğini
doğrulamak için ELF note'larını (
readelf -n) AArch64 BTI feature bit'i için incele. - CPU'nun BTI advertise ettiğini doğrula:
grep -o bti /proc/cpuinfo(HWCAP2_BTI). ILL_BTCFIile birSIGILL, bir indirect branch'in illegal bir target'a isabet ettiğini gösterir — runtime'da denenmiş bir JOP-tarzı hijack'in güçlü bir sinyali.