From: sashiko-bot@kernel.org
To: "Michael Grzeschik" <grzeschik@puzzle.ch>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH 1/2] usbip: stub: reference count struct stub_device
Date: Wed, 11 Nov 2026 12:07:27 +0000 [thread overview]
Message-ID: <sashiko-outbox-208935@kernel.org> (raw)
In-Reply-To: <20261111-usbip-v1-1-da5217ac71d7@puzzle.ch>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] usbip: stub: hung stub_tx, leaks, and URB UAF when shutdown is
missed
- [Medium] usbip: use-after-free in event_handler() reading eh_ops.put
after wake_up()
--
commit cd9a80911da15b88ceb306a5e8d623b311108647
Author: Michael Grzeschik <grzeschik@puzzle.ch>
usbip: stub: reference count struct stub_device
This commit adds kref reference counting to struct stub_device and holds
references across device binding, the rx/tx kthreads, and queued events so
that stub_device and its usb_device are not freed while still in use.
> diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
> index abfa11d6bde79..27d1e9c8db176 100644
> --- a/drivers/usb/usbip/stub_dev.c
> +++ b/drivers/usb/usbip/stub_dev.c
> @@ -11,6 +11,42 @@
> #include "usbip_common.h"
> #include "stub.h"
>
> +/*
> + * A stub_device is referenced by its binding to the USB device (from probe
> + * until disconnect), by the rx and tx threads while they run, and by the
> + * event handler while an event for it is queued or being handled. It must
> + * not be freed before all of them are done with it: stopping the threads
> + * relies on the event handler, which can miss a shutdown request or still
> + * have an event queued when disconnect wants to free the device.
> + */
> +static void stub_device_release(struct kref *kref)
> +{
> + struct stub_device *sdev = container_of(kref, struct stub_device, kref);
> +
> + usb_put_dev(sdev->udev);
> + kfree(sdev);
> +}
[Severity: High]
If the rx and tx threads outlive stub_disconnect() because
stub_shutdown_connection() was missed, does stub_tx_loop() hang forever on
sdev->tx_waitq, or does stub_device_release() free sdev while in-flight
URBs and connection resources are still active?
Once shutdown_busid() queues SDEV_EVENT_REMOVED during stub_disconnect(),
USBIP_EH_BYE is set in ud->event, which causes any later usbip_event_add()
call to return early without scheduling stub_shutdown_connection():
drivers/usb/usbip/usbip_event.c:usbip_event_add() {
if (ud->event & USBIP_EH_BYE)
return;
}
Without stub_shutdown_connection() calling kthread_stop_put(ud->tcp_tx),
stub_tx_loop() blocks indefinitely in wait_event_interruptible() on
sdev->tx_waitq because neither socket closure nor usbip_event_add() wakes
that queue.
Even if both threads exit on a socket error and drop their references,
stub_device_release() only drops sdev->udev and frees sdev without running
the cleanup from stub_shutdown_connection(). That leaks the ud->tcp_rx and
ud->tcp_tx task structs, ud->tcp_socket, and the sdev->unlink_tx and
sdev->unlink_free lists, and leaves in-flight URBs on sdev->priv_init to
dereference the freed sdev in stub_complete(). In addition, letting
stub_disconnect() return while threads or events are still running allows
usbip_host_exit() to destroy stub_priv_cache and finish unloading the
module while sdev is still in use.
[ ... ]
> diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c
> index 0e00c2d000f89..eea9a71f0eac2 100644
> --- a/drivers/usb/usbip/usbip_event.c
> +++ b/drivers/usb/usbip/usbip_event.c
> @@ -94,6 +94,10 @@ static void event_handler(struct work_struct *work)
> mutex_unlock(&ud->sysfs_lock);
>
> wake_up(&ud->eh_waitq);
> +
> + /* drop the reference taken by usbip_event_add() */
> + if (ud->eh_ops.put)
> + ud->eh_ops.put(ud);
> }
> }
[Severity: Medium]
Can waking ud->eh_waitq before reading ud->eh_ops.put cause a
use-after-free on ud?
vhci and vudc do not set eh_ops.get or eh_ops.put, and their removal paths
free the enclosing device as soon as usbip_stop_eh() returns from waiting
on ud->eh_waitq:
CPU0 (event_handler) CPU1 (vudc_remove)
unset_event(ud, ...)
wake_up(&ud->eh_waitq)
usb_del_gadget_udc()
vgadget_pullup()
usbip_stop_eh(&udc->ud) /* returns */
kfree(udc)
if (ud->eh_ops.put) <-- use-after-free
For stub_device, waking usbip_stop_eh() before ud->eh_ops.put(ud) runs (or
while a second event queued for the same ud is still on event_list) also
lets stub_disconnect() and usbip_host_exit() finish unloading usbip-host.ko
while event_handler() in usbip-core.ko is still about to call
stub_eh_put().
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261111-usbip-v1-0-da5217ac71d7@puzzle.ch?part=1
next prev parent reply other threads:[~2026-11-11 12:07 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 11:34 [PATCH 0/2] usbip: stability changes Michael Grzeschik
2026-11-11 11:34 ` [PATCH 1/2] usbip: stub: reference count struct stub_device Michael Grzeschik
2026-11-11 12:07 ` sashiko-bot [this message]
2026-11-11 11:34 ` [PATCH 2/2] usbip: identify the event handler with current_work() Michael Grzeschik
2026-11-11 11:42 ` sashiko-bot
2026-11-11 15:35 ` John Ernberg
2026-11-11 21:58 ` Michael Grzeschik
2026-11-12 22:46 ` [PATCH 0/2] usbip: stability changes Shuah Khan
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=sashiko-outbox-208935@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=grzeschik@puzzle.ch \
--cc=linux-usb@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.