Copy Fail (CVE-2026-31431) 核心分析
这是一个极其危险且优雅的 Linux 内核本地提权漏洞,732 字节 Python 脚本直取 root。
───
为什么它不一样
恐怖之处:
• 跨发行版:Ubuntu、Amazon Linux、RHEL、SUSE 全中,无需改脚本
• 隐蔽:只污染 page cache,磁盘文件不变,文件完整性校验(checksum)检不出
• 跨容器:page cache 全系统共享,容器逃逸 + Kubernetes 节点沦陷(Part 2 会讲)
───
技术根因(三层叠加)
三层独立合理的改动,在 2017 年交叉,沉默近十年。
───
攻击流程(4 步)
1. 开 socket:
2. 构造写:
3. 触发写:
4. 执行:HMAC 失败返回错误,但 4 字节已写入。
攻击者控制三样东西:
• 哪个文件:任何当前用户可读的文件
• 哪个偏移:通过 splice 的 offset/length/assoclen 精确计算
• 写什么值:AAD 的 bytes 4-7
───
修复
内核补丁(
•
•
•
───
现在该做什么
───
一个有趣的点
这个漏洞是AI 辅助发现的——Theori 的 Taeyang Lee 用 Xint Code 扫描 crypto 子系统,operator prompt 就一句话:
这 bug 的优雅在于它不是内存越界、不是 use-after-free,而是一个跨十年的架构层交集——2011 年的 scratch pad 习惯、2015 年的接口迁移、2017 年的性能优化,各自合理,合在一起就是 root。
经典。
这是一个极其危险且优雅的 Linux 内核本地提权漏洞,732 字节 Python 脚本直取 root。
───
为什么它不一样
| 漏洞 | 条件 | Copy Fail |
| ---------- | ------------ | ------------ |
| Dirty Cow | 需要竞态条件,可能崩溃 | ❌ 不需要 |
| Dirty Pipe | 版本特定,需精确管道操作 | ❌ 全版本通吃 |
| Copy Fail | 直线路径,无竞态,无重试 | ✅ 一个脚本跑所有发行版 |
恐怖之处:
• 跨发行版:Ubuntu、Amazon Linux、RHEL、SUSE 全中,无需改脚本
• 隐蔽:只污染 page cache,磁盘文件不变,文件完整性校验(checksum)检不出
• 跨容器:page cache 全系统共享,容器逃逸 + Kubernetes 节点沦陷(Part 2 会讲)
───
技术根因(三层叠加)
2011: authencesn 加入内核(IPsec ESN 支持)
↓ 用调用者的 dst buffer 当 scratch pad,写超出边界
2015: AF_ALG 支持 AEAD + splice() 路径
↓ splice 能把 page cache 页直接塞进 crypto scatterlist
2015: authencesn 迁移到新 AEAD 接口
↓ 引入 assoclen + cryptlen 越界写
2017: algif_aead 加入"原地操作"优化 ← 致命一击
↓ req->src = req->dst,page cache 页被链进**可写**的 dst scatterlist
三层独立合理的改动,在 2017 年交叉,沉默近十年。
───
攻击流程(4 步)
1. 开 socket:
AF_ALG 绑定 authencesn(hmac(sha256),cbc(aes)),无需特权2. 构造写:
sendmsg() 发 AAD(控制 4 字节写入值)+ splice() 把目标文件(如 /usr/bin/su)的 page cache 页送进 crypto3. 触发写:
recv() 触发解密。authencesn 在重组 ESN 时把 seqno_lo 写到 dst[assoclen + cryptlen]——这个位置恰好是 splice 链进来的 page cache 页4. 执行:HMAC 失败返回错误,但 4 字节已写入。
execve("/usr/bin/su") 加载被污染的 page cache,shellcode 以 root 运行攻击者控制三样东西:
• 哪个文件:任何当前用户可读的文件
• 哪个偏移:通过 splice 的 offset/length/assoclen 精确计算
• 写什么值:AAD 的 bytes 4-7
───
修复
内核补丁(
a664bf3d603d)直接回滚 2017 年的原地优化,改回 out-of-place:•
req->src → 指向 TX SGL(只读,可能含 page cache)•
req->dst → 指向 RX SGL(用户 buffer,可写)•
sg_chain 机制整个被移除───
现在该做什么
# 1. 打补丁 / 更新内核包
sudo apt update && sudo apt upgrade # 或对应发行版的命令
# 2. 临时缓解:禁用 algif_aead 模块
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
───
一个有趣的点
这个漏洞是AI 辅助发现的——Theori 的 Taeyang Lee 用 Xint Code 扫描 crypto 子系统,operator prompt 就一句话:
"注意:splice() 可以把只读文件的 page cache 引用送到 crypto TX scatterlist"一小时扫描,Copy Fail 是最高危输出。
这 bug 的优雅在于它不是内存越界、不是 use-after-free,而是一个跨十年的架构层交集——2011 年的 scratch pad 习惯、2015 年的接口迁移、2017 年的性能优化,各自合理,合在一起就是 root。
经典。