What is CVE-2026-98432?
CVE-2026-98432 is a use-after-free in the IPv4 TCP implementation of the Linux kernel, disclosed in October 2026 with a critical CVSS 3.1 score of 9.8. A race condition in how the kernel manages socket options during connection establishment lets one CPU free a buffer while another CPU is still reading it. Anthropic’s Frontier Red Team then reported that an unreleased AI model had built a working zero-click remote root exploit chain for the bug, targeting systems with a Multipath TCP (MPTCP) listener.
This article covers the vulnerable code paths, the RCU-based fix, the disputed severity score, the affected kernels, and what the AI-built exploit means for defenders.
How lockless TCP scaling set up the race condition
The Linux networking stack has to process millions of packets per second at low latency, so one wrong assumption about how long a piece of memory lives can put the whole system at risk. CVE-2026-98432 comes out of that pressure, and the place to start is how the kernel handles incoming connection requests.
Historically, a listening socket held a global lock while it processed the initial SYN and the rest of the three-way handshake. That was safe, but it became a bottleneck on high-throughput, multi-core servers. Upstream commit 079096f103fa changed the design by installing SYN-received requests directly into the established hash table (ehash). Request sockets could now be processed without the listener lock, which scaled much better across CPUs and also made the concurrency harder to reason about.
When a client opens a connection, the kernel allocates a lightweight request_sock plus an inet_request_sock structure for IPv4-specific metadata. That metadata includes the IPv4 socket options, stored in an ip_options buffer that controls how optional IP header fields are processed. With no listener lock in the way, several CPUs can touch the same pending connection at once, so any mistake in memory lifetime turns into a race.
How the use-after-free happens in tcp_v4_syn_recv_sock()
The child socket race
The defect appears when a pending request socket becomes a fully established child socket. When the final ACK of the handshake arrives, the kernel calls tcp_v4_syn_recv_sock() to create the child socket. To avoid copying memory, it moves the IPv4 options pointer (ireq_opt) from the request socket to the new child socket (inet_opt). It reads the pointer with rcu_dereference() and assigns it with RCU_INIT_POINTER(). The buffer itself is never copied, only the ownership reference moves. This is a common optimization in high-performance networking, and it depends on a guarantee that no other code path is still reading the buffer.
That guarantee breaks when a second CPU handles a retransmitted SYN for the same connection request while the first CPU is finishing the handshake. The retransmission path enters tcp_check_req() and heads toward building a duplicate SYN-ACK through tcp_v4_send_synack(). Along the way, inet_csk_route_req() and ip_options_build() read the IPv4 options to construct the outgoing packet.
Now suppose the child socket from the first CPU is destroyed quickly, because of a connection reset, a timeout, or an application closing the accepted file descriptor right away. Its destructor, inet_sock_destruct(), frees the IPv4 option buffer with kfree(). The second CPU is still reading opt->optlen inside ip_options_build(), but the memory has already gone back to the slab allocator. That is a textbook use-after-free. Depending on what the allocator does with the freed memory in the meantime, the result can be a kernel panic, silent memory corruption, or, as researchers have shown, controlled execution flow.
A second path through request-socket migration
The upstream advisory also describes a parallel path through TCP request-socket migration. Many Linux deployments combine SO_REUSEPORT with BPF programs to spread incoming connections across several listening sockets. With certain configurations, controlled by the net.ipv4.tcp_migrate_req sysctl or BPF return codes such as SK_REUSEPORT_SELECT_OR_MIGRATE, the kernel can move a pending request from one listener to another.
During migration, the kernel calls inet_reqsk_clone() to duplicate the request socket, and for a short time the original and the clone share the same IPv4 option buffer. The migration logic then clears the pointer in the original request, but it does not wait for CPUs that are still running in the context of the original request to stop using the shared memory. If the clone is destroyed first, its destructor, tcp_v4_reqsk_destructor(), frees the shared buffer, and any CPU still walking the original request hits the same use-after-free.
📬 Stay Ahead of Cyber Threats
Get the latest cybersecurity news, critical vulnerabilities, threat intelligence, tutorials, and exclusive giveaways delivered straight to your inbox. No spam. Unsubscribe anytime.
Subscribe to the Newsletter →Both paths share a root cause. A state change that looks finished on one CPU does not invalidate the memory references held by readers on other CPUs.

