mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yu Zhang <yuz08559@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [BUG] usb: gadget: u_serial: use-after-free of gserial in gs_write()/gs_flush_chars() remote-wakeup path
Date: Mon, 19 Oct 2026 13:34:46 +1000	[thread overview]
Message-ID: <20261019033446.73554-1-yuz08559@gmail.com> (raw)

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.

             reply	other threads:[~2026-10-19  3:34 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-19  3:34 Yu Zhang [this message]
2026-10-19  6:44 ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261019033446.73554-1-yuz08559@gmail.com \
    --to=yuz08559@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®