Skip to content

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_releaseunix_release_sockunix_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:

  1. io_uring ile writable bir temporary file register et ve ona karşı bir IORING_OP_WRITEV çağır.
  2. unix_gc'yi tetikle (ilgili AF_UNIX socket'i kapatarak) ki registered struct file request ortasında free edilsin.
  3. Read-only bir file (örn. /etc/passwd) aç; free edilen filp slot'u read-only file'ın struct file'ı tarafından reclaim edilir.
  4. 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_iter path'inde inode_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.

References