Skip to content

Malicious filesystem image mount attack surface

Attacker-crafted bir filesystem image'i mount etmek, in-kernel on-disk parser'ı hostile superblock/inode/extent metadata'sı üzerinde çalıştırır — userns + FUSE/loop ve removable-media automount ile unprivileged erişilebilen, syzkaller'ın sürekli beslediği yoğun bir ring0 bug kaynağı.

Mechanism

Her filesystem driver, on-disk structure'ları (superblock, block/inode bitmap, directory entry, B-tree/extent node, journal) parse eden bir kod yolu içerir. Bu kod tarihsel olarak güvenilen bir invariant üzerine yazıldı: "disk'teki metadata, kendi mkfs'imizin ürettiği geçerli bir image'dir." Bir image attacker tarafından craft edildiğinde o invariant düşer ve length/offset/count field'ları artık trust edilemez.

Note

Bug class'ı şudur: on-disk'ten okunan bir değer (bir key length, bir extent count, bir directory record boyu, bir bitmap index) sonraki bir memory işlemini boyutlandırmak/indexlemek için kullanılır ama allocation sınırına, blok boyutuna ya da array cap'ine karşı validate edilmez. Sonuç OOB read/write, UAF ve integer overflow'dur — hepsi ring0'da, çünkü parser fully privileged kernel context'inde koşar. Boundary "untrusted disk data → trusted kernel struct" sınırında geçilir; kernel'in her hfs_bnode_read_u16(), le32_to_cpu(ext->count) çağrısı bir trust-boundary crossing'idir.

Warning

Kritik nokta kim mount edebilir'dir. Klasik varsayım "image mount etmek CAP_SYS_ADMIN ister, yani local + privileged, yani düşük risk"tir. İki gelişme bunu bozar: (1) unprivileged user namespace içinde bir process kendi userns'inde CAP_SYS_ADMIN kazanır ve FUSE gibi bazı filesystem'leri userns'ten mount edebilir; (2) desktop automount (udisks2 + polkit) console user'ının takılan removable media'yı initial namespace'te explicit CAP_SYS_ADMIN tutmadan mount etmesine izin verir. Böylece "physical access / privileged" varsayımı, "USB tak" ya da "unprivileged process"e iner.

Neden bu surface bu kadar yoğun: syzkaller/syzbot mounted image'leri iki boyutta fuzz'lar — hem image byte'larını hem de mount sonrası syscall'ları mutate eder. Nadir/legacy parser'lar (hfs+, hfs, udf, f2fs, ntfs3, jfs, reiserfs, ufs, squashfs, minix) az test edilmiş fakat build'lerde enabled kaldığı için düşük asılı meyve olur.

Walkthrough

Kavramsal reprodüksiyon; herhangi bir parser bug'ı için ortak iskelet (concrete örnek: HFS+ CVE-2025-0927, ayrıca bkz. sibling not):

  1. Surface seç. Hedef distro'da mount edilebilen ama az test edilmiş bir filesystem type seç (nadir on-disk format = daha zayıf validation).
  2. Image craft et. Geçerli bir base image'i mkfs ile üret, sonra tek bir metadata field'ı hedefle: bir key/record length'i, bir extent/entry count'unu ya da bir offset'i allocation'ı aşacak şekilde patch'le. Amaç parser'ın early sanity check'lerini geçip vulnerable read/copy'ye ulaşmaktır.
  3. Mount tetikle. Image'i loop device üzerinden mount et, ya da automount tetiklesin diye media tak, ya da uygun tipse userns + FUSE üzerinden mount et. Mount sırasında superblock/tree parse çalışır ve hostile field consume edilir.
  4. Boundary cross. Unvalidated field OOB write/read ya da UAF'e dönüşür. Bu tek başına bir memory-corruption primitive'idir; onu LPE'ye çevirmek image bug'ından bağımsız, standart slab/heap exploitation'dır ve bu katalogda ayrı tutulur.
Kavramsal fragment — validate edilmeyen on-disk length

/* parser bir on-disk u16/u32'yi doğrudan trust ediyor */
len = le16_to_cpu(rec->key_len);      /* attacker-controlled */
memcpy(kbuf, rec->key, len);          /* kbuf sabit boyutlu → OOB write */

/* güvenli hali: cap'e karşı clamp */
if (len > tree->max_key_len)           /* eksik olan check budur */
    return -EIO;
Gerçek bug'larda pattern aynıdır; sadece field ve struct değişir (extent count, dir reclen, bitmap index...).

Detection

  • KASAN / KFENCE: debug kernel'de bug tam olarak parser fonksiyonunda patlar (*_read_key, *_bread, ext4_*, ntfs_*), slab-out-of-bounds ya da use-after-free olarak. syzbot report'ları bu imzayı taşır.
  • Mount telemetry: untrusted/removable bir source'un nadir bir filesystem type ile mount edilmesi gözlemlenebilir bir olaydır. auditd ile mount syscall'ını ve fstype'ı logla; udisks2/systemd-udevd automount event'lerini izle; beklenmedik fstype=hfsplus|udf|jfs|... bir sinyaldir.
  • Crash pattern: removable media insertion ya da unprivileged mount denemesiyle korele olan kernel oops/panic (özellikle bir fs modülünün ilk kez load olması).
  • Module load: normalde hiç kullanılmayan bir filesystem modülünün (modprobe hfsplus) autoload edilmesi; /proc/modules ve module autoload audit'i bunu yakalar.

Mitigation

  • Nadir filesystem'leri kaldır/blokla. İhtiyaç duyulmayan on-disk parser'ları autoload edilemez yap: install <fs> /bin/false ya da blacklist <fs> (/etc/modprobe.d/). CIS benchmark'ları tam da bunu önerir (cramfs, freevxfs, hfs, hfsplus, jffs2, squashfs, udf...). Build kontrolün varsa ilgili CONFIG_*_FS'i tamamen disable et.
  • Automount'u kıs. udisks2/polkit removable-media mount policy'sini bir allow-list'e daralt; kiosk/server rollerinde automount'u kapat. Air-gapped transfer host'larında image'i mount etmeden, userspace tool ile parse et.
  • userns'i hardening'le. Gerekmiyorsa unprivileged user namespace'i kapat (kernel.unprivileged_userns_clone=0 Debian/Ubuntu'da, ya da user.max_user_namespaces=0); AppArmor userns mediation kullan. Bu, userns+FUSE üzerinden ulaşılabilen parser surface'ini keser.
  • seccomp / sandbox. Container ve sandbox profillerinde mount/move_mount/fsopen/fsconfig syscall'larını blokla; böylece process kendi image'ini mount ettiremez.
  • Patch + fuzz-hardening. Distro kernel'lerini güncel tut; syzbot'un mounted-image bug'ları için üretilen fix'ler hızlı akar. Maintainer'lar (örn. XFS) fstests içinde image-fuzzing suite tutarak parser'ları proaktif sertleştiriyor — LWN'deki responsible-disclosure tartışması bu trade-off'u özetler.

References