计算在哪里出了错
CVE-2025-37858 涉及 fs/jfs/jfs_dmap.c 中 dbExtendFS() 的分配组大小计算。代码使用的是 1 << l2agsize。Linux CVE 公告指出,在 32 位系统上移位量超过 31 时,会产生未定义行为和无效的分配组大小。
微妙之处在于表达式本身。整数字面量 1 并不会因为结果要存入一个更宽的字段,就自动变成 64 位操作数。先计算移位,再进行赋值。只审查目标变量的类型,就会忽略真正产生这个值的运算。
移位之前先拓宽操作数
修复在移位之前把左操作数转换为 s64。这样运算就使用了预期的位宽,并与分配组大小字段的类型一致。下面的对比展示了公告中记录的表达式改动。
如果对已经算完的表达式再做转换,就为时已晚。乘法运算和分配大小计算也同样需要注意这一区别。更宽的中间类型同样需要适当的范围检查;仅仅拓宽类型,并不能让所有可能的输入都变得安全。
- bmp->db_agsize = 1 << l2agsize;
+ bmp->db_agsize = (s64)1 << l2agsize;审查中间值
针对每一个大小计算,写下操作数的实际类型、有无符号以及有效的输入范围。在赋值之前检查表达式,包括类型提升和显式转换。如果 32 位和 64 位配置会影响类型或构建行为,两种受支持的配置都要审查。
边界测试应覆盖预期上限附近的取值,并断言所得的大小或拒绝结果。Sanitizer 和静态分析可以提供帮助,但审计人员仍需把这些算术运算与下一步操作的假设联系起来。
为什么这不只是文件系统的问题
公开公告提到,无效的分组大小可能导致文件系统损坏和内核崩溃。但这并不能说明您应用中某个看似相似的表达式会造成什么影响;要弄清这一点,需要把结果一路追踪到使用它的地方。
在处理长度、偏移量、缓冲区以及不可信文件元数据的原生应用中,这一审计思路同样有用。一次范围明确的安全代码审计,可以检查该计算以及受它控制的内存或存储操作。对于已部署的 Linux 软件包,请以最新的 CVE 记录和厂商公告来确认修复状态。
参考来源
漏洞记录
CVE-2025-37858需要在您自己的产品中检查这个问题吗?
安全代码审计想学会自己发现这类漏洞吗?
安全代码审计课程(一对一)