> ## Content Index
> Fetch the complete content index at: https://sudosecurity.org/llms.txt
> Use this file to discover other available public pages before exploring further.

# Red Hat Called This Bug a 5.9. Two Weeks Later It Was a 9.8.
- URL: https://sudosecurity.org/cve-2026-98432-linux-kernel-tcp-uaf/
- Published: 2026-11-09T13:24:12.000Z
- Updated: 2026-11-09T13:24:12.000Z
- Description: CVE-2026-98432 is a use-after-free in the IPv4 TCP handshake, reachable by anybody who can reach a listening port, sitting in the kernel since 4.4. Red Hat scored it 5.9 moderate and deferred the fix. Then 8.1. Then 9.8.
- Author: Traven
- Tags: Cybersecurity, Linux Kernel, CVE, Vulnerabilities, Linux, Systems Administration

You know the drill. A CVE drops, you look it up, your vendor says moderate. You've got a window in three weeks and a dozen things already elbowing each other for it, so this goes in the pile.

And that's the right call! You cannot emergency-patch every moderate. If you did you'd never ship anything, and the one time you skipped a change-control step would be the time you took prod down over a 5.9.

So it goes in the pile. Then the number changes.

That's CVE-2026-98432, and I want to walk through it, because the bug itself is kind of boring. Textbook. The interesting bit is what the severity rating did over two weeks, and what it did to whether anyone wrote you a patch.

## So what's actually broken

Use-after-free in the IPv4 TCP handshake. Introduced in Linux **4.4** — January 2016\. It's been sitting there about a decade, which tells you something all by itself about how much of the network stack nobody's re-read lately.

