Back to Blog
LinuxKernelCybersecurityVulnerability ManagementKubernetes

Linux Kernel CVE-2026-98432: Who Is Exposed and How to Patch or Mitigate It

CVE-2026-98432 is a remote flaw in the Linux TCP handshake, in every kernel since 4.4. Who is exposed, how to check your real kernel, and how to block it before the fix ships.

P
Davi Nunes
October 29, 202610 min read

On 15 October 2026, the Linux kernel fixed CVE-2026-98432, a use-after-free in the code that handles incoming IPv4 TCP connections. It is rated 9.8 out of 10. An attacker needs no account and no open application bug: the flaw sits in the TCP handshake itself, before any service sees the connection, and it has been in every kernel since version 4.4, released in January 2016.

It went from a line in a changelog to a headline on 27 October, when an AI research lab reported that one of its unreleased models had turned the bug into a working remote root exploit in a lab, with no credentials and no user interaction.

Debian already ships fixed kernels. At the time of writing, Ubuntu does not: its fixes are prepared but not yet published. Below: what the flaw is, who is actually exposed, how to check the kernel you are really running, how to patch, and how to block the trigger on systems that are still waiting for a package.

What the Flaw Actually Is

IPv4 packets can carry options in their header. Two of them, Record Route and Timestamp, ask the receiver to echo information back. When a connection request (a SYN) arrives with one of these options, the kernel stores a copy of them with the half-open connection, and uses it again when it builds the reply (the SYN-ACK).

The bug is a race over who owns that copy. When the handshake completes, the new connection takes over the stored options without duplicating them. If the client retransmits its SYN at the same moment, another CPU can still be building a SYN-ACK from those options while the connection that now owns them is torn down and frees them. The SYN-ACK is then built from freed memory.

Depending on what has reused that memory, the result ranges from a kernel crash, to kernel memory copied into a packet sent back to the attacker, to writes into kernel memory that can be steered. A second variant affects request-socket migration, a feature that is off by default (net.ipv4.tcp_migrate_req).

Affected: every kernel from 4.4 onwards. Fixed upstream in 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10 and 7.3. Kernel lines older than 5.10, including 5.4, get no upstream fix.

Who Is Exposed

The vector is IPv4 TCP: any Linux machine that accepts TCP connections over IPv4 from a network an attacker can reach. That includes services listening on all addresses (::), because IPv4 connections to them take the same path. The service behind the port does not matter, because the bug fires during the handshake, before the application is involved.

  • Anything with its own public IP and an open TCP port. SSH, VPN gateways, mail servers, databases exposed for convenience, game and voice servers, Kubernetes API servers.
  • Your own reverse proxies and load balancers. If they run Linux and face the internet, they are exactly where the attacker's SYN lands.
  • Kubernetes nodes and container hosts. Containers have no kernel of their own. Every pod on a node shares the node's kernel, so rebuilding images changes nothing here.
  • Internal systems. Many networks drop packets with IP options at the edge, but an attacker who is already inside, on a compromised workstation or in the same cloud network, is not behind that edge.

What is usually not exposed: a backend that only receives connections from a CDN or a proxy that opens its own connections to it. The attacker's packets end at the proxy, and the backend only ever sees the proxy's SYNs. The proxy itself is a different story if you run it.

How Big This Is

  • Ten years of kernels. The affected range starts at 4.4 (January 2016), so practically every Linux server, virtual machine and Kubernetes node in production today is in scope until it is patched and rebooted.
  • Every distribution, and not all of them are covered. Fixes landed in eight stable kernel lines. Older lines get nothing upstream, and long-term distributions that still run them depend entirely on their vendor's backport.
  • A lab built a zero-click root exploit. On 27 October, an AI research lab reported that one of its unreleased models had built an exploit chain for this bug: it defeated kernel address randomisation remotely in about 48 minutes, then needed about five more to get a root shell. The lab also reported that a lost race only fails the handshake without crashing the machine, so an attacker can keep retrying. Its target was a server listening with Multipath TCP (MPTCP), more on that in Step 3.

The honest caveat: the exploit was built in a lab and has not been released, there are no known attacks in the wild, and the vulnerability is not on the official list of vulnerabilities known to be exploited. The public record describes a plain IPv4 TCP fix, and only the lab's own write-up ties the exploit to this CVE. Some distributions also rate the bug lower than 9.8, because winning the race is harder than the score assumes.

That is a reason to patch on a schedule, not to skip it. The fix is public, so the bug is easy to find, and the lab's result shows the race can be won reliably with enough patience.

Not sure which of your machines accept connections directly from the internet? That is the first question. Request a free Linux kernel exposure assessment and our security team will map it with you.

Step 1: Check the Kernel You Are Actually Running

A kernel update does nothing until the machine reboots into it, so check the running kernel, not the installed packages:

bash
uname -r

On Ubuntu, uname -r hides part of the version. The fixed 22.04 kernel is 5.15.0-203.213, but uname -r only shows 5.15.0-203-generic. The full version is here:

bash
cat /proc/version_signature

On Debian, uname -v includes the package version. For a fleet, collect the same information from every host, and remember the machines nobody logs into any more.

On Kubernetes, the node list shows each node's kernel in the KERNEL-VERSION column:

bash
kubectl get nodes -o wide

Inside a container, uname -r reports the host's kernel. That is the one that has to be fixed.

Step 2: Patch and Reboot

Debian has fixed kernels: 6.1.190-1 for 12 (bookworm) and 6.12.113-1 for 13 (trixie).

