Skip to content

Field manual · linux

CVE-2026-98432: A Remote Root Bug in the Linux TCP Handshake. Patch the Host, Not the App.

A race in how the Linux kernel frees IPv4 options during the TCP handshake can be turned into remote root. What it is, who is exposed, how to check your kernel, and what to do while your distro catches up. Status as of Nov 1, 2026.

CVE-2026-98432: A Remote Root Bug in the Linux TCP Handshake. Patch the Host, Not the App.

CVE-2026-98432: A Remote Root Bug in the Linux TCP Handshake. Patch the Host, Not the App.

Field notes · Security · Updated Nov 1, 2026

A bug in the Linux kernelThe core of an operating system that runs with full hardware control and decides how every program gets CPU time, memory, and device access. Read more → lets an attacker on the network corrupt memory while your server is still answering a new connection. No login, no clicks, no app bug needed. Anthropic’s research team says it turned this bug into a working exploit that runs commands as root on servers with a multipath TCPA transport protocol that guarantees reliable, ordered delivery of data between two devices by establishing a connection before sending. Read more → listener. The fix is two changed lines and it has been in the upstream stable kernels since mid October. As of Nov 1, 2026, Ubuntu and RHEL have not shipped fixed kernels yet. That gap is why this note exists.

If you run Linux servers, containers, or KubernetesAn open-source platform for automating the deployment, scaling, and management of containerized applications across clusters of machines. Read more → nodes, the short version is this. Find out what kernel you run. Find out whether your distro has shipped the fix. If it has, install it and reboot. If it has not, put a stopgap in place today and watch your vendor’s page. The rest of this note explains each step and why.

Status as of Nov 1, 2026. Distro fix status, livepatch coverage, KEV listing, and exploit availability are all moving. Every one of those claims below names its source and the date I checked it. Check again before you act.

Contents

  1. The plain version
  2. Words you need
  3. What actually breaks in the kernel
  4. Who is affected
  5. Check your kernel and your distro
  6. Mitigations while you wait, and what each one costs
  7. The Go 1.24 MPTCP default
  8. Livepatch
  9. What I would do in production
  10. Gotchas
  11. Summary table

The plain version

Think of a busy restaurant. A guest walks up and hands the host a sticky note: “booth by the window, no peanuts.” The host keeps the note on the podium while the table gets set. When the table is ready, the host hands that same sticky note to the server and the guest sits down.

Now the guest, impatient, walks up a second time and repeats the request. A second host grabs the sticky note off the podium to write a reply. At that same moment the guest leaves, the server throws the note away, and someone else’s note lands in the same spot on the podium. The second host is now reading a note that belongs to somebody else. If an attacker controls what lands in that spot, the host does what the attacker wrote.

That is the bug. The sticky note is a set of IPv4 options the client sent. The podium is a slot of kernel memory. The two hosts are two CPU cores handling the same connection at once. The note gets thrown away while one of them is still reading it.

Words you need

  • Kernel. The core of the operating system. It runs with full control of the machine, and it handles networking before any of your apps see a packetA small unit of data transmitted over a network, containing both the payload (actual data) and headers with routing information. Read more →. A bug here sits below every app, containerA lightweight, portable package that bundles an application with its dependencies and runs in an isolated process on the host OS, sharing the kernel. Read more →, and firewallA security device or software that monitors and controls incoming and outgoing network traffic based on predefined rules. Read more → rule in user space.
  • TCP handshake. The three packets that open a TCP connection. The client sends SYN, the server answers SYN-ACK, the client sends ACK. This bug lives in the server’s half of that exchange.
  • Use-after-free. The program gives a piece of memory back, then keeps reading or writing it. Something else may have moved into that memory by then. In the kernel, that is often the first step to running attacker code.
  • CVEA standardized identifier for publicly known cybersecurity vulnerabilities, enabling organizations to track and prioritize security patches. Read more →. A public ID for one specific vulnerability, so everyone talks about the same bug. More in the CVE entry.
  • CVSS. A 0 to 10 severity score based on how the bug is reached and what it gives an attacker. Different vendors score the same CVE differently, and this one is a good example.
  • MPTCP. Multipath TCP. An extension that lets one connection use several network paths at once, for example Wi-Fi and cellular together. Linux supports it, and some software turns it on by default.