[Atlas has the clearest plain-English version](https://atlasum.net/blog/cve-2026-98432-linux-ipv4-tcp-uaf?ref=sudosecurity.org). Server accepts an IPv4 TCP connection. Kernel tracks the half-open handshake in a request socket. If the peer's packet carried IPv4 options, the kernel keeps them around so it can echo them back in replies.

And here's the whole bug: those saved options get handed from the request socket to the new connection **without being copied**. One block of memory, two owners. When the connection ends it gets freed — while another CPU might still be reading it to build a handshake reply.

[Upwind names the functions](https://www.upwind.io/feed/threat-post/cve-2026-98432-linux-kernel-ipv4-tcp-synack-race-triggers-uaf-in-ip%5Foptions%5Fbuild?ref=sudosecurity.org) if you want to go read it yourself. `tcp_v4_syn_recv_sock()` shares `ireq->ireq_opt` with the child. A retransmitted SYN gets `tcp_check_req()` building a SYNACK at the same moment the options are being freed by `inet_sock_destruct()` and `tcp_v4_reqsk_destructor()`. The SYNACK build reads them in `ip_options_build()` and they're already gone — "causing UAF in `ip_options_build()`."

What you need to attack it: reach a listening TCP port over IPv4, send a retransmitted SYN timed to race with SYNACK construction. No credentials. No user interaction. Nothing cooperating from inside the box. All of it happening before anything you wrote ever sees the connection.

The CNA lists the impact as kernel heap disclosure to the peer, out-of-bounds kernel writes, or a crash. Keep that list in mind, it matters in a minute.

### The fix is four lines of idea

Commit `e3f33b0`, Eric Dumazet, and the subject line of the [kernel CVE announcement](https://lists.openwall.net/linux-cve-announce/2026/10/15/1?ref=sudosecurity.org) gives you the entire thing: *ipv4: free inet\_opt and ireq\_opt after an RCU grace period.*

Two plain `kfree()` calls become `kfree_rcu()`. Memory doesn't get released until every reader's done with it. That's the fix. That's it.

The part I can't stop thinking about: **every other path that replaces these same options was already using RCU.** The pattern was right everywhere else in the file. Two call sites didn't get it and stayed wrong for ten years.

If you've ever shipped that bug — correct handling in nine places, a plain free in the tenth — you know precisely how it happens, and it's not carelessness. It's that each individual site looks fine. There's nothing to notice. It's a different animal from [the Copy Fail privilege escalation](https://sudosecurity.org/cve-2026-31431-copy-fail-linux-kernel-privilege-escalation/) I wrote up before, and I find this one worse, because that one was a logic error you could at least argue about in review.

Two more things while we're in the commit. It also covers the same problem in request-socket migration. And **a related IPv6 case is getting fixed in a separate patch** — so the main bug here is IPv4-only, but don't go telling people IPv6 is fine.

## The number that wouldn't sit still

Okay. This is the part I actually wanted to write about.

| Date            | Red Hat's rating                                              | Attested by                                                                                                                                                                                                                                                                                                                                                                                  |
| --------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Oct 15 – Oct 28 | **5.9 Moderate**, AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H         | [Patchmon](https://patchmon.net/blog/cve-2026-98432-linux-kernel-tcp-use-after-free-patch?ref=sudosecurity.org), [Rescana](https://www.rescana.com/post/linux-kernel-tcp-cve-2026-98432-use-after-free-prepare-now?ref=sudosecurity.org), [Panelica](https://panelica.com/blog/cve-2026-98432-why-this-linux-kernel-bug-is-a-98-on-ubuntu-but-a-59-on-red-hat?ref=sudosecurity.org) (Oct 29) |
| Oct 29          | **8.1 Important**, confidentiality and integrity impact added | [TuxCare](https://tuxcare.com/blog/cve-2026-98432-linux-tcp-remote-root/?ref=sudosecurity.org)                                                                                                                                                                                                                                                                                               |
| Oct 30          | **9.8 Critical**                                              | [Atlas](https://atlasum.net/blog/cve-2026-98432-linux-ipv4-tcp-uaf?ref=sudosecurity.org)                                                                                                                                                                                                                                                                                                     |

Stare at that first vector a second, because it's the whole story. `C:N` — no confidentiality impact. `I:N` — no integrity impact. `A:H` — availability only.

Red Hat was saying: this knocks your box over, and that's all it does. Remote DoS. Irritating, not an emergency.

Fifteen days later they're at 9.8, matching the kernel CNA exactly, and their bulletin now says a remote unauthenticated attacker "could exploit a race condition during TCP connection request processing to trigger remote code execution."

That's not a tweak. That's "it falls over" to "it runs code." Atlas reports the escalation cited "the lack of network prerequisites and the potential for severe system instability."

Now — I don't think Red Hat did anything wrong, and I want to be really clear about that before anyone quotes me. Scoring a use-after-free before anybody's demonstrated exploitability is hard. The conservative read — *we can see it crash, we can't see it leak* — is defensible on day one. Then somebody demonstrated more, and they moved. Twice. That's the process working exactly as designed.

But here's the thing that gets me. Go look at [Anthropic's own writeup](https://www.anthropic.com/research/discovering-vulnerabilities-with-claude?ref=sudosecurity.org) of their proof of concept. Stage one: exploit the race so the kernel "reads an attacker-controlled length field and copies extra bytes back," and you learn the kernel layout "as long as one such overread contains a kernel pointer in the reply."

Read that against `C:N`. Stage one of the published exploit chain is *reading kernel memory back off the wire.* That is a confidentiality impact. It's the definition of one. And the CNA's impact list had "kernel heap disclosure to the peer" in it from October 15.

So the information that contradicted the 5.9 was sitting in the CNA's own description the entire time. I'm not saying somebody was asleep. I'm saying that when two CNAs look at the same advisory and one writes `C:H` and the other writes `C:N`, at least one of them is reading something into it that isn't there, and you and I have no way to tell which from the outside.

**The severity number you triaged on is a snapshot, not a fact.** If you looked this up on October 20 you saw 5.9 and you were reading your vendor's honest best assessment. You were also reading a number about to move 3.9 points.

It's moved twice in two days. Go look at Red Hat's own CVE page rather than trusting my table or anybody else's, mine included.

## Why the score *is* the patch

Here's where it stops being a scoring curiosity and starts costing you something.

Red Hat scored it moderate. Red Hat marked the fix **deferred** for RHEL 8, 9 and 10\. Those aren't two facts, they're one fact. Severity feeds backport prioritisation, and a moderate in a stable enterprise kernel is exactly the thing that sits in a queue forever. Red Hat's own docs say plainly that deferred isn't a promise of anything.

And then this, which I did not expect at all. As of October 31, [Red Hat's Bugzilla for this](https://bugzilla.redhat.com/show%5Fbug.cgi?id=2553390&ref=sudosecurity.org) is still sitting at status **NEW** — with priority and severity both marked **urgent**.

Urgent, internally. Moderate, publicly, for two weeks. Fix deferred.

There's also a comment on it from October 29 asking whether setting `net.ipv4.tcp_migrate_req` and `net.mptcp.enabled` to 0 gives you partial mitigation, and asking for Red Hat's assessment for RHEL 8, 9 and 10\. Nobody had answered it as of the 31st. That's the single most useful question anyone could ask about this bug and it's sat there for two days.

If you run RHEL, your exposure to a decade-old remote use-after-free is currently a function of a process you have no window into.

## Who's patched and who isn't

| Distribution                                     | Status                                                                            |
| ------------------------------------------------ | --------------------------------------------------------------------------------- |
| Debian 13 (trixie)                               | **Fixed** Oct 16 — linux 6.12.113-1, DSA-6568-1                                   |
| Debian 12 (bookworm)                             | **Fixed** Oct 17 — linux 6.1.190-1 (DLA-4841-1); Oct 22 — linux-6.12 (DLA-4850-1) |
| Oracle Linux 7–10 (UEK)                          | **Fixed** Oct 16 — ELSA-2026-500397/-500398/-500399                               |
| SUSE SLES 16.0, Leap 16.0, SLE Micro 6.2         | **Fixed** — kernel-default 6.12.0-160000.40.1                                     |
| SUSE SLES 15 SP4–SP6 LTSS, SLE Micro 5.3–5.5     | **Fixed** — see SUSE's per-SP versions                                            |
| SUSE SLES 15 SP7                                 | In progress                                                                       |
| Amazon Linux 2023 kernel6.18                     | **Fixed** Oct 24 — ALAS2023-2026-3251                                             |
| Amazon Linux 2023 kernel6.12                     | **Fixed** Oct 29 — ALAS2023-2026-3335                                             |
| Amazon Linux 2023 default kernel, Amazon Linux 2 | Pending                                                                           |
| AlmaLinux                                        | In testing                                                                        |
| Ubuntu 22.04 / 24.04 / 26.04 / 26.10             | **Vulnerable** — fix in progress                                                  |
| Ubuntu 16.04 / 18.04 / 20.04                     | **Vulnerable**                                                                    |
| RHEL 8 / 9 / 10, kernel-rt, OpenShift 4          | **Fix deferred**                                                                  |
| RHEL 7, CentOS 7                                 | Not affected                                                                      |
| Rocky, CloudLinux, Oracle RHCK                   | Follow Red Hat                                                                    |

Oracle shipped in a day. Debian shipped in a day. The two distributions most likely to be underneath your production workloads are the two that haven't.

And there's a trap in those Debian rows I want to flag hard, because it's the kind of thing that makes you look stupid in an incident review: **the main bookworm and trixie suites still ship vulnerable kernels.** The fix lives in the security archive. If `security.debian.org` isn't in your sources list, `apt upgrade` runs clean, tells you everything's current, and leaves you exactly as vulnerable as you were. Go look at your sources before you trust a green checkmark.

## Checking your own boxes

Upstream fixed versions by branch: **5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3**.

Start obvious:

```bash
uname -r

```

```
6.18.44-fc-v185

```

That one's on the 6.18 branch, fixed in 6.18.56\. Forty-four is less than fifty-six. Vulnerable.

Distro kernels carry their own version strings though, so `uname` doesn't always settle it. Check the package too, and check you actually rebooted:

```bash
rpm -q kernel                      # RPM distros
dpkg -l 'linux-image*' | grep ^ii  # Debian/Ubuntu
needs-restarting -r                # are you running what you installed?

```

That last one wants `dnf-utils` installed, and it catches the thing that gets everybody: you patched, nobody rebooted, you're still running the old kernel. "We're patched" and "the package is installed" are different sentences and I've heard the second one delivered as the first more than once.

For a branch-aware sweep across a fleet:

```bash
#!/usr/bin/env bash
# Compare the running kernel against the CVE-2026-98432 fixed version for its branch.
set -euo pipefail

declare -A fixed=(
  [5.10]=5.10.272 [5.15]=5.15.223 [6.1]=6.1.190  [6.6]=6.6.159
  [6.12]=6.12.113 [6.18]=6.18.56  [7.2]=7.2.10
)

running=$(printf '%s' "$(uname -r)" | cut -d- -f1)
branch=$(printf '%s' "$running" | cut -d. -f1,2)
target=${fixed[$branch]:-}

if [ -z "$target" ]; then
  # 7.3 and later carry the fix in the base release; anything older and
  # unlisted is affected with no upstream fix for that branch.
  if [ "$(printf '%s\n7.3\n' "$branch" | sort -V | head -1)" = "7.3" ]; then
    echo "$running (branch $branch): fix present in base release"
  else
    echo "$running (branch $branch): AFFECTED, no upstream fix for this branch"
  fi
  exit 0
fi

lowest=$(printf '%s\n%s\n' "$running" "$target" | sort -V | head -1)
if [ "$running" = "$target" ] || [ "$lowest" = "$target" ]; then
  echo "$running >= $target (branch $branch): upstream fix present"
else
  echo "$running < $target (branch $branch): VULNERABLE upstream"
fi

```

Two honest caveats, because I'd rather you trust it for the right reasons than the wrong ones. It compares upstream version numbers, so a distro kernel that backported the fix without bumping to the upstream version shows a false positive — read "VULNERABLE" as "go check your vendor's advisory," not as a verdict. And `sort -V` is GNU coreutils, so Alpine and BusyBox need something else.

The unlisted-branch path matters more than it looks, too. If you're on something between 4.4 and 5.10 that never got a stable backport — a 4.19 or a 5.4, and plenty of appliances and forgotten VMs are — there's no upstream fix for your branch at all. The script tells you that instead of sending you off to find an advisory that was never written.

## Stuff you can do while you wait

None of this replaces a fixed kernel. None of it has been tested against a working exploit. I'm handing you the commands because "wait for Red Hat" isn't a plan, not because I think any of this is good.

**Drop inbound TCP carrying IPv4 options.** Legitimate traffic basically never sets them. Atlas's nftables version hooks prerouting:

```bash
nft add table ip cve_2026_98432
nft add chain ip cve_2026_98432 pre '{ type filter hook prerouting priority -300; }'
nft add rule ip cve_2026_98432 pre meta l4proto tcp ip hdrlength gt 5 counter drop

```

Rip it out with `nft delete table ip cve_2026_98432`. The `counter` is deliberate — watch it before you trust it, because if that number climbs fast you've just started silently dropping something you needed.

On RHEL 9 and 10 the iptables equivalent won't work at all, because those kernels don't ship `xt_u32`. Everywhere else:

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

```

Two warnings from AlmaLinux you want *before* you deploy either of those: **traffic between containers on the same host may bypass the rule entirely**, and don't use it on networks that depend on CIPSO labels. Red Hat's own line on the approach is that it "reduces exposure to this vulnerability but cannot fully prevent it," which is about as warm as vendor language gets.

**Confirm the migration path is shut.** Off by default, so most people glance and move on:

```bash
sysctl net.ipv4.tcp_migrate_req

```

Wants to be `0`, with no `BPF_SK_REUSEPORT_SELECT_OR_MIGRATE` program attached.

**Kill MPTCP if you don't use it.** This does not fix the bug. It removes the setup the only demonstrated root chain needs:

```bash
echo 'net.mptcp.enabled = 0' | sudo tee /etc/sysctl.d/90-disable-mptcp.conf
sudo sysctl -w net.mptcp.enabled=0
ss -Mlnp    # what's actually listening on MPTCP

```

Three gotchas that'll bite you if you stop at the sysctl. Listeners already open **stay** MPTCP, so restart those services. Every new network namespace starts with MPTCP back on, so containers need `--sysctl net.mptcp.enabled=0`. And for a single Go program there's `GODEBUG=multipathtcp=0`, which the Go Security Team itself calls "a fragile mitigation" — their words: "a single MPTCP listener left exposed still leaves a system vulnerable."

On CloudLinux, AlmaLinux or Debian, go check whether your livepatch vendor shipped. Rebootless patching is the one option here that's actually better than waiting, rather than just different.

## What this doesn't cover

No exploit, no proof-of-concept code, no race-winning technique. The mechanism's here because you can't evaluate a deferred fix without knowing what's being deferred, and that's where I'm stopping.

I'm also not pretending the mitigations above are equivalent to patching. They're what you do while you wait, and the nftables rule in particular is something I'd deploy with a counter on it and a calendar reminder to take it back off.

One correction, because it's circulating and it will talk somebody out of patching. [One vendor writeup](https://aviatrix.ai/threat-research-center/linux-kernel-tcp-flaw-98-cvss-cve-2026-98432-ubuntu-rhel/?ref=sudosecurity.org) describes this as affecting systems "with a multipath TCP (MPTCP) listener enabled." That's the precondition for a *proof of concept*, not for the vulnerability. The bug wants an IPv4 TCP listener. If you grep for MPTCP, find none, and conclude you're clear, you've misread it — and [The Hacker News made the same catch](https://thehackernews.com/2026/10/anthropics-unreleased-ai-model-chains.html?ref=sudosecurity.org), noting that "the Linux CVE record describes an IPv4 TCP fix, not a multipath TCP one."

### On that proof of concept

Anthropic's Frontier Red Team published October 27\. An unreleased internal research model wrote the exploit "after initial prompting," for a bug their own team found. Two stages: leak a kernel pointer to defeat KASLR, then reuse the UAF to overflow a buffer, overwrite a callback pointer with a payload already staged in kernel memory, and chain existing kernel functions into a root shell. Their numbers: "it takes 48 minutes to leak a kernel pointer and another five minutes to reach the shell command execution." Target is servers with an MPTCP listener.

How much of that is independently confirmed? Not much. TuxCare says flatly it "hasn't reproduced the exploit," no public reproduction had turned up as of October 30, and Anthropic didn't publish the code, the kernel version, or the configuration. The Hacker News is blunt that "the capability claim rests on Anthropic's own account," that the model is unnamed, and that the "initial prompting" and "little human involvement" framing never gets broken down into who did what.

So: treat it as a vendor claim. The Linux chain is one of five they describe — Chrome, Safari, Android and a Windows DoS being the others — and some of those have independent corroboration in vendor credits while the Linux one, as far as I can find, doesn't yet.

The one detail from it that *is* load-bearing, and the reason I think the kernel team's `AC:L` beats the vendors' `AC:H`: Anthropic notes "a lost race only fails the handshake without crashing the whole system." The attacker retries. Forever. For free. A race you can attempt a few thousand times a second until it lands is not high complexity in any sense I recognise, and I'd bet that's what moved Red Hat.

On exploitation in the wild: nobody's reporting any. Not the vendors, not any CERT, not the kernel CVE team, and it wasn't in CISA's KEV as of catalog version 2026.10.28\. Meaningfully different posture from [the PHP pair that went into KEV last week](https://sudosecurity.org/php2shell-cve-2026-109618/) — worth keeping straight when you're deciding what gets the emergency window, because they are not the same kind of problem.

## What I'd actually do

Debian, SUSE, Oracle UEK, AL2023: you have a fix. Install it, reboot, run `needs-restarting -r` and confirm you're on it.

Ubuntu: it's coming. Watch the tracker.

RHEL or a rebuild: you're in the worst spot on this list. No fix, a deferred status, the single best mitigation question unanswered in your vendor's own tracker, and a score that just landed on 9.8\. That's the case for the nftables rule plus a hard, unsentimental look at what's actually reachable on IPv4 from outside. I've argued before for [treating the host as the security boundary](https://sudosecurity.org/minecraft-server-vps-hardening/) instead of the app, and this is that argument in its purest form, because there is nothing you can configure above the kernel that helps you here. Not your WAF. Not your app. Nothing.

And the thing I'm taking out of this one, which I'll admit is uncomfortable: I've spent years using vendor severity as a triage shortcut. Reading every CVE properly doesn't scale, and the vendors are usually right. They *are* usually right.

But this went 5.9 to 9.8 in fifteen days without one line of the code changing, and the evidence contradicting the low score was in the CNA's own impact list on day one. Anybody who deferred it on the strength of that first number did everything correctly and still got it wrong. I don't have a tidy answer for that. Mostly it's got me wanting to go re-read the ones I deferred.