CVE-2023-53671CVE-2023-53671是Linux内核中SRCU(Sleepable Read-Copy-Update,可睡眠读拷贝更新)模块的一个高可用性影响漏洞。该漏洞源于内核提交994f706872e6("srcu: Make Tree SRCU able to operate without snp_node array"),该提交错误地假设CPU 0在系统运行期间始终处于在线状态。然而,在实际应用场景中,存在CPU 0不在线而其他CPU作为引导CPU的情况,例如使用maxcpus=1引导参数启动kdump内核时。
当该缺陷被触发时,系统会出现严重挂起现象。从漏洞描述中的内核日志可以看到,systemd进程(PID 1)和kworker/u16:1工作线程均被阻塞超过122秒,调用栈显示它们在等待fsnotify相关的资源销毁操作完成。具体而言,fsnotify_mark_destroy_workfn工作队列在执行fsnotify_wait_marks_destroyed时无限等待,导致整个系统进入不可用状态。该漏洞主要影响PowerPC架构平台,因为PowerPC上的kdump内核更容易出现非CPU 0作为引导CPU的情况。
该漏洞的CVSS 3.1评分为5.5分,属于中等严重级别。虽然攻击需要本地低权限触发且无需用户交互,但其对系统可用性造成的影响为高(Availability: High),可能导致系统完全挂起,需要强制重启才能恢复。该问题已在Linux内核稳定版中通过多个提交修复,包括2c4d26dad76e、7f24626d6dd8和c7c0bc03fa44等补丁。
从技术层面分析,该漏洞的根本原因在于SRCU树形实现中对引导CPU的错误假设。在Linux内核的SRCU子系统中,当使用SRCU_SIZE_SMALL配置时,相关工作会被委托给一个特定的CPU执行。原提交994f706872e6在重构Tree SRCU使其能够在没有snp_node数组的情况下运行时,隐式地假设了CPU 0始终在线,因此将相关工作硬编码到CPU 0上执行。
然而,在以下场景中CPU 0可能不在线:
1. 使用maxcpus=1引导参数启动kdump内核时,内核可能选择非0号CPU作为引导CPU;
2. 在多CPU系统中,如果CPU 0被配置为离线状态,系统会选择其他CPU作为引导CPU。
当引导CPU不是CPU 0时,SRCU模块尝试将工作委托给不在线的CPU 0,导致工作永远无法被执行。这会引发连锁反应:fsnotify子系统中的标记销毁工作无法完成,进而导致inotify_release、fsnotify_destroy_group等关键清理操作永久阻塞,最终使整个系统陷入挂起状态。
修复方案是修改SRCU模块,使其将工作正确地委托给实际的引导CPU(boot CPU),而非硬编码的CPU 0。这一修改通过获取当前在线的引导CPU ID来实现,确保无论哪个CPU作为引导CPU,SRCU的清理工作都能被正确调度和执行。