Stack infoleak to kernel-pointer leak (CVE-2016-5244)¶
Bir kernel routine'i, stack'te yerleşik bir struct'ı field'larından birini initialize etmeden userspace'e kopyalar ve stale kernel-stack byte'larını sızdırır — burada RDS subsystem'indeki
struct rds_info_message'ın sondakiflagsmember'ı.
Mechanism¶
Note
Bu, bir uninitialized-stack-memory information leak'idir. Bir kernel routine'i, stack'inde
sabit-layout'lu bir yapı kurar ve onu userspace'e kopyalar, ama her field'ı (padding dahil)
initialize etmez. İhlal edilen invariant şudur: kernel→user sınırını geçen bir yapının her
byte'ı açıkça initialize edilmelidir. Kernel'in per-thread stack'i syscall'lar arasında
yeniden kullanıldığı ve varsayılan olarak sıfırlanmadığı için, uninitialized field önceki bir
çağrının orada bıraktığı her ne ise onu tutar. Tek bir sızdırılmış byte/field bile kernel
verisini açığa çıkarmaya yeter; stack grooming'le zincirlendiğinde kernel pointer'larını
sızdırabilir ve KASLR'yi yenebilir. CVE-2016-5244'te RDS (Reliable Datagram Sockets) info
path'i, stack'te bir struct rds_info_message minfo kurar ve onu sondaki flags
member'ı set edilmeden kopyalar.
Walkthrough¶
- Dosya:
net/rds/recv.c; fonksiyon:rds_inc_info_copy; struct:struct rds_info_message(localminfo); sızdıran field:minfo.flags. - Fix, kopyadan önce field'ı yalnızca zero-initialize eder:
Upstream commit mesajı şunu belirtir: "The last field 'flags' of object 'minfo' is not initialized. Copying this object out may leak kernel stack data. Assign 0 to it to avoid leak." Kangjie Lu tarafından yazıldı, David S. Miller tarafından commit edildi.
Yakından ilişkili bir takip, daha sonra IPv6 variant'ını düzeltti — net/rds: Fix info leak in
rds6_inc_info_copy() — aynı bug sınıfı.
Warning
Etkilenen: 4.6.3'e kadar Linux; commit 4116def2337991b39919f3b448326e21c40e0dbb ile
fix'lendi (mainline artı stable backport'ları).
Detection¶
Bu sınıf için yapılmış static/dynamic analyzer'lar bunu doğrudan bulur — örn. UniSan (uninitialized-data leak'leri için bir compiler sanitizer) ve uninitialized stack variable'larından kernel pointer'ları sızdırmaya dair WOOT'20 çalışması, uninitialized member'larla userspace'e kopyalanan struct'ları işaretler.
Mitigation¶
- Compiler auto-initialization —
CONFIG_INIT_STACK_ALL_ZERO/-ftrivial-auto-var-init=zero— ve structleak plugin'i (CONFIG_GCC_PLUGIN_STRUCTLEAK), bu tür stack struct'larını generic olarak sıfırlar ve bu leak'i etkisiz kılardı. - Canonical fix, kopyadan önce açık field initialization'ıdır.