RE: [PATCH] phy: renesas: rcar-gen3-usb2: Fix use-after-free in rcar_gen3_phy_usb2_remove due to race condition
Biju Das <[email protected]> Tue, 4 Aug 2026 08:34:18 +0000
| Newsgroups | org.kernel.vger.linux-renesas-soc,org.infradead.lists.linux-phy,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <TY3PR01MB1134664317D6A75D8230DB51B86D42@TY3PR01MB11346.jpnprd01.prod.outlook.com> |
Hi Pei Xiao, Thanks for the patch. > -----Original Message----- > From: Pei Xiao <[email protected]> > Sent: 04 August 2026 09:02 > Subject: [PATCH] phy: renesas: rcar-gen3-usb2: Fix use-after-free in rcar= _gen3_phy_usb2_remove due to > race condition >=20 > In rcar_gen3_phy_usb2_probe, &channel->work is bound with rcar_gen3_phy_u= sb2_work. rcar_gen3_phy_usb2_irq > can schedule this work on system_wq via rcar_gen3_device_recognition(), a= nd the role sysfs store can also > schedule it via rcar_gen3_init_for_host() / rcar_gen3_init_for_peri(). >=20 > If we remove the device, rcar_gen3_phy_usb2_remove makes cleanup and the = memory allocated for channel > with devm_kzalloc() is released by the devm cleanup after the remove call= back returns, while the work > mentioned above may still be pending or running. The sequence of operatio= ns that may lead to a UAF bug is > as follows: >=20 > CPU0 CPU1 >=20 > | rcar_gen3_phy_usb2_irq > | rcar_gen3_device_recognition > | rcar_gen3_init_for_host > | schedule_work(&ch->work) > rcar_gen3_phy_usb2_remove | > device_remove_file(&pdev->dev, | > &dev_attr_role) | > // remove returns | > // devm cleanup: free_irq, | > // kfree(channel) | > | rcar_gen3_phy_usb2_work > | // use ch (use-after-free) >=20 > Fix it by disabling the OTG interrupts, so the IRQ handler cannot schedul= e new work, and canceling the > work before the remaining cleanup in rcar_gen3_phy_usb2_remove and the de= vm release of channel. >=20 > Fixes: c14f8a4032ef ("phy: rcar-gen3-usb2: fix mutex_lock calling in inte= rrupt") > Assisted-by: Codex:deepseek-v4-flash > Signed-off-by: Pei Xiao <[email protected]> > --- > drivers/phy/renesas/phy-rcar-gen3-usb2.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) >=20 > diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renes= as/phy-rcar-gen3-usb2.c > index 9a45d840efeb..fa0e680a4b91 100644 > --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c > +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c > @@ -1067,8 +1067,16 @@ static void rcar_gen3_phy_usb2_remove(struct platf= orm_device *pdev) { > struct rcar_gen3_chan *channel =3D platform_get_drvdata(pdev); >=20 > - if (channel->is_otg_channel) > + if (channel->is_otg_channel) { > + /* Disable OTG interrupts so the IRQ handler cannot > + * schedule new work. > + */ > + rcar_gen3_control_otg_irq(channel, 0); > + > device_remove_file(&pdev->dev, &dev_attr_role); > + > + cancel_work_sync(&channel->work); What about pending wq that is still about execute after "device_remove_file(&pdev->dev, &dev_attr_role);" ? Cheers, Biju > + } > } >=20 > static int rcar_gen3_phy_usb2_suspend(struct device *dev) > -- > 2.25.1 >=20