Skip to content

kallsyms address restriction

/proc/kallsyms (ve /proc/modules) tarafından export edilen runtime adreslerini CAP_SYSLOG ve kptr_restrict arkasına al; böylece unprivileged okuyucular symbol isimlerini, adresleri sıfırlanmış halde görür.

Mechanism

Neden çalışır

/proc/kallsyms, her kernel ve module sembolünü <address> <type> <name> formatında canlı virtual address'iyle listeler. KASLR kernel text base'ini boot başına yalnızca bir kez randomize ettiği için tek bir gerçek symbol adresi tüm slide'ı geri kazandırır ve commit_creds / prepare_kernel_cred gibi privesc gadget'larını konumlandırır. Bu yüzden ham adresleri herhangi bir kullanıcıya export etmek KASLR'yi tamamen yener.

kallsyms address restriction şu invariant'ı zorunlu kılar: symbol→address haritası privileged'dir; unprivileged bir okuyucu isimleri görebilir ama adres olarak 0 görmek zorundadır. Adresler %pK specifier'ı ve kallsyms_show_value(cred) görünürlük predicate'i ile basılır; bu predicate kernel.kptr_restrict'i çağıranın capability'leriyle birleştirir:

  • kptr_restrict = 0: non-root bir okuyucu 0 alır, ama root gerçek adresleri görür (birçok distro'da default, çünkü isimlerin okunabilir kalması gerekir).
  • kptr_restrict = 1: adresler yalnızca CAP_SYSLOG'a sahip ve euid==ruid, egid==rgid olan çağıranlara gösterilir (örn. root ya da sudo ile çalışan process'ler); privilege separation ile açılan (effective/real credential'ları uyuşmayan) bir process CAP_SYSLOG taşısa bile 0 görür.
  • kptr_restrict = 2: adresler herkes için, root dahil, sıfırlanır.

Kritik olan, predicate'in open()'da değil, read() anında okuyan task'ın credential'larına karşı değerlendirilmesidir; yani dosyayı root olarak açıp descriptor'ı adres sızdırmak için unprivileged bir process'e veremezsin. Aynı kallsyms_show_value() gate'i /proc/modules'ü ve symbol taşıyan birkaç başka interface'i de kapsar.

Walkthrough

1. Privileged ve unprivileged okumaları karşılaştır.

$ id -u
1000
$ cat /proc/sys/kernel/kptr_restrict
1
$ grep -E ' (commit_creds|prepare_kernel_cred)$' /proc/kallsyms
0000000000000000 T commit_creds
0000000000000000 T prepare_kernel_cred

$ sudo grep -E ' (commit_creds|prepare_kernel_cred)$' /proc/kallsyms
ffffffff8a0b1d40 T commit_creds
ffffffff8a0b1a90 T prepare_kernel_cred

Satır formatı, boşlukla ayrılmış üç field'dır: <address> <type> <name>. Yalnızca adres sütunu redact edilir; symbol isimleri görünür kalır, böylece module araçları çalışmaya devam eder.

2. Aynı restriction /proc/modules için de geçerli.

$ cat /proc/modules | head -1            # unprivileged
nf_tables 327680 1 - Live 0x0000000000000000

$ sudo head -1 /proc/modules             # privileged
nf_tables 327680 1 - Live 0xffffffffc0a31000

3. Gate'i sıkılaştır. Address restriction kptr_restrict ile sürülür:

$ sudo sysctl -w kernel.kptr_restrict=1   # require CAP_SYSLOG to see addresses
$ sudo sysctl -w kernel.kptr_restrict=2   # zero addresses for everyone

Restriction adreslere yöneliktir, varlığa değil

Symbol isimleri her seviyede okunabilir kalır, yani bir fonksiyonun varlığı asla gizlenmez — yalnızca konumu gizlenir. CAP_SYSLOG tutan bir process (değer 1) yine de gerçek adresleri elde eder ve ilgisiz leak primitive'leri ya da side channel'lar bu ayardan bağımsız olarak slide'ı geri kazanabilir.

Detection

/proc/kallsyms ve /proc/modules'ün adres sütununun unprivileged çağıranlar için 0 okuyup okumadığını gözlemle ve sysctl kernel.kptr_restrict'i kontrol et. Hardening baseline'ları yaygın olarak kptr_restrict >= 1 ister.

Mitigation

(Residual risk / bypass.) Bu yalnızca kallsyms/modules symbol interface'lerini korur. Slide hâlâ adres sızdıran diğer %pK/%px sink'leri, dmesg, perf symbolization'ı, BPF ya da ../kernel/entrybleed-kpti-kaslr-bypass.md gibi microarchitectural KASLR oracle'ları üzerinden geri kazanılabilir; ayrıca bkz. ../kernel/proc-kallsyms-symbol-address-leak.md. Bu, daha geniş kptr-restrict politikasının kallsyms'e özgü uygulamasıdır.

References