The arc_emac_probe() function calls devm_request_irq() with the net_device as the dev_id. However, in the error path of emac_rockchip_probe(), free_netdev(ndev) is called before the devm cleanup happens. This creates a race window where an interrupt can fire and the ISR (arc_emac_intr) will access the already freed net_device structure. Race window: CPU 0 (probe error path) CPU 1 (interrupt) ------------------------ ------------------ emac_rockchip_probe() arc_emac_probe() devm_request_irq(..., ndev) [probe fails] goto out_netdev; free_netdev(ndev) // freed! arc_emac_intr() ndev = dev_instance priv = netdev_priv(ndev) // UAF! Accessing freed mem return err; devres_release_all() // Driver core cleanup devm_irq_release() // IRQ disabled too late! Fix this by using devm_alloc_etherdev() instead of alloc_etherdev(). With fully managed allocation, the devres mechanism ensures proper LIFO cleanup order: IRQ is released before net_device memory, thus eliminating the race window entirely. Remove the now-unnecessary free_netdev() calls from both the probe error path and the remove function, as the memory is automatically freed by devres when the device is detached. Fixes: 6eacf31139bf ("ethernet: arc: Add support for Rockchip SoC layer device tree bindings") Signed-off-by: Fan Wu --- drivers/net/ethernet/arc/emac_rockchip.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c index 780e70ea1c22..a695ea6547c8 100644 --- a/drivers/net/ethernet/arc/emac_rockchip.c +++ b/drivers/net/ethernet/arc/emac_rockchip.c @@ -103,7 +103,7 @@ static int emac_rockchip_probe(struct platform_device *pdev) if (!pdev->dev.of_node) return -ENODEV; - ndev = alloc_etherdev(sizeof(struct rockchip_priv_data)); + ndev = devm_alloc_etherdev(dev, sizeof(struct rockchip_priv_data)); if (!ndev) return -ENOMEM; platform_set_drvdata(pdev, ndev); @@ -240,7 +240,6 @@ static int emac_rockchip_probe(struct platform_device *pdev) out_clk_disable: clk_disable_unprepare(priv->refclk); out_netdev: - free_netdev(ndev); return err; } @@ -258,8 +257,6 @@ static void emac_rockchip_remove(struct platform_device *pdev) if (priv->soc_data->need_div_macclk) clk_disable_unprepare(priv->macclk); - - free_netdev(ndev); } static struct platform_driver emac_rockchip_driver = { -- 2.34.1