[PATCH] net: ethernet: arc: fix use-after-free in probe error path

Fan Wu fanwu01 at zju.edu.cn
Tue Mar 3 18:53:03 PST 2026


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!
                                       <Interrupt fires>
                                       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 <fanwu01 at zju.edu.cn>
---
 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




More information about the Linux-rockchip mailing list