The upstream fix: deferred freeing with RCU and kfree_rcu()
The fix landed in upstream commit e3f33b0a1d89d738e2b913dab519226eaf76e15b. It does not redesign the TCP handshake or bring back heavy locking. It applies Read-Copy-Update (RCU) so that memory reclamation matches what the readers already expect. RCU suits cases where reads are frequent and must stay fast, while updates and deletions can tolerate a short delay.
The concurrent readers of the IPv4 options were already running inside rcu_read_lock() critical sections. That protection did nothing here, because the destructor freed the buffer immediately with kfree(). A read-side lock only tells the RCU subsystem that a reader is active. It does not stop a concurrent kfree().
The patch closes the gap by swapping immediate release for deferred reclamation. With kfree_rcu(opt, rcu) in place of kfree(opt), the kernel queues a callback and returns the memory to the slab allocator only after a full RCU grace period. A grace period guarantees that every CPU that was inside a read-side critical section when kfree_rcu() was called has since passed through a quiescent state, so nobody can still be reading the buffer.
This simplified snippet shows the change in lifetime handling:
/* Vulnerable Implementation: Immediate reclamation */void inet_sock_destruct(struct sock *sk) { struct inet_sock *inet = inet_sk(sk); if (inet->inet_opt) { kfree(inet->inet_opt); /* Triggers UAF if RCU readers are active */ inet->inet_opt = NULL; }}/* Patched Implementation: Deferred reclamation via RCU */void inet_sock_destruct(struct sock *sk) { struct inet_sock *inet = inet_sk(sk); if (inet->inet_opt) { kfree_rcu(inet->inet_opt, rcu); /* Safe: waits for grace period */ inet->inet_opt = NULL; }}
The change is small, and it adds no measurable cost on the fast path.
How an AI model built a zero-click root exploit for CVE-2026-98432
On October 27, 2026, Anthropic published a research post describing how an unreleased Claude research model autonomously developed a working exploit chain for CVE-2026-98432. The target was an internet-facing Linux server exposing an MPTCP listener, a setup that is increasingly common in high-availability data centers. The exploit worked in two stages and had to get past modern kernel mitigations.
Stage 1: defeating KASLR
The first stage defeats Kernel Address Space Layout Randomization (KASLR). By steering the race condition, the exploit made the kernel read an attacker-controlled length field while building a malformed packet. That produced an out-of-bounds read, and the over-read data contained a leaked kernel pointer that revealed the randomized base address of the kernel. By Anthropic’s proof-of-concept figures, this took about 48 minutes of sustained race triggering.
Stage 2: control-flow hijacking
With KASLR defeated, the model reused the same use-after-free primitive to hijack control flow. It sent crafted packets that pushed the slab allocator into a predictable pattern of allocations and frees, a technique known as heap grooming. The aim is for the freed ip_options buffer to be reallocated as a different kernel object that holds a function pointer, such as an sk_buff destructor or a socket filter operation. The stale pointer on the racing CPU then overwrites that function pointer.
Since the kernel base was already known, the attacker knew where existing kernel gadgets sat. Redirecting the callback into a Return-Oriented Programming (ROP) chain lets execution move through existing kernel code, get around Supervisor Mode Execution Prevention (SMEP) and Supervisor Mode Access Prevention (SMAP), and end in arbitrary code execution in ring 0. Once the kernel pointer was leaked, the path from the first packet to a remote root shell took roughly five minutes.
Multi-stage memory corruption chains like this used to come almost exclusively from elite human research teams. Here an AI agent produced one.
CVSS 9.8 vs 5.9: why the severity of CVE-2026-98432 is disputed
The two main scores for this bug are far apart. The CVE.org record rates it Critical at 9.8, using a vector that assumes low attack complexity and high impact on confidentiality, integrity, and availability. Red Hat initially rated it Moderate at 5.9. Its reasoning was that the race is hard to win reliably and the most likely outcome is a denial of service through a kernel panic. That is the conservative stance most vendors take on kernel races, where the gap between a theoretical memory corruption and a reliable exploit is usually wide.
Anthropic’s result weakens that argument. The model needed a specific configuration (an MPTCP listener) and a long time to win the race reliably, but a demonstrated path to ring-0 execution means the bug cannot be filed as a stability issue. I would treat 9.8 as the working number and not discount it because the race is difficult.
Affected Linux kernel versions and how to patch CVE-2026-98432
The flaw traces back to a commit introduced years ago and persists in kernels up to the 7.3 development branch. The upstream fix has been backported to the stable long-term support branches 5.10.272, 5.15.223, 6.1.190, and 6.6.159.
Checking uname -r is not enough to know whether you are exposed. Ubuntu, Red Hat Enterprise Linux, and Debian routinely backport security fixes into their own kernel packages without changing the upstream version number. Look up the CVE in your distribution’s security tracker, then install the updated kernel package with the native package manager.
Disabling request-socket migration with sysctl -w net.ipv4.tcp_migrate_req=0 may close the secondary path. It does nothing for the primary race in child socket creation. The only complete mitigation is to deploy the patched kernel and reboot, so the fixed code is what actually runs.
What CVE-2026-98432 means for AI-assisted exploit development
The bug is a familiar kind. Two performance optimizations, lockless hash table insertion and zero-copy pointer transfer, broke the lifetime guarantee that memory safety depends on. What is new is who built the exploit. Chaining kernel vulnerabilities used to take specialized human teams years of experience, and an AI model has now done it for this CVE. As models get better at this, the barrier to finding and chaining complex kernel bugs will keep dropping.
For Linux operators the immediate steps are to patch the networking stack, reboot into the patched kernel, and verify the fix through your distribution’s tracker. Patch cycles will have to keep pace with automated exploit development.









