Skip to content

Hashed kernel pointers (%p hashing)

Linux 4.15'ten beri %p printf specifier'ı kernel pointer'larını SipHash ile hash'ler; böylece ham kernel address'leri log, sysfs veya procfs üzerinden leak olmaz; gerçek bir address yazmak için %px kullanılmalıdır.

Mechanism

Note

Invariant: süssüz herhangi bir %p artık gerçek bir kernel address yaymaz. lib/vsprintf.c, düz %p'yi pointer değerini rastgele üretilmiş, per-boot bir key (ptr_key) ile key'lenen SipHash üzerinden geçiren ptr_to_id() üzerinden yönlendirir. Pointer yerine 32-bit sonuç yazılır, böylece kernel çıktısını okuyan bir attacker kernel memory layout'unu geri kazanamaz (bir info-leak / KASLR-bypass primitive'ini yenerek). Gerçek address'i yazmak artık açık, greppable bir specifier (%px) gerektirir.

Tobin C. Harding'in commit'inden (Kees Cook tarafından önerildi) gelen motivasyon, süssüz %p ile address yazan kabaca 14.000 site olmasıydı. Her birini audit etmek yerine default değiştirildi, böylece %p güvenli oldu ve gerçekten ham bir address'e ihtiyacı olan kod %px ile opt-in yapıyor.

64-bit sistemlerde hash'in üst 32 bit'i sıfırlanır. Key'i seed etmek için yeterli randomness mevcut olmadan önce, %p tahmin edilebilir bir değer yerine (ptrval) placeholder'ını yazar.

Warning

%px, %lx ile fonksiyonel olarak eşdeğerdir ve ham address'i hashing olmadan yazar. Onu yalnızca değerin hassas kernel memory layout'unu unprivileged okuyuculara expose edemeyeceğini doğruladıktan sonra kullan. %pK, kptr_restrict sysctl'i ile gate'lenmiş ayrı bir mekanizmadır ve yalnızca userspace-okunabilir dosyalar (procfs/sysfs) için tasarlanmıştır, kernel log'ları için değil.

Walkthrough

Observe hashing in dmesg

Düz bir %p yazımı, bir address değil boot başına sabit bir hash verir:

$ dmesg | grep -i 'some pointer'
... ptr = 000000005e1b8f3a

Aynı değer %px ile yazılsa gerçek kernel virtual address'ini gösterirdi (ör. ffffffff81a0c2e0).

Hashing'i debugging için, her %p'nin address'i değiştirmeden yazmasını sağlayan belgelenmiş kernel parametresiyle boot ederek devre dışı bırak:

no_hash_pointers

no_hash_pointers ile reboot'tan sonra %p çıktısı %px çıktısıyla eşleşir. Parametre yalnızca debugging için tasarlanmıştır ve kernel'in artık address leak ettiğine dair bir warning yazar.

Detection

Bir %p değerini iki boot arasında karşılaştır: hashing aktifse yazılan değer her boot'ta değişir (yeni rastgele ptr_key); makul bir ffffffff... kernel address'i olan bir değer %px, no_hash_pointers veya weak-hash debug build'ini gösterir.

Mitigation

%p hashing, ASLR bypass'larını besleyen pointer leak'lerine karşı bir defense-in-depth önlemidir; kptr_restrict, dmesg_restrict ve kallsyms address restriction'ı tamamlar. Kasıtlı %px kullanımı veya diğer side channel'lar üzerinden leak'leri durdurmaz — bkz. info-leak / pointer-leak / ASLR bypass.

References