九年 Linux 高危漏洞被披露:CVE-2026-31431 "Copy Fail" 允许本地提权至 root

CVE-2026-31431 Copy Fail

漏洞概述

2026 年 4 月 29 日,安全研究公司 Xint Code(隶属 Theori)公开披露了一个 Linux 内核高危本地提权漏洞,编号 CVE-2026-31431,研究者将其命名为 "Copy Fail"

该漏洞位于 Linux 内核加密子系统的 algif_aead 模块,允许任何本地普通用户在任意可读文件的页缓存(page cache)中写入受控的 4 字节数据。攻击者可以利用这一点修改 setuid 二进制文件的内存映像,实现确定性、无竞争条件的本地提权至 root。整个 PoC 仅 732 字节 Python 代码,只依赖标准库(ossocketzlib)。

kernel.org 已发布修复补丁,NVD 收录的 CVSS 评分为 7.8 HIGH(CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)。

与 Dirty Cow / Dirty Pipe 的对比

Linux 历史上有过多个知名的本地提权漏洞:

  • Dirty Cow(CVE-2016-5195):需要赢得 VM 子系统 copy-on-write 路径中的竞态条件,经常需要多次尝试,有时会导致系统崩溃。
  • Dirty Pipe(CVE-2022-0847):特定版本才有,需要精确操作 pipe buffer。

Copy Fail 和这两者不同——它是一个直线逻辑缺陷,不需要竞态条件、不需要重试、没有容易崩溃的时序窗口。同一份 PoC 在所有受测发行版和架构上直接运行,无需针对不同发行版调整偏移量,也不需要编译额外的 payload。

漏洞原理

根本原因

AF_ALG 是 Linux 内核提供的一种 socket 类型,允许非特权用户空间程序直接使用内核的加密子系统。用户可以打开一个 socket,绑定到任意 AEAD(Authenticated Encryption with Associated Data)模板,然后对任意数据执行加密或解密操作。

漏洞的核心在于 algif_aead.crecvmsg() 实现中,解密操作被设置为 in-place 模式——输入和输出使用同一个 scatterlist。具体流程:

  1. 用户通过 splice() 将一个文件的页缓存页直接注入 AF_ALG socket 的输入 scatterlist
  2. AEAD 解密的输入格式为:AAD(关联认证数据)|| 密文 || 认证标签(Tag)
  3. AAD 和密文部分通过 memcpy_sglist 从输入 scatterlist 拷贝到输出缓冲区,这是真实的拷贝
  4. 认证标签不拷贝——内核通过 sg_chain() 将输入 scatterlist 末尾的 tag 条目直接链到输出 scatterlist 的末尾
  5. 输出 scatterlist 现在包含两个区域:用户缓冲区(已拷贝的 AAD + 密文)+ 链接的 tag 页(仍指向原始文件的页缓存页)

authencesn 模块处理扩展序列号(Extended Sequence Number)的字节重排时,它会使用输出 scatterlist 中的空间作为临时暂存区。由于 tag 区域的页缓存页被标记为可写输出,authencesn 的越界暂存写入就直接落在了这些页缓存页上。

三个独立变更的交汇

这个漏洞的成因是三个在时间线上独立的内核变更,单独看都合理,叠加后形成了可利用的漏洞:

  1. 2011 年authencesn 模块在处理 IPsec 扩展序列号时,使用调用方的 scatterlist 作为字节重排的临时暂存区。这个设计在 scatterlist 内容由内核自身管理时没有问题。

  2. 2015 年AF_ALG socket 获得 AEAD 支持,splice() 可以将文件页缓存页直接注入 scatterlist,无需拷贝。这让非特权用户可以将任意文件的内容以零拷贝方式送入内核加密路径。

  3. 2017 年:一次性能优化将 algif_aead 的解密改为 in-place 模式,通过 sg_chain() 将页缓存页链入可写输出 scatterlist。这让 authencesn 的越界暂存写入直接落在用户可控的页缓存页上。

页缓存写入的特殊性

被修改的页不会被内核的 writeback 机制标记为 dirty,因此磁盘上的文件不会被改变。传统的文件完整性检测工具(对比磁盘校验和)会完全漏掉这个修改。但页缓存是系统范围内所有进程共享的——当任何进程读取、mmap 或 execve 该文件时,拿到的是被篡改的内存版本。

这也意味着该漏洞可以跨越容器边界:页缓存在宿主机上共享,容器内的攻击者可以修改宿主机文件的页缓存,实现容器逃逸。

影响范围

几乎所有 2017 年后内核版本的主流 Linux 发行版均受影响,包括但不限于:

  • Ubuntu 24.04 LTS
  • Amazon Linux 2023
  • RHEL(Red Hat Enterprise Linux)
  • SUSE 及其衍生发行版

云端多租户节点、CI/CD 环境、Jupyter 平台等允许普通用户访问的场景尤其危险。

修复方案

kernel.org 已发布修复补丁,修复方式是将 algif_aead 回退为 out-of-place 操作。建议用户:

  1. 立即升级到包含修复补丁的内核版本
  2. 重启系统使新内核生效

临时缓解

在内核升级之前,可以通过禁用 authencesn 模块来缓解:

bash
echo "install authencesn /bin/false" >> /etc/modprobe.d/security.conf

这会阻止 authencesn 模块加载,从而使攻击路径失效。

检测

Xint Code 提供了一个检测脚本,可用于检查系统是否存在该漏洞:

https://github.com/rootsecdev/cve_2026_31431

时间线

  • 2011 年:authencesn 模块引入,使用调用方 scatterlist 作为暂存区
  • 2015 年:AF_ALG 获得 AEAD 支持,splice() 可注入页缓存页
  • 2017 年:algif_aead 改为 in-place 操作(commit 72548b093ee3),三个条件正式交汇
  • 2026-04-29:Xint Code 公开披露,kernel.org 同步发布修复补丁

来源