io_uring UAF:Linux 内核异步 I/O 子系统释放后重用提权漏洞(CVE-2022-2602)

文档版本:v1.0 · 更新日期:2026-05-18 适用对象:安全研究员、系统管理员、DevSecOps 团队


漏洞速览

属性详情
CVE 编号CVE-2022-2602
漏洞别名io_uring UAF / DirtyCred
CVSS 评分7.8(HIGH)
CVSS 向量AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
漏洞类型CWE-416:释放后重用(Use-After-Free)
攻击向量本地(Local)
权限要求低权限(Low)
用户交互不需要(None)
公开日期2022-10-18
PoC 状态已公开
补丁版本Linux Kernel >= 6.1-rc1
临时缓解可禁用 io_uring 或限制非特权用户访问

关键时间线

2022-10-18 ── oss-security 邮件列表公开披露漏洞详情
2022-12-06 ── Linux 主线合并修复补丁(包含在 6.1-rc1 合并窗口中)
2022-12-11 ── 稳定版内核 6.1 发布,正式修复
2022-12-21 ── 详细技术分析与 EXP 公开(DirtyCred 文件利用技术)
2023-01-20 ── 各发行版完成 backport 修复发布

漏洞简介

io_uring 是 Linux 内核自 5.1 版本引入的高性能异步 I/O 子系统。它允许用户态程序通过共享内存环形缓冲区(Ring Buffer)向内核提交 I/O 操作请求,内核异步完成后将结果写入完成队列(Completion Queue),大幅减少了系统调用开销和上下文切换。io_uring 被广泛应用于高性能网络服务、数据库(如 ScyllaDB)、存储引擎等场景。

CVE-2022-2602 位于 io_uring 的 IORING_REGISTER_FILES 功能中,涉及文件描述符(file 结构体)的生命周期管理错误。当攻击者通过 io_uring_register() 注册文件描述符后,利用 unix_gc(Unix 域套接字垃圾回收)机制触发已注册文件的异常释放,导致 io_uring 内部仍然持有指向已释放 file 结构体的悬空指针(Dangling Pointer)。随后对该指针的引用即构成 Use-After-Free,攻击者可通过堆喷(Heap Spray)技术控制释放后的内存区域,实现内核任意代码执行。

该漏洞的特别之处在于:它不仅是 io_uring 子系统自身的问题,还涉及了 Unix 域套接字的 垃圾回收(GC)路径与 io_uring 文件注册路径之间的非预期交互,展现了内核子系统间耦合带来的安全隐患。


技术原理

利用链概述

低权限进程
    │
    ├── ① 创建 io_uring 实例(io_uring_setup)
    │
    ├── ② 创建 Unix 域套接字对,将一端注册到 io_uring
    │       io_uring_register(IORING_REGISTER_FILES, fds_array)
    │
    ├── ③ 操纵套接字形成引用循环,触发 unix_gc
    │       Unix 域套接字的垃圾回收器错误释放已注册的 file 结构体
    │
    ├── ④ io_uring 仍持有悬空指针 → UAF
    │
    ├── ⑤ 通过堆喷控制释放后的内存区域
    │       植入精心构造的伪造 file 结构体(f_op 指向攻击者控制区)
    │
    └── ⑥ 触发 io_uring 操作 → 内核代码执行 → 提权至 root

详细步骤

步骤一:io_uring 文件注册

io_uring 提供了 IORING_REGISTER_FILES 操作,允许用户预注册一组文件描述符。这使得后续 I/O 操作可以通过固定索引引用文件,减少每次 fget() 调用的开销。

int ring_fd = io_uring_setup(entries, &params);  // 创建 io_uring 实例
int fds[] = {socket_fd};
io_uring_register(ring_fd, IORING_REGISTER_FILES, fds, 1);

注册后,io_uring 内部通过 io_uring->registered_files[] 数组持有 file 结构的引用计数。正常情况下,即使用户态 close() 文件描述符,注册的文件也不会被释放。

步骤二:Unix 域套接字 GC 异常释放

攻击者构造 Unix 域套接字之间的引用循环(如通过 SCM_RIGHTS 传递文件描述符),然后打破循环触发内核的 unix_gc(垃圾回收)。unix_gc 在特定条件下会错误地将已注册到 io_uring 的 file 结构体释放,而未检查其是否仍被 io_uring 引用。

攻击者控制的套接字拓扑:
    skA ──── SCM_RIGHTS(skB) ────> skB
     ↑                                  │
     └──── SCM_RIGHTS(skA) ────────────┘
     形成循环 → 触发 unix_gc → 释放已注册 file

步骤三:UAF 触发

释放发生后,io_uring 的 registered_files[] 中仍保留指向已释放内存的指针。当攻击者通过 io_uring 操作(如 IORING_OP_READ)引用该索引时,内核访问已释放的 file 结构体:

// 内核代码简化示意
struct file *file = io_uring->registered_files[index];  // 悬空指针!
if (file) {
    file->f_op->read(file, buf, count, &pos);           // UAF 引用!
}

步骤四:堆喷占位与内核 RCE