Ubuntu, at the time of writing (29 October), has fixes prepared but not published. The fixed kernels for 22.04 (5.15.0-203.213), 24.04 (6.8.0-149.149) and 26.04 (7.0.0-43.43) are in the -proposed testing pocket, not yet in the normal updates. Cloud-optimised kernels carry their own version numbers, listed on Ubuntu's page for the CVE. 20.04 and older are listed as vulnerable. The -proposed pocket is for testing, not production: until the packages reach the normal updates, use Step 3.

Other distributions: follow your vendor's advisory for CVE-2026-98432 and compare it with the kernel you actually run.

On Debian and Ubuntu, once the fixed kernel is available:

bash
sudo apt update
sudo apt full-upgrade
sudo reboot

Use full-upgrade: a new kernel often arrives as a new package, which a plain upgrade can hold back. If you use a kernel live-patching service, check whether it covers this CVE. If it does not, the reboot is the fix.

On Kubernetes, roll the nodes one at a time so workloads move instead of stopping:

bash
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# patch and reboot the node, then:
kubectl uncordon <node>

On managed Kubernetes, the fix arrives as a new node image: upgrade the node pools once your provider publishes it.

Step 3: If There Is No Package Yet, Block the Trigger

The first variant needs an IPv4 SYN that carries Record Route or Timestamp options. Legitimate TCP traffic practically never carries IPv4 options, so dropping TCP packets that have them removes the trigger without touching normal connections. This reduces exposure, it does not replace the patch.

With nftables, on the host:

bash
sudo nft add table ip ipopts
sudo nft add chain ip ipopts pre '{ type filter hook prerouting priority -300; }'
sudo nft add rule ip ipopts pre ip protocol tcp ip hdrlength != 5 counter drop

A header length of 5 means no options, so anything longer is dropped. The rule sits in the earliest hook, which also covers traffic forwarded to containers and pods on that host. We tested it: SYNs with Record Route or Timestamp options get no reply, and normal connections work as before. It is limited to TCP on purpose. Multicast group management (IGMP) uses an IP option, so a rule that dropped every packet with options would break multicast.

With iptables instead:

bash
sudo iptables -t raw -I PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" -j DROP

To see how many packets the rule has dropped, or to remove it:

bash
sudo nft list chain ip ipopts pre
sudo nft delete table ip ipopts

Rules added this way are lost on reboot. To keep the rule, save it to a file and load it at boot with your configuration management:

nftables
# /etc/ipopts.nft (load with: sudo nft -f /etc/ipopts.nft)
table ip ipopts
delete table ip ipopts
table ip ipopts {
  chain pre {
    type filter hook prerouting priority raw; policy accept;
    ip protocol tcp ip hdrlength != 5 counter drop
  }
}

The first two lines make the file safe to load more than once. Do not add it to a stock /etc/nftables.conf that starts with flush ruleset on a host running Docker or Kubernetes: reloading that file wipes their rules.

Also check two settings.

  • net.ipv4.tcp_migrate_req should be 0, the default. That keeps the second variant out of reach unless a program uses the same migration feature through BPF.
  • Multipath TCP. The lab's exploit targeted an MPTCP listener, and you may have more of those than you think: programs built with Go 1.24 or later listen with MPTCP by default on Linux. We tested it: the same listener is plain TCP with Go 1.23 and MPTCP with Go 1.24 and 1.25. Turning MPTCP off does not fix the bug, but it removes the setup the published exploit used. If you do not need it, set net.mptcp.enabled to 0, or start Go services with GODEBUG=multipathtcp=0, then restart them. The setting only affects new sockets, and it is per network namespace, so check it inside containers too.
bash
sysctl net.ipv4.tcp_migrate_req net.mptcp.enabled

Step 4: Watch for Attempts

Do not wait for crashes. A lost race does not have to crash the machine, so a quiet kernel log proves nothing. Watch for the trigger instead. This captures incoming connection requests that carry IPv4 options, and on a normal server it should stay silent:

bash
sudo tcpdump -nni any 'ip[0] & 0xf > 5 and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn'

If you deployed the nftables rule, its counter does the same job permanently. A counter that keeps growing means someone is sending these packets to you.

Crashes still deserve a look when they happen. An unexpected reboot, or a kernel log mentioning skb_under_panic or ip_options_build, on a machine that accepts outside connections, is worth investigating:

bash
# this boot
sudo journalctl -k -b 0 | grep -E 'skb_under_panic|ip_options_build'
# the previous boot, if the journal is persistent
sudo journalctl -k -b -1 | grep -E 'skb_under_panic|ip_options_build'

The Real Problem Is the Patch That Needs a Reboot

Most teams have a working routine for packages: images are rebuilt, dependencies updated, scanners turn green. Kernels fall outside it. The fix is installed by the routine updates and then waits for a reboot nobody schedules, on hosts that look patched to every tool that reads package lists.

The useful questions are which kernel each machine is actually running, which machines accept connections straight from the internet, and how long a fixed kernel waits before the reboot that activates it.

Get a Free Linux Kernel Exposure Assessment

If you are not sure which of your servers, nodes or appliances are exposed, or how to cover them until your distribution ships a fix, our security team will work it out with you at no cost.

The free assessment covers:

  • An inventory of the kernels you actually run across hosts, virtual machines and Kubernetes nodes, checked against the fixed versions for your distribution, not against the installed packages
  • A map of what accepts connections directly from the internet or from untrusted networks, including the hosts behind your proxies and load balancers
  • A prioritised plan for the period before a fix ships: where to block the trigger, where to switch off MPTCP, and how to schedule the reboots without downtime

You get a written list of what is exposed and what to do about it, with no obligation attached.

Request your free Linux kernel exposure assessment, or read more about our Linux consulting, Kubernetes consulting and cybersecurity practice. The same "check what is really running" rule applied to the Brotli flaw last week.

Linux Kernel CVE-2026-98432: How to Fix | Privum Consulting