[PATCH] net: atheros: atl1: Fix use-after-free in atl1_remove due to race condition

Pei Xiao <[email protected]> Tue, 4 Aug 2026 11:02:20 +0800
Newsgroups gmane.linux.network,gmane.linux.kernel
Message-ID <59fa855b60e30eb37bb073b41fbde94b4c68901a.1785812450.git.xiaopei01@kylinos.cn>
In atl1_probe, &adapter->reset_dev_task is bound with
atl1_reset_dev_task, and &adapter->link_chg_task is bound with
atlx_link_chg_task. atl1_intr (on PHY link down, DMA errors or link
events) and atlx_tx_timeout can schedule these works on system_wq.

If we remove the device, atl1_remove makes cleanup and the memory
allocated for adapter with netdev_priv() is released by free_netdev(),
while the works mentioned above may still be pending or running. The
sequence of operations that may lead to a UAF bug is as follows:

CPU0                                      CPU1

                                          | atl1_intr
                                          | schedule_work(&adapter->reset_dev_task)
atl1_remove                               |
iowrite16(0, adapter->hw.hw_addr +        |
            REG_PHY_ENABLE)               |
unregister_netdev(netdev)                 |
// ndo_stop -> atl1_close -> atl1_down    |
// -> free_irq (IRQ handler stopped)      |
pci_iounmap(pdev, adapter->hw.hw_addr)    |
pci_release_regions(pdev)                 |
free_netdev(netdev)                       |
// adapter is freed                       |
                                          | atl1_reset_dev_task
                                          | // use adapter (use-after-free)

Fix it by canceling the works after the sources that can schedule
them (IRQ handler atl1_intr and the kernel netdev watchdog, which
calls atlx_tx_timeout) have been stopped, and before proceeding with
the remaining cleanup in atl1_remove.

Fixes: f3cc28c79760 ("Add Attansic L1 ethernet driver.")
Assisted-by: Codex:deepseek-v4-flash
Signed-off-by: Pei Xiao <[email protected]>
---
 drivers/net/ethernet/atheros/atlx/atl1.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 98a4d089270e..bb5a1d61c52c 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -3142,6 +3142,10 @@ static void atl1_remove(struct pci_dev *pdev)
 
 	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
 	unregister_netdev(netdev);
+
+	cancel_work_sync(&adapter->reset_dev_task);
+	cancel_work_sync(&adapter->link_chg_task);
+
 	pci_iounmap(pdev, adapter->hw.hw_addr);
 	pci_release_regions(pdev);
 	free_netdev(netdev);
-- 
2.25.1