io_uring DirtyCred UAF (CVE-2022-2602)¶
io_uring registered file'ları ile AF_UNIX SCM garbage collector'ı arasındaki bir race, io_uring'in hâlâ kullandığı bir
struct file'ı free eder ve DirtyCred file exploitation ile root'a dönüştürülen bir UAF verir.
Mechanism¶
io_uring, bir uygulamanın context'inde IORING_REGISTER_FILES ile file descriptor'ları register etmesine izin verir. Bu io_uring fd'leri kendileri bir AF_UNIX socket üzerinden geçirildiğinde, kernel'in SCM garbage collector'ına (unix_gc) tabi olurlar; bu collector erişilemeyen file referanslarını reclaim eder.
Note
UAF, bir io_uring request bir registered file üzerinde işlenirken unix_gc eşzamanlı çalıştığında ve io_uring fd'sini ve register edilen struct file object'lerini in-flight request'in altından free ettiğinde gerçekleşir. Cleanup path'i unix_release → unix_release_sock → unix_gc çalıştırır. Free edilen object, filp cache'inden bir struct file'dır.
Warning
Bir file üzerindeki permission, write path execute olmadan önce bir kez kontrol edilir. Kernel'i o check ile gerçek write arasında tutarak, bir attacker kontrol edilen file'ın free edilip değiştirilmesini sağlayabilir — DirtyCred'in temeli.
Walkthrough¶
DirtyCred file exploitation'ı io_uring UAF'ına uygulamak:
- io_uring ile writable bir temporary file register et ve ona karşı bir
IORING_OP_WRITEVçağır. unix_gc'yi tetikle (ilgili AF_UNIX socket'i kapatarak) ki registeredstruct filerequest ortasında free edilsin.- Read-only bir file (örn.
/etc/passwd) aç; free edilenfilpslot'u read-only file'ınstruct file'ı tarafından reclaim edilir. - Permission'ı orijinal writable file'a karşı doğrulanmış olan in-flight write, artık read-only file'a karşı execute olur — onun üzerinden yazar. File locking (
ext4_buffered_write_iterpath'indeinode_lock) kernel thread'ini permission doğrulaması ile write execution'ı arasında duraklatmak için kullanılır.
Thadeu Lima de Souza Cascardo tarafından keşfedildi; "vulnerability, bir io_uring request bir registered file üzerinde işlenirken ve Unix GC çalışıp io_uring fd'sini ve tüm registered fd'leri free ettiğinde gerçekleşen bir use-after-free'dir." Fix, Unix GC'nin io_uring registered file'larını yok saymasını sağlar.
Race-window timeline (conceptual — sıralama yaklaşıktır, kernel'e göre değişir):
io_uring write thread unix_gc thread (AF_UNIX close)
───────────────────── ──────────────────────────────
IORING_OP_WRITEV başlar
permission check .
(writable file'a karşı OK) .
| .
inode_lock üzerinde DURAKLAR ──────┤ unix_gc registered file'ı
(write henüz execute olmadı) | free eder ──┐
| . (struct file → filp cache)
| . │
| attacker open("/etc/passwd", O_RDONLY) ─────────┘ reclaim aynı slot
| │
inode_lock devam eder ◄───────────────────────────────────┘
write EXECUTE olur
→ ama artık read-only file'ın struct file'ına yazar
Anahtar nokta: permission check ile gerçek write arasındaki pencerede aynı struct file slot'u free edilip yeniden tahsis edildiği için, doğrulanan object ile yazılan object farklıdır (DirtyCred'in çekirdeği).
Detection¶
KASAN, unix_gc sırasında io_uring submission path'inde bir struct file üzerinde bir use-after-free raporlar. Etkilenen kernel'ler 6.0.19'a kadar çalışır.
Mitigation¶
Düzeltilmiş bir kernel'e güncelle; patch garbage collector'ın hâlâ io_uring tarafından referans verilen file'ları free etmesini engeller. Fix commit 0091bfc81741b8d3aeb3b7ab8636f911b2de6e80 ("io_uring/af_unix: defer registered files gc to io_uring release"), 6.1-rc1'de; distro backport'ları (Ubuntu USN-5691/5692/5693/5700/5752). Unprivileged user'lar için io_uring'i disable etmek (yeni kernel'lerde /proc/sys/kernel/io_uring_disabled) attack surface'i kaldırır. Generic DirtyCred hardening (privileged file object'lerini izole etmek) dönüştürme adımını köreltir.