Skip to content

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 / bts metotları): 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.

References