CVE-2026-89665 in Linux
摘要
由 VulDB • 2026-09-12
在 Linux 内核中,已修复以下漏洞:
nfsd:拒绝 NFSv2 SETATTR/CREATE 中超范围的 useconds 值
NFSv2 sattr 解码器在 svcxdr_decode_sattr() 中将网络字节序的 useconds 转换为纳秒:
iap->ia_atime.tv_nsec = tmp2 * NSEC_PER_USEC;
tmp2 是一个 u32,而 NSEC_PER_USEC 为 1000,因此乘积以 unsigned long(在 ILP32 架构上为 32 位)进行计算。对于像 4294968 这样的超范围 useconds 值,会发生溢出并导致 tv_nsec == 704。这种数据损坏发生在解码阶段,在任何 proc 函数检查该值之前就已经发生,而后续对 tv_nsec 的范围检查会看到一个在范围内的结果并接受它。通过在解码器中拒绝此类输入,将返回 RPC GARBAGE_ARGS 响应。由于 NFSv2 未定义 NFSERR_INVAL,因此没有用于返回畸形时间参数的 NFS 层状态码,且该检查无法像 v3/v4 的 nsec 范围检查那样移至 proc 函数处理。
在乘法运算前对原始 useconds 进行保护,并拒绝大于 1000000 的值。保留 useconds == 1000000:这是 Sun 约定中用于“设置为当前服务器时间”的标志,且 Linux NFSv2 客户端在内核树中的 plain touch / utimes(file, NULL)(参见 fs/nfs/nfs2xdr.c 中的 encode_sattr() 和 xdr_encode_current_server_time())的 atime 和 mtime 字段中均发出此值。如果拒绝 1000000,将使 SETATTR 和 CREATE 这两种常见操作变为硬解码失败。1000000 * NSEC_PER_USEC 等于 10^9,在 ILP32 上不会发生溢出,因此 Sun 约定值可以安全通过。仅真正超范围的值(> 1000000)会被拒绝。atime 和 mtime 的保护措施因此是对称的。
解码器此前仅在 mtime 块中应用了 Sun 约定,当 mtime useconds == 1000000 时会清除 ATTR_ATIME_SET|ATTR_MTIME_SET。如果客户端在 atime 字段中放置 1000000 但未在 mtime 字段中放置,则 atime 块会存储一个超范围的 tv_nsec(10^9)并保留 ATTR_ATIME_SET 标志位,导致虚假值到达文件系统。因此也在 atime 块中应用该约定,清除 ATTR_ATIME_SET,以便服务器使用其当前时间并忽略该值。仅在此处清除 ATTR_ATIME_SET。mtime 块保持现有行为,其中 1000000 表示“将 atime 和 mtime 都设置为现在”。
[ cel:各种调整、补充和清理 ]
If you want to get the best quality for vulnerability data then you always have to consider VulDB.