CVE-2025-68234

The Ol' Switcheroo: How a Typos in io_uring Nuked Kernel Queues

Alon Barad
Alon Barad
Software Engineer

Jan 15, 2026·5 min read

Executive Summary (TL;DR)

In io_uring network commands, a call to skb_queue_splice() had its arguments transposed. This caused the permanent socket error queue to be moved into a temporary on-stack list that gets destroyed when the function returns. The result is data loss, state corruption, and a high probability of a kernel crash (DoS) triggered by a local user.

A classic logic error in the Linux kernel's io_uring subsystem where a developer confused the source and destination arguments in a list-splicing function. Instead of saving temporary data to the socket queue, the kernel accidentally emptied the socket's critical error queue into a temporary variable destined for oblivion.

The Hook: io_uring Strikes Again

Ah, io_uring. The Linux kernel's high-performance asynchronous I/O interface that keeps on giving. It’s fast, it’s complex, and it’s become a favorite hunting ground for vulnerability researchers. If you want speed, you use io_uring. If you want job security as an exploit dev, you also use io_uring.

This specific vulnerability (CVE-2025-68234) hides in the cmd_net implementation—essentially the part of io_uring handling advanced network commands. Specifically, it involves the handling of packet timestamps (SO_TIMESTAMPING).

When you're doing high-precision networking, knowing exactly when a packet hit the wire is crucial. The kernel supports this by queuing timestamp notifications back to the user. But in this case, the mechanism to retry retrieving those timestamps had a fatal flaw. It wasn't a buffer overflow, and it wasn't a race condition. It was something far simpler and more embarrassing: a developer got their left and right mixed up.

The Flaw: A Tale of Two Lists

To understand the bug, you have to understand how the kernel manages lists of socket buffers (SKBs). The kernel frequently moves packets between queues. The function skb_queue_splice(list, head) is designed to take all elements from the list (source) and append them to head (destination).

In the vulnerable code path, the kernel has a temporary local list (on the stack) containing some SKBs that need to be put back into the socket's persistent error queue (sk->sk_error_queue).

The logic should have been: "Take the stuff from my temporary list and put it safely into the socket."

Instead, the code did this: skb_queue_splice(&sk->sk_error_queue, &list);

See the problem? They passed the socket's permanent queue as the source and the temporary stack list as the destination.

This is the programming equivalent of trying to pour a glass of water into the ocean, but accidentally pouring the entire ocean into your glass. The physics of the kernel (and reality) don't like that.

The Code: The Smoking Gun

Let's look at the diff. It is painfully simple. This single line caused the entire vulnerability.

In io_uring/net.c, inside the retry loop for timestamp retrieval, the code attempts to clean up:

// VULNERABLE CODE (Before)
// 'list' is a temporary struct sk_buff_head on the stack.
// 'sk->sk_error_queue' is the persistent socket queue.
 
skb_queue_splice(&sk->sk_error_queue, &list); 

Because skb_queue_splice empties the first argument into the second, this instruction rips every existing error packet out of the socket and dumps it into list.

When the function eventually returns, list goes out of scope. Depending on how the cleanup code handles list, those packets are either leaked into the void (memory leak) or freed while the socket might still think it owns them (state corruption).

Here is the fix in commit c85d2cfc5e24e6866b56c7253fd4e1c7db35986c:

// PATCHED CODE (After)
// Now we correctly move the temporary items back to the socket.
 
skb_queue_splice(&list, &sk->sk_error_queue);

One comma, two arguments swapped. That's the difference between a stable system and a kernel panic.

The Exploit: Crashing the Party

Exploiting this isn't about gaining root immediately; it's about causing chaos (Denial of Service). A local user with low privileges can trigger this because io_uring is generally available to users.

Here is the attack strategy:

  1. Setup: Create a socket and enable SO_TIMESTAMPING. We need the kernel to generate error queue entries (timestamps) for us.
  2. Fill the Queue: Send enough traffic to populate sk->sk_error_queue with timestamp notifications.
  3. Trigger the Bug: Issue an io_uring network command that hits the retry path in cmd_net. This is the tricky part—you need to induce a condition where the kernel decides to splice the lists. Usually, this happens during error handling or retries.
  4. The Crash: When the bug triggers, the socket's queue is emptied.

If the kernel subsequently tries to access those packets via the socket (expecting them to be there), it hits a NULL pointer or a dangling reference. Alternatively, if the stack variable list destroys the SKBs when it goes out of scope, but the socket logic still tracks the count of packets it thinks it has, we get a beautiful state inconsistency that usually ends in a panic.

Researcher Note: While currently classified mainly as a DoS, whenever you have "unaccounted for freeing of objects" (if the local list cleanup frees them), you are technically flirting with Use-After-Free (UAF) scenarios if you can race another thread to access that socket queue before the cleanup finishes.

The Fix: RTFM (Read The Function Manual)

The mitigation is straightforward: Apply the patch. The Linux kernel team fixed this in 6.18 and backported it to 6.17.11.

If you are stuck on a vulnerable kernel (6.17 - 6.17.10) and cannot reboot, your options are limited. You could try to block io_uring access entirely using sysctl, which effectively kills the attack vector at the cost of performance for applications that rely on it:

sysctl -w kernel.io_uring_disabled=1

But really, just patch your kernel. This is a logic bug in a core subsystem; it's not going away with a firewall rule.

Official Patches

Fix Analysis (2)

Technical Appendix

CVSS Score
6.2/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H
EPSS Probability
0.02%
Top 94% most exploited

Affected Systems

Linux Kernel 6.17Linux Kernel 6.17.1Linux Kernel 6.17.2Linux Kernel 6.17.3Linux Kernel 6.17.4Linux Kernel 6.17.5Linux Kernel 6.17.6Linux Kernel 6.17.7Linux Kernel 6.17.8Linux Kernel 6.17.9Linux Kernel 6.17.10

Affected Versions Detail

Product
Affected Versions
Fixed Version
Linux Kernel
Linux
>= 6.17, < 6.17.116.17.11
AttributeDetail
Attack VectorLocal
CVSS v3.16.2 (Medium)
ImpactDenial of Service (System Crash)
Vulnerability TypeLogic Error (Argument Transposition)
Affected Subsystemio_uring / net
EPSS Score0.00024
CWE-683
Function Call with Incorrect Order of Arguments

The product calls a function, procedure, or routine, but the caller specifies the arguments in an incorrect order, leading to incorrect behavior or security vulnerabilities.

Vulnerability Timeline

Patch Committed to Mainline
2025-12-16
CVE Published
2025-12-16
Backported to Stable
2025-12-18

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.