Skip to content

Strict kernel RWX (no W+X mappings)

Kernel space'te W^X'i zorunlu kılar: text/rodata read-only map'lenir, tüm data non-executable map'lenir, böylece hiçbir kernel page aynı anda writable ve executable olmaz.

Mechanism

CONFIG_STRICT_KERNEL_RWX ve CONFIG_STRICT_MODULE_RWX, kernel'in kendi memory region'larına ayrı, minimal permission'lar uygulamasını sağlar: kernel/module text'i read-only + executable (RO+X) olur, rodata read-only + non-exec olur ve sıradan data read-write + non-executable (RW+NX) olur. Aynı prensip module text/rodata'sına ve diğer executable region'lara (JIT page'leri vb.) uzanır.

Neden işe yarar

Code-injection ve birçok code-reuse kurulumu, hem writable (instruction'ları yerleştirmek ya da yeniden yazmak için) hem executable (onları çalıştırmak için) bir page'e ihtiyaç duyar. Kernel dokümantasyonu amacı doğrudan belirtir: code writable değildir, data executable değildir ve read-only data ne writable ne executable'dır. Bu, ring 0'a uygulanan W^X invariant'ıdır ("write XOR execute"): her mapping için W ve X bit'leri asla birlikte set edilmez. Bir saldırgan bir kernel write primitive'i elde ederse, RO+X text mevcut code'u yerinde patch'leyemeyeceği anlamına gelir; RW+NX data ise yazabileceği bir buffer'a branch edilip onun execute edilemeyeceği anlamına gelir. Koruma yapısaldır — belirli bir exploit'i tespit etmek yerine yeteneği kaldırır — dolayısıyla tüm "kernel memory'ye yaz, sonra onu execute et" saldırı sınıfı için çıtayı yükseltir ve düşmanları bunun yerine saf ROP/JOP'a ya da page-table manipulation'a iter.

Permission'lar architecture set_memory_ro/_rw/_x/_nx API'si üzerinden kurulur (module'ler için, kernel/module/strict_rwx.c'deki module_enable_* helper'ları, örn. module_enable_text_rox). Kernel invariant'ı runtime'da, bir W+X mapping check'i gerçekleştiren page-table dumper'ı (ptdump) üzerinden doğrulayabilir.

Walkthrough

Seçeneklerin etkin olduğunu doğrula:

grep -E 'STRICT_(KERNEL|MODULE)_RWX' /boot/config-$(uname -r)
# CONFIG_STRICT_KERNEL_RWX=y
# CONFIG_STRICT_MODULE_RWX=y

Boot'ta W+X self-check'i çalıştıran kernel'lerde, dmesg sonucu raporlar:

dmesg | grep -i 'w+x'
# Checked W+X mappings: passed, no W+X pages found
ptdump üzerinden page-table permission'larını incelemek

CONFIG_PTDUMP_DEBUGFS (eskiden CONFIG_X86_PTDUMP / arm karşılıkları) ve debugfs mount edilmişken, kernel page table'larını açar:

mount -t debugfs none /sys/kernel/debug   # if not already mounted
cat /sys/kernel/debug/kernel_page_tables  # x86; arm64: kernel_page_tables

Her region kendi flag'lerini yazar. Sağlıklı çıktı, text aralıklarını ro ... x ve data aralıklarını RW ... NX olarak gösterir — asla hem RW hem executable olan bir aralık olmaz. Runtime checker ptdump_check_wx() bu table'ları walk eder ve "Checked W+X mappings" verdict'ini üreten şeydir.

Uyarılar

  • Self-modifying makineler için — instruction alternative'leri, breakpoint'ler, kprobe'lar — kernel'in update sırasında bir page'i geçici olarak writable yapıp sonra orijinal permission'ları geri yüklediği kısa, kontrollü istisnalar vardır. Bunlar dar pencerelerdir, kalıcı W+X mapping'leri değil.
  • Çoğu architecture'da bu seçenekler zorla açıktır ve user-selectable değildir; help metni ve default'lar arch'a göre değişir.

Detection

Boot-time ptdump_check_wx() verdict'i ("Checked W+X mappings: passed") ve /sys/kernel/debug/kernel_page_tables dump'ı, kalıcı W+X kernel page'i olmadığını doğrulamanın kanonik yollarıdır. Bir failure çıktısı sorunlu aralıkları listeler.

Mitigation

Residual risk / nasıl bypass edildiği:

References

  • Linux kernel docs, "Kernel Self-Protection" (Executable Memory — CONFIG_STRICT_KERNEL_RWX / CONFIG_STRICT_MODULE_RWX): https://docs.kernel.org/security/self-protection.html
  • Linux Kernel Driver DataBase, CONFIG_STRICT_KERNEL_RWX: https://cateee.net/lkddb/web-lkddb/STRICT_KERNEL_RWX.html
  • Linux Kernel Driver DataBase, CONFIG_STRICT_MODULE_RWX: https://cateee.net/lkddb/web-lkddb/STRICT_MODULE_RWX.html