Linux USB gadget / configfs attack surface¶
USB gadget subsystem'i iki yönlü bir ring0 attack surface'idir: configfs/functionfs ile bir gadget compose etme yolu (lifetime/refcount race'leri, teardown UAF'leri) ve host tarafında kötü niyetli bir device'ın descriptor/setup-packet parsing yolu — her ikisi de authentication'dan önce, düşük ayrıcalıkla erişilebilir.
Mechanism¶
Linux USB gadget subsystem'i bir host'un gördüğü USB device'ını yazılımda üretir. Bir gadget üç ayrı yerden sürülebilir: configfs üzerinden statik composition (/sys/kernel/config/usb_gadget/...), FunctionFS (f_fs) üzerinden userspace'in ep0'ı ve endpoint'leri beslediği fonksiyonlar ve Raw Gadget / Dummy HCD ile tamamen emüle edilmiş controller. Bir device UDC'ye bind edildiğinde host onu enumerate eder ve descriptor'ları parse eder.
Bu iki yol iki farklı bug sınıfı doğurur:
Note
İhlal edilen invariant iki katmanlıdır. (1) Host parsing tarafı: device'tan gelen bir bLength/wTotalLength/count/index alanına, gerçekte alınan buffer'a karşı asla güvenilmemeli — bozuk descriptor slab-out-of-bounds ve UAF verir (bkz. usb-descriptor-parsing-bug-class). (2) Gadget composition tarafı: configfs/functionfs, kernel object'lerinin lifetime'ını userspace tarafından sürülen mkdir/rmdir/symlink ve open/close olaylarına bağlar. Bir object'in refcount'u veya state machine'i (ör. ffs->opened, gadget config switch, UDC pullup) bu concurrent olaylar altında yanlış yönetilirse, teardown bir başka thread hâlâ pointer'ı tutarken belleği free eder — klasik lifetime UAF. Boundary şu yüzden aşılır: ayrıcalıksız kullanıcı-sürülen bir olay dizisi, ring0 object teardown'ının sıralamasını kontrol edebilir.
Warning
Descriptor-parsing tarafına fiziksel BadUSB, emüle bir gadget veya USB/IP ile ulaşılır; hiçbir credential gerekmez ve auto-bind eden bir victim'de kötü niyetli bir kablo doğrudan parser'a değer. Composition tarafındaki race'ler ise, gadget configfs/functionfs'e erişimi olan (containerize edilmiş ya da ADB/daemon aracılığıyla) local bir aktör için ulaşılabilirdir.
Somut, public ve yamalı örnekler:
- CVE-2022-50704 — "USB: gadget: Fix use-after-free during usb config switch": RNDIS'ten başka bir config'e geçerken hardware
->pullupcallback'i desteklemiyor ya da düşük olasılıklı bir fault ile fail ediyorsa,composite_disconnect→gether_disconnect→rndis_closeyolu free edilmiş belleğe dokunur ve panic/UAF üretir. Bug, teardown'ın hardware davranışından bağımsız olmasını sağlamamaktan kaynaklanır. - FunctionFS
ffs->openedopen/removal race:ffs->opened == 1(açık ep0) iken bir threadffs_data_opened()'dan önce preempt edilir; başka bir thread ep0'ı kapatır,->opened0'a düşer,ffs_data_clear()→ffs_epfiles_destroy()epfiles array'ini free eder. İlk thread'infile->private_data'sı artık free array'e bakar; open başarılı olur ve sonraki her read()/write()epfilepointer'ı üzerinden UAF olur.
Walkthrough¶
Yüksek seviyeli, kavramsal iki senaryo — public dökümana dayanır, silahlandırılmış zincir yok.
A. configfs ile bir gadget compose etme (host tarafını fuzz'a maruz bırakma):
# /sys/kernel/config/usb_gadget altında
mkdir g1 && cd g1
echo 0x1d6b > idVendor ; echo 0x0104 > idProduct
mkdir configs/c.1
mkdir functions/ffs.usb0 # ya da rndis.0 vb.
ln -s functions/ffs.usb0 configs/c.1/
echo <udc_name> > UDC # bind → host enumerate etmeye başlar
- functionfs seçilirse userspace, mount edilmiş
ffsüzerinden ep0'a descriptor + string tablosunuwrite()eder ve endpoint dosyalarını open eder; ep0'ı kapatmak/mount'u teardown etmek yukarıdaki lifetime race'lerini tetikleyebilen olaylardır. - Fuzzing kurulumunda gadget tarafı Raw Gadget + Dummy HCD ile emüle edilir; böylece host parser'ına donanımsız, tek kernel içinde bozuk descriptor sunulabilir.
B. Config switch teardown race'ini kavramsal olarak sergileme (CVE-2022-50704 sınıfı):
- Gadget'ı RNDIS içeren bir config ile bind et, host'un config'i seçmesini sağla.
- UDC pullup'ı fail eden ya da yavaşlatan bir durumda config'i switch/unbind et; teardown yolu (
rndis_close) devam ederken ilgili object free edilmişse UAF gözlenir.
KASAN'ın gadget teardown yolunda gösterdiği tipik iz
Detection¶
- Test/CI kernel'lerini
CONFIG_KASAN=y(+CONFIG_KFENCE=y) ile derle; USB reproducer'larını Raw Gadget + Dummy HCD üzerinde çalıştır. KASAN hem parser OOB/UAF'ini hem gadget teardown UAF'ini call trace ile gösterir. - Host tarafında USB authorization ve enumeration'ı denetle:
/sys/bus/usb/devices/usbN/authorized, beklenmedik device-class bind'leri, çok kısa aralıklı connect/disconnect (BadUSB / gadget spoofing sinyali). - Endpoint host'larında (Android/embedded) configfs/functionfs olaylarını izle: kısa süreli tekrar eden gadget bind/unbind ve UDC pullup fail'leri, teardown race'lerini tetiklemeye çalışan davranışın işareti olabilir.
- syzbot dashboard'unda USB/gadget bug akışını takip et; bu yüzeyden sürekli yeni raporlar gelir.
Mitigation¶
- Patch tut: CVE-2022-50704 gibi teardown UAF'leri upstream fix commit'leriyle kapatılır; stable kernel'e güncelle.
- FunctionFS open/removal race'i için fix, opener'ları
ffs->mutexüzerinde serialize eder, dynamic dosyalardaatomic_inc_not_zero()kullanır (0 ise fail) ve open'da state'inFFS_ACTIVEolduğunu ve inode'un removed işaretlenmediğini doğrular — yani refcount/state invariant'ını yeniden kurar. - Attack surface'i daralt: gadget subsystem'ini gerektirmeyen host'larda
CONFIG_USB_GADGET/functionfs/dummy_hcd modüllerini derleme ya da yükleme; container'lara configfs//dev/raw-gadgeterişimi verme. - Host tarafı:
CONFIG_USB_DEFAULT_AUTHORIZATION_MODE/ USBGuard ile bilinmeyen device'ları reddet, kullanılmayan class driver'ları disable et, USB port'larını kilitle; descriptor parser'larını da yamalı tut (bkz. usb-descriptor-parsing-bug-class). - Genel hardening: KASAN/KFENCE ile CI, syzkaller USB fuzzing'ini akışta tut.
References¶
- Linux USB gadget configured through configfs — kernel.org docs
- How FunctionFS works — kernel.org docs
- CVE-2022-50704 — USB: gadget: Fix use-after-free during usb config switch
- functionfs open/removal UAF race — linuxppc-dev mail-archive
- External USB fuzzing for Linux kernel — google/syzkaller docs
- USB Raw Gadget — kernel.org docs