What actually breaks in the kernel

The upstream commit message is unusually clear, so I am going to follow it closely. The fix is e3f33b0a1d89, “ipv4: free inet_opt and ireq_opt after an RCU grace period”, written by Eric Dumazet and dated Oct 1, 2026. The reporter is Xinyang Ge of Anthropic.

Path one: the retransmitted SYN.

  1. A SYN arrives carrying IPv4 options. The kernel stores them on the request socket as ireq->ireq_opt.
  2. The handshake completes. tcp_v4_syn_recv_sock() hands that pointer to the new child socket as newinet->inet_opt. It does not copy it.
  3. On another CPU, a retransmitted SYN for the same request arrives. tcp_check_req() sends a SYN-ACK. tcp_v4_send_synack() and inet_csk_route_req() read ireq_opt under rcu_read_lock() only, and ip_build_and_send_pkt() and ip_options_build() read opt->optlen twice.
  4. Meanwhile the child socket goes away. TCP child sockets do not have SOCK_RCU_FREE, and inet_sock_destruct() frees inet_opt with a plain kfree().
  5. The SYN-ACK builder is now reading freed memory. Use-after-free in ip_options_build().

This became possible with commit 079096f103fa, “tcp/dccp: install syn_recv requests into ehash table”, which lets request sockets be processed without holding the listener lock. The CNA record marks Linux 4.4 as the first affected version.

Path two: request socket migration. If net.ipv4.tcp_migrate_req=1 is set, or a BPF_SK_REUSEPORT_SELECT_OR_MIGRATE program is attached, reqsk_timer_handler() clones the request socket with inet_reqsk_clone(). The old socket and the clone share the same ireq_opt. When the clone is freed, tcp_v4_reqsk_destructor() also uses a plain kfree(), while another CPU may still be using those options. The fix lists a second root commit for this path, c905dee62232. AlmaLinux notes that tcp_migrate_req is off by default.

The fix. Readers of these options already use RCU, and other code that replaces inet_opt already frees it with kfree_rcu(). The patch makes the two destructors do the same:

--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
-	kfree(rcu_dereference_protected(inet->inet_opt, 1));
+	kfree_rcu(rcu_dereference_protected(inet->inet_opt, 1), rcu);

A matching one-line change lands in tcp_v4_reqsk_destructor() in net/ipv4/tcp_ipv4.c. Two insertions, two deletions. kfree_rcu() waits for an RCU grace period, so no CPU still inside a read-side section can be holding the pointer when the memory goes back to the allocator.

IPv6. Not affected by path one, because tcp_v6_syn_recv_sock() copies the options. tcp_v6_reqsk_destructor() has the same migration problem with ipv6_opt, which only CALIPSO sets. The commit says that will get its own patch.

Why it is worse than it sounds. Anthropic’s write-up says the exploit runs in two stages. First it wins the race so the kernel reads an attacker-controlled length and sends back extra bytes, which leaks a kernel pointer and defeats KASLR. Then it uses the same bug to overflow a buffer and overwrite a callback pointer, ending with a shellThe program that reads the commands you type, runs them, and shows the results; Bash is the default on most Linux systems. Read more → command as root. The key line from the post: “a lost race only fails the handshake without crashing the whole system, so a determined attacker can retry indefinitely.” In their proof of concept, the pointer leak took 48 minutes and the jump to root took another five. A bug that fails quietly and can be retried forever is the kind I worry about.

Who is affected

The CNA record, published Oct 15, 2026, lists affected kernels as 4.4 and later, fixed in these stable releases:

BranchFirst fixed release
5.105.10.272
5.155.15.223
6.16.1.190
6.66.6.159
6.126.12.113
6.186.18.56
7.27.2.10
mainline7.3

