Skip to content

Commit 45e7a91

Browse files
Chen Yufengopsiff
authored andcommitted
usb: cdns3: gadget: Use-after-free during failed initialization and exit of cdnsp gadget
[ Upstream commit 87c5ff5 ] In the __cdnsp_gadget_init() and cdnsp_gadget_exit() functions, the gadget structure (pdev->gadget) was freed before its endpoints. The endpoints are linked via the ep_list in the gadget structure. Freeing the gadget first leaves dangling pointers in the endpoint list. When the endpoints are subsequently freed, this results in a use-after-free. Fix: By separating the usb_del_gadget_udc() operation into distinct "del" and "put" steps, cdnsp_gadget_free_endpoints() can be executed prior to the final release of the gadget structure with usb_put_gadget(). A patch similar to bb9c74a("usb: dwc3: gadget: Free gadget structure only after freeing endpoints"). Signed-off-by: Chen Yufeng <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit ea37884097a0931abb8e11e40eacfb25e9fdb5e9) Signed-off-by: Wentao Guan <[email protected]>
1 parent f15d443 commit 45e7a91

File tree

1 file changed

+6
-2
lines changed

1 file changed

+6
-2
lines changed

drivers/usb/cdns3/cdnsp-gadget.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,7 +1975,10 @@ static int __cdnsp_gadget_init(struct cdns *cdns)
19751975
return 0;
19761976

19771977
del_gadget:
1978-
usb_del_gadget_udc(&pdev->gadget);
1978+
usb_del_gadget(&pdev->gadget);
1979+
cdnsp_gadget_free_endpoints(pdev);
1980+
usb_put_gadget(&pdev->gadget);
1981+
goto halt_pdev;
19791982
free_endpoints:
19801983
cdnsp_gadget_free_endpoints(pdev);
19811984
halt_pdev:
@@ -1997,8 +2000,9 @@ static void cdnsp_gadget_exit(struct cdns *cdns)
19972000
devm_free_irq(pdev->dev, cdns->dev_irq, pdev);
19982001
pm_runtime_mark_last_busy(cdns->dev);
19992002
pm_runtime_put_autosuspend(cdns->dev);
2000-
usb_del_gadget_udc(&pdev->gadget);
2003+
usb_del_gadget(&pdev->gadget);
20012004
cdnsp_gadget_free_endpoints(pdev);
2005+
usb_put_gadget(&pdev->gadget);
20022006
cdnsp_mem_cleanup(pdev);
20032007
kfree(pdev);
20042008
cdns->gadget_dev = NULL;

0 commit comments

Comments
 (0)