|
|
——从显卡黑屏到 3 个未修补的内核 LPE,再到一块快没电的 CMOS 电池:作为一个安全 PM,我为什么不放过任何"小问题"
━━━━━━━━━━━━━━━━━━━━
一、流亡的硬盘
那天下班前,公司那台陪了我两年的台式机——一块 H61 主板的低配机——突然不开机了。POST 没过,电源一闪就熄。
主板修不划算,我做了个决定:把硬盘和显卡拎回家,插到家里那台同样老的 X79 主板上接着用。
为什么这么折腾?因为那块硬盘是双系统:Windows 10 + Ubuntu 24.04。重装一次系统少说半天,把所有开发环境、配置、密钥重新搬一遍,得两天。只要硬盘没坏,主板坏了就只是换一台机器的事。
晚上 9 点,我把 GTX 660 从原机扒下来,连同硬盘一起塞进 X79 那台。开机,Windows 引导正常进了桌面,Ubuntu 也能起来——但屏幕越看越不对劲:分辨率怪、字体糊。
那一刻我下意识做了一个事后想起来错得离谱的判断:会不会是 GTX 660 也跟着主板一起坏了?
家里抽屉还有一块从老笔记本拆下来的 GTX 950M(虽然是笔记本卡,但配上转接卡能在台式机上用)。换上吧,先不让显卡耽误事。
然后……灾难开始了。
━━━━━━━━━━━━━━━━━━━━
二、错怪了一块好卡
GTX 950M 装上去,Ubuntu 桌面终于"看起来正常"——分辨率对了、字也清楚了。我心想问题搞定,做我的事去。
直到我习惯性地。
显示器黑屏。
主机风扇狂转。
硬盘灯不亮。
键盘 NumLock 灯按了没反应。
像一台被某个无形的手按住的机器——电是通的,但什么也没在跑。
等了 30 秒、1 分钟、3 分钟……还是这样。我只能长按电源键强制关机。开机,进系统,一切正常。再,又卡死。
当时的我,盯着那块嗡嗡作响的机箱,脑子里只有一个念头:这块 950M 是不是又坏了?
折腾了快 1 个小时之后,我意识到这事不对劲。我把 GTX 660 重新装回去。这次我决定不再凭直觉做判断,而是好好把问题查清楚。
━━━━━━━━━━━━━━━━━━━━
三、真相:是我自己装错了一整代驱动
把 660 装回去之后开机,跑,得到的回应是:
- NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver.
复制代码
我顺手查了下当前装的是哪个驱动:
- $ dpkg -l | grep nvidia-driver
- ii nvidia-driver-535 535.288.01-0ubuntu0.24.04.2
复制代码
535 系列。
然后我搜了一下:NVIDIA 在 495 版本之后,就完全放弃了 Kepler 架构(GTX 6 系/7 系)的支持。也就是说——
535 这个驱动,在 GTX 660 上根本不会工作。
更荒诞的是:那块"被我冤枉"的 GTX 950M 是 Maxwell 架构,本来 535 是支持它的,但我有一种强烈的怀疑——之前公司那台机器上配的是 H61 + GTX 660,那套 Ubuntu 是当年配着 660 装的,整套显示驱动是按 660 当年版本配的老驱动。后来某次 apt 自动升级把驱动拉到了 535,但那时候机器还是 660,所以显示其实早就半残了,只是表现得不那么明显。
塞进 X79 之后我看到的"分辨率怪、字体糊",根本不是硬件问题,是 nouveau 接管的回退显示。我换上 950M 之后能正常显示,是因为 950M 的 Maxwell 架构是 535 驱动还支持的——但卡死那个现象,是另一个独立问题:老 950M + 新内核 + 不完整驱动栈,关机阶段在卸载 nvidia 模块时死锁了,于是机器进了一个"半关机"状态。
这是给所有技术人的第一个钩子:
当一个症状出现的时候,最危险的不是没思路,而是凭直觉得出第一个结论,然后从此只为这个结论找证据。 >我看到屏幕黑了,立刻就锁定"显卡坏了"——但其实显卡好得很,是我自己装了一个根本不该装的驱动。
打个比方:这就像你给一台 iPhone 4 装了 iOS 18。系统看起来"装上去了",但开机之后要么黑屏要么没反应。你以为是手机坏了,其实是你逼一台 2010 年的硬件去跑 2024 年的代码。
修复方案很简单——但简单不代表轻松。
━━━━━━━━━━━━━━━━━━━━
四、给显卡找回它该穿的"码"
GTX 660 是 Kepler 架构(2012 年的卡),NVIDIA 官方最后支持它的驱动分支是 470 系列。这就是它该穿的"码"。
我做了这件事:
第一步:把当前的 535 系列彻底清干净,然后装 470。
- sudo apt-get purge -y 'nvidia-*' 'libnvidia-*'
- sudo apt-get autoremove -y
- sudo apt-get install -y nvidia-driver-470
- sudo reboot
复制代码
重启完——依然失败。这是第二个坑。
排查发现:DKMS 包确实安装了,但编译模块这一步静默地失败了,根本没有 nvidia.ko 文件被生成到当前内核目录下。
>Linux 内核每升一次小版本(哪怕是个修 bug 的版本),它的"内部接口"都可能微调。显卡驱动要继续工作,就得针对当前内核重新编译一遍——这件事就是 DKMS 自动做的。 >如果哪天 DKMS 编译失败了(比如内核升得太新、驱动太老),它不会大喊大叫——它只会把状态从变成,然后等着你某天发现。
我手动触发了一次编译:
- sudo dkms install nvidia/470.256.02 -k $(uname -r) --force
复制代码
这次它跑了出来,5 个 .ko 模块全部就位。终于亮起来:
- NVIDIA GeForce GTX 660, Driver 470.256.02, 1991 MiB
复制代码
第三步:保证下次开机能自动加载。
这一步必须做,否则关机后这套配置就丢了。我做了两件事:
- # 把 nouveau 拉黑(防止它和 nvidia 抢 GPU)
- echo -e "blacklist nouveau\noptions nouveau modeset=0" \
- | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
- # 声明开机自动加载 nvidia 模块
- echo -e "nvidia\nnvidia_modeset\nnvidia_uvm\nnvidia_drm" \
- | sudo tee /etc/modules-load.d/nvidia.conf
- sudo update-initramfs -u
- sudo reboot
复制代码
重启之后再跑——一次成功。
整个过程花了大约 2 个小时。这 2 个小时里我至少强制关机了 5 次,怀疑过显卡、内存、主板、电源。但真正的问题,从头到尾就是一个:我让一个 2022 年的驱动去管一块 2012 年的显卡。
━━━━━━━━━━━━━━━━━━━━
五、那就别再升级内核了
显卡的事搞定后,我又意识到一个隐患:Ubuntu 默认每个月都会推送新的内核 ABI 版本。每次升级内核,DKMS 就要重新编译一次 nvidia 模块——而 470 驱动已经停止官方维护,新内核出来又会越来越多和它不兼容的地方。
我突然不想再玩这个滚石上山的游戏了。我又不做内核开发,硬件也老了,何必每个月被 apt 推着走?
锁定内核版本,Linux 上用一行命令就能搞定:
- sudo apt-mark hold linux-generic linux-image-generic linux-headers-generic
复制代码想象 apt 是一个负责"管家"的角色,它每个月例行去仓库里给所有东西换新版本。就相当于你贴了张便条在某几个箱子上写:"这些不要动"。其它箱子(浏览器、SSH 服务、桌面环境)该升还是升,只是内核不动。 >
到这一步如果停下,我也就是把一件"前期问题"做完了。但下一个钩子出现了——而且是真正属于我职业本能的。
━━━━━━━━━━━━━━━━━━━━
六、安全 PM 的职业病发作了
我是做网络安全行业的产品经理。"锁住内核"这个动作刚做完,脑子里立刻条件反射地冒出一句话:
最近几个月那几个挺火的 Linux LPE 漏洞,我这版内核打补丁了吗?
LPE = Local Privilege Escalation = 本地提权。白话翻译:你以普通用户登录到系统里,能找到办法变成 root。
这种漏洞看起来"我自己用的电脑无所谓"——但在很多场景下它是致命的最后一公里。比如:
一个 Web 漏洞让攻击者获得了 nginx 用户的 shell ——单独看是低危
但如果他在系统里能找到 LPE ——他能立刻拿到 root
1 + 1 = 拿下整台服务器
这就是为什么搞安全的人对未打补丁的 LPE 漏洞如此敏感。
我查了下 2026 年 5 月公开的几个:
| 漏洞 | 别名 | 影响模块 | 披露日期 |
|---|---|---|---|
| CVE-2026-31431 | Copy Fail |(用户态加密接口) | 2026-04-30 |
| CVE-2026-43284 | Dirty Frag (ESP) | IPsec ESP | 2026-05-08 |
| CVE-2026-43500 | Dirty Frag (RxRPC) | AFS 文件系统协议 | 2026-05-08 |
然后我对照了 Ubuntu 安全公告。结论让我手心微微一凉:
直到今天(2026-05-14),Ubuntu 24.04 还没有发布修复内核。 哪怕我现在解锁内核去升级到最新的,它也是 4 月 11 日打包的——比所有这三个漏洞披露日期都早。 >
换句话说:全世界用 Ubuntu 24.04 的人,此刻都在裸奔。
打个比方:这就像整个小区刚发现自己的门锁可以用回形针拧开,但是锁匠还没赶来。等锁匠没有意义——你能做的事是用别的方法堵住那扇门。
幸好这三个漏洞都不是无解的——Ubuntu 安全团队给出了应用层缓解:
Copy Fail:通过升级包(不在我锁定的范围内)→ 自动 blacklist模块
Dirty Frag (ESP):手动 blacklist、模块(我又不用 IPsec VPN,无影响)
Dirty Frag (RxRPC):手动 blacklist模块(AFS 文件系统,更没人用)
我写了个脚本一次搞定:
- #!/usr/bin/env bash
- # 缓解 2026-05 的三个 Linux 内核 LPE
- set -e
- sudo apt-get update
- sudo apt-get install -y --only-upgrade kmod # Copy Fail
- cat <<EOF | sudo tee /etc/modprobe.d/blacklist-lpe-2026-05.conf
- install esp4 /bin/true
- install esp6 /bin/true
- install rxrpc /bin/true
- blacklist esp4
- blacklist esp6
- blacklist rxrpc
- EOF
- for m in esp4 esp6 rxrpc algif_aead; do
- lsmod | grep -q "^$m " && sudo rmmod "$m" || true
- done
- sudo update-initramfs -u
复制代码
跑完之后我做了一件很关键的验证——主动模拟攻击者去加载这些模块,看会不会被拦下:
- $ sudo modprobe -n -v algif_aead
- install /bin/false # ← 拦截成功
- $ sudo modprobe -n -v esp4
- install /bin/true # ← 拦截成功
- $ sudo modprobe -n -v rxrpc
- install /bin/true # ← 拦截成功
复制代码这一步比写脚本更重要:永远不要相信"我配置完了"这句话,要相信"我验证过了"。
到这一步,那三扇被回形针能撬开的门,都已经被木条钉死了。等 Ubuntu 出补丁的那天,再把木条拆掉就行。
━━━━━━━━━━━━━━━━━━━━
七、最后是那块快没电的电池
时间已经过去三个多小时了。一切都按部就班地修好了,我本该去睡觉。但脑子里又冒出来一个执念:
这块主板 BIOS 是 2019 年的,主板上的 CMOS 电池估计也是 7 年前装上去的。 如果哪天它真没电了,每次断电后 BIOS 设置都会重置——启动顺序、CPU 频率、SATA 模式全部回到出厂。
软件层面,没法直接测 CMOS 电池电压——消费级主板不通过 SMBus 暴露这个数据。但有几个间接信号可以推断它的状态:
- # 1. RTC 时钟漂移:开机时硬件时间 vs 真实时间
- timedatectl status
- # 2. 历次开机时间是否合理(如果偶尔跳回 1970/2010,就是电池坏了)
- last reboot -n 10
- # 3. 内核启动期 RTC 相关错误
- sudo journalctl -b -k | grep -iE "rtc|cmos"
复制代码
我跑下来:RTC 漂移 = 1 秒(极优秀);过去 10 次开机时间都正常连续;没有 CMOS 错误。电池目前是健康的。
但——电池都 7 年了,CR2032 设计寿命是 5–10 年,已经进入"还能用,但已开始衰减" 的区间。这种情况怎么办?
主板关机休眠的时候,机箱里唯一还活着的东西就是它——靠它续着 BIOS 设置、维持时钟、记着启动顺序。 它失效之前不会"提示"你,只会某天断电后开机让你发现日期回到 2010 年、SATA 模式被重置、Windows 因找不到启动盘而蓝屏。
我顺手下单了一块松下 CR2032——5 块钱不到。
预防性更换比等出问题再修,省的不是钱,是当时那种"屎到临头才发现"的崩溃感。
━━━━━━━━━━━━━━━━━━━━
八、为什么我要折腾这一晚?
凌晨 1 点多,所有事都做完了。我合上电脑前回想了一下整晚做的事:
第一遍:搬硬盘,原以为是搬完就完事
第二遍:换 GTX 950M,以为修了显卡
第三遍:换回 GTX 660,发现是驱动错了
第四遍:装 470 驱动,遇到 DKMS 静默失败
第五遍:锁内核 + 应用 CVE 缓解
第六遍:检查 CMOS 电池
6 件事,每一件都本来可以"算了,先用着再说"。 但我都没放过。
我并不是要在公众号面前装个"完美主义"的人设。让我说为什么——
作为技术人,最伤人的不是 bug,是"先放着"留下的心理债。
那块"先放着不查的显卡问题"会变成:以后每次重启心里都不踏实,怕它再卡死。
那行"先不动的 535 驱动"会变成:某天你换了别的硬件,突然发现根本起不来。
那条"等等再装的 CVE 缓解"会变成:某天看到一篇新闻里有公司因为这个被入侵了,你心里咯噔一下。
那块"过几年再换的 CMOS 电池"会变成:某次断电之后开机蓝屏,你才想起来一年前就该换。
每一个"先放着"的问题,都会在某个最不该出问题的时刻冒出来咬你。
反过来——每一个被刨根究底解决掉的问题,都是一笔复利:
弄清楚了 Kepler 架构和 470 驱动的关系 → 以后再装老显卡不会再绕弯
学会了 DKMS 的"静默失败"机制 → 以后任何内核相关问题都会想到去看一眼
理解了的边界 → 知道它能锁什么、不能锁什么
见识了"漏洞已公开但 Ubuntu 还没修"的真实窗口期 → 以后会主动跟 USN 公告,而不是等 apt 推
知道了 RTC 漂移可以反推 CMOS 电池状态 → 这事将来对任何老机器都适用
每个被刨根究底的问题,都从"以后会回来咬你的隐患"变成了"以后帮你省事的资产"。 >每个被"先放着"的问题,反过来——它会在你脑子里安一个小钩子,时不时提醒你"那个事还没解决"。 它会变成你内心的一块阴影。
技术人成长这件事,没有别的捷径。它就是由无数个"我本可以放过它,但我没有"组成的。
━━━━━━━━━━━━━━━━━━━━
写在最后
这篇文章很长,但其实只想说一件事——
遇到问题,就一次性把它修好;想清楚问题,就一次性把根挖到底。
可能你说"我没那么多时间"——但其实你算过吗?我今晚花的 3 个多小时,省下来的是未来 N 次"莫名其妙问题"的折腾时间、是未来某个安全事件发生时"我以为我没事"的窗口期、是未来某次断电后开机蓝屏的崩溃感。
这不是完美主义,这是工程师的"复利账户"。
愿你今晚不要错过一个本可以查清楚的问题。
━━━━━━━━━━━━━━━━━━━━
本文从一次硬件搬迁讲到 LPE 漏洞缓解再到 CMOS 电池——背后所有的脚本都是真实跑过的、所有的命令都是可以复用的。如果对其中某个细节感兴趣,欢迎评论区或加微信群一起讨论。
 |
|