
Linux内核的FUSE(用户空间文件系统)子系统中存在一处安全缺陷,本地攻击者能够通过构造恶意的目录条目填满页缓存,最终获取root权限。该漏洞编号为 CVE-2026-31694,影响内核在缓存 FUSE readdir 请求结果时使用的代码路径。
漏洞概述
FUSE 允许用户空间文件系统通过 /dev/fuse 与内核通信,同时内核可以缓存目录条目以加速后续的读取操作。问题出在 fuse_add_dirent_to_cache() 函数中:该函数根据服务器返回的文件名长度计算目录条目大小,然后将条目复制到单个缓存页,却从未检查条目本身是否会超出单个页面的大小。
关键之处在于,恶意的 FUSE 服务器可以返回一个序列化后大小为 4120 字节的目录条目(在 4KiB 页面大小的系统上),这比标准页面多了 24 字节。当内核将偏移量重置为零并强制复制该记录时,多出的字节就会溢出到下一个内存页面中。危害不仅仅在于内存损坏本身,更在于被破坏数据所在的位置——这些字节会污染页面缓存中的关键内容。
攻击原理与影响
在已验证的攻击场景中,攻击者利用这一溢出破坏 SUID 二进制文件(例如 /usr/bin/su)在页面缓存中的映射,将可执行代码的开头替换为一个简短的 payload。该 payload 在正常流程继续之前调用 setuid(0) 和 setgid(0)。一旦这些特权提升系统调用在 root 属主的程序上下文中成功执行,攻击者便能绕过常规的身份验证检查,获得一个 root shell。
该攻击要求攻击者具备挂载或运行 FUSE 文件系统的能力——通常可通过无特权用户命名空间或 fusermount3 实现。漏洞仅影响使用 4KiB 内存页面的系统,且在 libfuse readdir 缓冲区较大的新内核上可以被利用。使用更大页面大小的系统不会受到此特定溢出大小的影响。
修复与缓解
修复方案十分简单:在缓存任何目录条目之前,直接拒绝那些长度超出单个页面大小的条目。管理员也可以通过限制 FUSE 的使用、在不需要时移除 fusermount3 的 setuid 标志,以及合理限制无特权命名空间来降低暴露风险。
参考来源:Linux Kernel FUSE Vulnerability Lets Attackers Gain Root Privileges
|