FAILED: patch "[PATCH] bna: prevent IOC timer rearm during teardown" failed to apply to 5.15-stable tree
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 77b1718e39e5c9f6956fb60807326af20baf889d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092952-unknotted-program-cc12@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 77b1718e39e5c9f6956fb60807326af20baf889d Mon Sep 17 00:00:00 2001
From: Myeonghun Pak <[email protected]>
Date: Mon, 21 Sep 2026 21:46:05 -0400
Subject: [PATCH] bna: prevent IOC timer rearm during teardown
bna: prevent IOC timer rearm during teardown
bnad_pci_remove() and the probe disable_ioceth path call timer_delete_sync() for ioc_timer, sem_timer and hb_timer, but not for iocpf_timer. bnad_iocpf_timeout() then takes bnad->bna_lock after free_netdev() has freed the struct bnad.
Deleting iocpf_timer last does not fix this. sem_timer and iocpf_timer rearm each other: bnad_iocpf_sem_timeout() can arm iocpf_timer, and bnad_iocpf_timeout() arms sem_timer from bfa_ioc_hw_sem_get() when the semaphore is busy. timer_delete_sync() only waits out its own callback. bnad_ioceth_disable() can time out and leave that callback live.
Shut all four IOC timers down with timer_shutdown_sync() on both paths, so a later mod_timer() is ignored.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
drivers/net/ethernet/brocade/bna/bnad.c +18 -6
@@ -2571,6 +2571,22 @@ bnad_ioceth_disable(struct bnad *bnad)return err; } +/* +* The IOC timers rearm one another, so deleting one cannot stop a +* sibling callback from arming it again. Shut them down so a later +* mod_timer() is ignored. +*/ +static void +bnad_ioc_timers_shutdown (struct bnad *bnad) +{ +struct bfa_ioc *ioc = &bnad->bna.ioceth.ioc; + +timer_shutdown_sync (&ioc->ioc_timer); +timer_shutdown_sync (&ioc->sem_timer); +timer_shutdown_sync (&ioc->hb_timer); +timer_shutdown_sync (&ioc->iocpf_timer); +} +static int bnad_ioceth_enable (struct bnad *bnad) {
@@ -3727,9 +3743,7 @@ bnad_pci_probe(struct pci_dev *pdev,bnad_res_free (bnad, &bnad->mod_res_info[0 ],BNA_MOD_RES_T_MAX ); disable_ioceth:bnad_ioceth_disable (bnad); -timer_delete_sync (&bnad->bna.ioceth.ioc.ioc_timer); -timer_delete_sync (&bnad->bna.ioceth.ioc.sem_timer); -timer_delete_sync (&bnad->bna.ioceth.ioc.hb_timer); +bnad_ioc_timers_shutdown (bnad);spin_lock_irqsave (&bnad->bna_lock, flags);bna_uninit (bna);spin_unlock_irqrestore (&bnad->bna_lock, flags);
@@ -3770,9 +3784,7 @@ bnad_pci_remove(struct pci_dev *pdev)mutex_lock (&bnad->conf_mutex);bnad_ioceth_disable (bnad); -timer_delete_sync (&bnad->bna.ioceth.ioc.ioc_timer); -timer_delete_sync (&bnad->bna.ioceth.ioc.sem_timer); -timer_delete_sync (&bnad->bna.ioceth.ioc.hb_timer); +bnad_ioc_timers_shutdown (bnad);spin_lock_irqsave (&bnad->bna_lock, flags);bna_uninit (bna);spin_unlock_irqrestore (&bnad->bna_lock, flags);
Sasha Levin
maintainerPATCH 1/1 bna: prevent IOC timer rearm during teardown
From: Myeonghun Pak <[email protected]>
[ Upstream commit 77b1718e39e5c9f6956fb60807326af20baf889d ]
bna: prevent IOC timer rearm during teardown
bnad_pci_remove() and the probe disable_ioceth path call timer_delete_sync() for ioc_timer, sem_timer and hb_timer, but not for iocpf_timer. bnad_iocpf_timeout() then takes bnad->bna_lock after free_netdev() has freed the struct bnad.
Deleting iocpf_timer last does not fix this. sem_timer and iocpf_timer rearm each other: bnad_iocpf_sem_timeout() can arm iocpf_timer, and bnad_iocpf_timeout() arms sem_timer from bfa_ioc_hw_sem_get() when the semaphore is busy. timer_delete_sync() only waits out its own callback. bnad_ioceth_disable() can time out and leave that callback live.
Shut all four IOC timers down with timer_shutdown_sync() on both paths, so a later mod_timer() is ignored.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/net/ethernet/brocade/bna/bnad.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/net/ethernet/brocade/bna/bnad.c +10 -6
@@ -3745,9 +3745,11 @@ bnad_pci_probe(struct pci_dev *pdev,bnad_res_free (bnad, &bnad->mod_res_info[0 ],BNA_MOD_RES_T_MAX ); disable_ioceth:bnad_ioceth_disable (bnad); -del_timer_sync (&bnad->bna.ioceth.ioc.ioc_timer); -del_timer_sync (&bnad->bna.ioceth.ioc.sem_timer); -del_timer_sync (&bnad->bna.ioceth.ioc.hb_timer); +/* The IOC timers rearm one another. Shut down all of them. */ +timer_shutdown_sync (&bnad->bna.ioceth.ioc.ioc_timer); +timer_shutdown_sync (&bnad->bna.ioceth.ioc.sem_timer); +timer_shutdown_sync (&bnad->bna.ioceth.ioc.hb_timer); +timer_shutdown_sync (&bnad->bna.ioceth.ioc.iocpf_timer);spin_lock_irqsave (&bnad->bna_lock, flags);bna_uninit (bna);spin_unlock_irqrestore (&bnad->bna_lock, flags);
@@ -3788,9 +3790,11 @@ bnad_pci_remove(struct pci_dev *pdev)mutex_lock (&bnad->conf_mutex);bnad_ioceth_disable (bnad); -del_timer_sync (&bnad->bna.ioceth.ioc.ioc_timer); -del_timer_sync (&bnad->bna.ioceth.ioc.sem_timer); -del_timer_sync (&bnad->bna.ioceth.ioc.hb_timer); +/* The IOC timers rearm one another. Shut down all of them. */ +timer_shutdown_sync (&bnad->bna.ioceth.ioc.ioc_timer); +timer_shutdown_sync (&bnad->bna.ioceth.ioc.sem_timer); +timer_shutdown_sync (&bnad->bna.ioceth.ioc.hb_timer); +timer_shutdown_sync (&bnad->bna.ioceth.ioc.iocpf_timer);spin_lock_irqsave (&bnad->bna_lock, flags);bna_uninit (bna);spin_unlock_irqrestore (&bnad->bna_lock, flags);
Signature · 1 line
2.53.0