summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFan Wu <fanwu01@zju.edu.cn>2026-03-03 07:33:44 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-03-11 16:18:16 +0100
commit3cbc242b88c607f55da3d0d0d336b49bf1e20412 (patch)
tree85025b0f0bc48b55c4ec2e405d361255035392f8
parent14ae24cba291bddfdc296bbcbfd00cd09d0498ef (diff)
usb: renesas_usbhs: fix use-after-free in ISR during device removal
In usbhs_remove(), the driver frees resources (including the pipe array) while the interrupt handler (usbhs_interrupt) is still registered. If an interrupt fires after usbhs_pipe_remove() but before the driver is fully unbound, the ISR may access freed memory, causing a use-after-free. Fix this by calling devm_free_irq() before freeing resources. This ensures the interrupt handler is both disabled and synchronized (waits for any running ISR to complete) before usbhs_pipe_remove() is called. Fixes: f1407d5c6624 ("usb: renesas_usbhs: Add Renesas USBHS common code") Cc: stable <stable@kernel.org> Suggested-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Fan Wu <fanwu01@zju.edu.cn> Link: https://patch.msgid.link/20260303073344.34577-1-fanwu01@zju.edu.cn Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/renesas_usbhs/common.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index cf4a0367d6d6..8c93bde4b816 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -815,6 +815,15 @@ static void usbhs_remove(struct platform_device *pdev)
usbhs_platform_call(priv, hardware_exit, pdev);
reset_control_assert(priv->rsts);
+
+ /*
+ * Explicitly free the IRQ to ensure the interrupt handler is
+ * disabled and synchronized before freeing resources.
+ * devm_free_irq() calls free_irq() which waits for any running
+ * ISR to complete, preventing UAF.
+ */
+ devm_free_irq(&pdev->dev, priv->irq, priv);
+
usbhs_mod_remove(priv);
usbhs_fifo_remove(priv);
usbhs_pipe_remove(priv);