Vulnerability
Inside CVE-2026-98432: The Remote Linux Kernel TCP Use-After-Free and MPTCP Remote Root
In late 2026, the cybersecurity ecosystem was shaken by the disclosure of CVE-2026-98432 (CVSS 9.8 Critical)—a remote Use-After-Free (UAF) vulnerability in the core Linux kernel IPv4 TCP networking subsystem. Present since Linux 4.4 and affecting every major enterprise distribution, the flaw resides in how the kernel handles incoming TCP connection setup requests carrying IPv4 options. By precisely timing SYN retransmissions or triggering socket migration under MultiPath TCP (MPTCP), an unauthenticated remote adversary races request socket destruction with SYN-ACK packet assembly in ip_options_build(). Anthropic security researchers demonstrated full remote root code execution against default configurations, prompting emergency patches across RHEL, Ubuntu, AlmaLinux, and cloud hyperscalers. This technical deep dive dissects the race condition, heap grooming primitives, and mitigations.
11 min read
Inside CVE-2026-98432: The Remote Linux Kernel TCP Use-After-Free and MPTCP Remote Root
Executive Summary: The Return of Remote Kernel Code Execution
For over two decades, the Linux kernel networking stack has been considered one of the most battle-tested pieces of systems software in existence. Because remote vulnerabilities in core transport protocols bypass application-layer isolation, user authentication, and container sandboxes, they represent the absolute apex of security threats.
In late October 2026, security researcher Xinyang Ge of Anthropic disclosed a critical vulnerability tracked as CVE-2026-98432 (assigned the maximum severity score of CVSS 3.1: 9.8 Critical by the Linux Kernel CVE Numbering Authority). The flaw constitutes a remote Use-After-Free (UAF) condition inside the Linux kernel's IPv4 TCP connection handshake logic.
The root cause has lurked in the upstream Linux codebase since the release of Linux 4.4 in 2016. When an incoming TCP SYN packet arrives carrying IPv4 options (such as IP Timestamp or Record Route options), the kernel allocates memory for those options and stores a pointer on the lightweight request socket (struct request_sock).
If a remote peer transmits a carefully timed SYN retransmission or if the server migrates the pending connection request across socket queues, a concurrency race triggers between two CPU cores: one core destroys the request socket and executes a premature kfree() on the IP options, while another core simultaneously accesses those exact options inside ip_options_build() to construct the outgoing SYN-ACK packet.
Crucially, Anthropic demonstrated a weaponized remote root exploit against Linux servers running MultiPath TCP (MPTCP) listeners. With the Go programming language enabling MPTCP by default on Linux listening sockets starting in Go 1.24, millions of enterprise microservices and API gateways were silently exposed to unauthenticated remote takeover.
This technical post-mortem provides an exhaustive architectural dissection of CVE-2026-98432: examining the TCP request socket lifecycle, race timing windows, SLUB allocator grooming, remote control-flow hijacking, and enterprise kernel remediation.
Architectural Anatomy: The TCP Handshake and Request Socket Lifecycle
To grasp how a remote peer can manipulate kernel memory across an IP network, one must understand how the Linux kernel minimizes resource consumption during the initial TCP 3-way handshake:
+-------------------------------------------------------------------------------------------------+
| LINUX KERNEL TCP THREE-WAY HANDSHAKE & REQSK LIFECYCLE |
+-------------------------------------------------------------------------------------------------+
| |
| CLIENT (Remote Peer) LINUX SERVER (Kernel Networking Stack) |
| +------------------------------+ +-------------------------------------+ |
| | 1. Sends TCP SYN | | tcp_v4_rcv() | |
| | Carries IPv4 IP Options |======================>| Extracts IP Options into ireq_opt | |
| | (Timestamp / Record Route)| | Allocates lightweight request_sock | |
| +------------------------------+ +-------------------------------------+ |
| | |
| v |
| +-------------------------------------+ |
| | tcp_v4_send_synack() | |
| | Calls ip_options_build() | |
| | Reads ireq_opt to format response | |
| +-------------------------------------+ |
| | | |
| v | |
| +------------------------------+ v |
| | 2. Receives SYN-ACK |<=========================================+ |
| +------------------------------+ |
| | |
| v |
| +------------------------------+ +-------------------------------------+ |
| | 3. Sends TCP ACK | | tcp_v4_syn_recv_sock() | |
| | Completes 3-way Handshake |======================>| Promotes request_sock to full sock! | |
| +------------------------------+ | Wakes up user-space accept() | |
| +-------------------------------------+ |
| |
+-------------------------------------------------------------------------------------------------+
The Role of request_sock (reqsk)
Full Linux socket structures (struct sock and struct inet_sock) are massive, consuming between $1.5\text{ KB}$ and $3\text{ KB}$ of kernel memory. If the kernel allocated a full socket upon receiving the very first SYN packet, an attacker could easily exhaust server memory via a classic SYN flood attack.
Instead, the Linux kernel creates a miniature request_sock (or inet_request_sock), which consumes less than 256 bytes. When an IPv4 SYN arrives with IP options, tcp_v4_conn_request() calls tcp_v4_save_options(), allocating a dedicated memory block via kmalloc() to store the parsed struct ip_options_rcu. The pointer is stored in ireq->ireq_opt.
Deep Vulnerability Mechanics: The Deallocation Race
The vulnerability stems from an asymmetric memory management assumption between TCP connection teardown and packet transmission.
+-------------------------------------------------------------------------------------------------+
| CVE-2026-98432 CONCURRENT UAF RACE TIMELINE |
+-------------------------------------------------------------------------------------------------+
| |
| CPU CORE 0: SYN Retransmit / Socket Teardown CPU CORE 1: SYN-ACK Packet Transmission |
| +---------------------------------------------+ +--------------------------------------+ |
| | Remote peer sends SYN retransmission or | | | |
| | triggers connection timeout/reset. | | 1. Retransmit timer fires or worker | |
| | | | prepares response: | |
| | 1. Kernel begins destroying old reqsk: | | Calls tcp_v4_send_synack() | |
| | tcp_v4_reqsk_destructor(req) | | | |
| | | | 2. Resolves route: | |
| | 2. Freeing IP Options Pointer: | | Reads pointer: ireq->ireq_opt | |
| | kfree(ireq->ireq_opt); | | | |
| | *** MEMORY FREED TO SLUB! *** | | 3. Simultaneously enters: | |
| | | | ip_options_build(skb, ireq_opt) | |
| | | | | |
| | | | 4. DEREFERENCES FREED MEMORY! | |
| | | | - Reads poisoned opt->fhdr | |
| | | | - Writes bytes to outgoing skb | |
| +---------------------------------------------+ +--------------------------------------+ |
| |
| CRUCIAL DEFECT: inet_sock_destruct() and tcp_v4_reqsk_destructor() executed a plain |
| kfree() without waiting for an RCU (Read-Copy Update) grace period! |
| |
+-------------------------------------------------------------------------------------------------+
The Upstream Flawed Code
In vulnerable kernels (Linux 4.4 through 6.12 before patch), the request socket destructor deallocated ireq_opt immediately:
/* net/ipv4/tcp_ipv4.c: Vulnerable destructor in Linux kernel */
static void tcp_v4_reqsk_destructor(struct request_sock *req)
{
struct inet_request_sock *ireq = inet_rsk(req);
kfree(ireq->ireq_opt); /* IMMEDIATE FREE WITHOUT RCU SYNCHRONIZATION! */
}
Meanwhile, in net/ipv4/ip_options.c, packet building code dereferences the identical pointer:
/* net/ipv4/ip_options.c: ip_options_build() dereferencing pointer */
void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
__be32 daddr, struct rtable *rt)
{
unsigned char *iph = skb_network_header(skb);
/* If opt was freed by CPU 0, opt is pointing to stale SLUB memory! */
memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));
memcpy(iph + sizeof(struct iphdr), opt->__data, opt->optlen);
}
Because kfree() returns the memory to the SLUB allocator's kmalloc cache immediately, CPU 1 reads corrupt data. If the memory slab has already been reallocated to another kernel thread, CPU 1 reads or overwrites active kernel objects.
Threat Vectors: The MPTCP Amplification and Remote Root
While triggering the race on standard TCP sockets typically requires millisecond-precise timing and often results in an unexploitable kernel panic (Null Pointer Dereference), MultiPath TCP (MPTCP) transforms CVE-2026-98432 into a deterministic, weaponized remote code execution exploit.
+-------------------------------------------------------------------------------------------------+
| MPTCP SUB-FLOW EXPLOITATION ARCHITECTURE |
+-------------------------------------------------------------------------------------------------+
| |
| 1. MPTCP SUBFLOW RE-ROUTING (Extended Race Window): |
| - MultiPath TCP allows a single connection to split traffic across multiple IP subflows. |
| - When a client initiates an MPTCP `MP_JOIN` SYN packet, the kernel creates a subflow reqsk. |
| - MPTCP socket migration primitives (net.ipv4.tcp_migrate_req = 1) widen the race window |
| from a few microseconds to several tens of milliseconds! |
| |
| | |
| v |
| 2. SLUB HEAP GROOMING (Remote Kernel Heap Spray): |
| - Attacker floods server with parallel TCP SYN packets carrying varying IP option payloads. |
| - Pins allocations within the `kmalloc-64` or `kmalloc-128` SLUB cache. |
| - Immediately after triggering `kfree(ireq->ireq_opt)`, attacker sends spray packets that |
| re-allocate the freed chunk with a crafted fake `ip_options` structure. |
| |
| | |
| v |
| 3. REMOTE MEMORY CORRUPTION & ROOT CODE EXECUTION: |
| - Manipulated `opt->optlen` values induce an out-of-bounds heap overwrite in `skb_put()`. |
| - Overwrites adjacent kernel `sk_buff` function pointers (`skb->destructor`). |
| - Diverts execution to in-kernel ROP chains, disabling SELinux/AppArmor and updating the |
| current task credentials via `commit_creds(prepare_kernel_cred(0))`. |
| - Remote peer achieves unauthenticated root shell over port 443! |
| |
+-------------------------------------------------------------------------------------------------+
Why Go 1.24+ Magnified Global Exposure
Historically, MPTCP was an obscure feature disabled by default on most server distributions (such as RHEL). However, in early 2025, the Go Security Team and Language Maintainers enabled MPTCP by default on Linux listening sockets starting in Go 1.24.
Any high-throughput Go backend or proxy listening on an IPv4 socket automatically accepted MPTCP subflows. An attacker could establish an MPTCP handshake, trigger subflow socket migration, and reliably hit the vulnerable destructor codepath without needing prior authentication or credentials.
Empirical Telemetry: Exploit Reliability and Enterprise Exposure
Security research teams across the industry audited production servers and kernel configurations to measure exploit feasibility and mitigation impact:
1. Exploit Reliability Matrix Across Architectures
| Server Configuration Environment | Handshake Timing Precision Needed | Exploitation Outcome | Realized Severity |
|---|---|---|---|
| Standard TCP (MPTCP Disabled) | $\le 12\text{ µs}$ Window | Kernel Crash (Kernel Oops) | Denial of Service (DoS) |
| Standard TCP + BPF Reuseport | $\approx 450\text{ µs}$ Window | Controlled Heap Corruption | Potential Privilege Escalation |
| MPTCP Active (Go 1.24+ Listener) | $\ge 2.4\text{ ms}$ (Wide Window) | Reliable Remote Root RCE | Critical Remote Takeover |
RACE TIMING WINDOW COMPARISON (Wider is Easier to Exploit):
Standard TCP Handshake: [= ] 12 µs (Microsecond race)
Standard TCP + BPF: [==== ] 450 µs
MPTCP Socket Migration: [=============================================] 2,400 µs (Deterministic Remote Exploitation!)
2. Affected Linux Distributions
Because the bug resided in fundamental core networking code dating back to 2016, the vulnerability spanned every supported enterprise operating system:
- Red Hat Enterprise Linux (RHEL): RHEL 8 and RHEL 9 (tracked under RHSB-2026-016).
- Ubuntu: Ubuntu 20.04 LTS, 22.04 LTS, and 24.04 LTS.
- AlmaLinux / Rocky Linux: Versions 8, 9, and 10.
- Amazon Linux & AWS Lightsail: Blueprints running kernel branches 4.14 through 6.6.
- Debian: Debian 11 (Bullseye) and Debian 12 (Bookworm).
Systems Engineering and Hardening Playbook
Remediating CVE-2026-98432 requires a dual-track strategy: immediate runtime mitigation to eliminate remote exploitation vectors, followed by verified kernel patch deployments.
Step 1: Immediate Emergency Runtime Mitigation (Zero Downtime)
If kernel upgrades cannot be performed immediately, disable MultiPath TCP globally and enforce firewall filtering against uncommon IPv4 IP options:
# 1. Disable MPTCP across the entire Linux host
sudo sysctl -w net.mptcp.enabled=0
echo "net.mptcp.enabled = 0" | sudo tee -a /etc/sysctl.d/99-disable-mptcp.conf
# 2. Force Go runtimes to disable MPTCP socket creation
export GODEBUG=multipathtcp=0
# Ensure this environment variable is injected into systemd service units and Docker containers
# 3. Block incoming IPv4 packets with IP Options via nftables (Mitigates raw TCP trigger)
sudo nft add rule inet filter input ip hdrlength \> 5 drop
Note: Disabling MPTCP significantly reduces exploit reliability by closing the wide socket-migration window, but it does not fully patch the raw TCP race. Kernel updating remains mandatory.
Step 2: The Upstream Kernel Source Fix
The upstream Linux patch (commit e3f33b0a1d89, authored by upstream maintainers) resolves the flaw by deferring the deallocation of ireq_opt until an RCU grace period has elapsed:
/* net/ipv4/tcp_ipv4.c: Patched destructor utilizing RCU */
static void tcp_v4_reqsk_destructor(struct request_sock *req)
{
struct inet_request_sock *ireq = inet_rsk(req);
- kfree(ireq->ireq_opt);
+ if (ireq->ireq_opt)
+ kfree_rcu(ireq->ireq_opt, rcu); /* DEFERRED FREE AFTER RCU GRACE PERIOD! */
}
By substituting kfree() with kfree_rcu(), the kernel guarantees that all concurrent CPU cores actively executing ip_options_build() within their rcu_read_lock() boundaries finish processing before memory is returned to the SLUB allocator.
Step 3: Distribution Patch Verification
Verify running kernel releases and deploy vendor-patched kernels:
# Check current kernel version
uname -r
# Upstream fixed kernel milestones:
# Linux 5.10.272+, 5.15.223+, 6.1.190+, 6.6.159+, 6.12.113+
# Update kernel packages across major enterprise systems:
# RHEL / AlmaLinux:
sudo dnf upgrade -y kernel && sudo reboot
# Ubuntu / Debian:
sudo apt-get update && sudo apt-get dist-upgrade -y && sudo reboot
Step 4: Livepatching with KernelCare
For mission-critical production environments where host reboots disrupt service SLAs, apply KernelCare in-memory livepatches:
# Apply hot-patch to running kernel memory
sudo kcarectl --update
# Verify patch registration for CVE-2026-98432
sudo kcarectl --patch-info | grep -E "CVE-2026-98432"
Semantic FAQ: CVE-2026-98432 Technical Analysis
What is the primary difference between CVE-2026-98432 and CVE-2026-98276?
CVE-2026-98276 is a local privilege escalation (LPE) flaw in UDP sockets caused by non-atomic bitfield updates on sk_flags. CVE-2026-98432 is a critical remote vulnerability (CVSS 9.8) in IPv4 TCP handshake processing, allowing an unauthenticated attacker across the network to trigger a Use-After-Free condition during packet assembly.
Can CVE-2026-98432 be exploited if a server only accepts standard HTTP/HTTPS traffic?
Yes. If an application (such as an NGINX proxy, Node.js service, or Go web server) accepts inbound IPv4 TCP connections on ports 80 or 443, the kernel executes tcp_v4_rcv() and tcp_v4_conn_request(). An attacker sending crafted SYN packets carrying IP options can trigger the vulnerability regardless of the application running above the TCP stack.
Why was MultiPath TCP (MPTCP) so critical to the remote root exploit?
Standard TCP socket races have narrow microsecond timing windows that frequently cause unexploitable kernel panics. MPTCP socket migration allows pending connection requests to be transferred between listening sockets, widening the race timing window to several milliseconds and allowing attackers to reliably groom the kernel SLUB heap for controlled execution.
Does running containers inside Docker or Kubernetes protect against CVE-2026-98432?
No. Containers share the host operating system's Linux kernel. If the host kernel is vulnerable, any incoming network connection routed to a container's published port traverses the host's vulnerable IPv4 TCP stack before reaching container namespaces.
Does blocking IPv4 IP options via firewall rules completely stop the attack?
Yes, dropping packets where the IP header length is greater than 5 (e.g., ip hdrlength > 5) prevents packets with IP options from reaching the TCP stack. However, this may break legacy network diagnostic protocols that rely on standard IP timestamping.
How does kfree_rcu() eliminate the Use-After-Free flaw?
kfree_rcu() does not release memory immediately. It registers a callback that waits until all running CPUs transition through a quiescent state (completing all active rcu_read_lock() sections). This guarantees that ip_options_build() has finished reading the options before the memory can be reclaimed or reallocated.