korina_poll_media() rearms the media check timer by calling mod_timer()
unconditionally before returning. korina_close() stops it with
timer_delete(), which does not wait for a callback already running on
another CPU.
Such a callback can continue to access the netdev private data and can
rearm the timer. Once korina_remove() returns, devres releases the
netdev and its private data, so either the running callback or a later
timer expiry can dereference freed memory through lp->dev, lp->mii_if,
or lp->eth_regs.
The only timer armers are the callback itself and korina_open(). RTNL
serializes open against close, and timer_delete_sync() waits for a
running callback and removes the timer it rearmed. It is therefore
sufficient here while preserving the close/open cycle.
This issue was found by an in-house static analysis tool.
Fixes: 4d5ef9f0f588 ("korina: periodically poll the media")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5.6
Co-developed-by: Song Li <redacted>
Signed-off-by: Song Li <redacted>
Signed-off-by: Fan Wu <redacted>
---
drivers/net/ethernet/korina.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 891a94d89f4b..b7de2238f4b3 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -1240,7 +1240,7 @@ static int korina_close(struct net_device *dev)
struct korina_private *lp = netdev_priv(dev);
u32 tmp;
- timer_delete(&lp->media_check_timer);
+ timer_delete_sync(&lp->media_check_timer);
/* Disable interrupts */
disable_irq(lp->rx_irq);