fs/fuse/readdir.c:fuse_add_dirent_to_cache() 中缺少边界检查。一个 FUSE 服务器返回一个 namelen = 4095 的目录项,序列化后为 4120 字节的记录。内核将其复制到一个 4096 字节的页缓存页中,并溢出 24 个服务器可控字节到下一个物理页。
本仓库包含一个用于写入原型的标记 PoC,以及一个本地提权利用,该利用将溢出整理到 /etc/passwd 的页缓存副本上,并将 root 账户改为无密码账户。
FUSE_NAME_MAX 提升到 PATH_MAX - 1 使 readdir 路径可达)51a8de6c50bf9 "fuse: reject oversized dirents in page cache"(五个稳定版本反向移植之一)该溢出是对 FUSE 缓存页紧随其后的任何物理页的内核写入。该利用旨在将写入定向到选定的页,但这是概率性的。如果失败,24 字节可能会命中不相关的页:
仅在一次性虚拟机中运行。此处的脚本始终在 QEMU/KVM 内部运行利用,绝不在宿主机上运行。
exploit.c PoC 和 LPE(单个文件,静态构建)
Makefile 构建 ./exploit(静态)
vm/config.sh 所有路径和设置(编辑 KERNEL_TREE)
vm/make_rootfs.sh 构建 Ubuntu 24.04 客户机镜像(以 root 运行)
vm/build_vuln_kernel.sh 从内核树构建易受攻击的 bzImage
vm/run_vm.sh 无头启动客户机
vm/provision_guest.sh 客户机内设置(通过 ssh 运行)
vm/run_in_vm.sh 单个命令:启动、配置、运行、验证
宿主机:带有 KVM 的 Linux(/dev/kvm 存在,用户属于 kvm 组),以及:
qemu-system-x86_64、sshpass、gcc、makemake_rootfs.sh:debootstrap(以及 root 权限)还需要一个 Linux 内核源码树来构建易受攻击的内核。
编辑 vm/config.sh。必须设置的值是 KERNEL_TREE:一个 Linux 源码签出的路径。使用修复版本 51a8de6c50bf9 之前的 revision(任何 6.15..7.0 的签出都包含此 bug)。如果树已经包含修复,build_vuln_kernel.sh 会在构建时移除防护,并在之后恢复文件。其他所有设置(内存、CPU、ssh 端口、镜像路径)都有默认值,可以保留。任何值也可以从环境变量设置,例如 KERNEL_TREE=/path/to/linux vm/run_in_vm.sh。
构建客户机镜像(Ubuntu 24.04,需要 root 权限用于 debootstrap):
sudo vm/make_rootfs.sh
这将创建一个 test:test 的 sudo 用户、一个串行控制台、ssh 密码认证和 fuse3。
构建易受攻击的内核:
vm/build_vuln_kernel.sh
端到端(启动、配置、标记 PoC、LPE、验证 uid 0):
vm/run_in_vm.sh
手动:
vm/run_vm.sh & # 无头启动;控制台输出到 vm/serial.log
make # 构建静态 exploit
# 将 ./exploit 复制到客户机中,然后以 test 用户身份运行:
./exploit --poc -n 20 # 标记测试
./exploit # 预热,然后 LPE
停止虚拟机:
pkill -f bzImage-fuse-vuln
--poc 仅标记模式,不修改 /etc/passwd
-n N 轮数
(无参数)5 轮预热,然后最多 200 次 LPE 尝试;成功后,将无密码的 root 行写入
/etc/passwd 并清除缓存
标记模式每轮打印命中数和总数,例如 20/20 (100.0%)。
LPE 模式打印 Warmup: 5/5,然后打印 LPE n/200 ... HIT! 行,将 /etc/passwd 的第一行从 root:x:0:0:root:/root:/bin/bash 更改为 root::0:0:root:/root:/bin/sh,然后使用空密码执行 su -s /bin/sh root 返回 uid 0。
readdir 缓存路径将每个目录项复制到页缓存页中。大小检查仅询问目录项是否适合当前页的剩余空间;从不过问目录项是否适合一个页。当 namelen = 4095 时,记录为 4120 字节,因此复制会超出新页面末尾 24 字节。
利用耗尽每 CPU 页(PCP)空闲列表,使分配器从伙伴分裂中分配物理相邻的页,然后安排 readdir 缓存页和受害页成为邻居。对于 LPE,受害页是 /etc/passwd 的页缓存副本:24 字节溢出重写 root 的行,使其密码字段为空,并且使用 PAM nullok(Ubuntu 默认),su root 随后使用空密码成功。
完整文章:https://cyberstan.co.uk/fuse-readdir-oob/
由 Qi Tang 和 Zijun Hu 上游报告;修复由 Samuel Page 编写。我独立发现并报告了此问题。上游功劳和 CVE-2026-31694 归属他们。此 bug 已在主线及稳定版本树中修复。
MIT,见 LICENSE。仅用于教育和授权测试。