Those numbers only apply if you run upstream or near-upstream kernels, such as Arch, Gentoo, or your own builds. Distro kernels carry backports, so a RHEL 9 kernel called 5.14.something can be fixed or not regardless of the upstream number. Compare against your vendor’s package version, not kernel.org.

Exposure in practice: any host with a listening IPv4 TCP port reachable from an attacker. The demonstrated exploit needs an MPTCP listener. The Go Security Team says plainly that “the underlying bug is not specific to MPTCP” and that systems without MPTCP listeners may be open to similar attacks. Treat every internet-facing Linux box as in scope.

Containers do not help here. Every container on a host shares that host’s kernel, so patching an image does nothing. The fix is a host kernel update and a reboot. On Kubernetes, that means the nodes.

Scores, and why they differ

  • The Linux kernel CNA scores it CVSS 3.1 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H). NVD shows that score as coming from the CNA. As of Nov 1, 2026, NVD’s own analysis status is “Received” and NVD has not added its own score.
  • Red Hat rates it Critical with a 9.8 CVSS 3.1 score on its CVE page.
  • SUSE rates it important, and lists 9.8, 9.8 and 8.1 CVSS 3 scores on its page.
  • Amazon Linux rates it Important at 8.1. Oracle Linux lists 8.1 and calls the score preliminary.
  • Ubuntu’s page shows a CVSS 4.0 score of 8.3 next to the 9.8 CVSS 3.1 score.

The spread mostly comes down to how hard each vendor thinks the race is to win. The Anthropic numbers above are why I would plan around the higher score.

Is it being exploited?

As of Nov 1, 2026, CVE-2026-98432 does not appear in the CISA KEV catalog (I checked the catalog feed, version 2026.10.30). That only means CISA has not added it. It is not proof nobody is using it. Anthropic’s post describes the exploit but does not include exploit code, and as of Nov 1, 2026 I have not found a primary source that publishes one. This is not a zero-day: the fix shipped upstream before the CVE went public. The risk now is the window between public details and your distro’s package.

Check your kernel and your distro

Start with what is running, not what is installed:

uname -r

On a box that has updated but not rebooted, the installed package can be fixed while the running kernel is not. Check both:

# Debian / Ubuntu
dpkg -l 'linux-image*' | awk '/^ii/{print $2, $3}'

# RHEL / Alma / Rocky / Oracle / Amazon
rpm -q kernel

Then look for MPTCP listeners:

sudo ss -Mlnp

Anything listed there is a listening MPTCP socket and the owning process. On many systems the list is empty. If it is not, those services are the exact shape of the demonstrated exploit.

Three commands to run today: uname -r, ss -Mlnp, sysctl net.mptcp.enabled.

Now the vendor status. Each line below was checked on Nov 1, 2026, on the vendor’s own page.

Fixed upstream. As of Nov 1, 2026, Ubuntu and RHEL have not shipped. Check your vendor page.
VendorStatus as of Nov 1, 2026Source
Debian 12 (bookworm)Fixed in the security archive: linux 6.1.190-1 (DLA-4841-1), linux-6.12 6.12.113-1~deb12u1 (DLA-4850-1)Debian security tracker
Debian 13 (trixie)Fixed in the security archive: linux 6.12.113-1 (DSA-6568-1)Debian security tracker
Ubuntu 22.04, 24.04, 26.04, 26.10Vulnerable, fix work in progress for the main kernels. No fixed package published.ubuntu.com/security/CVE-2026-98432
Ubuntu 16.04, 18.04, 20.04Vulnerablesame
RHEL 8, 9, 10, OpenShiftAffected, no fixed kernel released. RHEL 6 and 7 not affected.Red Hat CVE page and RHSB-2026-016
AlmaLinux 8, 9, 10Patched kernels in the testing repo, not yet in production: 4.18.0-553.180.2.el8_10, 5.14.0-687.61.2.el9_8, 6.12.0-211.69.2.el10_2AlmaLinux blog, Oct 30
SUSEFixed packages released for several products, including live patches. Check your product row.suse.com CVE page
Oracle Linux UEKAdvisories ELSA-2026-500397, -500398, -500399 listedlinux.oracle.com CVE page
Amazon LinuxFixed packages listed for some kernels, including ALAS2023-2026-3251 and ALAS2023-2026-3335. Check your kernel package.Amazon Linux security center

