* [BUG] usb: gadget: u_serial: use-after-free of gserial in gs_write()/gs_flush_chars() remote-wakeup path
@ 2026-10-19 3:34 Yu Zhang
2026-10-19 6:44 ` Greg Kroah-Hartman
0 siblings, 1 reply; 2+ messages in thread
From: Yu Zhang @ 2026-10-19 3:34 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-usb, linux-kernel
Hi,
gs_write() and gs_flush_chars() cache
struct gserial *gser = port->port_usb;
at function entry, before taking port->port_lock. In the
"if (port->suspended)" branch they drop port_lock and call
gserial_wakeup_host(gser) on that cached pointer, with no re-check of
port->port_usb -- unlike the sibling gs_start_tx() path in the very same
functions, which is guarded by "if (port->port_usb)" after re-acquiring
the lock.
gserial_wakeup_host() dereferences gser->func.config->cdev->gadget. A
concurrent gserial_disconnect() clears port->port_usb (under port_lock),
and the following unbind / function teardown frees the enclosing
struct f_acm / struct f_gser (which embeds the gserial) via ->free_func.
The cached gser is then used after free:
BUG: KASAN: slab-use-after-free in gs_write+0x120/0x240
Read of size 8 at addr ffff888006c5d430 by task ...
gs_write+0x120/0x240
n_tty_write+0x355/0xc30
file_tty_write.isra.0+...
vfs_write+...
ksys_write+...
Allocated by task ...:
acm_alloc_func+0x34/0x1f0
config_usb_cfg_link+0x15c/0x220
configfs_symlink+...
Freed by task ...:
kfree+...
acm_free_func+0x29/0x60
config_usb_cfg_unlink+0x1a9/0x240
configfs_unlink+...
__x64_sys_unlink+0x34/0x50
gs_flush_chars() has the identical shape.
== Reproduction ==
acm gadget on dummy_hcd (CONFIG_USB_DUMMY_HCD, CONFIG_USB_U_SERIAL,
CONFIG_USB_CONFIGFS_ACM), KASAN. Put the bus into suspend so
port->suspended is set: write "auto" to the gadget's host-side
.../power/control with autosuspend_delay_ms=0, which makes dummy_hcd
suspend the port and run the gadget ->suspend / gserial_suspend. Then:
- task A: write to /dev/ttyGS0 (enters the gs_write() suspended branch)
- task B: echo "" > g1/UDC ; rm g1/configs/c.1/acm.0 ; rmdir g1/functions/acm.0
(unbind + drop the acm function -> frees the gserial)
The gserial_wakeup_host(gser) call in task A then touches freed memory.
(I widened the window after the port_lock drop with a debug mdelay to make
it deterministic; without it this is a narrow race.)
The sibling gs_start_tx() call in the same two functions is guarded with
"if (port->port_usb)" after re-acquiring port_lock; the suspended/wakeup
branch dereferences the pre-lock cached gser with no equivalent check.
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [BUG] usb: gadget: u_serial: use-after-free of gserial in gs_write()/gs_flush_chars() remote-wakeup path
2026-10-19 3:34 [BUG] usb: gadget: u_serial: use-after-free of gserial in gs_write()/gs_flush_chars() remote-wakeup path Yu Zhang
@ 2026-10-19 6:44 ` Greg Kroah-Hartman
0 siblings, 0 replies; 2+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-19 6:44 UTC (permalink / raw)
To: Yu Zhang; +Cc: linux-usb, linux-kernel
On Mon, Oct 19, 2026 at 01:34:46PM +1000, Yu Zhang wrote:
> Hi,
>
> gs_write() and gs_flush_chars() cache
>
> struct gserial *gser = port->port_usb;
>
> at function entry, before taking port->port_lock. In the
> "if (port->suspended)" branch they drop port_lock and call
> gserial_wakeup_host(gser) on that cached pointer, with no re-check of
> port->port_usb -- unlike the sibling gs_start_tx() path in the very same
> functions, which is guarded by "if (port->port_usb)" after re-acquiring
> the lock.
Great, can you submit a patch for this after testing this on linux-next
to verify it's not already resolved?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-19 6:44 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19 3:34 [BUG] usb: gadget: u_serial: use-after-free of gserial in gs_write()/gs_flush_chars() remote-wakeup path Yu Zhang
2026-10-19 6:44 ` Greg Kroah-Hartman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox