Dirty Pipe:Linux 内核管道 Page Cache 覆写提权漏洞(CVE-2022-0847)

文档版本:v1.0 · 更新日期:2026-05-18 适用对象:安全研究员、系统管理员、渗透测试工程师


漏洞速览

属性详情
CVE 编号CVE-2022-0847
漏洞别名Dirty Pipe(脏管道)
CVSS 评分7.8(HIGH)
CVSS 向量AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
漏洞类型CWE-668:资源暴露于错误控制范围(Page Cache 覆写)
攻击向量本地(Local)
权限要求低权限(Low)
用户交互不需要(None)
公开日期2022-03-07
PoC 状态已公开,在野利用
补丁版本Linux Kernel >= 5.16.11 / 5.15.25 / 5.10.102
临时缓解不可行(需补丁修复)

关键时间线

2021-04-29 ── 匿名安全研究员通过漏洞赏金计划向内核安全团队报告(corrupted files ticket)
2022-02-19 ── Max Kellermann 独立发现并分析漏洞根因
2022-02-20 ── Max Kellermann 向内核安全团队提交漏洞详情与补丁
2022-02-23 ── 修复补丁合并至 Linux 主线(commit 9d2231c5d74e)
2022-02-24 ── 稳定版内核发布(5.16.11/5.15.25/5.10.102)
2022-03-07 ── Max Kellermann 公开披露漏洞详情
2022-03-08 ── 首个公开 PoC 出现,各发行版集中发布安全更新
2022-04-01 ── 在野利用广泛出现

漏洞简介

Linux 内核的管道(Pipe)机制用于进程间通信(IPC),数据通过内核维护的环形缓冲区(Pipe Buffer)在进程间传递。2016 年,内核引入了 PIPE_BUF_FLAG_CAN_MERGE 标志位,允许 splice() 系统调用将文件 Page Cache 中的数据直接合并到管道缓冲区,实现零拷贝数据传输,大幅提升 I/O 性能。

CVE-2022-0847(Dirty Pipe)正是这一优化中的逻辑缺陷。由于 PIPE_BUF_FLAG_CAN_MERGE 标志位在管道缓冲区初始化时未被正确清除,当 splice() 将 Page Cache 页面合并到管道后,调用 write() 向管道写入数据时,内核错误地允许写入操作直接修改属于已被释放的 Page Cache 页面——而不是管道自己的缓冲区。攻击者可通过此机制向只读文件写入任意内容。

Dirty Pipe 被认为是 Dirty Cow 的 “精神续作”——两者均通过 Page Cache 污染实现提权。但 Dirty Pipe 相比 Dirty Cow 具有显著优势:不需要竞态条件(确定性触发)、利用稳定可靠、攻击门槛更低。该漏洞一经披露即被广泛利用,被称为 “近几年 Linux 最危险的本地提权漏洞之一”。


技术原理

利用链概述

低权限进程
    │
    ├── ① 创建 pipe() 管道
    │
    ├── ② splice() 将只读文件的 Page Cache 页面接到管道
    │       此时 pipe_buffer->flags 包含 PIPE_BUF_FLAG_CAN_MERGE
    │
    ├── ③ write() 向管道写入恶意数据
    │       内核检测到 CAN_MERGE 标志 → 跳过新页面分配 →
    │       直接覆写 splice 引用的 Page Cache 页面
    │
    └── ④ 只读文件被篡改(内存层面)→ SUID 二进制被注入恶意代码 → root

详细步骤

步骤一:管道创建与 splice 注入

攻击者首先创建一个管道(pipe()),然后使用 splice() 系统调用将目标只读文件(如 /etc/passwd)的内容通过 Page Cache 引入管道:

int p[2];
pipe(p);                                    // 创建管道
 
int fd = open("/etc/passwd", O_RDONLY);     // 打开只读目标文件
unsigned int offset = 0;
// splice 将文件内容注入管道(零拷贝,引用 Page Cache 页面)
splice(fd, &offset, p[1], NULL, 1, 0);

此时,管道的 pipe_buffer 结构直接指向文件的 Page Cache 页面,而非复制数据。关键的是,此时 pipe_buffer->flags 保留了 PIPE_BUF_FLAG_CAN_MERGE 标志。

步骤二:标志位未正确清除

正常流程下,PIPE_BUF_FLAG_CAN_MERGE 允许新数据追加到现有缓冲区末尾。但在 splice() 操作后,新的 pipe_buffer 从对应的 struct page 创建时,其 flags 字段未显式初始化为 0,而是沿用了前一个缓冲区的标志位。