攻击者通过内核堆喷(如使用 msg_msg 消息队列、sk_buff 网络缓冲区或其他内核对象分配器)精确占据释放后的内存区域。通过精心构造数据,覆盖 file->f_op 函数指针表,使其指向攻击者控制的 ROP 链或内核 shellcode:

// 伪造的 file 结构体布局
struct fake_file {
    // ... 填充合法值通过检查 ...
    struct file_operations *f_op = &fake_fops;  // 指向攻击者控制的函数表
};
 
struct fake_file_operations {
    ssize_t (*read)() = rop_chain;       // 触发 read → 执行 ROP
    ssize_t (*write)() = rop_chain;      // 触发 write → 执行 ROP
    // ...
};

当后续 io_uring_enter() 触发 I/O 操作时,内核调用被劫持的函数指针,攻击者获得内核态任意代码执行能力,最终通过 commit_creds(prepare_kernel_cred(0)) 将当前进程权限提升至 root。

关键技术点

组件作用
io_uring_register()注册文件描述符到 io_uring,内部持有 file 引用
unix_gcUnix 域套接字垃圾回收,错误释放已注册文件
struct file内核中的文件对象,包含 f_op 函数指针表
file_operations文件操作的虚函数表,UAF 后劫持的跳板
内核堆喷(Heap Spray)通过分配特定内核对象占位,控制释放后的内存内容

受影响版本

组件受影响版本安全版本备注
Linux Kernel(主线)5.1 ~ 6.0.x>= 6.1io_uring 自 5.1 引入,修复在 6.1-rc1
Linux Kernel(5.15 LTS)5.15.0 ~ 5.15.xbackport 修复版本(发行版跟进)
Linux Kernel(5.10 LTS)5.10.0 ~ 5.10.x(如启用 io_uring)backport 修复版本部分发行版默认未开启
Ubuntu 22.04kernel >= 5.15发行版已 backport检查 USN 公告
Debian 11(Bullseye)kernel 5.10+发行版已 backport
RHEL 9 / AlmaLinux 9kernel 5.14+发行版已 backport
CentOS / RHEL 7/8默认内核 < 5.1N/A不受影响(io_uring 未引入或默认禁用)
内核 < 5.1N/AN/A不受影响(io_uring 子系统不存在)

漏洞影响场景

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

  • 前提条件:运行受影响内核,io_uring 可用且非特权用户可创建 io_uring 实例(kernel.io_uring_disabled=0
  • 攻击过程:编译执行公开 EXP,利用 UAF 劫持内核执行流
  • 最坏影响:获取 root 权限

场景 2:容器逃逸

  • 前提条件:容器内 io_uring 未被 seccomp 拦截,宿主机内核受影响
  • 攻击过程:在容器内运行 io_uring UAF EXP,利用内核漏洞获取宿主机 root
  • 最坏影响:突破容器隔离,攻击宿主机及其他容器

场景 3:云环境 / Kubernetes 集群

  • 前提条件:Worker Node 运行受影响内核,Pod SecurityContext 未限制 io_uring
  • 攻击过程:恶意 Pod 使用 io_uring 执行提权攻击
  • 最坏影响:Node 级别沦陷,访问 etcd 密钥、Secrets、横向移动

场景 4:高性能计算 / 数据库服务器

  • 前提条件:HPC 集群或数据库节点运行受影响内核
  • 攻击过程:共享环境中低权限用户利用漏洞提权
  • 最坏影响:窃取科研数据、破坏计算任务完整性

修复措施

推荐修复(根本解决)

升级内核至 6.1 或发行版 backport 修复版本。

# Ubuntu / Debian
sudo apt update && sudo apt upgrade -y linux-image-generic
sudo reboot
 
# RHEL 9 / AlmaLinux 9
sudo dnf update kernel -y
sudo reboot
 
# Fedora
sudo dnf update kernel -y
sudo reboot
 
# 验证
uname -r
# 期望:>= 6.1 或发行版修复版本(检查对应安全公告)

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

方案一:禁用 io_uring(推荐)

# 运行时禁用(立即生效,重启后失效)
sudo sysctl -w kernel.io_uring_disabled=2
 
# 持久化禁用
echo "kernel.io_uring_disabled=2" | sudo tee -a /etc/sysctl.d/99-disable-io_uring.conf
sudo sysctl -p /etc/sysctl.d/99-disable-io_uring.conf

kernel.io_uring_disabled 值含义:

  • 0:所有进程均可创建 io_uring(默认)
  • 1:仅 CAP_SYS_ADMIN 进程可创建
  • 2:完全禁用 io_uring
副作用说明
影响高性能应用依赖 io_uring 的应用(ScyllaDB、某些存储引擎)将无法正常工作
不支持即时恢复禁用后已运行的 io_uring 实例不受影响,需重启服务

方案二:Seccomp 限制(容器环境)

# Kubernetes Pod SecurityContext 示例
securityContext:
  seccompProfile:
    type: RuntimeDefault

在容器中,使用 seccomp profile 拦截 io_uring_setup 系统调用(syscall 425)。


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

检查脚本

#!/bin/bash
# io_uring UAF (CVE-2022-2602) 漏洞检查脚本
# 用途:检查系统是否可能受 io_uring UAF 漏洞影响
# 限制:基于内核版本和 io_uring 状态判断
 
echo "=== io_uring UAF (CVE-2022-2602) 漏洞检查 ==="
echo ""
 
KERNEL_VER=$(uname -r | cut -d'-' -f1)
echo "当前内核版本:$(uname -r)"
 
MAJOR=$(echo "$KERNEL_VER" | cut -d'.' -f1)
MINOR=$(echo "$KERNEL_VER" | cut -d'.' -f2)
 
echo ""
 
# 检测 io_uring 状态
IO_URING_DISABLED=$(sysctl -n kernel.io_uring_disabled 2>/dev/null)
if [ -z "$IO_URING_DISABLED" ]; then
    IO_URING_DISABLED=0
fi
 
echo "io_uring 状态:"
case $IO_URING_DISABLED in
    0) echo "  → 所有进程可用(⚠️  风险最高)" ;;
    1) echo "  → 仅 CAP_SYS_ADMIN 可用(风险降低)" ;;
    2) echo "  → 已完全禁用(✅ 不受影响)" ;;
