In the Linux kernel, the following vulnerability has been resolved:
tcp: restore RCU grace period in tcpaodestroy_sock
Commit 51e547e8c89c ("tcp: Free TCP-AO/TCP-MD5 info/keys without RCU") removed the callrcu() callback from tcpaodestroysock(), arguing that "the destruction of info/keys is delayed until the socket destructor" and therefore "no one can discover it anymore".
That argument does not hold for the call site in tcpconnect() (net/ipv4/tcpoutput.c:4327-4332). At that point the socket is in TCPSYNSENT, has already been inserted into the inet ehash by inethashconnect() in tcpv4connect(), and is therefore very much discoverable: any softirq running tcpv4rcv() on another CPU can take the socket out of the ehash, walk into tcpinboundhash(), and load tp->aoinfo via implicit RCU before bhlocksocknested() is taken on the destroying CPU.
The reader path then enters _tcpaodolookup() (net/ipv4/tcpao.c:208) which re-loads tp->aoinfo via rcudereferencecheck(); the re-load can still observe the (about-to-be-freed) pointer because there is no synchronizercu() between rcuassignpointer(tp->aoinfo, NULL) and tcpaoinfofree() in tcpaodestroysock(). The captured pointer is then walked at line 223:
hlist_for_each_entry_rcu(key, &ao->head, node, ...)
The writer's synchronous kfree() is free to complete between the line 218 re-fetch and the line 223 hlist iteration. The slab is reused (or simply LIST_POISON1-stamped if not yet reused) and the iteration walks attacker-controlled or poison memory in softirq context.
Reproducer (no debug shim, stock x8664 v7.1-rc2 SMP+KASAN, QEMU+KVM): an unprivileged uid=1000 process inside CLONENEWUSER|CLONENEWNET installs TCPMD5SIG + TCPAOADDKEY on a TCP socket, sprays forged TCP-AO segments toward its eventual 4-tuple via raw sockets, then calls connect(). The md5-wins reconciliation in tcpconnect() fires tcpaodestroy_sock(); the softirq backlog reader on the loopback NAPI path crashes on the freed ao->head.first walk:
Oops: general protection fault, probably for non-canonical address 0xfbd59c000000002f KASAN: maybe wild-memory-access in range [0xdead000000000178-0xdead00000000017f] CPU: 0 UID: 1000 PID: 100 Comm: repro_userns RIP: 0010:__tcpaodo_lookup+0x107/0x1c0 Call Trace: <IRQ> _tcpaodolookup+0x107/0x1c0 tcpaoinboundlookup.constprop.0+0x12a/0x200 tcpinboundaohash+0x5ea/0x1520 tcpinboundhash+0x7ce/0x1240 tcpv4rcv+0x1e7a/0x3e10 ...
Restore the RCU grace period: re-add struct rcuhead to tcpaoinfo and replace the synchronous tcpaoinfofree() with a callrcu() callback. Readers that captured tp->aoinfo before rcuassignpointer NULLed it now see the object remain valid until rcureadunlock(). With the patch applied the reproducer runs cleanly for 2000 iterations on the same kernel build.
{
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/64xxx/CVE-2026-64459.json"
}