SMBus is busy, can‘t use it! + task blocked 120s - i2c-i801 错误路径释放未获取资源致 hung task(CVE-2026-64205)

📅 2026/8/16 9:18:45
SMBus is busy, can‘t use it! + task blocked 120s - i2c-i801 错误路径释放未获取资源致 hung task(CVE-2026-64205)
title: “运维漏洞指南SMBus is busy, can’t use it! 日志洪泛 INFO: task blocked for more than 120 seconds——i2c-i801 驱动错误路径释放未获取资源导致 hung task panicCVE-2026-64205 内核源码级解析”column: “运维漏洞指南”tags: [“i2c-i801”, “SMBus”, “hung task”, “printk”, “CVE-2026-64205”, “内核驱动”, “livelock”, “console livelock”]TL;DR2026-07-20 公开的内核漏洞 CVE-2026-64205i2c: i801揭示了一条反直觉的故障链驱动在错误处理路径里「清理」了一个它从未真正获取的硬件资源直接把 SMBus 硬件状态机打坏随后陷入「SMBus is busy, can’t use it!」printk 无限刷屏 hung task watchdog 双双告警的死循环。根因不在硬件而在drivers/i2c/busses/i2c-i801.c的i801_access()当i801_check_pre()失败如 SMBus 控制器正被 BIOS/ACPI 占用返回-EBUSY时代码跳转到out标签后无条件执行iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv))——强行清除 INUSE_STS 锁并复位硬件状态标志但此时驱动根本没拿到控制器所有权。这一写直接打断了正在进行的 BIOS/ACPI 事务SMBus 状态机彻底错乱之后每次访问都在 pre-check 阶段失败无限打印SMBus is busy, cant use it!。在慢速串口控制台上printk 洪泛垄断 CPUConsole Livelock饿死等待mmap_lock的其他进程最终触发 hung task watchdog。修复只移动了out标签一行代码i801_check_pre()失败时绕过iowrite8()只释放软件锁pm_runtime 和 mutex——严格遵循「未获取的资源不得释放」。现象双告警同时出现先别急着重启你看到的日志服务器突然卡顿dmesg里同时出现两类告警i801_smbus 0000:00:1f.3: SMBus is busy, cant use it! i801_smbus 0000:00:1f.3: SMBus is busy, cant use it! i801_smbus 0000:00:1f.3: SMBus is busy, cant use it! ...无限刷屏 INFO: task kworker/0:1 blocked for more than 120 seconds. INFO: task kworker/0:1 blocked for more than 120 seconds.这两类日志放在一起第一反应通常是「SMBus 硬件坏了」或「hung task 是磁盘问题」。但真实因果是printk 洪泛是原因hung task 是结果。排查的第一原则遇到「刷屏 hung task」组合第一步不是看业务进程而是看刷屏的 printk 来自哪个驱动journalctl -k | grep -E i801|i2c|smbus控制台是什么串口 console 还是虚拟终端dmesg -n 3能否压住刷屏能压住 可以临时止血继续排查如果刷屏的是 i2c-i801 驱动的SMBus is busy不要怀疑硬件——先查内核版本这个故障链在 6.3 及以上内核都可能存在直到 2026-07 修复6.18.39 / 7.1.4 已合入。排查回合制从刷屏到根因回合 1确认刷屏源# 看 SMBus 刷屏频率和来源dmesg|grep-cSMBus is busy# 数量几分钟内成千上万dmesg|grepi801_smbus|tail-20# 确认驱动 设备地址典型输出[12345.678] i801_smbus 0000:00:1f.3: SMBus is busy, cant use it!0000:00:1f.3是 Intel 平台的 SMBus 控制器PCH 上的 I2C/SMBus 主机控制器这是几乎所有 Intel 服务器/台式机都有的设备——不是你的服务器特殊是每个人都会碰到这条路径。回合 2区分「偶发 busy」与「故障态 busy」SMBus is busy这条日志本身偶发出现是正常的——BIOS/ACPI 有时会占用 SMBus 做内存条 SPD 读取、温度监控、风扇控制。故障态的标志是「持续刷屏」# 10 秒内刷屏次数正常 0-1 次故障态几百上千timeout10sh-cdmesg -w | grep -c SMBus is busy回合 3查 hung task 与 printk 的关联# hung task 的调用栈关键看是否在等 mmap_lockcat/proc/sys/kernel/hung_task_timeout_secs# 默认 120dmesg|grep-A20blocked for more than 120 seconds|head-40CVE-2026-64205 报告中的复现场景并发 fuzzing里hung task 的调用栈指向等待mmap_lock读锁——因为 printk 刷屏在慢速串口上每个字符都要等串口发送完成CPU 时间几乎全被刷屏消耗其他进程拿不到调度饿死在锁等待上。回合 4确认内核版本受影响uname-r# 受影响区间 6.3该版本引入无条件清理代码的回归# 已修复6.18.39 / 7.1.4 / 7.2-rc1 之后的版本触发条件i801_check_pre()返回失败典型为-EBUSYSMBus 控制器正被 BIOS/ACPI 使用 并发访问 SMBus。fuzzing 是最容易触发的方式但生产环境的 i2c 工具i2cdetect、i2cget、lm-sensors 监控脚本、BMC 带外管理通道都可能成为触发器——只要有一个访问在 BIOS/ACPI 占用期间发起就进入损坏路径。根因解析一行 iowrite8 如何毁掉硬件状态机正常流程 vs 错误流程i801_access()是 i2c-i801 驱动所有 SMBus 事务的入口。正常流程// drivers/i2c/busses/i2c-i801.c修复前逻辑staticinti801_access(structi2c_adapter*adap,u16 addr,...){intret;structi801_priv*privi2c_get_adapdata(adap);pm_runtime_get_sync(priv-pci_dev-dev);// ① 获取软件锁pm_runtimemutex_lock(priv-bus_lock);// ② 获取互斥锁reti801_check_pre(priv);// ③ 检查硬件是否可用if(ret0)gotoout;// ← 错误跳转/* ... 正常执行 SMBus 事务 ... */reti801_check_post(priv,status);out:/* 无条件硬件清理问题代码 */iowrite8(SMBHSTSTS_INUSE_STS|STATUS_FLAGS,SMBHSTSTS(priv));// ④ 清硬件锁pm_runtime_put(priv-pci_dev-dev);// ⑤ 释放软件锁mutex_unlock(priv-bus_lock);returnret;}问题所在当 ③i801_check_pre()失败返回-EBUSY因为 SMBus 控制器正被 BIOS/ACPI 占用代码跳到out后仍然执行了 ④iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv))。这行写操作干了什么SMBHSTSTS_INUSE_STS是硬件寄存器里的「使用中」锁位。BIOS/ACPI 正在占用 SMBus 时这个位由 BIOS/ACPI 设置驱动在没有获取硬件所有权i801_check_pre失败 没拿到锁的情况下强行iowrite8把这个位清掉写 1 到该位 清除中断状态位同时STATUS_FLAGS把状态寄存器里的各种标志位也一起复位了。这一写直接打断了正在进行中的 BIOS/ACPI SMBus 事务——对方的事务被硬生生中断SMBus 控制器的内部状态机从此错乱。蝴蝶效应链i801_check_pre() 失败-EBUSYBIOS/ACPI 占用中 │ ▼ 无条件 iowrite8 清 SMBHSTSTS打断 BIOS/ACPI 事务 │ ▼ SMBus 硬件状态机错乱 │ ▼ 后续所有 i801_access() 都在 pre-check 失败 │ ▼ 无限 printk SMBus is busy, cant use it! │ ▼ 慢速串口 console → Console Livelockprintk 垄断 CPU │ ▼ 其他进程饿死等 mmap_lock_down_read→ hung task watchdog修复移动一行修复 commit00904687b9c55等的核心是把out标签移到硬件清理之后reti801_check_pre(priv);if(ret0)gotoout;// 错误路径不再执行 iowrite8/* ... 正常事务 ... */iowrite8(SMBHSTSTS_INUSE_STS|STATUS_FLAGS,SMBHSTSTS(priv));// 只在正常路径清理out:pm_runtime_put(priv-pci_dev-dev);mutex_unlock(priv-bus_lock);returnret;原则一句话没获取的资源不得释放do not release resources that were never acquired。这不仅是 i2c-i801 的问题是所有驱动错误路径的通用检查点——错误处理代码必须知道「当前持有哪些资源」而不是盲目清理。通用教训错误路径的资源所有权审计CVE-2026-64205 的根因模式在 Linux 驱动里反复出现。做代码审查或排障时对每个错误路径问三问问题案例这个清理动作对应的「获取」在错误路径里真的执行了吗i801i801_check_pre失败 → 没获取硬件锁 → 却清硬件锁错误路径是否跳过了部分获取步骤但执行了全部释放步骤常见于先 pm_runtime_get 成功、后 mutex_lock 失败但释放时两个都释放或都跳过释放顺序与获取顺序是否完全相反获取 A→B释放必须 B→A内核自带的检测工具CONFIG_DEBUG_ATOMIC_SLEEP检测原子上下文里的睡眠CONFIG_PROVE_LOCKINGlockdep检测锁顺序反转和错误释放CONFIG_KASAN检测 use-after-free / 越界如果当时跑着 lockdep这种「未获取就清理」的问题在开发阶段就可能暴露——但硬件寄存器清理不走 lockdep 管的路所以只能靠代码审查 fuzzingsyzkaller 正是抓到这类问题的利器。排障决策表SMBus is busy 对号入座症状根因第一动作偶发一次 SMBus is busyBIOS/ACPI 瞬态占用无需处理持续刷屏 hung taski2c-i801 错误路径破坏状态机CVE-2026-64205升级内核≥6.18.39 / 7.1.4dmesg -n 3 止血开机即刷屏BIOS 初始化阶段冲突检查 BIOS 设置SMBus 占用相关项i2cdetect 报 Can’t use SMBus Quick Write工具/总线功能位问题非内核 bug与本文故障区分不是刷屏型故障刷屏但无 hung taskprintk 洪泛尚未饿死进程立即止血防止升级成 livelock常见误区表误区为什么错正确做法「SMBus is busy 说明硬件坏了」该日志只表示控制器正被占用持续刷屏才是故障态先看内核版本再判断是否硬件「hung task 是磁盘/文件系统问题」hung task 只是「进程 120 秒没调度」的通用告警根因可能是 printk 垄断 CPU先看刷屏日志hung task 往往是被牵连的「重启就能解决不用管」重启确实恢复 SMBus 状态机但同一触发条件会复发重启后必须升级内核否则下次并发 fuzzing/访问还会触发「dmesg -n 3 治好了」只是压低日志级别硬件状态机已坏SMBus 功能仍不可用只做临时止血必须升级内核「这问题只有 fuzzing 才碰到生产没事」生产环境的 i2c 工具、lm-sensors、BMC 通道都可能成为触发器高危场景大量监控脚本读 SMBus更该升级进阶风险视角什么时候它会变成业务事故CVE-2026-64205 不只是「内核日志刷屏」的学术问题在特定场景会直接演变成业务事故带外管理通道依赖 SMBus 的服务器BMC/IPMI 与主机的 SMBus 共享控制器状态机损坏后带外温度/电源监控失效可能误触发硬件保护如风扇全速、断电保护。慢速串口控制台 高密度日志串口 console9600/115200 baud比虚拟终端慢几个数量级同样的 printk 洪泛在串口上饿死进程的速度快得多——机房通过串口管理的老服务器是重灾区。监控自愈脚本误判dmesg刷屏会被监控系统当成「SMBus 硬件故障」告警自动化脚本可能触发误重启/误切换反而扩大故障面。触发条件的「巧合性」BIOS/ACPI 占用 SMBus 的时机不受你控制内存 SPD 刷新、ACPI 电源事件任何一次「恰好并发」的 i2c 访问都可能踩中——这解释了为什么故障看起来「无缘无故」。内核版本与修复演进表版本状态说明 6.3不受影响该回归由 6.3 引入错误路径无条件清理代码6.3 ~ 6.18.38受影响触发条件i801_check_pre()失败 后续 SMBus 访问6.18.39已修复首个稳定修复版本7.1.4已修复LTS 分支修复7.2-rc1已修复主分支修复00904687等 commit各发行版 backport视厂商Ubuntu/Debian/RHEL 的 backport 版本需查厂商安全公告升级前确认触发条件是否在你的环境存在Intel PCH SMBus0000:00:1f.3 任何 i2c 访问工具 BIOS/ACPI 并发占用。没有 SMBus 设备的纯 ARM 服务器不受影响但排查日志时仍可能看到别的驱动刷屏——方法论通用。复盘方法论日志洪泛 挂起类故障的三步定位这次排查可以用一条通用方法论复用到所有「刷屏 卡顿」故障先找洪泛源再查挂起dmesg里刷屏的那条日志通常是根因hung task / 高负载只是受害者。先grep -c数刷屏再grep -A 20 blocked看挂起栈。区分「提示性日志」与「故障态日志」SMBus is busy单条是提示持续刷屏才是故障。任何日志都要看频率不看单条。追溯代码的「资源所有权」当排障指向驱动/内核模块时回到源码看错误路径是否「释放了未获取的资源」——这是 CVE-2026-64205 的根因也是驱动类 bug 的高发模式。解决方案与自检清单修复步骤升级内核 6.18.39/ 7.1.4或厂商已 backport 的发行版内核临时止血升级前dmesg -n 3压低 console 日志级别缓解 console livelock不治本硬件状态机已坏重启恢复 SMBus 硬件状态机重启后 BIOS 重新初始化控制器排查哪些进程在频繁访问 SMBuslsmod | grep i2c、lm-sensors、i2c-tools 脚本故障态下停止访问验证dmesg | grep -c SMBus is busy不再增长i2cdetect -l正常列出总线温度/风扇监控依赖 SMBus 的 hwmon恢复读数自检清单内核版本 6.18.39 / 7.1.4或厂商修复版SMBus is busy不再刷屏10 秒 0-1 次hung task 告警消失lm-sensors / BMC 带外通道读取正常触发场景并发 fuzzing / 高频率 i2c 访问 BIOS 占用已消除启示CVE-2026-64205 的价值不在 SMBus 本身而在它演示的排障顺序当「日志洪泛 hung task」同时出现先找洪泛源别被 hung task 带偏。刷屏的驱动日志往往是根因hung task 只是 printk 垄断 CPU 的受害者。另外所有「错误路径清理」代码都值得用「未获取不释放」这条铁律重新审一遍——一个看似无害的iowrite8在错误路径上能通过「打断硬件状态机 → 无限刷屏 → console livelock → hung task」的连锁反应让一台 128 核服务器看着像硬件故障实际只是一行标签位置错了。最后补充一个运维直觉内核驱动日志的「单条出现」和「持续刷屏」是两个完全不同的世界。前者是正常提示SMBus 被 BIOS 占用瞬间后者是故障信号状态机已坏。给监控系统配告警时务必基于「频率阈值」而非「单条出现」——否则你会被SMBus is busy这种正常日志淹没真正的故障反而被忽略。这次的内核修复移动 out 标签在 patch 里只有几行但背后的教训——错误路径必须精确知道「我持有哪些资源」——适用于任何需要清理资源的代码从内核驱动到应用层连接池都成立。原始出处CVE-2026-64205NVD2026-07-20 发布kernel.org 报告修复 commits00904687b9c5527d569d9a1ca72119823e735a61/10dd1a736d557e310a77117832874729a0175d57/bb5133a7d5f3fe5c387770e25f2e00e682ce11ed等受影响Linux 6.3 起修复于 6.18.39 / 7.1.4 / 7.2-rc1。