CVE-2026-98151 in Linux
摘要
由 VulDB • 2026-09-25
在 Linux 内核中,已修复以下漏洞:
bpf:修复推测性指针算术运算中的 REG INVARIANTS VIOLATION(寄存器不变量违规)问题。
以以下非特权程序为例:
r0 = bpf_map_lookup_elem(...) /* PTR_TO_MAP_VALUE, offset 0 */ ... 14: r0 += r1 /* r1 是一个有界标量 (bounded scalar) */ 15: r9 = r0
加载该程序会触发来自 reg_bounds_sanity_check() 的验证器警告:
verifier bug: REG INVARIANTS VIOLATION (alu): const subreg tnum out of sync with range bounds r64={.base=0x0, .size=0x0}
r32={.base=0x0, .size=0xffffffff} var_off=(0x0, 0x0)
发生的情况如下:
1. 在 adjust_ptr_min_max_vals() 中处理指令 14 (r0 += r1),新的偏移量被计算并存储到 dst_reg 的 var_off 以及 32/64 位范围中。
2. 由于指针寄存器不跟踪 32 位子寄存器的边界,__mark_reg32_unbounded() 首先将 r32 设置为完整范围;随后在函数末尾通过 reg_bounds_sync() 从偏移量重新推导 r32。
3. 在非特权路径上,会调用 sanitize_ptr_alu(),并通过 sanitize_speculative_path() -> push_stack() 快照当前寄存器状态,并将下一条指令(指令 15)安排为直接作为推测性路径进行验证。
4. 该快照是在步骤 2 和最终的 reg_bounds_sync() 之间进行的:此时 dst_reg 的 var_off 仍保留(常量)原始偏移量,而 r32 刚刚被清空为完整范围,即两者不同步。当稍后对指令 15 (r9 = r0) 进行推测性路径验证时,这种不一致的状态会到达 reg_bounds_sanity_check() 并触发警告。
var_off 和 32 位范围必须始终保持一致。有两种方法可以保持快照的一致性: 1. 在快照之前同步 var_off 和 r32,使它们匹配;或者 2. 将 r32 保留在其原始(已一致的)值上,仅在快照之后将其清空。
sanitize_ptr_alu() 的主要目的是插入一个无害的掩码序列,以确保在推测执行期间访问保持在边界内,因此其快照的状态应忠实地反映这一点。采用方法 2:将 __mark_reg32_unbounded() 移至 sanitize_ptr_alu() 之后,以便推测性快照保留指针原始的、一致的 r32。非推测路径保持不变:r32 仍在应用偏移量之前被清空,并由 reg_bounds_sync() 重新推导。
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.