[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