AxisOps Harbour
Labs

Insights

Mitigation code available CVE-2026-98432

CVE-2026-98432: a use-after-free in every supported Ubuntu release back to 16.04

Status, 29 October 2026. No fixed kernel is released for any Ubuntu series. What is published below is a mitigation, not a fix: it denies the bug its trigger, and the bug stays in the kernel until a fixed one is running. When Ubuntu releases the fixed kernels we will update the published mitigation to recognise them. Detection will then report against the real versions, the apply will remove the rule from hosts that reboot into one and we will update this note to say so.

CVE-2026-98432 is a use-after-free in the Linux kernel's IPv4 TCP code, published on 15 October and carrying a CVSS of 9.8. When the kernel handles an incoming SYN it saves any IPv4 options the packet carried, and ownership of that saved copy later passes to the new connection. Two paths can free the copy while another CPU is still reading it to build the SYN+ACK. The upstream fix, e3f33b0a1d89, is small: free the options after an RCU grace period instead of immediately.

Ubuntu's page, as of yesterday's update, is an unusual read. Every supported release is listed as affected, back to 16.04. The fixed kernel versions are on the page, release by release and flavour by flavour, each one marked "work in progress". Nothing is released. Only 14.04 is unaffected. That is odd for the oldest kernel on the page, and a reminder that this class of race arrived with a performance improvement: request sockets have been processed without the listener lock since 2015, and the freeing discipline did not keep up with the sharing.

So on 29 October a use-after-free that CVSS scores 9.8, Critical, and that Canonical's tracker rates priority High, reachable by anything that can send the first packet of a TCP handshake, is present on every supported Ubuntu release back to 16.04, and the updates channel has nothing to install. The page's mitigation section says none.

What the fix tells you

A patch you cannot install is still a specification of the bug. Both racing paths in the fix read the same object: the IPv4 options saved off the incoming SYN. The SYN+ACK builder reads them while connection setup can free them, and request-socket migration shares then frees the same copy. When the incoming SYN carries no IPv4 options, the kernel saves nothing, the pointer is null and there is nothing to free or to race over. We read the commit to check that precondition before trusting it; it holds for both halves.

That is the mitigation the tracker does not list: take the trigger away.

table inet samp_cve_2026_98432 {
  chain prerouting {
    type filter hook prerouting priority -300; policy accept;
    ip hdrlength > 5 tcp flags & (syn | ack) == syn counter drop \
        comment "CVE-2026-98432: drop inbound IPv4 SYN carrying IP options"
  }
}

One rule, in a table of its own so it cannot collide with Docker's or anything else's, dropping inbound IPv4 SYNs whose header is longer than twenty bytes. TCP almost never carries IP options; several option types are dropped by many networks as standing policy (RFC 7126), and a connection that needs them is rarer than the counter on that rule will ever show. We put a packet generator behind it before trusting it: a SYN carrying options is dropped and counted, a plain SYN passes untouched.

What it does not do

It does not drop fragmented SYNs on a host with no connection tracking, because nothing reassembles them at that hook. It does nothing for IPv6, which this CVE does not reach. It does not make the kernel fixed: the race is still there, waiting for anyone who removes the rule before rebooting into a fixed kernel that does not yet exist. And a client that genuinely sends optioned SYNs stops connecting, which is the trade, stated.

It also does not survive a reboot, on purpose. The rule lives in kernel memory and is never written to disk, because a mitigation pack that installs boot-time configuration becomes a persistence mechanism of its own. After a reboot the rule is gone, the next detection says so (rule_live=0 on the result line) and the next apply puts it back. Re-applying after every reboot is the operating model, not a failure of it; anyone running the role by hand instead of under automation needs to know the protection does not outlive the uptime.

To be precise about what it is: the repository below is a mitigation, not a fix. The fix is a kernel, and nobody can ship you one tonight. The rule, the detection that reads a running kernel against the tracker's versions and the removal path for when fixed kernels land are published at github.com/axisops/CVE-2026-98432, runnable as a standalone Ansible role. The work-in-progress kernel versions from the tracker sit in the defaults as a comment, ready to become the fixed-version table the day they ship.

"No mitigation" on a tracker page means no patch-shaped mitigation. The fix names what the bug needs to fire. Needs can be denied.