In the Linux kernel, the following vulnerability has been resolved:
tcp: defer md5sig_info kfree past RCU grace period in tcp_connect
The md5+ao reconciliation in tcp_connect() (net/ipv4/tcp_output.c) has two symmetric branches:
if (needs_md5) { tcp_ao_destroy_sock(sk, false); } else if (needs_ao) { tcp_clear_md5_list(sk); kfree(rcu_replace_pointer(tp->md5sig_info, NULL, ...)); }
Both branches free a per-socket auth-info object while the socket is in TCP_SYN_SENT and is already on the inet ehash (inserted by inet_hash_connect() in tcp_v4_connect()). Both branches are reachable by softirq RX-path readers that load the corresponding info pointer via implicit RCU before bh_lock_sock_nested() is taken.
The needs_md5 branch is fixed in the prior patch by re-introducing the call_rcu() free in tcp_ao_destroy_sock(): the equivalent per-key loop runs inside tcp_ao_info_free_rcu(), the RCU callback, so by the time it frees each tcp_ao_key all softirq readers that captured the container have already completed rcu_read_unlock().
The needs_ao branch is not symmetric in the same way. The container free can be deferred via kfree_rcu(md5sig, rcu) -- struct tcp_md5sig_info already has the required rcu member (include/net/tcp.h:1999-2002), and the rest of the tree already does this in the tcp_md5sig_info_add() rollback paths (net/ipv4/tcp_ipv4.c:1410, 1436). But the per-key teardown is done by tcp_clear_md5_list() in process context BEFORE the container's RCU grace period: it walks &md5sig->head and frees each tcp_md5sig_key with bare hlist_del + kfree. A concurrent softirq reader in __tcp_md5_do_lookup() / __tcp_md5_do_lookup_exact() (tcp_ipv4.c:1253, 1298) walks the same list via hlist_for_each_entry_rcu() and races with that bare kfree on the keys themselves -- a per-key slab use-after-free of the same class as the TCP-AO bug, on the same race window.
Fix this in two halves:
1. Convert the bare kfree() in tcp_connect() to kfree_rcu() so the md5sig_info container joins the rest of the md5sig lifecycle. The local-variable lift is mechanical and required because kfree_rcu() is a macro that expects an lvalue.
2. Make tcp_clear_md5_list() RCU-safe by replacing hlist_del + kfree(key) with hlist_del_rcu + kfree_rcu(key, rcu). struct tcp_md5sig_key already carries the rcu member (include/net/tcp.h:1995) and tcp_md5_do_del() (net/ipv4/tcp_ipv4.c:1456) already uses kfree_rcu, so this restores the lifecycle invariant the rest of the file follows rather than introducing a one-off.
The other caller of tcp_clear_md5_list() is tcp_md5_destruct_sock() (net/ipv4/tcp.c:412), which runs from the sock destructor when the socket is already unhashed and unreachable; the extra grace period there is unnecessary but harmless. Making the helper unconditionally RCU-safe is the cleaner contract.
The needs_ao branch is not reachable by the userns reproducer used to demonstrate the AO-side splat (the repro installs both keys but ends up in the needs_md5 branch because the connect peer matches the MD5 key, not the AO key); however the symmetric race exists and a maintainer touching this code should not have to think about which branch escapes RCU and which one does not.
[also credits to Qihang, who found that this races with tcp-diag]
| Product | Vendor Advisory | Solution File | Added | Published |
|---|---|---|---|---|
| Redhat_linux | — | No solution exists | Aug 20, 2026 | Aug 15, 2026 |
| Ubuntu | — | Upgrade linux-image-7.0.0-1012-oracleUpgrade linux-image-7.0.0-34-generic-64kUpgrade linux-image-oracle-64k-7.0Upgrade linux-image-7.0.0-1014-oemUpgrade linux-image-7.0.0-34-genericUpgrade linux-image-generic-64k-hwe-26.04Upgrade linux-image-7.0.0-1007-gkeUpgrade linux-image-7.0.0-1013-gcpUpgrade linux-image-7.0.0-1020-raspiUpgrade linux-image-azure-lts-26.04Upgrade linux-image-aws-64k-7.0Upgrade linux-image-azure-fdeUpgrade linux-image-gcp-7.0Upgrade linux-image-gke-64k-7.0Upgrade linux-image-aws-7.0Upgrade linux-image-generic-64k-7.0Upgrade linux-image-azure-fde-7.0Upgrade linux-image-7.0.0-34-realtimeUpgrade linux-image-oem-26.04Upgrade linux-image-raspiUpgrade linux-image-generic-64kUpgrade linux-image-7.0.0-1020-raspi-realtimeUpgrade linux-image-genericUpgrade linux-image-ibmUpgrade linux-image-ibm-7.0Upgrade linux-image-gke-64kUpgrade linux-image-realtime-7.0Upgrade linux-image-7.0.0-1016-azure-fdeUpgrade linux-image-7.0.0-1017-azureUpgrade linux-image-virtual-hwe-26.04Upgrade linux-image-azureUpgrade linux-image-raspi-realtime-7.0Upgrade linux-image-realtime-hwe-26.04Upgrade linux-image-oracle-7.0Upgrade linux-image-7.0.0-1013-aws-64kUpgrade linux-image-gke-64k-hwe-26.04Upgrade linux-image-generic-hwe-26.04Upgrade linux-image-oracleUpgrade linux-image-realtime-64k-hwe-26.04Upgrade linux-image-7.0.0-34-realtime-64kUpgrade linux-image-azure-7.0Upgrade linux-image-generic-7.0Upgrade linux-image-azure-fde-lts-26.04Upgrade linux-image-7.0.0-1013-gcp-64kUpgrade linux-image-virtualUpgrade linux-image-oem-26.04aUpgrade linux-image-7.0.0-1007-gke-64kUpgrade linux-image-raspi-realtimeUpgrade linux-image-awsUpgrade linux-image-gkeUpgrade linux-image-oem-7.0Upgrade linux-image-oracle-64kUpgrade linux-image-7.0.0-1012-oracle-64kUpgrade linux-image-virtual-hwe-24.04Upgrade linux-image-aws-64kUpgrade linux-image-7.0.0-1014-ibmUpgrade linux-image-gcp-64kUpgrade linux-image-gcpUpgrade linux-image-virtual-7.0Upgrade linux-image-realtime-64kUpgrade linux-image-generic-hwe-24.04Upgrade linux-image-realtimeUpgrade linux-image-raspi-7.0Upgrade linux-image-gcp-64k-7.0Upgrade linux-image-7.0.0-1013-awsUpgrade linux-image-realtime-64k-7.0Upgrade linux-image-gke-7.0Upgrade linux-image-gke-hwe-26.04Upgrade linux-image-generic-64k-hwe-24.04 | Sep 24, 2026 | Aug 15, 2026 |
| Vmware Photon_os | — | Use 'tdnf update' to upgrade all packages to the latest version. | Aug 25, 2026 | Aug 15, 2026 |
With curated Threat Intelligence, you can see which vulnerabilities truly put you at risk, prioritize what matters most, and act before attackers do.
Explore Intelligence Hub