From: Mattijs Korpershoek <mkorpershoek@kernel.org>
To: "Michal Vokáč" <michal.vokac@ysoft.com>,
"Marek Vasut" <marex@denx.de>, "Tom Rini" <trini@konsulko.com>
Cc: "Lukasz Majewski" <lukma@denx.de>,
"Mattijs Korpershoek" <mkorpershoek@kernel.org>,
u-boot@lists.denx.de, "Petr Beneš" <petr.benes@ysoft.com>,
"Michal Vokáč" <michal.vokac@ysoft.com>
Subject: Re: [PATCH 1/2] usb: ci_udc: Check ci_ep->desc before use
Date: Thu, 27 Nov 2025 11:12:29 +0100 [thread overview]
Message-ID: <87fr9zss1e.fsf@kernel.org> (raw)
In-Reply-To: <20251125085846.507591-1-michal.vokac@ysoft.com>
Hi Michal,
Thank you for the patch.
On Tue, Nov 25, 2025 at 09:58, Michal Vokáč <michal.vokac@ysoft.com> wrote:
> From: Petr Beneš <petr.benes@ysoft.com>
>
> There are two places where ci_ep->desc could be accessed despite it is
> not valid at that moment. Either the endpoint has not been enabled yet
> or it has been disabled meanwhile (The ethernet gadged behaves this way
> at least.). That results in dereferencing a null pointer.
I wonder if this is not a generic problem (that ep->desc) is reused.
Looking at usb_ep_enable() in include/linux/usb/gadget.h:
"""
static inline int usb_ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
{
int ret;
if (ep->enabled)
return 0;
ret = ep->ops->enable(ep, desc);
if (ret)
return ret;
"""
Can you please explain why the generic code is not enough to handle
this?
>
> Moreover, the patch gets rid of possible outstanding requests if the
> endpoint's state changes to disabled.
>
> Signed-off-by: Petr Beneš <petr.benes@ysoft.com>
> Signed-off-by: Michal Vokáč <michal.vokac@ysoft.com>
> ---
> drivers/usb/gadget/ci_udc.c | 43 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 43 insertions(+)
>
> diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
> index 4bff75da759d..b3bbbb6ad32c 100644
> --- a/drivers/usb/gadget/ci_udc.c
> +++ b/drivers/usb/gadget/ci_udc.c
> @@ -308,6 +308,27 @@ static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *req)
> free(ci_req);
> }
>
> +static void request_complete(struct usb_ep *ep, struct ci_req *req, int status)
> +{
> + if (req->req.status == -EINPROGRESS)
> + req->req.status = status;
> +
> + DBG("%s: req %p complete: status %d, actual %u\n",
> + ep->name, req, req->req.status, req->req.actual);
> +
> + req->req.complete(ep, &req->req);
> +}
> +
> +static void request_complete_list(struct usb_ep *ep, struct list_head *list, int status)
> +{
> + struct ci_req *req, *tmp_req;
> +
> + list_for_each_entry_safe(req, tmp_req, list, queue) {
> + list_del_init(&req->queue);
> + request_complete(ep, req, status);
> + }
> +}
> +
> static void ep_enable(int num, int in, int maxpacket)
> {
> struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
> @@ -335,6 +356,12 @@ static int ci_ep_enable(struct usb_ep *ep,
> int num, in;
> num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
> in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
> +
> + if (ci_ep->desc) {
> + DBG("%s: endpoint num %d in %d already enabled\n", __func__, num, in);
> + return 0;
> + }
> +
> ci_ep->desc = desc;
> ep->desc = desc;
>
> @@ -385,16 +412,27 @@ static int ep_disable(int num, int in)
> static int ci_ep_disable(struct usb_ep *ep)
> {
> struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
> + LIST_HEAD(req_list);
> int num, in, err;
>
> + if (!ci_ep->desc) {
> + DBG("%s: attempt to disable a not enabled yet endpoint\n", __func__);
> + goto nodesc;
> + }
> +
> num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
> in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
>
> + list_splice_init(&ci_ep->queue, &req_list);
> + request_complete_list(ep, &req_list, -ESHUTDOWN);
> +
> err = ep_disable(num, in);
> if (err)
> return err;
>
> ci_ep->desc = NULL;
> +
> +nodesc:
> ep->desc = NULL;
> ci_ep->req_primed = false;
> return 0;
> @@ -606,6 +644,11 @@ static int ci_ep_queue(struct usb_ep *ep,
> int in, ret;
> int __maybe_unused num;
>
> + if (!ci_ep->desc) {
> + DBG("%s: ci_ep->desc == NULL, nothing to do!\n", __func__);
> + return -EINVAL;
> + }
> +
> num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
> in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
>
> --
> 2.43.0
next prev parent reply other threads:[~2025-11-27 10:12 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-25 8:58 [PATCH 1/2] usb: ci_udc: Check ci_ep->desc before use Michal Vokáč
2025-11-25 8:58 ` [PATCH 2/2] usb: ci_udc: cosmetics: EP and requests debug info Michal Vokáč
2025-11-27 10:16 ` Mattijs Korpershoek
2025-11-25 12:26 ` [PATCH 1/2] usb: ci_udc: Check ci_ep->desc before use Marek Vasut
2025-11-25 13:13 ` Petr Benes
2025-11-27 10:12 ` Mattijs Korpershoek [this message]
2025-11-27 13:44 ` Petr Benes
2025-11-28 8:42 ` Mattijs Korpershoek
2025-12-01 8:20 ` Petr Benes
2025-12-01 9:15 ` Mattijs Korpershoek
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=87fr9zss1e.fsf@kernel.org \
--to=mkorpershoek@kernel.org \
--cc=lukma@denx.de \
--cc=marex@denx.de \
--cc=michal.vokac@ysoft.com \
--cc=petr.benes@ysoft.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/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