data built 2026-10-19T13:16:53Z

Look up another CVE · open CVE-2026-90237 in the interactive tracker

CVE-2026-90237

netfilter: nft_ct: move custom expectation support to helper

7.8 EPSS 0.2% AV:L

Published 2026-09-17 (31 days ago) by the Linux kernel CNA. Subsystem include/net. Debian urgency: not yet assigned.

What to do, per Debian release

Debian's own status for CVE-2026-90237 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source

ReleaseStatus VersionWhat this means
Debian 12bookwormvulnerable6.1.190-1No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication.
Debian 13trixievulnerable6.12.113-1No fix published anywhere yet, neither in Debian nor upstream for the series trixie tracks. Watch the Debian tracker page for this CVE. Advisories for trixie have historically landed a median of 11 days after publication.
Debian 14forkyfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.
Debian unstablesidfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.

The vulnerability

What the bug is

Originally, the ct expectation support called nf_ct_helper_ext_add() for confirmed conntracks, which is invalid, triggering a splat. This was fixed by commit 1710eb913bdc ("netfilter: nft_ct: skip expectations for confirmed conntrack") which restricted it to unconfirmed conntracks. However, early insertion of expectations into the expectations list when the conntrack is unconfirmed leads to stale entries pointing to the wrong hlist_head through .pprev due to ct extension reallocation. Commit 7c9664351980 ("netfilter: move nat hlist_head to nf_conn") moved the nat hlist_head to nf_conn for this reason: 1. ... 2. When reallocation of extension area occurs we need to fixup the bysource hash head via hlist_replace_rcu. I'd rather not increase the size of the struct nf_conn for this feature has very limited scope: only one expectation can be created at a time given expect_clash() will make nf_ct_expect_related() reports EBUSY. For this reason, relax nf_ct_expect_related() not to drop packets in case expectation creation fails, therefore, expectation creation becomes best effort. To address this issue, add an internal ct helper and attach it to the conntrack entry to streamline the custom ct expectation support with existing ct helpers. Expose a new nf_conntrack_helper_release() function to release the internal helper that is allocated and attached to the conntrack entry to create the custom expectations. The nft_ct module removal always waits for rcu grace period, then the NULL helper callback is observed after this. This patch also restricts the creation of expectations to different helpers other than this custom helper that is created for this type of expectations.

Where it lives

The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.

include/net/netfilter/nf_conntrack_helper.h
net/netfilter/nf_conntrack_helper.c
net/netfilter/nft_ct.c

What this is
NETFILTERMAINTAINERS section matched on include/net/netfilter/ · netfilter-devel@vger.kernel.org · Maintained
Kernel module
nf_conntrack

Check it on the machine

grep -wE 'CONFIG_NETFILTER|CONFIG_NF_CONNTRACK' /boot/config-$(uname -r)

Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.

lsmod | grep -w nf_conntrack

Prints a line if that module is loaded right now, and nothing if it is not. One that is not loaded can still be loaded later by anything that needs it.

Show whether Debian builds this, per release

Debian builds this as a loadable module. Every release below compiles it as a module on every flavour, so whether the code is in the running kernel depends on whether that module is loaded.

  • bookworm, trixie, forky, sidm
m
a loadable module on every flavour - check lsmod, can be blacklisted
Build switches
CONFIG_NETFILTER, CONFIG_NF_CONNTRACK
Reads as
all on means the file is compiled; any one off means it is not.

From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages

Signals

Published
2026-09-17 (31 days ago)source
CVSS
7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it
Attack vector
local (AV:L)source
EPSS
0.17%, higher than 5.4% of all CVEssource
CISA KEV
not listedthe KEV catalogue
Debian urgency
not yet assignedsource
Subsystem
include/net

Upstream fixes

The versions the CNA records as introducing and fixing this, and the commit for each. source

IntroducedFixed inCommit
5.37.2.6af3fe52fd108
5.37.33679da4ad8be

Why the CNA scored it this way

Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source

AV:LAttack vector, local
The triggering state is created by a local NFT_MSG_NEWOBJ (nf_tables_newobj) of type NFT_OBJECT_CT_EXPECT plus an objref rule; nft_objref_eval then calls nft_ct_expect_obj_eval from nft_do_chain_ipv4 on a packet the attacker sends in their netns. No remote protocol field carries the malformed expectation-list linkage.
AC:LAttack complexity, low
After nf_ct_expect_insert stores exp->lnode into nf_conn_help.expectations, the attacker’s later expressions on the same packet (nft_ct_timeout_obj_eval, nft_ct_set_eval NFT_CT_EVENTMASK, or nft_nat_eval → nf_nat_setup_info → nfct_seqadj_ext_add) call nf_ct_ext_add so krealloc moves ct->ext; that rule order is attacker-chosen and needs no race.
PR:LPrivileges required, low
nfnetlink_rcv admits the NFT_MSG_NEWOBJ/NEWRULE batch only after netlink_net_capable(skb, CAP_NET_ADMIN) against sock_net(skb->sk)->user_ns, which an unprivileged user gets via unshare -Urn; nft_ct_expect_obj_init has no extra init-namespace capability check.
UI:NUser interaction, none
The attacker installs the ct expectation object and objref rule themselves, then emits their own UDP/TCP packet so nft_do_chain_ipv4 at NF_INET_LOCAL_OUT reaches nft_ct_expect_obj_eval; no other user must mount, open a file, or confirm the ruleset.
S:UScope, unchanged
krealloc of ct->ext leaves a dangling hlist_node.pprev in the host kernel heap (nf_conn_help.expectations); impact is in-kernel memory corruption on the same host, not a KVM/Xen guest-to-host escape or IOMMU/DMA bypass.
C:HConfidentiality impact, high
After nf_ct_ext_add’s krealloc frees the old nf_conn_help, exp->lnode.pprev still addresses that slab; spraying it and then walking help->expectations in nf_ct_remove_expectations is a use-after-free read of reused kernel memory.
I:HIntegrity impact, high
nf_ct_unlink_expect_report’s hlist_del_rcu(&exp->lnode) writes the next pointer through the stale pprev into the freed helper extension, a heap write primitive that can be groomed for control-flow hijack.
A:HAvailability impact, high
The same dangling pprev is used when the conntrack is destroyed (clean_from_lists → nf_ct_remove_expectations) or the expectation is unlinked, which oopses or panics if the old ct->ext slab was reused or poisoned.