PaX KERNEXEC¶
Kernel içinde W^X'i uygulayan PaX/grsecurity mekanizması: kernel data'sı asla executable değildir ve kritik kernel yapıları read-only'dir, böylece bir kernel write primitive'i data'yı koda çeviremez.
Mechanism¶
Note
KERNEXEC, kernel tarafı W^X (write XOR execute) invariant'ını uygular: "kernel memory must never be executable [where it is writable], and no W^X violations can occur within kernel space." Userland için NX/DEP'in kernel-içi karşılığıdır. Amaç klasik "bir kernel data page'ine shellcode yaz, sonra ona atla" adımını reddetmektir: her writable kernel page'i non-executable ve her executable kernel page'i read-only ise, bir kernel write primitive'ine sahip bir saldırganın enjekte edilmiş kodu yerleştirip çalıştıracak yeri yoktur. KERNEXEC ayrıca control flow'u belirleyen yapıları da sertleştirir — "syscall table, IDT, GDT, [and] page tables read-only" yaparak — böylece bunlar bir jump table'a yeniden yazılamazlar.
KERNEXEC, hardware SMEP'ten ve upstream CONFIG_STRICT_KERNEL_RWX W^X
enforcement'ından önce gelir ve onlarla örtüşür; ilgili hardware bitinden yoksun
CPU'larda bile garantiyi sağlar ve onu, stok kernel'lerin tarihsel olarak writable
bıraktığı table'lara genişletir.
Walkthrough¶
Implementasyon mimariye göre değişir (PaX belgelerine göre):
- i386: "code segment limit excluding userland" kullanır — kernel code segment'i, userland (ve non-text kernel) adresleri onun dışına düşecek ve supervisor mode'dan execute edilemeyecek şekilde boyutlandırılır. Bu, segment limit'lerinin hâlâ dikkate alındığı 32-bit x86'da mevcut bir segmentation numarasıdır.
- amd64: segment limit'leri uygulanmaz, bu yüzden KERNEXEC "function pointer /
return address handling" için bir compiler plugin'ine (PaX'in ayrı KERNEXEC
gcc plugin'i) artı paging'e dayanır. Bu plugin, indirect call/return call site'larını
instrument ederek function pointer'ların ve return address'lerin high bit'ini set
eder (
or/btsmetotları): userland'e yönlendirilmiş corrupt bir pointer, supervisor mode'da execute edilemeyen non-canonical (fault veren) bir adrese düşer. Bunun amacı hedefi kernel-space üst-yarısına kilitlemektir; kalıcı bir CFI hesap defteri tutan ayrı RAP mekanizmasıyla karıştırılmamalıdır — KERNEXEC plugin'i backward-edge CFI değil, W^X invariant'ının amd64 tarafındaki enforcement'ıdır. Paging tarafında ise data page'leri NX işaretlenir ve yukarıdaki hassas table'lar read-only yapılır.
Temsili korunan küme (belgeden): syscall table, IDT, GDT, page table'lar read-only yapılır; data page'leri non-executable işaretlenir.
# conceptual outcome KERNEXEC guarantees
kernel .text : r-x , read-only (cannot be made writable from a stray write)
kernel data : rw- , NX (cannot be executed even if attacker writes it)
IDT/GDT/pgd : r-- , read-only (cannot be rewritten into a control table)
PaX-hardened bir kernel'in bunu etkin edip etmediğini kontrol etmek için
savunucular kernel konfigürasyonunu ve PaX/KERNEXEC initialization mesajları için
boot dmesg'ini inceler (kesin string'ler grsecurity/PaX revizyonuna bağlıdır;
belirli banner metnini, build'inize karşı doğrulanmadıkça unverified olarak ele
alın).
Mitigation¶
KERNEXEC kendisi bir mitigation'dır. Upstream'e göre,
CONFIG_STRICT_KERNEL_RWX (kernel W^X) ile birleşmiş
SMEP'e (user page'lerinin supervisor
execution'ı yok) karşılık gelir, ama control table'larının read-only korumasını
ekler ve hardware özelliği olmadan çalışır. User/kernel ayrımının data-erişim
tarafını kapsayan PaX UDEREF ile eşleşir ve page table'larının
kendisini read-only tutarak page-table manipulation'a
karşı doğrudan çıtayı yükseltir.