Someone left the keys in the ignition of a car parked in a locked garage — technically stealable, but the garage door is on a timer
CVE-2026-98432 is a use-after-free in the Linux kernel's IPv4 TCP stack, present in every kernel from 4.4 through the fix commits (5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3-rc7). When tcp_v4_syn_recv_sock() hands off ireq->ireq_opt to a child socket, a second CPU processing a retransmitted SYN for the same request socket can still be reading those options under rcu_read_lock(). Since commit 079096f103fa removed the listener lock from request socket processing, nothing prevents the child socket from being freed mid-SYNACK construction. The result: ip_options_build() reads freed memory. A secondary path exists with request socket migration (net.ipv4.tcp_migrate_req=1), where the old request and its clone share the same ireq_opt. IPv6 is unaffected by the primary path.
The vendor (kernel.org CNA) assigned CVSS 9.8 CRITICAL with AC:L — this is wrong. This is a multi-CPU race condition requiring precise timing between SYN retransmit processing and child socket teardown. Red Hat correctly scored it 5.9 Moderate with AC:H and limited impact to availability only (C:N/I:N/A:H). Red Hat's attack-complexity call is accurate; their impact scope is conservative. An Anthropic research post claims an unreleased AI model chained this bug into a zero-click root RCE in ~53 minutes against an MPTCP listener, using the race for both a KASLR info leak and a callback-pointer overwrite. That chain is unverified and the PoC is withheld, but kernel UAFs in the networking stack have historically been weaponized (cf. CVE-2023-0461, CVE-2024-1086). The real score sits between 5.9 and 9.8 — the race is hard but the kernel is the ultimate high-value target.
5 steps from start to impact.
Identify target with exposed TCP listener
- Network path to a TCP listener on a vulnerable Linux host
- Target kernel version in the affected range (4.4 to pre-fix)
- Many high-value internal services are behind firewalls / segmented VLANs
- External-facing Linux services often run behind load balancers that terminate TCP, insulating the backend kernel
uname -r on target is sufficient for version check.Flood target with crafted SYN retransmissions
tcp_check_req() run concurrently with tcp_v4_syn_recv_sock() for the same request socket. This requires high packet rates and timing precision.- Ability to send raw TCP packets with IP options to the target
- Multi-core target system (single-core systems serialize the processing)
- Winning the race is non-trivial — Red Hat scored AC:H for this reason
- Network jitter, load balancers, and SYN cookies alter timing windows
- IDS/IPS signatures for SYN flood patterns may trigger before the race is won
Win the race: trigger use-after-free in ip_options_build()
inet_sock_destruct() → kfree(inet_opt)) while the retransmit path is still inside ip_options_build(), which reads opt->optlen from the now-freed memory. On a failed race attempt, the SYN handshake simply fails — no crash occurs — so the attacker can retry indefinitely. Anthropic's claimed PoC required ~48 minutes of sustained retries to achieve the first successful race.- Successful race condition between child socket teardown and SYNACK construction
- Multi-core system where the two code paths execute on different CPUs
- Each failed attempt is a failed TCP handshake, not a crash — but 48 minutes of anomalous SYN traffic is highly detectable
- KASLR must be defeated separately before the UAF can be leveraged for code execution
- Heap layout must be favorable for the freed slab to contain useful data
dmesg may show slab corruption warnings.Leverage UAF for information leak (KASLR bypass)
inet_opt slab so that the kernel reads an attacker-controlled length field and sends excess bytes in the SYNACK, potentially including a kernel pointer. This defeats KASLR. The technique is plausible: kernel info leaks via UAF in network-facing code have been demonstrated before (e.g., CVE-2024-1086's nf_tables chain).- Reliable race-win primitive from step 3
- Heap spray capability to place controlled data in the freed slab
- Ability to observe the SYNACK response bytes
- Heap grooming in kernel networking slabs is fragile across kernel versions and SLAB/SLUB configurations
- The Anthropic chain targets MPTCP listeners specifically, which are not enabled by default on most distributions
Achieve kernel code execution
- Successful KASLR bypass from step 4
- Knowledge of kernel version for gadget selection
- Heap spray to place payload in the freed slab
- CFI (Control-Flow Integrity) in newer kernels (6.1+ with CONFIG_CFI_CLANG) blocks function-pointer overwrites
- SMEP/SMAP prevent trivial user-space payload execution
- The full chain has never been publicly demonstrated or independently verified
e3f33b0a1d89 (kfree_rcu in inet_sock_destruct and tcp_v4_reqsk_destructor). Deploy within 30 days per noisgate mitigation SLA for HIGH. Prioritize: (1) internet-facing TCP services, (2) Kubernetes nodes, (3) hypervisors, (4) internal infrastructure. Debian and Oracle have packages available now. RHEL users must wait or apply kpatch. Amazon Linux 2023 is fixed in the 6.18 kernel packages.kpatch list for availability of a module targeting this CVE.iptables -A INPUT -p tcp --syn -m limit --limit 10/s --limit-burst 20 -j ACCEPT) dramatically increases the time needed to win the race. This raises the bar from 48 minutes to potentially hours, making detection near-certain.threshold: type both, track by_src, count 1000, seconds 60) to alert on abnormal SYN rates to specific ports. This won't prevent exploitation but provides early warning with very high confidence.- SELinux / AppArmor — the UAF occurs in kernel space (
ip_options_build()), entirely below the MAC enforcement layer. Mandatory access controls cannot prevent kernel memory corruption. - Application-layer WAFs (ModSecurity, AWS WAF) — this is a Layer 4 (TCP) attack, not Layer 7. WAFs never see the SYN packets.
- TCP SYN cookies alone — the race occurs *after* the SYN cookie is validated, during child socket creation. SYN cookies reduce the queue exhaustion risk but do not prevent the concurrent access pattern.
- Container isolation (namespaces/cgroups) — the vulnerable code runs in the host kernel. A container receiving TCP traffic on a vulnerable host kernel is fully exposed.
The supporting signals.
| In-the-wild exploitation | None observed. Not in CISA KEV. No GreyNoise, Shadowserver, or Shodan scanner activity detected as of 2026-10-29. Anthropic claims an internal research model built a working chain, but the PoC is withheld under a 45-day embargo. |
|---|---|
| Proof-of-concept availability | No public PoC. No repositories on GitHub named after CVE-2026-98432. Nothing on pocindex.io, ExploitDB, or Nuclei templates. Anthropic's claimed exploit is not published. The only public artifact is the upstream patch commit e3f33b0a1d89. |
| EPSS score | 0.00388 (0.39%) — 5th percentile per Rapid7. This places it in the lowest exploitation-probability tier, consistent with the absence of public weaponization. |
| KEV status | Not listed. No CISA KEV entry as of 2026-10-29. |
| CVSS vector dispute | CNA (kernel.org): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 CRITICAL. Red Hat: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H = 5.9 MODERATE. The AC:L vs AC:H disagreement is the crux — this is a race condition, and AC:L is unjustifiable for a multi-CPU race. |
| Affected versions | Linux kernel 4.4 through pre-fix (introduced by commit 079096f103fa). Every maintained branch was affected. |
| Fixed versions | 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3-rc7. Debian: bookworm-security 6.1.190-1, trixie-security 6.12.113-1. RHEL: no fix released yet (bug 2553390 still NEW). Oracle UEK: patched. Amazon Linux 2023: patched in 6.18 packages. |
| Distro patch status | Debian DSA-6568-1 and DLA-4841-1 issued. SUSE tracking at suse.com/security/cve/CVE-2026-98432. Red Hat has no fix as of 2026-10-29 — RHEL 8, 9, and 10 remain vulnerable. |
| Disclosure timeline | Upstream fix merged: ~2026-10-11 (stable releases 6.18.56, 7.2.10). CVE published: 2026-10-15. Red Hat bug filed: 2026-10-16. |
| Researcher / org | Patch authored by Eric Dumazet (Google, longtime kernel networking maintainer). The Anthropic exploit chain was attributed to an unnamed internal research model. |
Sources.
Why this verdict
- AC:H, not AC:L — the race is real friction. This is a multi-CPU race between
tcp_v4_syn_recv_sock()andtcp_check_req(). A failed race simply drops the handshake — no crash. Red Hat correctly scored AC:H. The CNA's AC:L is indefensible for a concurrency bug that Anthropic's own PoC needed 48 minutes to win. This single correction drops the CVSS from 9.8 to 8.1. - No public PoC, no in-the-wild exploitation, EPSS in the basement. At 0.39% EPSS, no KEV listing, and no GreyNoise activity, the real-world threat signal is weak. Anthropic's claimed chain is unverified, withheld, and targets MPTCP listeners specifically — a configuration that is not default on any major distribution.
- Kernel UAFs are historically weaponizable — the floor is HIGH. Despite the friction, kernel use-after-free bugs in the networking stack have been repeatedly turned into RCE by skilled attackers (CVE-2023-0461, CVE-2024-1086, CVE-2024-36971). Dismissing RCE potential would be naive.
- Role multiplier: the Linux kernel IS the canonical high-value component. This bug lives in the TCP stack — every Linux host running any TCP service is in the blast radius. On a Kubernetes node, exploitation means container escape and node takeover. On a KVM hypervisor, it means guest-to-host escape if the guest can reach a host TCP port. On a network edge appliance (many run Linux), it's a perimeter breach. On a domain-joined host running Samba as a DC, it's domain compromise. ≥10% of Linux kernel installs occupy high-value roles by definition — the floor is HIGH, approaching CRITICAL for canonical infrastructure roles. The race condition friction prevents reaching the CRITICAL floor.
Why not higher?
The race condition is genuine, sustained friction. Anthropic's claimed PoC needed 48 minutes of continuous SYN retransmission — a window easily detected by any network monitoring stack. The MPTCP-specific chain requires a non-default listener configuration. No independent verification of RCE exists. EPSS at 0.39% and zero observed exploitation do not support CRITICAL urgency. The CNA's AC:L scoring is simply wrong for a concurrency bug.
Why not lower?
Kernel UAFs in the networking path are the canonical RCE primitive class in Linux exploitation. Every Linux host accepting TCP connections is affected — this is not a niche subsystem. The UAF is remotely triggerable without authentication, and failed attempts don't crash the target (enabling unlimited retries). Anthropic's unverified claim is plausible given historical precedent. Red Hat's C:N/I:N/A:H is too conservative — it ignores the demonstrated pattern of kernel networking UAFs being escalated to code execution within months of disclosure.
Crowdsourced verification payload.
Run on each target Linux host as root (or any user with read access to /proc/version). Invoke: sudo bash check_cve_2026_98432.sh. No network access or special tools required — it parses the running kernel version against known-fixed versions. Exit code 1 = VULNERABLE, 0 = PATCHED, 2 = UNKNOWN.
#!/usr/bin/env bash
# check_cve_2026_98432.sh — Check for CVE-2026-98432
# Linux kernel IPv4 TCP use-after-free in inet_opt handling
# Affected: 4.4 <= kernel < fixed version per branch
# Fixed: 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3+
set -euo pipefail
KERNEL=$(uname -r)
# Extract major.minor.patch, stripping distro suffixes
VER=$(echo "$KERNEL" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+')
if [ -z "$VER" ]; then
echo "UNKNOWN — could not parse kernel version from: $KERNEL"
exit 2
fi
MAJOR=$(echo "$VER" | cut -d. -f1)
MINOR=$(echo "$VER" | cut -d. -f2)
PATCH=$(echo "$VER" | cut -d. -f3)
version_ge() {
# Returns 0 if $MAJOR.$MINOR.$PATCH >= $1.$2.$3
local cmp_maj=$1 cmp_min=$2 cmp_pat=$3
if [ "$MAJOR" -gt "$cmp_maj" ]; then return 0; fi
if [ "$MAJOR" -lt "$cmp_maj" ]; then return 1; fi
if [ "$MINOR" -gt "$cmp_min" ]; then return 0; fi
if [ "$MINOR" -lt "$cmp_min" ]; then return 1; fi
if [ "$PATCH" -ge "$cmp_pat" ]; then return 0; fi
return 1
}
version_lt() {
! version_ge "$1" "$2" "$3"
}
echo "Kernel: $KERNEL (parsed: $MAJOR.$MINOR.$PATCH)"
echo "CVE: CVE-2026-98432 (ipv4 inet_opt UAF)"
echo "---"
# Not affected: kernel < 4.4
if version_lt 4 4 0; then
echo "PATCHED — kernel predates the vulnerable commit (requires >= 4.4)"
exit 0
fi
# Check each stable branch
RESULT="UNKNOWN"
if [ "$MAJOR" -eq 5 ] && [ "$MINOR" -eq 10 ]; then
if version_ge 5 10 272; then RESULT="PATCHED"; else RESULT="VULNERABLE"; fi
elif [ "$MAJOR" -eq 5 ] && [ "$MINOR" -eq 15 ]; then
if version_ge 5 15 223; then RESULT="PATCHED"; else RESULT="VULNERABLE"; fi
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -eq 1 ]; then
if version_ge 6 1 190; then RESULT="PATCHED"; else RESULT="VULNERABLE"; fi
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -eq 6 ]; then
if version_ge 6 6 159; then RESULT="PATCHED"; else RESULT="VULNERABLE"; fi
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -eq 12 ]; then
if version_ge 6 12 113; then RESULT="PATCHED"; else RESULT="VULNERABLE"; fi
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -eq 18 ]; then
if version_ge 6 18 56; then RESULT="PATCHED"; else RESULT="VULNERABLE"; fi
elif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -eq 2 ]; then
if version_ge 7 2 10; then RESULT="PATCHED"; else RESULT="VULNERABLE"; fi
elif version_ge 7 3 0; then
RESULT="PATCHED"
elif [ "$MAJOR" -eq 4 ] || [ "$MAJOR" -eq 5 ] && [ "$MINOR" -lt 10 ]; then
# Kernel 4.x (>= 4.4) or 5.x < 5.10 — EOL branches, no backport
RESULT="VULNERABLE"
elif [ "$MAJOR" -eq 5 ] && [ "$MINOR" -gt 15 ] && [ "$MINOR" -lt 99 ]; then
# 5.x branches between 5.15 and 6.1 — EOL, no backport
RESULT="VULNERABLE"
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -gt 1 ] && [ "$MINOR" -lt 6 ]; then
RESULT="VULNERABLE"
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -gt 6 ] && [ "$MINOR" -lt 12 ]; then
RESULT="VULNERABLE"
elif [ "$MAJOR" -eq 6 ] && [ "$MINOR" -gt 12 ] && [ "$MINOR" -lt 18 ]; then
RESULT="VULNERABLE"
else
# Distro kernel with custom minor — check distro advisories
RESULT="UNKNOWN"
fi
# Also check for kpatch
KPATCH="not detected"
if command -v kpatch &>/dev/null; then
if kpatch list 2>/dev/null | grep -qi '98432\|inet_opt'; then
KPATCH="livepatch applied"
RESULT="PATCHED"
fi
fi
echo "kpatch: $KPATCH"
echo "Result: $RESULT"
case $RESULT in
VULNERABLE) echo "ACTION: Upgrade kernel to a fixed version."; exit 1 ;;
PATCHED) echo "No action required for this CVE."; exit 0 ;;
UNKNOWN) echo "Could not determine status — check distro advisory."; exit 2 ;;
esac