[PATCH net 1/2] hdlc_cisco: shut down the keepalive timer on ->detach
DORMANTno replies
From: Chengyu Liu <hidden>
Date: 2026-10-28 03:26:17
Also in:
stable
Subsystem:
generic hdlc (wan) drivers, networking drivers, the rest · Maintainers:
Krzysztof Halasa, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
cisco_start() arms st->timer unconditionally and cisco_timer() re-arms
itself on every fire. The only deletion lives in cisco_stop(), which is
unreachable on the protocol-detach path: detach_hdlc_protocol() calls
only ->detach() (never ->stop()) and then kfree()s hdlc->state. The
cisco hdlc_proto has no ->detach at all, so unregistering an up cisco
device leaves the keepalive timer armed on top of freed memory; it fires
within one keepalive interval and cisco_timer() writes through the dead
cisco_state (st->lock, st->txseq++, cisco_keepalive_send()).
Add a ->detach callback that shuts the timer down permanently before the
state is freed, mirroring the CVE-2026-63803 ppp fix
(timer_shutdown_sync() in ppp_timer_release()).
Initialize the timer in cisco_ioctl() when the protocol is attached and
drop the timer_setup() from cisco_start(), so the timer is initialized
exactly once at attach time: attach_hdlc_protocol() uses kmalloc() (not
kzalloc), so st->timer is uninitialized garbage until the first
timer_setup() and ->detach() must never run timer_shutdown_sync() on it.
This bug was found by static analysis and confirmed with a KASAN
reproducer: slab-use-after-free write in __run_timer_base() within one
keepalive interval after rmmod of an up cisco HDLC device (allocated by
attach_hdlc_protocol() via cisco_ioctl(), freed by
detach_hdlc_protocol() via unregister_hdlc_device()).
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: <redacted>
Signed-off-by: Chengyu Liu <redacted>
---
drivers/net/wan/hdlc_cisco.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index bfc978b15b..2173d5c6d6 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c@@ -274,7 +274,6 @@ static void cisco_start(struct net_device *dev) spin_unlock_irqrestore(&st->lock, flags); st->dev = dev; - timer_setup(&st->timer, cisco_timer, 0); st->timer.expires = jiffies + HZ; /* First poll after 1 s */ add_timer(&st->timer); }
@@ -293,9 +292,17 @@ static void cisco_stop(struct net_device *dev) spin_unlock_irqrestore(&st->lock, flags); } +static void cisco_detach(struct net_device *dev) +{ + struct cisco_state *st = state(dev_to_hdlc(dev)); + + timer_shutdown_sync(&st->timer); +} + static struct hdlc_proto proto = { .start = cisco_start, .stop = cisco_stop, + .detach = cisco_detach, .type_trans = cisco_type_trans, .ioctl = cisco_ioctl, .netif_rx = cisco_rx,
@@ -353,6 +360,7 @@ static int cisco_ioctl(struct net_device *dev, struct if_settings *ifs) memcpy(&state(hdlc)->settings, &new_settings, size); spin_lock_init(&state(hdlc)->lock); + timer_setup(&state(hdlc)->timer, cisco_timer, 0); dev->header_ops = &cisco_header_ops; dev->hard_header_len = sizeof(struct hdlc_header); dev->type = ARPHRD_CISCO;
--
2.25.1