Skip to content

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 sondaki flags member'ı.

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 (local minfo); sızdıran field: minfo.flags.
  • Fix, kopyadan önce field'ı yalnızca zero-initialize eder:
minfo.flags = 0;

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.

References