Re: [BUG REPORT] sound/usb: Fix Use-After-Free in snd-usb-audio error_timer during device disconnect
Takashi Iwai <[email protected]> Wed, 05 Aug 2026 11:29:58 +0200
| Newsgroups | org.kernel.vger.linux-usb,org.alsa-project.alsa-devel |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 05 Aug 2026 11:19:54 +0200, 张建 wrote: > > > Hi Takashi and Linux USB/ALSA maintainers, > > We identified a reproducible Use-After-Free (UAF) kernel panic in sound/usb/ > midi.c during USB MIDI device hot-unplug under active URB transfers. > > The issue was reproduced on Qualcomm platforms (Snapdragon 8 Gen 3 Linux > 6.1.145 / Android 14, Snapdragon 8 Elite Linux 6.6.77 / Android16 etc.). The > crash consistently hits __run_timers (timer softirq) dereferencing poison > pointer. > > Crash Trace > > [ 169.493907] I[ 1: surfaceflinger: 1794] Internal error: Oops - CFI: 00000000f2008234 [#1] PREEMPT SMP > [ 169.493941] I[ 1: surfaceflinger: 1794] sec,qc-rst_exinfo soc:samsung,qcom-rst_exinfo: fault handler : unknown > [ 169.495442] I[ 1: surfaceflinger: 1794] CPU: 1 PID: 1794 Comm: surfaceflinger Tainted: G S WC O 6.1.145-android14-11-3254743-abS9280ZCS6DZF2 #1 > [ 169.495447] I[ 1: surfaceflinger: 1794] Hardware name: Samsung E3Q PROJECT (board-id,09) (DT) > [ 169.495455] I[ 1: surfaceflinger: 1794] pstate: 02400005 (nzcv daif +PAN -UAO +TCO -DIT -SSBS BTYPE=--) > [ 169.495464] I[ 1: surfaceflinger: 1794] pc : call_timer_fn+0x44/0x26c > [ 169.495471] I[ 1: surfaceflinger: 1794] lr : __run_timers+0x1b8/0x30c > [ 169.495475] I[ 1: surfaceflinger: 1794] sp : ffffffc00800be40 > [ 169.495480] I[ 1: surfaceflinger: 1794] x29: ffffffc00800be40 x28: dead000000000122 x27: 0000000000000000 > [ 169.495490] I[ 1: surfaceflinger: 1794] x26: ffffffc00800be90 x25: 0000000000000001 x24: ffffff8a713312b0 > [ 169.495501] I[ 1: surfaceflinger: 1794] x23: ffffffc00a427000 x22: ffffff8868a70000 x21: ffffff804c485c40 > [ 169.495511] I[ 1: surfaceflinger: 1794] x20: ffffff804c485c58 x19: 0000000000000100 x18: 0000000000000000 > [ 169.495522] I[ 1: surfaceflinger: 1794] x17: 0000000091b4a83a x16: 0000000000000000 x15: 0000000000000000 > [ 169.495532] I[ 1: surfaceflinger: 1794] x14: ffffff804c485c40 x13: 000000000000000d x12: 0000000000000028 > [ 169.495542] I[ 1: surfaceflinger: 1794] x11: ffffffc00800be98 x10: ffffff8a71331240 x9 : 0000000100000100 > [ 169.495553] I[ 1: surfaceflinger: 1794] x8 : 0000000100000100 x7 : 0000002776497736 x6 : 0000002776497736 > [ 169.495563] I[ 1: surfaceflinger: 1794] x5 : 0000002776497736 x4 : 0000000000000001 x3 : 00000000000009c4 > [ 169.495573] I[ 1: surfaceflinger: 1794] x2 : 00000000ffff808d x1 : ffffff804c485c58 x0 : ffffff804c485c40 > [ 169.495584] I[ 1: surfaceflinger: 1794] Call trace: > [ 169.495591] I[ 1: surfaceflinger: 1794] call_timer_fn+0x44/0x26c > [ 169.495598] I[ 1: surfaceflinger: 1794] __run_timers+0x1b8/0x30c > [ 169.495605] I[ 1: surfaceflinger: 1794] run_timer_softirq+0x24/0x4c > [ 169.495614] I[ 1: surfaceflinger: 1794] handle_softirqs+0x120/0x3e0 > [ 169.495621] I[ 1: surfaceflinger: 1794] __do_softirq+0x14/0x20 > [ 169.495628] I[ 1: surfaceflinger: 1794] ____do_softirq+0x10/0x20 > [ 169.495635] I[ 1: surfaceflinger: 1794] call_on_irq_stack+0x3c/0x74 > [ 169.495641] I[ 1: surfaceflinger: 1794] do_softirq_own_stack+0x1c/0x2c > [ 169.495648] I[ 1: surfaceflinger: 1794] __irq_exit_rcu+0x54/0xb4 > [ 169.495655] I[ 1: surfaceflinger: 1794] irq_exit_rcu+0x10/0x1c > [ 169.495665] I[ 1: surfaceflinger: 1794] el0_interrupt+0x54/0x174 > [ 169.495671] I[ 1: surfaceflinger: 1794] __el0_irq_handler_common+0x18/0x28 > [ 169.495677] I[ 1: surfaceflinger: 1794] el0t_64_irq_handler+0x10/0x1c > [ 169.495683] I[ 1: surfaceflinger: 1794] el0t_64_irq+0x1a4/0x1a8 > [ 169.495690] I[ 1: surfaceflinger: 1794] Code: 72950751 72b23691 6b11021f 54000040 (d4304680) > [ 169.495696] I[ 1: surfaceflinger: 1794] ---[ end trace 0000000000000000 ]--- > > Root Cause & Race Condition > > There is a sequence defect in snd_usbmidi_disconnect() combined with the URB > completion handler: > > 1. In snd_usbmidi_disconnect(), del_timer_sync(&umidi->error_timer) is > invoked BEFORE killing in-flight IN URBs via usb_kill_urb(). > > 2. Prior to usb_kill_urb() finishing, an in-flight IN URB completes with an > unconventional error status (e.g., -EPIPE) when USB disconnect. > > 3. snd_usbmidi_in_urb_complete() calls snd_usbmidi_urb_error(urb). When > receiving non-disconnect error codes (This error code is outside the scope > of the error codes handled by snd_usbmidi_urb_error.), it invokes > mod_timer(&ep->umidi->error_timer, ...) without checking umidi-> > disconnected. > > 4. This re-arms error_timer AFTER del_timer_sync() has already executed. > > 5. snd_usbmidi_disconnect() completes and frees struct snd_usb_midi in > snd_usbmidi_free. > > 6. Later when error_timer fires on deallocated memory, leading to a UAF panic > in __run_timers. > > Please let us know your thoughts on this issue. Could you verify the issue with the very latest Linus tree, too? thanks, Takashi