esac
 
echo ""
 
# 版本判断
if [ "$MAJOR" -lt 5 ]; then
    echo "✅ 内核 < 5.1,io_uring 不存在,不受影响"
elif [ "$MAJOR" -ge 7 ]; then
    echo "✅ 内核 >= 7.0,假定已修复(请验证发行版公告)"
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -ge 1 ]; then
    echo "✅ 内核 >= 6.1,主线已修复"
elif [ "$IO_URING_DISABLED" -ge 2 ]; then
    echo "✅ io_uring 已禁用,不受此漏洞影响"
else
    echo "⚠️  当前系统可能受 io_uring UAF (CVE-2022-2602) 影响"
    echo "   建议:升级内核至 6.1+ 或禁用 io_uring"
fi
 
# 确认 io_uring 模块是否加载
if lsmod 2>/dev/null | grep -q io_uring; then
    echo ""
    echo "⚠️  io_uring 内核模块已加载"
fi
 
echo ""
echo "=== 检查完成 ==="

临时修复脚本

#!/bin/bash
# io_uring UAF (CVE-2022-2602) 临时修复脚本
# 用途:通过 sysctl 禁用 io_uring 子系统
# 注意:此操作可能影响依赖 io_uring 的应用程序
 
set -e
 
echo "=== io_uring UAF (CVE-2022-2602) 临时修复 ==="
echo ""
 
# 备份当前配置
CURRENT_VALUE=$(sysctl -n kernel.io_uring_disabled 2>/dev/null || echo 0)
echo "当前 kernel.io_uring_disabled = $CURRENT_VALUE"
echo "备份当前值到 /etc/sysctl.d/99-io_uring-backup.conf"
 
echo "kernel.io_uring_disabled=$CURRENT_VALUE" | sudo tee /etc/sysctl.d/99-io_uring-backup.conf > /dev/null
 
# 完全禁用 io_uring
echo "正在禁用 io_uring..."
sudo sysctl -w kernel.io_uring_disabled=2
 
# 持久化
echo "kernel.io_uring_disabled=2" | sudo tee /etc/sysctl.d/99-disable-io_uring.conf > /dev/null
sudo sysctl -p /etc/sysctl.d/99-disable-io_uring.conf
 
echo ""
echo "✅ io_uring 已禁用(立即生效 + 重启后保持)"
echo ""
echo "如需回滚,执行:"
echo "  sudo rm /etc/sysctl.d/99-disable-io_uring.conf"
echo "  sudo cp /etc/sysctl.d/99-io_uring-backup.conf /etc/sysctl.d/99-restore-io_uring.conf"
echo "  sudo sysctl -p /etc/sysctl.d/99-restore-io_uring.conf"

参考资源

官方与 NVD

技术分析

标题URL类型标签
DirtyCred: File Exploitation on io_uring UAFhttps://blog.hacktivesecurity.com/index.php/2022/12/21/cve-2022-2602-dirtycred-file-exploitation-applied-on-an-io_uring-uaf/技术分析
CSDN 内核 exploit 分析:CVE-2022-2602https://blog.csdn.net/panhewu9919/article/list/1技术分析/PoC
Red Hat CVE 页面https://access.redhat.com/security/cve/cve-2022-2602厂商公告
Ubuntu Security Noticehttps://ubuntu.com/security/CVE-2022-2602厂商公告

PoC 与工具

标题URL类型标签
CVE-2022-2602 PoC(GitHub)https://github.com/nickfoconnor/CVE-2022-2602-LPE [待验证]PoC

io_uring 的高性能以复杂的生命周期管理为代价。CVE-2022-2602 揭示了内核子系统间(io_uring + Unix GC)非预期交互的危险性——一个子系统的垃圾回收逻辑错误,可能被另一个子系统的垂悬引用放大为内核代码执行。