From: Ruoyu Wang <ruoyuw560@gmail.com>
To: Neal Liu <neal_liu@aspeedtech.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Joel Stanley <joel@jms.id.au>,
Andrew Jeffery <andrew@codeconstruct.com.au>,
linux-aspeed@lists.ozlabs.org, linux-usb@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Ruoyu Wang <ruoyuw560@gmail.com>
Subject: [PATCH] usb: gadget: aspeed_udc: check endpoint DMA allocation
Date: Mon, 8 Jun 2026 16:19:48 +0800 [thread overview]
Message-ID: <20260608081948.3-1-ruoyuw560@gmail.com> (raw)
ast_udc_probe() allocates a coherent DMA buffer used as the backing store
for endpoint buffers. ast_udc_init_ep() derives per-endpoint buffer
pointers from udc->ep0_buf, so a failed allocation is dereferenced during
probe.
Check the allocation before endpoint setup. The existing probe error path
called ast_udc_remove(), which unregisters the gadget unconditionally and
is not safe before usb_add_gadget_udc() succeeds. Add a local cleanup
helper for probe failures so pre-registration failures only unwind the
resources that were actually initialized.
This was found by a local static analysis checker for unchecked allocator
returns while scanning Linux 6.16. The change was checked by applying it
to current mainline and by running checkpatch. I do not have access to
Aspeed UDC hardware, so no runtime testing was performed.
Fixes: 055276c13205 ("usb: gadget: add Aspeed ast2600 udc driver")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
---
Note: a 2022 patch attempted to add only a NULL check for this
allocation:
https://lore.kernel.org/all/20221213025120.23149-1-jiasheng@iscas.ac.cn/
This version also fixes the probe unwind path so the clock is disabled
on allocation failure and usb_del_gadget_udc() is not called before the
gadget has been registered.
diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c
index 7fc6696b7..809a7d5b7 100644
--- a/drivers/usb/gadget/udc/aspeed_udc.c
+++ b/drivers/usb/gadget/udc/aspeed_udc.c
@@ -1434,11 +1434,34 @@ static void ast_udc_init_hw(struct ast_udc_dev *udc)
ast_udc_write(udc, 0, AST_UDC_EP0_CTRL);
}
+static void ast_udc_cleanup(struct platform_device *pdev)
+{
+ struct ast_udc_dev *udc = platform_get_drvdata(pdev);
+ unsigned long flags;
+ u32 ctrl;
+
+ spin_lock_irqsave(&udc->lock, flags);
+
+ /* Disable upstream port connection */
+ ctrl = ast_udc_read(udc, AST_UDC_FUNC_CTRL) & ~USB_UPSTREAM_EN;
+ ast_udc_write(udc, ctrl, AST_UDC_FUNC_CTRL);
+
+ clk_disable_unprepare(udc->clk);
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ if (udc->ep0_buf)
+ dma_free_coherent(&pdev->dev,
+ AST_UDC_EP_DMA_SIZE * AST_UDC_NUM_ENDPOINTS,
+ udc->ep0_buf,
+ udc->ep0_buf_dma);
+
+ udc->ep0_buf = NULL;
+}
+
static void ast_udc_remove(struct platform_device *pdev)
{
struct ast_udc_dev *udc = platform_get_drvdata(pdev);
- unsigned long flags;
- u32 ctrl;
usb_del_gadget_udc(&udc->gadget);
if (udc->driver) {
@@ -1453,23 +1476,7 @@ static void ast_udc_remove(struct platform_device *pdev)
return;
}
- spin_lock_irqsave(&udc->lock, flags);
-
- /* Disable upstream port connection */
- ctrl = ast_udc_read(udc, AST_UDC_FUNC_CTRL) & ~USB_UPSTREAM_EN;
- ast_udc_write(udc, ctrl, AST_UDC_FUNC_CTRL);
-
- clk_disable_unprepare(udc->clk);
-
- spin_unlock_irqrestore(&udc->lock, flags);
-
- if (udc->ep0_buf)
- dma_free_coherent(&pdev->dev,
- AST_UDC_EP_DMA_SIZE * AST_UDC_NUM_ENDPOINTS,
- udc->ep0_buf,
- udc->ep0_buf_dma);
-
- udc->ep0_buf = NULL;
+ ast_udc_cleanup(pdev);
}
static int ast_udc_probe(struct platform_device *pdev)
@@ -1523,6 +1530,10 @@ static int ast_udc_probe(struct platform_device *pdev)
AST_UDC_EP_DMA_SIZE *
AST_UDC_NUM_ENDPOINTS,
&udc->ep0_buf_dma, GFP_KERNEL);
+ if (!udc->ep0_buf) {
+ rc = -ENOMEM;
+ goto err_disable_clk;
+ }
udc->gadget.speed = USB_SPEED_UNKNOWN;
udc->gadget.max_speed = USB_SPEED_HIGH;
@@ -1553,20 +1564,20 @@ static int ast_udc_probe(struct platform_device *pdev)
udc->irq = platform_get_irq(pdev, 0);
if (udc->irq < 0) {
rc = udc->irq;
- goto err;
+ goto err_cleanup;
}
rc = devm_request_irq(&pdev->dev, udc->irq, ast_udc_isr, 0,
KBUILD_MODNAME, udc);
if (rc) {
dev_err(&pdev->dev, "Failed to request interrupt\n");
- goto err;
+ goto err_cleanup;
}
rc = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (rc) {
dev_err(&pdev->dev, "Failed to add gadget udc\n");
- goto err;
+ goto err_cleanup;
}
dev_info(&pdev->dev, "Initialized udc in USB%s mode\n",
@@ -1574,9 +1585,14 @@ static int ast_udc_probe(struct platform_device *pdev)
return 0;
+err_disable_clk:
+ clk_disable_unprepare(udc->clk);
+ goto err;
+err_cleanup:
+ ast_udc_cleanup(pdev);
+ goto err;
err:
dev_err(&pdev->dev, "Failed to udc probe, rc:0x%x\n", rc);
- ast_udc_remove(pdev);
return rc;
}
--
2.51.0
next reply other threads:[~2026-06-08 8:20 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-08 8:19 Ruoyu Wang [this message]
2026-06-10 11:45 ` [PATCH] usb: gadget: aspeed_udc: check endpoint DMA allocation Andrew Jeffery
2026-06-10 12:03 ` Ruoyu Wang
2026-06-10 12:10 ` [PATCH v2] " Ruoyu Wang
2026-06-11 5:06 ` Andrew Jeffery
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=20260608081948.3-1-ruoyuw560@gmail.com \
--to=ruoyuw560@gmail.com \
--cc=andrew@codeconstruct.com.au \
--cc=gregkh@linuxfoundation.org \
--cc=joel@jms.id.au \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-aspeed@lists.ozlabs.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=neal_liu@aspeedtech.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.