CVE-2022-2602 内核提权详细分析
字数 2979 2025-08-29 08:30:36
Linux内核漏洞CVE-2022-2602分析与利用教学文档
漏洞概述
漏洞编号: CVE-2022-2602
影响版本: Linux Kernel < v6.0.3
漏洞类型: Use-After-Free (UAF)
利用效果: 本地提权
漏洞模块: io_uring & unix_gc
漏洞本质: filp结构的UAF问题
环境搭建
复现环境:
- QEMU虚拟机
- Linux内核版本: v5.18.19
复现流程:
- 执行exp后会自动添加root用户
- 用户名: mowen
- 密码: mowen
- 使用
su mowen完成提权
漏洞原理深度分析
核心机制
-
io_uring文件注册机制:
io_uring_register系统调用中的IORING_REGISTER_FILES功能可以注册文件- 注册后文件会被放入
io_uring->sk->receive_queue - 在Linux垃圾回收(GC)机制中会将这些文件取出并尝试释放
-
飞行计数机制:
- Linux进程间通信(IPC)中用于传递文件描述符的引用计数机制
- 防止文件在传输过程中被意外释放
- 主要针对socket和io_uring等特殊文件类型
-
垃圾回收机制:
- 解决socket文件自引用导致的资源无法释放问题
- 通过
unix_gc()函数实现 - 遍历全局飞行列表
gc_inflight_list进行资源回收
技术细节
飞行计数工作原理
-
正常文件传递流程:
- 发送方: 文件引用计数+1 (防止接收前被关闭)
- 接收方: 成功接收后引用计数-1
- 如果接收前连接关闭: 通过
sock_release调用fput()减少引用计数
-
自引用问题:
- 当两个socket互相传递对方的fd时:
- A发送给B,B发送给A
- 引用计数都变为2
- 关闭用户态fd后引用计数为1
- 内核无法自动释放,形成资源泄漏
- 当两个socket互相传递对方的fd时:
SCM_RIGHTS发送流程
-
发送准备阶段 (
scm_send):- 获取file结构体
- 初始化
scm_cookie - 临时增加文件引用计数(通过
fget_raw)
-
发送处理阶段 (
unix_scm_to_skb):- 将
scm_cookie添加到skb - 调用
unix_attach_fds:- 通过
scm_fp_dup增加文件引用计数(正式发送增加) - 通过
unix_inflight增加飞行计数(仅对socket/io_uring)
- 通过
- 将
-
发送完成阶段:
- 将skb挂载到对端的
sk_receive_queue - 调用
scm_destroy释放临时增加的引用计数
- 将skb挂载到对端的
垃圾回收机制(unix_gc)
-
触发条件: socket被关闭时调用
-
工作流程:
- 遍历全局飞行列表
gc_inflight_list - 检查文件引用计数 == 飞行计数的对象("垃圾"候选)
- 将这些对象放入
gc_candidates队列 - 调用
scan_children处理sk_receive_queue中的文件 - 判断是否为真正的"闭环"引用
- 释放符合条件的资源
- 遍历全局飞行列表
-
关键函数:
scan_children: 处理sock->sk_receive_queue中的文件__skb_queue_purge: 实际释放资源的函数
io_uring相关机制
-
文件注册流程 (
io_sqe_files_register):- 调用
io_sqe_files_scm - 使用
get_file增加文件引用计数 - 调用
unix_inflight增加飞行计数(对socket/io_uring) - 将文件列表挂载到
io_uring自己的sk_receive_queue
- 调用
-
任务提交流程 (
io_submit_sqe):- 初始化IO请求
- 调用
io_queue_sqe执行任务 - 文件鉴权在
io_write中的io_rw_init_file完成
漏洞利用分析
漏洞形成原因
-
非法释放流程:
io_uring注册文件时会将文件放入自己的sk_receive_queue- 垃圾回收时会错误地释放这些文件
- 但后续任务仍会尝试使用已释放的文件结构体
-
关键问题:
io_uring自己的sk_receive_queue被垃圾回收机制误处理- 导致非socket文件被错误释放
完整利用流程
-
初始准备:
- 创建socket pair:
s[0]和s[1](引用计数=1) - 初始化
io_uring:io_fd(引用计数=1) - 打开普通文件:
file_fd(引用计数=1)
- 创建socket pair:
-
注册文件:
- 使用
io_uring_register注册s[1]和file_fd - 结果:
s[1]: 引用计数=2, 飞行计数=1file_fd: 引用计数=2
- 使用
-
发送io_fd:
- 通过
s[0]发送io_fd给s[1] io_fd: 引用计数=2, 飞行计数=1
- 通过
-
关闭文件:
- 关闭
file_fd: 引用计数=1 - 关闭
s[0]: 被完全释放 - 关闭
s[1]: 引用计数=1, 飞行计数=1
- 关闭
-
制造阻塞:
- 使用线程占用目标文件inode锁
- 提交
io_uring写任务(会被阻塞在实际写操作前)
-
触发漏洞:
- 关闭
io_uring(io_fd) - 触发垃圾回收:
- 错误释放
file_fd的文件结构体 - 但写任务仍在等待
- 错误释放
- 关闭
-
利用UAF:
- 喷射大量"/etc/passwd"文件
- 覆盖被释放的文件结构体
- 当阻塞解除后,写入操作会修改"/etc/passwd"
-
提权完成:
- 添加新的root用户
- 通过
su命令提权
防御措施
-
官方修复:
- Linux内核v6.0.3已修复此漏洞
- 主要修正垃圾回收机制对
io_uring文件的处理逻辑
-
缓解措施:
- 禁用
io_uring功能(如非必需) - 使用内核模块黑名单阻止
io_uring加载 - 及时更新内核版本
- 禁用
参考资源
- [kernel exploit]CVE-2022-2602垃圾回收错误释放iouring的file导致UAF — bsauce
- [漏洞分析] CVE-2022-2602 内核提权详细分析
- io_uring, SCM_RIGHTS, and reference-count cycles (https://lwn.net/Articles/779472/)
- The quantum state of Linux kernel garbage collection CVE-2021-0920 (Part I) (https://googleprojectzero.blogspot.com/2022/08/the-quantum-state-of-linux-kernel.html)
总结
CVE-2022-2602是一个典型的UAF漏洞,利用了Linux内核中io_uring模块与垃圾回收机制的交互问题。通过精心构造的文件引用关系,攻击者可以触发非法文件释放,进而实现权限提升。理解此漏洞需要深入掌握Linux内核的文件引用计数、飞行计数和垃圾回收机制,以及io_uring模块的工作原理。