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: 5+ 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
2026-10-26 13:21 ` 성병찬
2026-10-26 14:34 ` Greg KH
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 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.