Install, reboot, then run uname -r again and compare against the fixed version for your release.

Mitigations while you wait, and what each one costs

None of these is a fix. Red Hat, AlmaLinux, and the Go team all say the same thing: install a patched kernel. These buy time.

1. Drop IPv4 TCP packets that carry IP options

From Red Hat’s bulletin RHSB-2026-016. Save as cve-2026-98432.nft:

table inet cve_2026_98432 {
    chain input {
        type filter hook input priority -310; policy accept;
        ip protocol tcp ip hdrlength > 5 counter drop
    }
}

Apply and confirm:

sudo nft --check --file cve-2026-98432.nft
sudo nft --file cve-2026-98432.nft
sudo nft list table inet cve_2026_98432

An IPv4 header length over 5 words means IP options are present. Normal TCP options like MSS and SACK live in the TCP header, not the IP header, so ordinary traffic passes. Red Hat says the rule “reduces exposure to this vulnerability but cannot fully prevent it.”

What it costs you: anything that legitimately uses IPv4 options gets dropped. CIPSO labeled networking is the main real-world case, so if you run that, test first. The priority of -310 puts it ahead of conntrack. It is per host, so it has to land everywhere, and it has to come back out after you patch:

sudo nft delete table inet cve_2026_98432

Doing it at an upstream firewall or cloud security group is an option if your gear can match on IP header length. I have not tested that across vendors, so verify with a packet capture.

2. Turn off MPTCP system-wide

sudo sysctl -w net.mptcp.enabled=0

This closes off the demonstrated exploit’s entry point. AlmaLinux points out the limit: it only stops new MPTCP sockets from being created. Listeners already open stay open until you restart the services that own them, so run ss -Mlnp again after the change. To keep it across reboots, put net.mptcp.enabled = 0 in a file under /etc/sysctl.d/.

What it costs you: anything that actually relies on MPTCP falls back to plain TCP or fails. And it does nothing about the underlying bug in the regular IPv4 path.

3. Leave request migration off

If you set net.ipv4.tcp_migrate_req=1 or attach a BPF_SK_REUSEPORT_SELECT_OR_MIGRATE program, you have opened the second path. Check with sysctl net.ipv4.tcp_migrate_req. If it is 1 and you can live without migration until you patch, set it to 0. The cost is that pending connections on a closing listener are dropped instead of moved, which matters mostly during zero-downtime restarts.

The Go 1.24 MPTCP default

This is the detail that turned a kernel bug into a developer problem. According to the Go Security Team’s announcement on Oct 29, 2026, Go 1.24 and later enable MPTCP by default for listening sockets on Linux. Any Go service built with 1.24+ that calls net.Listen on a host with MPTCP enabled is likely sitting in ss -Mlnp right now.

Go 1.24+ listens with MPTCP by default. GODEBUG=multipathtcp=0 turns it off.

The Go team gives three ways to turn it off:

# Runtime, per process
GODEBUG=multipathtcp=0 ./your-service
// go.mod in the main module, build time
godebug multipathtcp=0
// Per socket, overrides GODEBUG
var lc net.ListenConfig
lc.SetMultipathTCP(false)
ln, err := lc.Listen(ctx, "tcp", ":8080")

net.Dialer.SetMultipathTCP does the same for outbound connections.

The Go team calls per-program disabling “a fragile mitigation.” One forgotten binary leaves the host exposed, and it assumes every working exploit needs MPTCP, which nobody has shown. They also say it is premature to change Go’s default and are discussing it on go.dev/issue/82717. My take: set the GODEBUG in your service units or container env as a seatbelt, but do the sysctl and the kernel patch too.

Livepatch

