mac80211: stop tpt LED trigger timer before freeing trigger
PATCH v2 1/1 mac80211: stop tpt LED trigger timer before freeing trigger
The throughput (tpt) LED trigger timer is only stopped in ieee80211_stop_tpt_led_trig(), which is reached via ieee80211_stop_device() when the interface is brought down. On a hot unplug, the device is torn down through ieee80211_unregister_hw() without ever going through ieee80211_do_stop(), so the timer is never stopped.
ieee80211_led_exit() then frees local->tpt_led_trigger (which embeds the timer) without cancelling it. The still-armed timer keeps firing and dereferences the freed tpt_trig, walking local->tpt_led's LED list in led_trigger_blink() -> led_blink_set_nosleep() on the freed rt2x00 LED class device, causing a use-after-free page fault in interrupt context.
Call ieee80211_stop_tpt_led_trig() in ieee80211_led_exit(), before unregistering the trigger and freeing the struct, so the timer is always stopped and can never run after the trigger/LEDs are torn down.
---
v2: move static function instead of forward declaration
net/mac80211/led.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
net/mac80211/led.c +14 -13
@@ -194,6 +194,19 @@ void ieee80211_led_init(struct ieee80211_local *local) } } +static void ieee80211_stop_tpt_led_trig (struct ieee80211_local *local) +{ +struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; + +if (!tpt_trig->running) +return ; + + tpt_trig->running = false; +timer_delete_sync (&tpt_trig->timer); + +led_trigger_event (&local->tpt_led,LED_OFF ); +} +void ieee80211_led_exit (struct ieee80211_local *local) {if (local->radio_led.name)
@@ -206,6 +219,7 @@ void ieee80211_led_exit(struct ieee80211_local *local)led_trigger_unregister (&local->rx_led);if (local->tpt_led_trigger) { +ieee80211_stop_tpt_led_trig (local);led_trigger_unregister (&local->tpt_led);kfree (local->tpt_led_trigger); }
@@ -335,19 +349,6 @@ static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)mod_timer (&tpt_trig->timer,round_jiffies (jiffies +HZ )); } -static void ieee80211_stop_tpt_led_trig (struct ieee80211_local *local) -{ -struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; - -if (!tpt_trig->running) -return ; - - tpt_trig->running = false; -timer_delete_sync (&tpt_trig->timer); - -led_trigger_event (&local->tpt_led,LED_OFF ); -} -void ieee80211_mod_tpt_led_trig (struct ieee80211_local *local,unsigned int types_on,unsigned int types_off) {
Signature · 1 line
2.55.0
Johannes Berg
maintainerQuoted 3 lines · Rosen Penev
On a hot unplug, the device is torn down
throughieee80211_unregister_hw()without ever going throughieee80211_do_stop(), so the timer is never stopped.
I don't buy this.
Also, missed wifi: prefix.
Please don't just feed me LLM garbage. Do you have a crash reported on this?
johannes
Quoted 6 lines · Johannes Berg
Quoted 3 lines · Rosen Penev
On a hot unplug, the device is torn down
throughieee80211_unregister_hw()without ever going throughieee80211_do_stop(), so the timer is never stopped.
Quoted 6 lines
I don't buy this.
Also, missed wifi: prefix.
Please don't just feed me LLM garbage. Do you have a crash reported on this?
Not formally no. However I am able to reliably panic the kernel. After this patch I can't.
Some output:
[20004.982362] Call Trace: [20004.982365] <IRQ> [20004.982369] led_trigger_blink+0x55/0x90 [20004.982375] ? __pfx_tpt_trig_timer+0x10/0x10 [mac80211 9e1764ff5588e2fa1476cc1f40fb40aa15fcf740] [20004.982444] ? __pfx_tpt_trig_timer+0x10/0x10 [mac80211 9e1764ff5588e2fa1476cc1f40fb40aa15fcf740] [20004.982500] call_timer_fn+0x2a/0x130 [20004.982505] __run_timers+0x27c/0x340 [20004.982511] run_timer_softirq+0x86/0xf0 [20004.982513] ? irqtime_account_irq+0x30/0xc0 [20004.982519] handle_softirqs+0xe3/0x2b0 [20004.982523] ? srso_alias_return_thunk+0x5/0xfbef5 [20004.982528] __irq_exit_rcu+0xb0/0x100 [20004.982530] sysvec_apic_timer_interrupt+0x71/0x90 [20004.982535] </IRQ> [20004.982536] <TASK>
I can do so with a USB wifi adapter using the rt2x00 driver but not the mt76 driver. I kept pointing the LLM at rt2x00 but it always determined rt2x00 to be fine and the issue being here.
Quoted 2 lines
johannes
Johannes Berg
maintainerQuoted 7 lines · Rosen Penev
Quoted 6 lines · Johannes Berg
Quoted 3 lines · Rosen Penev
On a hot unplug, the device is torn down
throughieee80211_unregister_hw()without ever going throughieee80211_do_stop(), so the timer is never stopped.
Quoted 8 lines
Quoted 6 lines
I don't buy this.
Also, missed wifi: prefix.
Please don't just feed me LLM garbage. Do you have a crash reported on this?
Not formally no. However I am able to reliably panic the kernel. After this patch I can't.
Then you can probably enable debug objects etc. to figure out why?
I don't think this patch really fixes the cause, just the symptom.
Maybe it's related to this:
https://lore.kernel.org/linux-wireless/20260904165722.044aa432f873.I601a67a2cd558b8ef8416a07554ae7efe896e9d8@changeid/
johannes
Quoted 18 lines · Johannes Berg
Quoted 7 lines · Rosen Penev
Quoted 6 lines · Johannes Berg
Quoted 3 lines · Rosen Penev
On a hot unplug, the device is torn down
throughieee80211_unregister_hw()without ever going throughieee80211_do_stop(), so the timer is never stopped.Quoted 8 lines
Quoted 6 lines
I don't buy this.
Also, missed wifi: prefix.
Please don't just feed me LLM garbage. Do you have a crash reported on this?
Not formally no. However I am able to reliably panic the kernel. After this patch I can't.
Quoted 6 lines
Then you can probably enable debug objects etc. to figure out why?
I don't think this patch really fixes the cause, just the symptom.
Maybe it's related to this:
https://lore.kernel.org/linux-wireless/20260904165722.044aa432f873.I601a67a2cd558b8ef8416a07554ae7efe896e9d8@changeid/
That... might have done it.
I rebuilt my kernel with that patch and cannot reproduce.
LLM seems to think so as well:
Probably yes — the oops is the exact bug that commit 29e3d27 targets.
Quoted 2 lines
johannes