977 字
3 分钟
MT7902 再再再续
2026-05-26

前情提要#

上回说到,我靠二进制补丁——改了 .ko 里 20 个字节——把 mt7902e 驱动的 NULL 指针给修了

系统安稳了半个月,没再锁死

我以为这事就完了

然后它又死了#

5 月 26 号早上,系统又双叒叕卡死了

跟以前一模一样的症状——鼠标能动但点不了东西,网断了,TTY 切不了,只能长按电源

查日志:

journalctl -b -1 -p 3
kernel: BUG: kernel NULL pointer dereference, address: 0000000000000000
kernel: RIP: mt7921_channel_switch_rx_beacon+0x18/0xa0 [mt7902e]
kernel: CR2: 0000000000000000

同一个函数,不同偏移

上回崩在 +0x9,这回升到了 +0x18——说明崩溃路径不一样

这次是怎么回事#

把堆栈和寄存器看了一遍:

RAX: 0000000000000000 ← 问题在这里,RAX 是 NULL

反汇编确认:

; 函数开头
mov 0x58(%rdi),%rax ; dev = hw->priv (安全)
; 然后直接
mov 0x8(%rax),%rax ; 上一条 RAX 非空,这步也安全
; ...
mov (%rax),%rcx ; CRASH! RAX=0

跟上回的区别:

  • 上回:第一层指针 phy 就是 NULL,mov 0x8(%rax) 直接崩
  • 这回:第一层指针拿到了,但走到后面 dev->new_ctx 是 NULL,解引用 new_ctx->def 才崩
// 罪魁祸首
if (cfg80211_chandef_identical(&chsw->chandef,
&dev->new_ctx->def) && // ← new_ctx 可能 NULL
chsw->count)

dev->new_ctx 是什么时候被清空的?remove_chanctx 会把它设 NULL。很简单的时序问题:AP 发了 CSA 信标,驱动收到信标时 new_ctx 已经被清了

这次换了个玩法#

上回是二进制改动 .ko 文件,因为那时候用的是内核自带的 stock 模块

但这回我换方案了——改用 DKMS 外部驱动mediatek-mt7927),理由就一个:DKMS 编译的模块在内核更新后会自动重建,不用每次 pacman -Syu 都重新打补丁

# 源码路径
/usr/src/mediatek-mt7927-2.10/mt76/mt7921/main.c

DKMS 驱动的爽点:改完源码 dkms build + install 就完事,内核更新后 dkms autoinstall 自动搞定

但 DKMS 有个坑——dkms.conf没有设 PATCH 指令,所以 patches/ 目录下那些 .patch 文件只是放着好看,build 的时候根本不会自动打进去。第一次跑的时候就被坑了,build 成功了但补丁没生效

修复#

跟上次一样的补丁逻辑——一行 NULL 守卫:

if (cfg80211_chandef_identical(&chsw->chandef,
if (dev->new_ctx &&
cfg80211_chandef_identical(&chsw->chandef,
&dev->new_ctx->def) &&
chsw->count) {

手动 sudo patch 到源码 → sudo dkms buildsudo dkms installsudo modprobe -r mt7902e && sudo modprobe mt7902e

WiFi 回来了,正常连上

这次和上次的区别#

项目上次这次
编译方式stock kernel 内置DKMS 外部驱动
修哪里二进制改 .ko源码改 .c
崩溃路径phy 指针 NULLdev->new_ctx 指针 NULL
补丁方式改 20 字节汇编加一行 dev->new_ctx &&
内核更新后要重新打补丁自动重建
对用户影响WiFi 断连重连同左

以后内核更新?跑一下 dkms-patch.sh 就行

所以为什么同一个函数崩两次#

回头看,mt7921_channel_switch_rx_beacon 这个函数是 mac80211 的回调,AP 发 CSA 信标时触发。但这个驱动在信道切换的整个流程里,有好几处指针可能会在时序竞争中被清 NULL

库里的二进制补丁修的是第一级指针路径,这次源码补丁修的是 new_ctx 路径。两条不同的崩溃路径,同一个入口函数

驱动是 2025 年底编译的,那时候上游 mt76 可能还没修全这些路径。不过现在有了源码级补丁,以后不管内核怎么升级,驱动都不会再因为这个崩了

补丁仓库#

源码补丁和打包脚本也一并更新到了之前的仓库:

GT001well
/
mt7902e-null-fix
Waiting for api.github.com...
00K
0K
0K
Waiting...

新增了 mt7902-null-ptr-csa-beacon.patch(源码级补丁)和 dkms-patch.sh(自动打补丁+重建脚本)

一点感受#

距离上次修这个 bug 已经过了半个月,当时我以为二进制补丁就能一劳永逸了

结果同一行代码,换了个时机,又坑了我一次

好在这次更彻底——源码级修复、DKMS 自动构建、更新不丢补丁

而且这次修完我还顺带把整个驱动源码都扫了一遍,确认了没有其他类似的危险解引用。应该不会再有三回了,吧

补丁已推送,等下次内核更新验证

我觉得应该不会有第四次了……吧?

系统: Arch Linux
内核: 7.0.3-zen1-2-zen
网卡: MediaTek MT7902 (Filogic 310) PCIe
驱动: mediatek-mt7927 DKMS 2.10
补丁仓库:
::github{repo="GT001well/mt7902e-null-fix"}

Saya提供技术支持

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

MT7902 再再再续
https://text.lilystar.cn/posts/mt7902-再再再续/
作者
Lily
发布于
2026-05-26
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录