Import Source
https://github.com/microsoft/AzureLinuxVulnerabilityData/blob/main/osv/AZL-89070.json
JSON Data
https://api.osv.dev/v1/vulns/AZL-89070
Upstream
Published
2026-05-28T10:16:27Z
Modified
2026-08-28T17:46:38.904124221Z
Summary
CVE-2026-46116 affecting package kernel for versions less than 6.6.141.1-1
Details

In the Linux kernel, the following vulnerability has been resolved:

xfrm: defensively unhash xfrm_state lists in __xfrmstatedelete

KASAN reproduces a slab-use-after-free in _xfrmstatedelete()'s hlistdelrcu calls under syzkaller load on linux-6.12.y stable (reproduced on 6.12.47, also reachable via the same code path on torvalds/master and on the ipsec tree). Nine unique signatures cluster in the xfrmstate lifecycle, the load-bearing one being:

BUG: KASAN: slab-use-after-free in __hlistdel include/linux/list.h:990 [inline] BUG: KASAN: slab-use-after-free in hlistdel_rcu include/linux/rculist.h:516 [inline] BUG: KASAN: slab-use-after-free in _xfrmstatedelete net/xfrm/xfrmstate.c Write of size 8 at addr ffff8881198bcb70 by task kworker/u8:9/435

Workqueue: netns cleanup_net Call Trace: __hlistdel / hlistdel_rcu _xfrmstatedelete xfrmstatedelete xfrmstateflush xfrmstatefini opsexitlist cleanupnet

The other observed signatures hit the same slab object from __xfrmstatelookup, xfrmallocspi, __xfrmstateinsert and an OOB write variant of __xfrmstatedelete, all on the byseq/byspi hash chains.

__xfrmstatedelete() guards its byseq and byspi unhashes with value-based predicates:

if (x->km.seq)
    hlist_del_rcu(&x->byseq);
if (x->id.spi)
    hlist_del_rcu(&x->byspi);

while everywhere else in the file (e.g. statecache, statecacheinput) the safer hlistunhashed() check is used. xfrmallocspi() sets x->id.spi = newspi inside xfrmstatelock and then immediately inserts into byspi, but a path that observes x->id.spi != 0 outside of xfrmstatelock can still skip-or-hit the byspi unhash inconsistently with whether x is actually on the list. The same holds for x->km.seq versus byseq, and the bydst/bysrc unhashes have no predicate at all, so a second _xfrmstatedelete() on the same object writes through LISTPOISON pprev.

The defensive change here:

  • Use hlistdelinitrcu() instead of hlistdelrcu() on bydst, bysrc, byseq and byspi so a second deletion is a no-op rather than a write through LISTPOISON pprev. The byseq/byspi nodes are already initialised in xfrmstatealloc().
  • Test hlist_unhashed() rather than the value predicate for byseq/byspi, so the unhash decision tracks list state rather than mutable scalar fields.

Empirical verification: applied this patch on top of v6.12.47, rebuilt, and re-ran the same syzkaller harness for 1h16m on a previously-crashy configuration that produced ~100 hits each of slab-use-after-free Read in xfrmallocspi / Read in __xfrmstatelookup / Write in __xfrmstatedelete. After the patch, 7.1M execs across 32 VMs at ~1550 exec/sec produced zero xfrmstate UAF/OOB hits. /proc/slabinfo confirms the xfrmstate slab is actively allocated and freed during the run (~143 KiB resident), so the fuzzer is still exercising those code paths -- they just no longer crash.

Reproduction:

  • Linux 6.12.47 x8664 + KASANGENERIC + KASAN_INLINE + KCOV
  • syzkaller @ 746545b8b1e4c3a128db8652b340d3df90ce61db
  • 32 QEMU/KVM VMs x 2 vCPU on AWS c5.metal bare metal
  • 9 unique signatures collected in ~9h, all within xfrm_state lifecycle
References

Affected packages

Azure Linux:3 / kernel

Package

Name
kernel
Purl
pkg:rpm/azure-linux/kernel

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
6.6.141.1-1

Database specific

source
"https://github.com/microsoft/AzureLinuxVulnerabilityData/blob/main/osv/AZL-89070.json"