// 内核代码简化示意:pipe_write() 中的关键分支
if (chars && !was_empty) {
    unsigned int mask = pipe->ring_size - 1;
    struct pipe_buffer *buf = &pipe->bufs[(head - 1) & mask];
    int offset = buf->offset + buf->len;
 
    // BUG: 此处仅检查 CAN_MERGE 标志,未验证 buf->page 的所有权
    if ((buf->flags & PIPE_BUF_FLAG_CAN_MERGE) &&
        offset + chars <= PAGE_SIZE) {
        // 直接向 buf->page 写入,而该 page 可能属于只读文件!
        memcpy(page_address(buf->page) + offset, src, chars);
        buf->len += chars;
        goto out;
    }
}

步骤三:写入触发覆写

攻击者随后调用 write() 向管道写入恶意数据:

char payload[] = "恶意数据,如覆盖 /etc/passwd 中的 uid=1000 为 uid=0";
write(p[1], payload, sizeof(payload));

内核在执行 pipe_write() 时检查到 CAN_MERGE 标志,错误地认为可以将数据直接写入 Page Cache 页面,从而实现对只读文件的内存层面篡改

步骤四:达成提权

由于写入仅发生在内核的 Page Cache 层,攻击者可修改任意只读文件的内容。常见利用路径:

  • 修改 /etc/passwd:移除 root 密码或添加特权账户
  • 注入 SUID 二进制:在 /usr/bin/su 等程序中写入 shellcode
  • 覆写 cron job 配置:植入定时后门

与 Dirty Cow 对比

维度Dirty Cow(CVE-2016-5195)Dirty Pipe(CVE-2022-0847)
漏洞类型Race Condition(竞态条件)逻辑缺陷(标志位残留)
触发方式多线程竞态单线程确定性触发
利用稳定性中等(依赖竞态窗口)极高(100% 稳定)
攻击门槛较高(需理解竞态条件)较低(简单系统调用序列)
写入粒度一次可写 1024 字节一次可写一页(通常 4096 字节)
受影响版本2.6.22 ~ 4.8.2(2007-2016)5.8 ~ 5.16.10(2020-2022)
核心原语/proc/self/mem + madvise()pipe + splice() + write()

受影响版本

组件受影响版本安全版本备注
Linux Kernel(主线)5.8 ~ 5.16.10>= 5.16.11漏洞自 2020 年 8 月引入(commit f6dd975583bd)
Linux Kernel(5.15 LTS)5.15.0 ~ 5.15.24>= 5.15.25影响大量现代发行版
Linux Kernel(5.10 LTS)5.10.0 ~ 5.10.101>= 5.10.102
Ubuntu 22.04(Jammy)kernel < 5.15.0-25>= 5.15.0-25初始发布受影响的 LTS 版本
Ubuntu 20.04(Focal)HWE kernel 5.13+发行版已 backport 修复
Fedora 35/36受影响的 5.x 内核已发布修复
RHEL 9kernel < 5.14.0-70>= 5.14.0-70
Debian 11(Bullseye)默认 5.10.x < 5.10.102>= 5.10.0-12
Android基于 5.8+ 内核的设备含 2022-03/04 安全补丁级别
内核 < 5.8N/AN/A不受影响(CAN_MERGE 优化未引入)
内核 >= 5.17-rc1N/AN/A主线在 5.17 合并窗口前已修复

漏洞影响场景

场景 1:本地低权限用户提权

  • 前提条件:攻击者拥有目标系统的普通 shell 账号(无需 sudo 权限)
  • 攻击过程:编译执行 Dirty Pipe PoC,覆写 /etc/passwd 或 SUID 二进制
  • 最坏影响:获取 root shell,完全控制系统

场景 2:容器环境攻击与逃逸

  • 前提条件:容器内进程以低权限运行,宿主机运行受影响内核
  • 攻击过程:在容器内执行 Dirty Pipe,直接修改宿主机 Page Cache 中的文件
  • 最坏影响:容器逃逸至宿主机 root,突破容器隔离

场景 3:CI/CD 与共享开发环境

  • 前提条件:多用户共享的 Linux 工作站或 CI Runner,任意用户可使用编译器
  • 攻击过程:上传并执行 Dirty Pipe EXP,污染 Runner 或宿主机
  • 最坏影响:窃取其他租户代码、CI Secrets、横向渗透

场景 4:Android 设备 Root

  • 前提条件:Android 设备运行基于 5.8+ 内核的 ROM
  • 攻击过程:通过用户安装的恶意应用或 ADB 执行 Dirty Pipe
  • 最坏影响:设备完全 Root,绕过 SELinux 和 Verified Boot

修复措施

推荐修复(根本解决)

升级内核至修复版本。

# Ubuntu / Debian
sudo apt update && sudo apt upgrade -y linux-image-generic
sudo reboot
 
# RHEL / CentOS / AlmaLinux 9
sudo dnf update kernel -y
sudo reboot
 
# Fedora
sudo dnf update kernel -y
sudo reboot
 
