CVE-2026-43121 Overview
CVE-2026-43121 is a race condition vulnerability in the Linux kernel's io_uring/zcrx (zero-copy receive) subsystem. The flaw exists in the io_zcrx_put_niov_uref() function, which manipulates the user_refs counter using a non-atomic check-then-decrement pattern. While that path is serialized by rq_lock, the concurrent io_zcrx_scrub() function modifies the same counter via atomic_xchg() without holding rq_lock. The resulting race allows the same niov to be pushed onto the freelist twice, producing a double-free and an out-of-bounds write into adjacent slab memory.
Critical Impact
A successful race triggers a double-free in kernel memory and an out-of-bounds u32 write past the kvmalloc'd freelist, corrupting adjacent slab objects and creating conditions suitable for kernel memory corruption.
Affected Products
- Linux kernel versions implementing io_uring zero-copy receive (zcrx) functionality
- SMP (symmetric multiprocessing) Linux systems where the race window is reachable
- Distributions shipping the affected io_uring/zcrx code prior to the upstream fix
Discovery Timeline
- 2026-05-06 - CVE-2026-43121 published to NVD
- 2026-05-06 - Last updated in NVD database
Technical Details for CVE-2026-43121
Vulnerability Analysis
The vulnerability resides in the io_uring zero-copy receive (zcrx) reference counting logic. The function io_zcrx_put_niov_uref() reads user_refs with atomic_read() and, if the value is greater than zero, performs a separate atomic_dec(). Although callers of this function are serialized by rq_lock, the io_zcrx_scrub() routine resets the same counter using atomic_xchg(uref, 0) without acquiring rq_lock. The split read and decrement opens a window for another CPU to set the counter to zero between the two operations.
Root Cause
The defect is an atomicity violation [CWE-362-class] in the reference counter handling for network I/O vectors (niov). The check-then-act sequence is not a single atomic transaction. When scrub executes atomic_xchg() after the refill path's atomic_read() but before its atomic_dec(), the decrement wraps the counter to -1 while scrub has already returned the niov to the freelist. The refill path then returns the same niov a second time.
Attack Vector
A local attacker with the ability to use io_uring and trigger zcrx scrub and refill paths concurrently on an SMP system can race the two code paths. The double push of an niov causes free_count to exceed nr_iovs. Subsequent freelist pushes write a u32 value past the end of the kvmalloc'd freelist array into an adjacent slab object, corrupting kernel memory. Refer to the kernel commits referenced below for the exact code paths and the upstream fix.
The vulnerability is described in prose only; see the kernel commit a94f096e28bf for the patch that replaces the non-atomic read-then-decrement with an atomic_try_cmpxchg loop.
Detection Methods for CVE-2026-43121
Indicators of Compromise
- Kernel oops, BUG, or KASAN reports referencing io_zcrx_put_niov_uref, io_zcrx_scrub, or return_niov_freelist in the call trace
- Slab corruption messages or slab-out-of-bounds warnings adjacent to io_uring zcrx allocations
- Unexpected process crashes or kernel panics on workloads that heavily use io_uring zero-copy receive
Detection Strategies
- Enable KASAN (Kernel Address Sanitizer) on test and pre-production kernels to surface the out-of-bounds write triggered by this race
- Audit running kernel versions across the fleet and compare against the patched stable releases referenced in the upstream commits
- Monitor dmesg and journalctl -k for io_uring-related warnings and ref-count anomalies
Monitoring Recommendations
- Collect kernel crash dumps with kdump and inspect for double-free patterns in io_uring/zcrx paths
- Track io_uring syscall usage by unprivileged workloads and flag abnormal volumes from non-trusted users
- Centralize kernel logs in a SIEM and alert on backtraces containing io_zcrx_* symbols
How to Mitigate CVE-2026-43121
Immediate Actions Required
- Apply the upstream Linux kernel patches that replace the non-atomic read-then-decrement with an atomic_try_cmpxchg loop in io_zcrx_put_niov_uref()
- Rebuild and deploy distribution kernel packages once vendors publish backported fixes for supported stable trees
- Restrict io_uring access for untrusted users where the workload allows, using kernel.io_uring_disabled sysctl
Patch Information
The fix is delivered through the following upstream kernel commits: 003049b1c4fb, 485dc691257b, and a94f096e28bf. The patch makes the test-and-decrement on user_refs a single atomic operation, eliminating the race against atomic_xchg() performed by io_zcrx_scrub() without requiring scrub to acquire rq_lock.
Workarounds
- Disable io_uring system-wide on kernels that support the toggle: sysctl -w kernel.io_uring_disabled=2
- Avoid using io_uring zero-copy receive (IORING_OP_RECV_ZC and related zcrx interfaces) until the kernel is patched
- Apply seccomp filters to block io_uring_setup, io_uring_register, and io_uring_enter for sandboxed or untrusted processes
# Disable io_uring for unprivileged users until patched kernel is deployed
sysctl -w kernel.io_uring_disabled=2
echo 'kernel.io_uring_disabled=2' >> /etc/sysctl.d/99-io-uring.conf
# Verify current kernel version against patched stable trees
uname -r
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


