Skip to content

DirtyCred file exploitation

Free a writable kernel struct file object after its write-permission check has passed, then let the kernel reclaim the freed slot with a privileged read-only file — so a pending write lands in the privileged file. Data-only privilege escalation that needs no control-flow hijack or KASLR leak. (Here struct file is a file object, not a credential object; DirtyCred's broader class also targets the struct cred credential object, covered separately — this note is the file variant.)

Mechanism

Note

DirtyCred (Lin, Wu, Xing — ACM CCS 2022), object'lerin içeriğini bozmak yerine kernel credential object'lerini heap reuse yoluyla takas ederek privilege yükseltir. Hedeflenen object'ler cred ve file'dır (makale inode'u da sayar ama allocation esnekliği eksikliği nedeniyle dışlar). Bir dosya açıldıktan sonra kernel, credential/permission bilgisini inode'dan ayırır ve struct file'a iliştirir; file object'i read/write izin bit'lerini (f_mode) taşır ve arkadaki credential'lara index'ler. Exploit'in iddia ettiği üç özellik: data-only (KASLR/heap-leak gerekmez), universal (kernel/mimari bağımsız) ve effective (upstream mitigation'ları bypass eder).

File variant'ı bir heap bug'ını (UAF, double-free, type confusion) şu yeteneğe çevirir: write-permission kontrolü zaten geçmiş yazılabilir bir file'ı free etmek, sonra o slab slot'unu privileged read-only bir file ile reclaim etmek; böylece bekleyen bir write privileged dosyaya düşer. Hiçbir control flow değiştirilmediği ve hiçbir object içeriği forge edilmediği için CFI, credential-integrity kontrolleri (örneğin Knox RKP) ve type-tabanlı object isolation (AUTOSLAB, xMP) bunu durduramaz.

Permission kontrolü ile asıl data write arasındaki race window, bir kernel-pause primitive ile genişletilir: userfaultfd, FUSE-destekli bir kaynak buffer veya — modern kernel'lerde en sağlam yöntem — yarışan büyük bir write tarafından tutulan filesystem inode lock.

Walkthrough

Klasik gösterim (makale Figure 1) CVE-2021-4154'ü kullanır; bu, kullanımda olan bir file object'ini free eden bir fs_context type confusion'dır. Referans exploit (Markakd/CVE-2021-4154) inode-lock variant'ını userfaultfd olmadan kullanır:

// THREAD A: hold the inode lock with a slow, large write
int fd_big = open("/tmp/x", O_WRONLY);
write(fd_big, big_buf, 4UL*1024*1024*1024);   // holds inode_lock ~dozens of seconds

// THREAD B: victim writable file object — open via a SYMLINK so the file lacks
//           FMODE_ATOMIC_POS (avoids the __fdget_pos position-lock stall)
int fd = open("/tmp/x_symlink", O_WRONLY);    // struct file allocated in filp_cache
write(fd, payload, len);                       // passes FMODE_WRITE check, then blocks
                                               // on inode_lock — this is the race window

// THREAD C: during B's lock-wait, free B's struct file and reclaim the slot
trigger_fsconfig_uaf();                        // CVE-2021-4154 frees B's struct file
int p = open("/etc/passwd", O_RDONLY);         // reclaims the freed filp_cache slot

// THREAD A finishes -> releases inode_lock -> THREAD B's write lands in /etc/passwd
// payload e.g. "hacker:x:0:0:root:/:/bin/sh\n"  -> a root account

Warning

struct file kendi özel slab cache'inde yaşar (filp_cache, sembol filp_cachep); CVE-2021-4154 örneğinde bu object'ler kmalloc-192'ye düşer. Yukarıdaki pseudo-code doğrulanmış adımları temsil eder, exploit'in birebir kopyası değildir. f_mode/FMODE_WRITE/FMODE_ATOMIC_POS dışındaki alan adları standart kernel bilgisidir, makaleden birebir değildir.

Beklenen sonuç: /etc/passwd'ye bir uid=0 satırı eklemek root bir login shell verir (örneğin su hacker), ve bunu hiçbir kernel pointer leak'lemeden yaparak escalation'ı gösterir.

Mitigation

Makale privilege-tabanlı isolation önerir: privileged object'leri (root cred, yazılabilir file) vmalloc bölgesine yerleştirip unprivileged object'leri direct-mapped kmalloc bölgesinde tutmak; böylece ikisi asla geri dönüştürülmüş page'leri paylaşmaz — cross-cache page-reuse pivot'unu etkisizleştirir. PoC patch'i (CONFIG_CRED_ISOLATION) write-mode dosyaları vzalloc() üzerinden yönlendirir ve kvfree() ile free eder. Upstream bunu benimsemedi, ama ilgili hardening eğilimi — 5.14'ten beri accounted ve unaccounted object'ler için ayrı slab cache'ler (kmalloc-cg-*) — spray yüzeyini daraltır.

References