Livepatching applies a kernel fix to the running kernel without a reboot. Status as of Nov 1, 2026:

  • SUSE lists released live patch packages for this CVE on its CVE page, covering some SLE 15 SP7 RT kernels and kernel-default-livepatch 6.12.0-160000.40.1 and later. Check that your exact kernel is in the list.
  • Red Hat has released no fixed kernel, and I found no kpatch for this CVE on its CVE page.
  • Ubuntu shows no released fix on its CVE page, and I found no Canonical Livepatch notice for this CVE. If you use Livepatch, run canonical-livepatch status --verbose and look for the CVE before you assume coverage.

Two things to keep in mind. A livepatch only fixes the running kernel; you still need the package installed so the next boot is fixed too. And confirm by CVE ID, not by “patch level looks recent.”

What I would do in production

In order:

  1. Inventory. Get uname -r and the distro for every Linux host, VM, and Kubernetes node. Get ss -Mlnp from each one. Hosts with internet-facing IPv4 TCP listeners go to the top. Hosts with MPTCP listeners go above them.
  2. Patch where you can. Debian, SUSE products with released fixes, Oracle UEK, the Amazon Linux kernels listed as fixed, upstream-tracking distros. Install, reboot, verify with uname -r.
  3. Stopgap where you cannot. Ubuntu and RHEL hosts as of today. Apply the nftables rule after a quick test, set net.mptcp.enabled=0, restart services that held MPTCP listeners, and check tcp_migrate_req.
  4. Go services. Add GODEBUG=multipathtcp=0 to systemd units and container specs. Cheap, and it catches the hosts where someone undoes the sysctl.
  5. Kubernetes. Cordon, drain, update the node OS or image, reboot, uncordon. One node at a time or one pool at a time. A new container image does nothing for this.
  6. Watch. Bookmark your vendor’s CVE page and check it daily. When the fix lands, patch, reboot, then remove the nftables table.
  7. Do not test the exploit on production. Even with no public code, a failed race attempt is just a failed handshake, so you would not see much anyway.

This is the same habit as my Proxmox node hardening note: fewer exposed listeners, fewer surprises. If you run Proxmox, the hypervisor hosts are Linux hosts with a kernel too.

Gotchas

  • Installed is not running. apt upgrade or dnf update without a reboot leaves you exposed. uname -r is the truth.
  • Upstream numbers do not map to distro kernels. A RHEL kernel called 5.14 is not “below 5.15.223.” Use the vendor’s fixed package version.
  • The sysctl does not close existing sockets. Restart services after net.mptcp.enabled=0.
  • Containers share the kernel. Rebuilding images does nothing here. An attacker who wins here does not need a privilege escalation step to get out of a container. The exploit lands as root in the host kernel.
  • Debian fixes are in the security suite. The plain bookworm and trixie suites still list vulnerable kernels. If your sources skip the security archive, you will not get the fix.
  • Testing repos are testing repos. AlmaLinux asks for help testing its kernels and recommends disabling the testing repo afterwards on production machines.
  • Leftover firewall rules. Put a ticket in to remove the nftables table after patching so it does not outlive its purpose by two years.
  • Scores vary by vendor. A scanner showing 8.1 does not mean your risk is lower than a scanner showing 9.8. It is the same bug.

Summary table

QuestionAnswer, as of Nov 1, 2026
What is itUse-after-free of IPv4 options during the TCP handshake, from a race between CPUs
AffectedLinux 4.4 and later, per the kernel CNA record
Fixed upstream5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3
ScoreCVSS 3.1 9.8 from the kernel CNA; some vendors rate 8.1
Demonstrated impactRemote root on servers with an MPTCP listener (Anthropic)
Exploited in the wildNot in CISA KEV as of Nov 1, 2026
UbuntuVulnerable, fix in progress
RHELAffected, no fixed kernel released
DebianFixed in 12 and 13
Stopgapsnftables IP-options drop, net.mptcp.enabled=0, GODEBUG=multipathtcp=0
Real fixVendor kernel update, then reboot

Build it, break it, write down what held. I will update this note when Ubuntu and Red Hat ship.

Difficulty: Intermediate.

Environment: Any Linux host on kernel 4.4 or later that accepts IPv4 TCP connections.

Read time given for this note: 14 min.


Sources: