CVE-2023-53655CVE-2023-53655是Linux内核RCU(Read-Copy-Update,读拷贝更新)子系统中存在的一个栈溢出漏洞。该漏洞位于内核函数`__rcu_irq_enter_check_tick()`中,当用户通过kprobes机制在该函数上注册探测点时,会导致内核栈发生无限递归调用,最终引发栈溢出并导致内核崩溃(Kernel Panic)。
该漏洞的触发条件相对简单:攻击者只需在启用了CONFIG_NO_HZ_FULL配置项的系统上,通过/sys/kernel/tracing/接口注册一个针对`__rcu_irq_enter_check_tick()`函数的kprobe,即可触发内核栈溢出。由于该函数在中断处理和RCU状态切换过程中会被频繁调用,kprobe的断点异常处理会再次进入该函数,形成递归调用链,最终耗尽内核栈空间。
该漏洞的影响范围涵盖多个Linux内核稳定版本,包括6.2.0-rc2等版本。漏洞的CVSS评分为5.5,属于中危级别。虽然该漏洞需要本地低权限访问才能利用,但其高可用性影响(导致系统完全崩溃)使其成为一个值得关注的安全问题。内核开发者通过将`__rcu_irq_enter_check_tick()`函数添加到kprobes黑名单(使用NOKPROBE_SYMBOL()宏)来修复此问题。
从技术层面分析,该漏洞的根本原因在于`__rcu_irq_enter_check_tick()`函数被设计为在中断进入路径中被频繁调用,特别是在启用了CONFIG_NO_HZ_FULL(无hz全模式)的情况下。当用户通过kprobes子系统在该函数上注册探测点时,每次执行到该函数的入口处,CPU会触发一个调试异常(BRK指令,AArch64架构下)。
调试异常处理函数`el1_dbg`会调用`arm64_enter_el1_dbg`,进而调用`ct_nmi_enter`,最终再次到达`__rcu_irq_enter_check_tick()`函数。由于kprobe断点仍然存在,这会形成无限递归调用链:
1. 用户代码执行到`__rcu_irq_enter_check_tick()`
2. CPU检测到kprobe断点,触发BRK异常
3. 异常处理程序el1_dbg被调用
4. 异常处理路径再次执行到`__rcu_irq_enter_check_tick()`
5. 再次触发BRK异常
6. 循环往复,直到内核栈耗尽
从崩溃日志中可以看到,调用栈反复出现`__rcu_irq_enter_check_tick -> arm64_enter_el1_dbg -> el1_dbg -> el1h_64_sync_handler -> el1h_64_sync`的循环,最终内核报告"Insufficient stack space to handle exception!"并触发Kernel Panic。
修复方案是使用`NOKPROBE_SYMBOL()`宏将该函数标记为不允许kprobe探测,这样内核在编译时会在该函数的入口处放置一个特殊的标记,kprobes子系统在注册时会检测到该标记并拒绝注册,从而防止递归调用的发生。