# 验证修复
uname -r
# 期望:>= 5.16.11 / 5.15.25 / 5.10.102 或发行版 backport

补丁核心修改(commit 9d2231c5d74e):在 pipe_write() 中,当创建新的 pipe_buffer 时,显式初始化 buf->flags = 0,确保 PIPE_BUF_FLAG_CAN_MERGE 不会被错误继承。

临时缓解(无法立即升级时)

Dirty Pipe 缺陷位于内核核心管道子系统中,没有可行的临时缓解措施

方案说明局限性
禁用非特权用户命名空间sysctl -w kernel.unprivileged_userns_clone=0仅限制部分利用路径,有功能副作用
SELinux/AppArmor 策略限制 splice() 调用配置复杂,可能影响正常应用
最小权限原则确保无本地非可信用户非根本解决方案

一键检查与执行临时修复脚本

检查脚本

#!/bin/bash
# Dirty Pipe (CVE-2022-0847) 漏洞检查脚本
# 用途:检查当前内核版本是否在受影响范围内
# 限制:仅通过版本号判断,不执行实际利用验证
 
echo "=== Dirty Pipe (CVE-2022-0847) 漏洞检查 ==="
echo ""
 
KERNEL_FULL=$(uname -r)
KERNEL_VER=$(echo "$KERNEL_FULL" | cut -d'-' -f1)
echo "当前内核版本:$KERNEL_FULL"
 
MAJOR=$(echo "$KERNEL_VER" | cut -d'.' -f1)
MINOR=$(echo "$KERNEL_VER" | cut -d'.' -f2)
PATCH=$(echo "$KERNEL_VER" | cut -d'.' -f3)
 
echo ""
 
# 漏洞引入:5.8(commit f6dd975583bd)
# 修复版本:5.16.11 / 5.15.25 / 5.10.102
check_affected() {
    if [ "$MAJOR" -lt 5 ]; then
        return 1  # < 5.0,不受影响
    fi
    if [ "$MAJOR" -eq 5 ] && [ "$MINOR" -lt 8 ]; then
        return 1  # < 5.8,不受影响
    fi
    if [ "$MAJOR" -gt 5 ]; then
        return 1  # >= 6.0,主线已修复(5.17-rc1 前合并)
    fi
 
    # 检查各分支修复版本
    if [ "$MINOR" -ge 17 ]; then
        return 1  # 5.17+,主线已修复
    fi
    if [ "$MINOR" -eq 16 ] && [ "$PATCH" -ge 11 ]; then
        return 1  # >= 5.16.11,已修复
    fi
    if [ "$MINOR" -eq 15 ] && [ "$PATCH" -ge 25 ]; then
        return 1  # >= 5.15.25,已修复
    fi
    if [ "$MINOR" -eq 10 ] && [ "$PATCH" -ge 102 ]; then
        return 1  # >= 5.10.102,已修复
    fi
 
    return 0
}
 
if check_affected; then
    echo "⚠️  当前内核版本可能受 Dirty Pipe (CVE-2022-0847) 影响"
    echo "   建议立即升级内核或确认发行版已 backport 补丁"
else
    echo "✅ 当前内核版本不在已知受影响范围"
    echo "   (如使用发行版定制内核,请查阅发行版安全公告确认)"
fi
 
echo ""
echo "=== 检查完成 ==="

重要提示:Dirty Pipe 没有有效的临时缓解措施。若检查发现受影响,应立即升级内核并重启。


参考资源

官方与 NVD

标题URL类型标签
NVD - CVE-2022-0847https://nvd.nist.gov/vuln/detail/CVE-2022-0847NVD
Max Kellermann 公开披露文章https://dirtypipe.cm4all.com/官方/技术分析
Linux 内核主线修复 commithttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9d2231c5d74e修复指南
oss-security 披露帖https://www.openwall.com/lists/oss-security/2022/03/07/1官方

发行版安全公告

标题URL类型标签
Ubuntu Security Noticehttps://ubuntu.com/security/CVE-2022-0847厂商公告
Red Hat CVE 页面https://access.redhat.com/security/cve/cve-2022-0847厂商公告
Debian Security Trackerhttps://security-tracker.debian.org/tracker/CVE-2022-0847厂商公告

PoC 与工具

标题URL类型标签
Max Kellermann 原始 PoChttps://haxx.in/files/dirtypipez.cPoC
Arthepsy PoC(增强版)https://github.com/Arthepsy/CVE-2022-0847-DirtyPipe-ExploitPoC
liamg/traitor(自动化提权工具)https://github.com/liamg/traitor工具

Dirty Pipe 代表了 Linux 内核安全中最危险的一种模式:看似无害的性能优化,在特殊条件下变成确定性提权原语。它的出现推动了内核社区对 splice() 与 Page Cache 交互安全性的全面审视。