From: sashiko-bot@kernel.org
To: tjdqudcks0424@naver.com
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH v2] usbip: vudc: reject submits after endpoint state changes
Date: Tue, 20 Oct 2026 18:29:19 +0000 [thread overview]
Message-ID: <sashiko-outbox-179473@kernel.org> (raw)
In-Reply-To: <20261020181832.461892-1-tjdqudcks0424@naver.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] usbip: vudc: v_recv_cmd_submit() -ESHUTDOWN return wedges connection
- [Medium] usbip: vudc: v_timer() and vep_disable() ignore queued URB generation
--
commit 7bd17351ae8c46943597685b7fdc609430437627
Author: Sung Byeongchan <tjdqudcks0424@naver.com>
usbip: vudc: reject submits after endpoint state changes
This commit adds a per-endpoint generation counter to vudc endpoints and
snapshots endpoint state under udc->lock in v_recv_cmd_submit(). Before
queuing an incoming urb_p onto udc->urb_queue, it revalidates that the
endpoint descriptor is still present and the generation has not changed.
> diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c
> index 5ef88117965d1..e3800d5e83a30 100644
> --- a/drivers/usb/usbip/vudc_dev.c
> +++ b/drivers/usb/usbip/vudc_dev.c
[ ... ]
> @@ -270,6 +271,7 @@ static int vep_disable(struct usb_ep *_ep)
>
> spin_lock_irqsave(&udc->lock, flags);
> ep->desc = NULL;
> + ep->generation++;
> nuke(udc, ep);
> spin_unlock_irqrestore(&udc->lock, flags);
[Severity: Medium]
What happens to urbs that were already validated and added to
udc->urb_queue before vep_disable() runs?
In drivers/usb/usbip/vudc_dev.c, vep_disable() clears ep->desc, increments
ep->generation, and calls nuke(udc, ep), which only drains gadget requests
from ep->req_queue while leaving udc->urb_queue untouched.
When v_timer() in drivers/usb/usbip/vudc_transfer.c iterates
udc->urb_queue, it neither checks ep->desc nor compares ep->generation
against urb_p->ep_generation:
drivers/usb/usbip/vudc_transfer.c:v_timer() {
...
list_for_each_entry_safe(urb_p, tmp, &udc->urb_queue, urb_entry) {
struct urb *urb = urb_p->urb;
ep = urb_p->ep;
if (urb->unlinked)
goto return_urb;
if (timer->state != VUDC_TR_RUNNING)
continue;
if (!ep) {
urb->status = -EPROTO;
goto return_urb;
}
...
switch (ep->type) {
...
default:
treat_control_like_bulk:
total -= transfer(udc, urb, ep, limit);
}
if (urb->status == -EINPROGRESS)
continue;
}
If the endpoint remains disabled, transfer() sees an empty ep->req_queue
and leaves urb->status unchanged, keeping urb_p queued on udc->urb_queue
and re-arming tr_timer every millisecond. If the endpoint is later
re-enabled via vep_enable(), v_timer() processes the stale urb_p from the
old generation against the new endpoint state and dispatches on the new
ep->type while v_send_ret_submit() uses the snapshotted urb_p->type.
Should vep_disable() or v_timer() also fail queued entries on
udc->urb_queue whose endpoint descriptor was cleared or whose
ep->generation no longer matches urb_p->ep_generation?
> diff --git a/drivers/usb/usbip/vudc_rx.c b/drivers/usb/usbip/vudc_rx.c
> index 51bb70837b902..3c459c7b57b5f 100644
> --- a/drivers/usb/usbip/vudc_rx.c
> +++ b/drivers/usb/usbip/vudc_rx.c
[ ... ]
> @@ -175,6 +179,13 @@ static int v_recv_cmd_submit(struct vudc *udc,
> goto free_urbp;
>
> spin_lock_irqsave(&udc->lock, flags);
> + if (urb_p->ep != &udc->ep[0] &&
> + (!urb_p->ep->desc ||
> + urb_p->ep->generation != urb_p->ep_generation)) {
> + spin_unlock_irqrestore(&udc->lock, flags);
> + ret = -ESHUTDOWN;
> + goto free_urbp;
> + }
> v_kick_timer(udc, jiffies);
> list_add_tail(&urb_p->urb_entry, &udc->urb_queue);
> spin_unlock_irqrestore(&udc->lock, flags);
[Severity: High]
Can returning this error from v_recv_cmd_submit() wedge the usbip
connection and vudc device state?
By the time v_recv_cmd_submit() reaches this check in
drivers/usb/usbip/vudc_rx.c, usbip_recv_xbuff() and usbip_recv_iso() have
already consumed the full submit payload from ud->tcp_socket. Jumping to
free_urbp drops urb_p without queuing a completion via
v_enqueue_ret_submit() and returns the negative error through v_rx_pdu() to
v_rx_loop():
drivers/usb/usbip/vudc_rx.c:v_rx_pdu() {
...
case USBIP_CMD_SUBMIT:
ret = v_recv_cmd_submit(udc, &pdu);
break;
...
return ret;
}
drivers/usb/usbip/vudc_rx.c:v_rx_loop() {
...
while (!kthread_should_stop()) {
if (usbip_event_happened(ud))
break;
ret = v_rx_pdu(ud);
if (ret < 0) {
pr_warn("v_rx exit with error %d", ret);
break;
}
}
return ret;
}
Unlike other fatal error paths in v_recv_cmd_submit() and v_rx_pdu(), this
path does not call usbip_event_add(), so vudc_shutdown() and
vudc_device_reset() in drivers/usb/usbip/vudc_dev.c are never scheduled:
drivers/usb/usbip/vudc_dev.c:vudc_shutdown() {
...
if (ud->tcp_socket)
kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
if (ud->tcp_rx) {
kthread_stop_put(ud->tcp_rx);
ud->tcp_rx = NULL;
}
if (ud->tcp_tx) {
kthread_stop_put(ud->tcp_tx);
ud->tcp_tx = NULL;
}
...
}
When ud->tcp_rx exits on its own without an event queued, ud->tcp_tx
remains asleep on udc->tx_waitq, ud->tcp_socket stays open with no reader,
the client hangs waiting for a submit reply, and udc->connected and
ud->status remain stuck in the active state.
Since the stream framing on ud->tcp_socket is still intact after reading
the payload, should v_recv_cmd_submit() complete the rejected urb_p back to
the client via v_enqueue_ret_submit() and return 0, or trigger connection
teardown via usbip_event_add()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261020181832.461892-1-tjdqudcks0424@naver.com?part=1
next prev parent reply other threads:[~2026-10-20 18:29 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 18:18 [PATCH v2] usbip: vudc: reject submits after endpoint state changes tjdqudcks0424
2026-10-20 18:29 ` sashiko-bot [this message]
2026-10-20 23:27 ` 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-179473@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tjdqudcks0424@naver.com \
/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