From 13b364c765e69db1f8446399d8db0b331c23b50c Mon Sep 17 00:00:00 2001 From: Binbin Deng <18983559317@163.com> Date: Tue, 20 Oct 2026 10:26:30 +0800 Subject: [PATCH] net: atlantic: Unregister before clearing RXNFC rules aq_pci_remove() clears the driver's RXNFC rule list before unregistering the netdevice. Until unregister_netdev() returns, ethtool operations can still call aq_get_rxnfc_rule(), aq_get_rxnfc_all_rules(), aq_add_rxnfc_rule(), or aq_del_rxnfc_rule(). Those paths traverse the same unlocked hlist that aq_clear_rxnfc_all_rules() is mutating and freeing. The race is reachable by issuing RXNFC ethtool commands concurrently with PCI device removal or driver unbind. A reader can dereference a node that has just been freed, and two writers can corrupt the list or free the same rule more than once, causing KASAN reports, list corruption, or a kernel panic. Reverse the removal order: unregister the netdevice first, then clear the RXNFC rules. After unregister_netdev() returns, ethtool can no longer enter the driver, while the PCI device is still available for the rule-clearing routine to issue hardware commands. Found during a static-analysis-assisted audit: candidate sites were surfaced by a Coccinelle rule, and the reader/writer paths were confirmed by LLM-assisted (GLM-5.3) code inspection. The issue was not observed at runtime; it is identified by code inspection only. Fixes: 8d0bcb012f57 ("net: aquantia: add infrastructure for ntuple rules") Signed-off-by: Binbin Deng <18983559317@163.com> Link: https://patch.msgid.link/20261020022630.515209-1-18983559317@163.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index 04b3ef840b36..7a4afd25d240 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -342,9 +342,9 @@ static void aq_pci_remove(struct pci_dev *pdev) struct aq_nic_s *self = pci_get_drvdata(pdev); if (self->ndev) { - aq_clear_rxnfc_all_rules(self); if (self->ndev->reg_state == NETREG_REGISTERED) unregister_netdev(self->ndev); + aq_clear_rxnfc_all_rules(self); #if IS_ENABLED(CONFIG_MACSEC) aq_macsec_free(self);