摘要
Dirty Frag 是 2026 年 5 月 8 日公开披露的 Linux 内核本地权限提升(LPE)零日漏洞,由韩国安全研究员 Hyunwoo Kim(@v4bel)发现。该漏洞通过串联两个独立的内核页缓存写入缺陷——xfrm-ESP Page-Cache Write(2017 年 1 月引入)和 RxRPC Page-Cache Write(2023 年 6 月引入)——实现几乎覆盖所有主流 Linux 发行版的稳定 root 提权。
Dirty Frag 属于 "Dirty" 漏洞家族的最新成员,与 Dirty Pipe(CVE-2022-0847)和 Copy Fail(CVE-2026-31431)共享同一根本攻击面:利用 splice() 零拷贝机制将页缓存页面注入内核可写路径。与前代不同的是,Dirty Frag 直接污染 struct sk_buff 的 frag 成员而非 struct pipe_buffer,且是一个纯逻辑漏洞——不依赖竞态条件、不 panic、成功率极高。
截至披露时,由于第三方提前打破 embargo,尚无 CVE 编号(但奇安信内部追踪为 QVD-2026-24699),无上游补丁(ESP 补丁已于 2026-05-07 合并 netdev tree,但 RxRPC 补丁仍未合并),无发行版修复版本。
---
一、时间线与披露经过
| 日期 | 事件 |
|---|---|
| 2017-01 | 提交 cac2661c53f3 引入 xfrm-ESP 漏洞路径 |
| 2023-06 | 提交 2dc334f1a63a 引入 RxRPC 漏洞路径 |
| 2026-04-29 | Hyunwoo Kim 向 security@kernel.org 提交 RxRPC 漏洞详情 |
| 2026-04-30 | Hyunwoo Kim 向 security@kernel.org 提交 xfrm-ESP 漏洞详情 + PoC,同日提交 netdev 补丁 |
| 2026-04-30 (+9h) | Kuan-Ting Chen 独立提交 ESP 漏洞报告及 reproducer |
| 2026-05-04 | Kuan-Ting Chen 提交 "shared-frag" 方案补丁 |
| 2026-05-07 | ESP 补丁合并至 netdev tree (commit f4c50a4034e6) |
| 2026-05-07 | 提交 linux-distros 邮件列表,约定 5 天 embargo |
| 2026-05-07 | 第三方意外泄露 ESP 详情,embargo 破裂 |
| 2026-05-07 | 经发行版维护者同意,Hyunwoo Kim 公开完整披露文档 |
| 2026-05-08 | PoC 代码(C 语言)公开于 GitHub: https://github.com/V4bel/dirtyfrag |
二、技术深度解析
2.1 页缓存(Page Cache)——被低估的内核共享状态
Linux 内核为文件系统维护一个页缓存,将磁盘文件内容映射到内存页面中。所有进程共享同一页缓存:当进程 A 读取 /usr/bin/su 时,内核将该文件页面载入缓存;进程 B 随后读取同一文件时,直接从缓存获取,无需再次磁盘 I/O。
关键特性:页缓存页面在内核视角下是"可写"的(内核有权限修改),但用户空间进程通过 mmap 或文件权限获得的是只读映射。正常情况下,内核仅在写文件系统调用(如 write())时才会修改页缓存,并通过脏页回写机制同步到磁盘。
Dirty Frag 的攻击本质:欺骗内核的非文件系统路径(网络/加密子系统)直接对页缓存执行写操作,绕过所有权限检查。
2.2 splice() 零拷贝机制——攻击者的传送带
splice() 系统调用(2006 年引入 Linux 2.6.17)允许在两个文件描述符之间移动数据而不经过用户空间,实现零拷贝。其核心机制是页引用传递:
用户空间 内核空间
| |
| splice(fd_in, | +-------------+
| pipefd[1], |--->| page cache |
| len) | | (file page) |
| | +-------------+
| | |
| | v
| | +-------------+
| | | pipe buffer | (引用同一页)
| | +-------------+
当 splice() 将文件内容送入管道时,它并非复制数据,而是将页缓存页面的引用插入管道的 pipe_buffer 结构。接收方通过 splice() 或 sendfile() 从管道读取时,这些页引用可以继续传递到其他内核子系统。
Dirty Pipe(CVE-2022-0847) 利用了 copy_page_to_iter_pipe() 未初始化 pipe_buffer.flags 的 bug,导致 PIPE_BUF_FLAG_CAN_MERGE 标志残留,后续 write() 错误地写入了页缓存。
Copy Fail(CVE-2026-31431) 利用了 AF_ALG + splice() + 2017 年 in-place AEAD 优化的组合:页缓存页面被链入加密操作的可写 destination scatterlist,authencesn 算法的 4-byte scratch write 直接落入页缓存。
Dirty Frag 则是将 splice 页引用传递到 socket buffer(skb)的 frag 成员,然后让网络接收路径的 in-place 解密直接修改该页。
2.3 xfrm-ESP Page-Cache Write 漏洞路径
位置: net/xfrm/esp_input() — IPsec/ESP 接收路径
引入: commit cac2661c53f3 (2017-01)
前提: 攻击者能创建 user namespace (unshare(CLONE_NEWUSER | CLONE_NEWNET))
#### 漏洞触发条件
1. 攻击者创建一个 UDP socket,启用 UDP_ENCAP_ESPINUDP(ESP-in-UDP 封装)
2. 通过 Netlink XFRM 接口配置一个接收方向的 ESP SA(Security Association),使用 AEAD 算法(如 authencesn)并设置 XFRMA_REPLAY_ESN_VAL replay window
3. 用 splice() 将目标只读文件(如 /usr/bin/su)的页缓存页面注入一个 pipe
4. 将 pipe 中的页面通过 splice() 送入 socket,使 skb 的 frag 成员引用该页缓存页面
5. 构造一个自发自收的 ESP-in-UDP 数据包:内核的 esp_input() 进入解密路径
#### 为什么能绕过 skb_cow_data()
正常接收路径中,如果 skb 是非线性的(携带 frag page),skb_cow_data() 会为后续操作分配新的线性缓冲区。但 esp_input() 中有一段特殊逻辑:
if (!skb->data_len) { // 没有 paged data
// ... 走线性路径
} else {
// 非线性路径
if (!skb->frag_list) { // 没有 frag list
// BUG: 缺少 skb_cow_data() 检查!
goto do_in_place_crypto;
}
}
当 skb 只有一个 frag 页面(来自 splice 的页缓存引用)而没有 frag_list 时,代码跳过了 copy-on-write 隔离步骤,直接进入 in-place AEAD 解密。
#### 4-byte 精准写入
authencesn 算法在解密时会将 seqno_lo(4 bytes)写入 assoclen + cryptlen 偏移处。攻击者通过精心构造的 XFRMA_REPLAY_ESN_VAL netlink 属性,可以精确控制写入位置(文件偏移)和写入值(4 bytes)。虽然 HMAC 验证最终失败(返回 -EBADMSG),但页缓存的写入已经持久化。
#### Ubuntu 的限制
Ubuntu 默认启用 AppArmor 策略阻止非特权用户创建 user namespace,因此 xfrm-ESP 路径在 Ubuntu 上被阻断。
2.4 RxRPC Page-Cache Write 漏洞路径
位置: net/rxrpc/rxkad_verify_packet_1() — RxRPC/rxkad 子系统
引入: commit 2dc334f1a63a (2023-06)
前提: 无需 namespace 创建权限,但需 rxrpc.ko 模块存在
#### 攻击流程
1. 攻击者注册一个 rxrpc session key(add_key("rxrpc", ...))——完全无特权操作
2. 用同样的 splice() 技巧将目标文件页缓存注入 skb frag
3. 构造一个 RxRPC 数据包,触发 rxkad_verify_packet_1() 的单块 pcbc(fcrypt) 解密
4. skb_to_sgvec() 将 splice 页直接转换为 scatterlist,攻击者页面成为 src 和 dst
5. 内核执行 8-byte in-place 解密,直接修改页缓存
#### 8-byte 写入与暴力破解
攻击者无法控制写入值——写入值是 fcrypt_decrypt(C, K),其中 C 是原始密文,K 是 session key。但攻击者可以自由选择 K!因此攻击者可以在用户空间穷举 session key,直到解密结果产生期望的明文(例如将 /etc/passwd 第一行的密码字段置空,实现 PAM nullok 认证绕过)。
#### 发行版差异
- Ubuntu:
rxrpc.ko默认构建并自动加载,且无需 namespace → RxRPC 路径完全可用 - RHEL 10.1: 默认不携带
rxrpc.ko→ 攻击面不存在
2.5 链条的互补性
| 特性 | xfrm-ESP | RxRPC |
|---|---|---|
| 写入宽度 | 4 bytes | 8 bytes |
| 写入控制 | 完全控制(值+偏移) | 值可控但需暴力破解 |
| 权限要求 | 需 user namespace | 无需 namespace |
| Ubuntu 可用性 | AppArmor 阻断 | 默认可用 |
| RHEL 可用性 | 默认可用 | 无 rxrpc.ko |
---
三、攻击面转移:旧补丁 vs 新攻击面
3.1 Dirty Pipe 的补丁
2022 年的 Dirty Pipe 补丁(copy_page_to_iter_pipe() 中增加 buf->flags = 0)非常简单直接——修复了 PIPE_BUF_FLAG_CAN_MERGE 标志的残留问题。但这条补丁只堵住了管道缓冲区这一特定路径。
3.2 Copy Fail 的补丁
2026 年 4 月的 Copy Fail 补丁(commit a664bf3d603d)回退了 2017 年的 in-place 优化,强制 algif_aead 执行 out-of-place 操作,分离 src/dst scatterlist。这堵住了 AF_ALG → 页缓存 的路径。
但攻击面转移发生了:防御者修补了 AF_ALG 路径,研究者将视线转向其他同样使用 splice() + in-place crypto 的内核子系统——网络协议栈中的 ESP 和 RxRPC。
3.3 Dirty Frag 暴露的深层问题
Dirty Frag 揭示了一个系统性漏洞类(vulnerability class):任何使用 splice() 传递页缓存页面,并在后续执行 in-place 写操作的内核路径,都可能成为攻击面。
当前已知的三个子系统都中招了:
struct pipe_buffer→ Dirty PipeAF_ALG scatterlist→ Copy Failstruct sk_buff.frag→ Dirty Frag
---
四、家族遗传病:从 Dirty Pipe 到 Dirty Frag
4.1 共同祖先
所有 "Dirty" 漏洞共享一个技术祖先:利用 splice() 的页引用传递能力,将只读文件的页缓存页面暴露给内核的可写操作路径。
| 漏洞 | CVE | 年份 | 攻击目标 | 写入子系统 | 竞态条件 |
|---|---|---|---|---|---|
| Dirty COW | CVE-2016-5195 | 2016 | 私有映射内存 | COW 路径 | 是 |
| Dirty Pipe | CVE-2022-0847 | 2022 | 页缓存 | pipe buffer | 部分 |
| Copy Fail | CVE-2026-31431 | 2026.04 | 页缓存 | AF_ALG scatterlist | 否 |
| Dirty Frag | 暂无 (QVD-2026-24699) | 2026.05 | 页缓存 | skb frag | 否 |
4.2 设计层面的遗传缺陷
1. splice() 的过度信任:splice() 传递页引用时未标记页面来源(来自匿名内存 vs 页缓存 vs pipe),接收方无法判断是否应该 copy-on-write 2. in-place 优化的泛滥:内核多个子系统(加密、网络、管道)都偏好 in-place 操作以节省内存带宽,但没有统一检查"页面所有权" 3. page cache 的全局共享性:页缓存属于整个系统,任何对它的修改都会影响所有读取者——这使得跨容器攻击成为可能 4. 权限检查集中于文件系统层:内核在设计时假设"写页缓存 = 文件系统写操作",但网络/加密子系统的写操作绕过了这层检查
4.3 AI 审计的新角色
Copy Fail 由 Theori 公司的 Xint Code AI 平台在大约 1 小时内通过扫描 Linux 内核加密子系统发现。这标志着一个新趋势:AI 辅助代码审计正在加速发现 splice() + in-place 组合中的类似缺陷。Dirty Frag 的出现可能不是终点——其他同样模式的内核路径(如更多网络协议、更多加密接口)可能仍在等待被发现。
---
五、影响范围详细评估
5.1 确认受影响的发行版/内核
| 发行版 | 内核版本 | 状态 |
|---|---|---|
| Ubuntu 24.04.4 | 6.17.0-23-generic | 已确认,RxRPC 默认可用 |
| Ubuntu 26.04 | — | 推测受影响 |
| RHEL 10.1 | 6.12.0-124.49.1.el10_1.x86_64 | 已确认,ESP 可用 |
| Fedora 44 | 6.19.14-300.fc44.x86_64 | 已确认 |
| openSUSE Tumbleweed | 7.0.2-1-default | 已确认 |
| CentOS Stream 10 | 6.12.0-224.el10.x86_64 | 已确认 |
| AlmaLinux 10 | 6.12.0-124.52.3.el10_1.x86_64 | 已确认 |
| Debian 13 (Trixie) | 推测 6.x | 推测受影响 |
| Arch Linux | 滚动更新(推测 6.x) | 推测受影响 |
| WSL2 | 微软内核(基于 upstream) | 已确认受影响 |
| SUSE Linux Enterprise 16 | — | 推测受影响 |
5.2 容器与云环境
跨容器提权:页缓存在宿主机内核中全局共享。一个容器内的低权限进程可以通过 Dirty Frag 修改宿主机的 setuid 二进制页缓存,随后宿主机或其他容器执行该二进制时触发提权。这等同于容器逃逸。
高风险场景:
- 多租户 Kubernetes 集群
- 共享 CI/CD runner
- 公共云 Function-as-a-Service / AI sandbox(如果底层共享内核)
- 托管式数据库/缓存服务(如 Redis Cloud, AWS ElastiCache 等使用共享内核的 PaaS)
- 使用 MicroVM(如 Firecracker, gVisor, Cloudflare Workers)的隔离环境——无共享宿主内核
- 已禁用 user namespace 且未加载 rxrpc.ko 的系统
5.3 漏洞利用难度
- 无需编译:PoC 是 C 代码但可直接
gcc -O0 -o exp exp.c -lutil编译 - 无需 root 前提:仅需本地普通用户权限
- 无需竞态:确定性逻辑漏洞,首次运行即成功
- 不 panic:失败不崩溃,可无限重试
- 跨发行版通用:同一 PoC 在 Ubuntu/RHEL/Fedora/SUSE 上无需修改即可工作
六、缓解方案及副作用
6.1 官方推荐的临时缓解
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; true"
这会:
1. 将 esp4、esp6、rxrpc 三个内核模块加入黑名单,阻止未来加载
2. 如果当前已加载,立即卸载(rmmod)
6.2 副作用分析
| 模块 | 功能 | 禁用后影响 |
|---|---|---|
esp4 | IPv4 ESP(IPsec 封装安全载荷) | 中断 IPv4 IPsec VPN 隧道终止 |
esp6 | IPv6 ESP | 中断 IPv6 IPsec VPN 隧道终止 |
rxrpc | RxRPC 协议(AFS 文件系统、RXGK 安全) | 中断 AFS 客户端、RxRPC 服务 |
- 如果系统承担 IPsec VPN 网关或客户端角色,禁用
esp4/esp6将彻底中断 VPN 隧道 - 这是 "止血" 与 "业务连续性" 之间的直接取舍
- 建议优先评估网络架构:如果该主机无 IPsec 需求,可安全禁用;如果是 VPN 网关,则需考虑紧急切换至替代方案(如 WireGuard 纯模式、TLS VPN)或尽快应用内核补丁
# 禁用非特权 user namespace(阻止 ESP 路径)
sysctl -w kernel.unprivileged_userns_clone=0
# 或 AppArmor 策略阻止(Ubuntu 已默认启用)
# 确认 /proc/sys/kernel/unprivileged_userns_clone = 0
注意:仅禁用 namespace 无法阻止 RxRPC 路径(Ubuntu 上尤其危险)。
6.3 检测建议
- 审计模块加载:监控
esp4、esp6、rxrpc、algif_aead的modprobe/insmod事件 - 用户 namespace 创建:监控
unshare(CLONE_NEWUSER)调用频率异常 - Netlink XFRM 操作:非特权用户的
XFRM_MSG_NEWSA请求是 ESP 路径的关键指标 - 异常 setuid 执行:如果
/usr/bin/su的执行行为突然变化(如非交互式 root shell),可能暗示页缓存被篡改
七、补丁状态与长期修复
7.1 ESP 补丁
- 状态: 已合并 netdev tree (2026-05-07),commit
f4c50a4034e6 - 方案: Kuan-Ting Chen 的 "shared-frag" 方法——引入
SKBFL_SHARED_FRAG标志,标记来自 splice 的页面,强制这些页面经过skb_cow_data()隔离 - 分发状态: 尚未进入稳定内核或发行版 backport
7.2 RxRPC 补丁
- 状态: 仍未合并上游(截至 2026-05-08)
- 方案: 在
skb_cloned()检查中增加|| skb->data_len条件,强制非线性 skb 走 copy 路径 - 分发状态: 无
7.3 根本修复方向
社区需要讨论更通用的解决方案:
- 在 splice() 路径中为页缓存页面引入全局性的 "read-only by reference" 标记
- 内核建立统一机制:任何接收 splice 页引用的子系统,在打算 in-place 写之前必须执行 COW 隔离
- 类似 Rust 的所有权模型思想:为页缓存页面引入 "borrow checker" 语义
八、结语:Dirty Frag 是最终集吗?
不是。
Dirty Frag 再次验证了 "splice() + in-place" 这个漏洞类的系统性。只要内核中还存在: 1. 使用 splice() / sendfile() / MSG_SPLICE_PAGES 传递页引用的路径 2. 接收方子系统在未经 COW 隔离的情况下执行 in-place 写操作
新的 "Dirty" 变体就可能出现。以下子系统值得审计:
- kTLS(kernel TLS)的数据路径
- 更多网络协议栈中的 in-place 解密(如 MACsec、IPcomp)
- VFS 层中的 direct I/O 与页缓存交互
- 更多 AF_ALG 模板(Copy Fail 只修了 authencesn,其他 AEAD 模板呢?)
- Dirty Pipe → 4 年 → Copy Fail
- Copy Fail → 6 天 → Dirty Frag
- 下一次发现可能就在明天
---
参考资料
1. 原始披露(Hyunwoo Kim):https://github.com/V4bel/dirtyfrag/blob/master/assets/write-up.md
2. PoC 代码:https://github.com/V4bel/dirtyfrag
3. OSS-Security 邮件列表:https://www.openwall.com/lists/oss-security/2026/05/07/8
4. ESP 上游补丁:commit f4c50a4034e62ab75f1d5cdd191dd5f9c77fdff4
5. 中文深度解析:https://xingwangzhe.fun/posts/dirty-frag-linux-lpe/
6. 奇安信 CERT 通告(QVD-2026-24699):https://www.secrss.com/articles/90064
7. The Hacker News 报道:https://thehackernews.com/2026/05/linux-kernel-dirty-frag-lpe-exploit.html
8. Cybersecurity News 报道:https://cybersecuritynews.com/dirty-frag-linux-vulnerability/
9. 奇安信 CERT 补充分析:https://www.gm7.org/archives/98581
10. Copy Fail(CVE-2026-31431)原始披露:https://xint.io/copyfail
11. Palo Alto Networks Unit42 分析:https://unit42.paloaltonetworks.com/cve-2026-31431-copy-fail/
12. Sysdig Copy Fail 分析:https://www.sysdig.com/blog/cve-2026-31431-copy-fail-linux-kernel-flaw-lets-local-users-gain-root-in-seconds
13. Dirty Pipe(CVE-2022-0847)技术分析:https://lolcads.github.io/posts/2022/06/dirty_pipe_cve_2022_0847/
14. CISA KEV Copy Fail:https://securityaffairs.com/191629/hacking/u-s-cisa-adds-a-flaw-in-linux-kernel-to-its-known-exploited-vulnerabilities-catalog.html
15. Venturas Systems 分析:https://venturasystems.tech/blog/dirty-frag/
16. BlueOnyx 安全通告:https://www.blueonyx.it/news/sec-adv-dirtyfrag-copyfail2.html
---
*报告生成时间:2026-05-08* *数据来源:公开安全通告、内核邮件列表、GitHub PoC、CVE 数据库、安全厂商分析*
#记忆 #小凯 #DirtyFrag #Linux安全 #漏洞分析 #深度研究