Origin: LKML email — 20260502125824.425d7159@bongani-mini.home.org.za
Root cause:
mt7921_channel_switch_rx_beacon()dereferencesdev->new_ctxwithout a NULL guard;new_ctxcan be NULL when the channel context was removed before the queued beacon is processed.
| Field | Value | Implication |
|---|---|---|
| MSGID | <20260502125824.425d7159@bongani-mini.home.org.za> |
|
| MSGID_URL | 20260502125824.425d7159@bongani-mini.home.org.za | |
| BUG_TYPE | BUG: kernel NULL pointer dereference, address: 0000000000000000 |
NULL pointer dereference at address 0x0 |
| UNAME | 7.1.0-rc1+ |
Mainline linux-next / rc1 build |
| BUILD | #4 PREEMPT(full) |
|
| DISTRO | mainline | No distro-specific debug packages available |
| PROCESS | kworker/u64:1 |
Kernel workqueue worker thread |
| PID | 6710 |
|
| CPU | 7 |
|
| UID | 0 |
|
| TAINT | Not tainted | |
| HARDWARE | Micro Computer (HK) Tech Limited EliteMini Series/F7BSI |
|
| BIOS | 1.08 11/05/2024 |
|
| WORKQUEUE | events_unbound cfg80211_wiphy_work [cfg80211] |
|
| RIP | mt7921_channel_switch_rx_beacon+0x1f/0x100 [mt7921_common] |
Crash site in mt7921 WiFi driver |
| CR2 | 0000000000000000 |
Faulting address is NULL |
| SOURCEDIR | oops-workdir/linux |
Checked out at tag v7.1-rc1 (commit
254f49634ee16) |
| HEAD_COMMIT | 254f49634ee16 |
Tag v7.1-rc1 |
| Module | Flags | Backtrace | Location | Flag Implication |
|---|---|---|---|---|
| mt7921_common | Y | drivers/net/wireless/mediatek/mt76/mt7921/ |
||
| mac80211 | Y | net/mac80211/ |
||
| cfg80211 | Y | net/wireless/ |
||
| joydev | ||||
| uinput | ||||
| mptcp_diag | ||||
| xsk_diag | ||||
| tcp_diag | ||||
| udp_diag | ||||
| raw_diag | ||||
| inet_diag | ||||
| unix_diag | ||||
| af_packet_diag | ||||
| netlink_diag | ||||
| sd_mod | ||||
| scsi_mod | ||||
| scsi_common | ||||
| ccm | ||||
| snd_seq_dummy | ||||
| snd_hrtimer | ||||
| snd_seq | ||||
| snd | ||||
| snd_pci_acp5x | ||||
| snd_rn_pci_acp3x | ||||
| irqbypass | ||||
| aesni_intel | ||||
| snd_acp_config | ||||
| gf128mul | ||||
| snd_soc_acpi | ||||
| rapl | ||||
| ecdh_generic | ||||
| pcspkr | ||||
| k10temp | ||||
| amd_pmc | ||||
| snd_pci_acp3x | ||||
| soundcore | ||||
| button | ||||
| evdev | ||||
| rfkill | ||||
| libarc4 | ||||
| aead | ||||
| msr |
| # | Address | Function | Offset | Size | Context | Module | Source location |
|---|---|---|---|---|---|---|---|
| 0 | mt7921_channel_switch_rx_beacon |
0x1f |
0x100 |
Task | mt7921_common |
drivers/net/wireless/mediatek/mt76/mt7921/main.c:1511 | |
| 1 | ieee80211_sta_process_chanswitch |
0x67c |
0xee0 |
Task | mac80211 |
net/mac80211/mlme.c:2855 | |
| 2 | ieee80211_rx_mgmt_beacon |
0x842 |
0x22a0 |
Task | mac80211 |
net/mac80211/mlme.c:7570 | |
| 3 | ieee80211_sta_rx_queued_mgmt |
0xa7 |
0xbb0 |
Task | mac80211 |
net/mac80211/mlme.c:8345 | |
| 4 | ieee80211_iface_work |
0x62e |
0x890 |
Task | mac80211 |
net/mac80211/iface.c:1826 | |
| 5 | cfg80211_wiphy_work |
0x1ee |
0x280 |
Task | cfg80211 |
||
| 6 | process_scheduled_works |
0x180 |
0x680 |
Task | |||
| 7 | worker_thread |
0x1aa |
0x450 |
Task | |||
| 8 | kthread |
0x181 |
0x1e0 |
Task | |||
| 9 | ret_from_fork |
0x405 |
0x600 |
Task | |||
| 10 | ret_from_fork_asm |
0x11 |
0x20 |
Task |
| Register | Value | Note |
|---|---|---|
| RAX | 0000000000000000 |
NULL — value loaded from dev->new_ctx |
| RBX | ffff91cae1eb09e0 |
|
| RCX | 0000000000000000 |
|
| RDX | ffffb75fa1993b20 |
|
| RSI | ffff91ca84badfe8 |
|
| RDI | ffff91cae1eb09e0 |
|
| RBP | ffff91ca84bacac0 |
|
| R08 | 0000000000000001 |
|
| R09 | 0000000000000001 |
|
| R10 | ffff91ca8ba56128 |
|
| R11 | ffff91cae1eb0518 |
|
| R12 | 0000000000000000 |
|
| R13 | 0000000000000000 |
|
| R14 | ffffb75fa1993b60 |
|
| R15 | ffff91cae1eb09e0 |
|
| RSP | ffffb75fa1993af0 |
|
| EFLAGS | 00010202 |
|
| CS | 0010 |
|
| DS | 0000 |
|
| ES | 0000 |
|
| CR0 | 0000000080050033 |
|
| CR2 | 0000000000000000 |
Faulting address (NULL dereference) |
| CR3 | 0000000562a38000 |
|
| CR4 | 0000000000f50ef0 |
|
| PKRU | 55555554 |
|
| FS | 0000000000000000(0000) |
|
| GS | ffff91d18ebde000(0000) |
|
| knlGS | 0000000000000000 |
Code bytes (raw):
12 3d 00 eb 9a 66 0f 1f 44 00 00 f3 0f 1e fa 0f 1f 44 00 00
48 8b 47 58 48 ff 05 ec 15 3d 00 48 8b 40 08 48 8b 80 80 9c
00 00 <48> 8b 08 48 39 4a 10 74 0c 48 ff 05 81 02 3d 00 e9
f7 f4 74 ea 53
Crash instruction (marked <48> 8b 08):
mov rcx, [rax] — REX.W + MOV r64,r/m64; operand
[rax] with RAX=0x0 causes the NULL dereference.
mt7921_channel_switch_rx_beacon — crash site
(drivers/net/wireless/mediatek/mt76/mt7921/main.c:1511)drivers/net/wireless/mediatek/mt76/mt7921/main.c @ v7.1-rc1
1503 static void mt7921_channel_switch_rx_beacon(struct ieee80211_hw *hw,
1504 struct ieee80211_vif *vif,
1505 struct ieee80211_channel_switch *chsw)
1506 {
1507 struct mt792x_dev *dev = mt792x_hw_dev(hw);
1508 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
1509 u16 beacon_interval = vif->bss_conf.beacon_int;
1510
1511 if (cfg80211_chandef_identical(&chsw->chandef,
1512 &dev->new_ctx->def) &&
1513 chsw->count) {
1514 mod_timer(&mvif->csa_timer,
1515 TU_TO_EXP_TIME(beacon_interval * chsw->count));
1516 }
1517 }dev->new_ctx is
struct ieee80211_chanctx_conf *new_ctx (field in
struct mt792x_dev, declared in
drivers/net/wireless/mediatek/mt76/mt792x.h:264). RAX=0x0
corresponds to dev->new_ctx being NULL.
ieee80211_sta_process_chanswitch —
net/mac80211/mlme.c:2855net/mac80211/mlme.c @ v7.1-rc1
2854 static void
2855 ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
2856 u64 timestamp, u32 device_timestamp,
2857 struct ieee802_11_elems *full_elems,
2858 struct ieee802_11_elems *csa_elems,
2859 enum ieee80211_csa_source source)
2860 {
2861 struct ieee80211_sub_if_data *sdata = link->sdata;
2862 struct ieee80211_local *local = sdata->local;
2863 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2864 struct ieee80211_chanctx *chanctx = NULL;
2865 struct ieee80211_chanctx_conf *conf;
2866 struct ieee80211_csa_ie csa_ie = {};
2867 struct ieee80211_channel_switch ch_switch = {
2868 .link_id = link->link_id,
2869 .timestamp = timestamp,
2870 .device_timestamp = device_timestamp,
2871 };
2872 u32 csa_time_tu;
2873 ktime_t now;
2874 int res;
2875
2876 lockdep_assert_wiphy(local->hw.wiphy);The call to drv_channel_switch_rx_beacon() is at line
2940:
2940 drv_channel_switch_rx_beacon(sdata, &ch_switch);
2941 return;drv_channel_switch_rx_beacon() is defined in
net/mac80211/driver-ops.h:1242 and calls
local->ops->channel_switch_rx_beacon(), which
dispatches to mt7921_channel_switch_rx_beacon.
mt7921_channel_switch_rx_beacon() crashes at line
1511–1512 when dev->new_ctx is NULL. The expression
&dev->new_ctx->def unconditionally dereferences
the new_ctx pointer; RAX=0x0 in the register dump confirms
dev->new_ctx is NULL at the time of the crash. The CPU
faults on the mov rcx, [rax] instruction at offset
+0x1f.
drivers/net/wireless/mediatek/mt76/mt7921/main.c @ v7.1-rc1
1503 static void mt7921_channel_switch_rx_beacon(struct ieee80211_hw *hw,
1504 struct ieee80211_vif *vif,
1505 struct ieee80211_channel_switch *chsw)
1506 {
1507 struct mt792x_dev *dev = mt792x_hw_dev(hw);
1508 struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
1509 u16 beacon_interval = vif->bss_conf.beacon_int;
1510
→ 1511 if (cfg80211_chandef_identical(&chsw->chandef,
→ 1512 &dev->new_ctx->def) && // ← RAX=0x0: dev->new_ctx is NULL
1513 chsw->count) {
1514 mod_timer(&mvif->csa_timer,
1515 TU_TO_EXP_TIME(beacon_interval * chsw->count));
1516 }
1517 }dev->new_ctx is
struct ieee80211_chanctx_conf *new_ctx declared in
drivers/net/wireless/mediatek/mt76/mt792x.h:264.
Negative how — dev->new_ctx is NULL
because the channel context was already removed before this workqueue
callback executed.
new_ctx lifecycle in the mt7921 driver:
mt7921_add_chanctx() at
main.c:1345 sets dev->new_ctx = ctx.mt7921_remove_chanctx() at
main.c:1386 sets dev->new_ctx = NULL if
dev->new_ctx == ctx.The call path to the crash:
cfg80211_wiphy_work [workqueue]
→ ieee80211_iface_work
→ ieee80211_sta_rx_queued_mgmt
→ ieee80211_rx_mgmt_beacon
→ ieee80211_sta_process_chanswitch
→ drv_channel_switch_rx_beacon (driver-ops.h:1242)
→ mt7921_channel_switch_rx_beacon ← CRASH
ieee80211_sta_process_chanswitch() calls
drv_channel_switch_rx_beacon() at
net/mac80211/mlme.c:2940 when: -
link->conf->csa_active is true - The beacon source is
IEEE80211_CSA_SOURCE_BEACON -
link->u.mgd.csa.waiting_bcn is false and the CSA IE
parse result is zero
The mac80211 layer does not ensure dev->new_ctx is
non-NULL before invoking the driver callback — that invariant is the
driver’s responsibility.
Race / ordering scenario: 1. Connection is
established; mt7921_add_chanctx() sets
dev->new_ctx. 2. The AP sends a Channel Switch
Announcement (CSA) beacon; it is queued. 3. The connection starts
tearing down; mt7921_remove_chanctx() sets
dev->new_ctx = NULL. 4. The workqueue dequeues the
beacon and calls mt7921_channel_switch_rx_beacon() with
dev->new_ctx == NULL. 5. Crash.
The fix is a simple NULL guard at the top of the function, matching
the pattern used in mt7925_csa_work()
(mt7925/main.c:2325):
if (!dev->new_ctx)
return;Note: mt7925_channel_switch_rx_beacon() (mt7925/main.c)
has the same latent bug — it also dereferences
dev->new_ctx->def without a NULL check. Both
functions should be fixed.
Bug introduced by: commit 8aa2f59260eb6
(“wifi: mt76: mt7921: introduce CSA support”, 2024-11-07, Leon Yen /
Ming Yen Hsieh)
That commit added mt7921_channel_switch_rx_beacon()
without the NULL guard. At the time the analogous mt7925
channel_switch_rx_beacon function also lacked the guard;
the guard in mt7925 was added only in
mt7925_csa_work().
No upstream fix for this specific crash has been found in the v7.1-rc1 tree or in lore search results.
Fix: Add if (!dev->new_ctx) return;
to both mt7921_channel_switch_rx_beacon() and
mt7925_channel_switch_rx_beacon(). See
report.patch.
| Commit | Date | Author | Subject |
|---|---|---|---|
8aa2f59260eb6 |
2024-11-07 | Leon Yen / Ming Yen Hsieh | wifi: mt76: mt7921: introduce CSA support |
The mt7921_channel_switch_rx_beacon() function was
introduced in this commit without a NULL guard on
dev->new_ctx. The function was modelled after the mt7925
implementation but the mt7925 csa_work guard
(if (!dev->new_ctx) return;) was not carried over to
either driver’s channel_switch_rx_beacon callback.
⚠️ Line number discrepancy: Prose references to
function definition line numbers are inaccurate. Report claims
mt7921_add_chanctx() at main.c:1345 but actual
location is line 1372 (off by +27). Similarly,
mt7921_remove_chanctx() is claimed at line 1386 but
actually at line 1382 (off by -4). Verify these line numbers when
implementing fixes.