net/tcp-ao: fix use-after-free of current_key on reconnect to another peer
In the Linux kernel, the following vulnerability has been resolved: net/tcp-ao: fix use-after-free of current_key on reconnect to another peer tcp_inbound_ao_hash() is called before bh_lock_sock_nested() is taken, with only rcu_read_lock() held. On the fast path for established sockets, if the rnext_keyid sent by the peer differs from current_key->sndid, the key the peer asked for is looked up and stored in current_key. The lookup is inside the RCU read side, but current_key outlives it. When the socket is disconnected and connect() is called again for another peer, tcp_ao_connect_init() unlinks every key that does not match the new peer and frees it with call_rcu(). If current_key points at such a key, it is cleared to NULL. The fast path reads sk_state only once on entry, so a softirq that got into it while the socket was still established can update current_key after that loop has already run. The update is inside the RCU read side, so it comes before the call_rcu() callback, and once the callback frees the key, current_key is left pointing at freed memory. The next transmission picks that pointer up in tcp_get_current_key(). tcp_ao_transmit_skb() then reads the traffic key from the freed object, which is the use-after-free. Wait for one grace period before unlinking, and only if a key is going to be removed. By the time tcp_connect() runs the socket is already in TCP_SYN_SENT, and TCP_AO_ESTABLISHED does not contain TCPF_SYN_SENT, so a softirq entering after the wait cann
- Products
- Kernel
- Affected versions
- Not specified
- Fixed versions
- 6.12.108, 6.18.49, 7.1.13, 7.2.3
- CVEs
- CVE-2026-80849
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 3 Nov 2026, 15:19 UTC · Revision 1
Source evidence
net/tcp-ao: fix use-after-free of current_key on reconnect to another peer
core-osv · Original sourcePublished 4 Sept 2026, 15:54 UTC
In the Linux kernel, the following vulnerability has been resolved: net/tcp-ao: fix use-after-free of current_key on reconnect to another peer tcp_inbound_ao_hash() is called before bh_lock_sock_nested() is taken, with only rcu_read_lock() held. On the fast path for established sockets, if the rnext_keyid sent by the peer differs from current_key->sndid, the key the peer asked for is looked up and stored in current_key. The lookup is inside the RCU read side, but current_key outlives it. When the socket is disconnected and connect() is called again for another peer, tcp_ao_connect_init() unlinks every key that does not match the new peer and frees it with call_rcu(). If current_key points at such a key, it is cleared to NULL. The fast path reads sk_state only once on entry, so a softirq that got into it while the socket was still established can update current_key after that loop has already run. The update is inside the RCU read side, so it comes before the call_rcu() callback, and once the callback frees the key, current_key is left pointing at freed memory. The next transmission picks that pointer up in tcp_get_current_key(). tcp_ao_transmit_skb() then reads the traffic key from the freed object, which is the use-after-free. Wait for one grace period before unlinking, and only if a key is going to be removed. By the time tcp_connect() runs the socket is already in TCP_SYN_SENT, and TCP_AO_ESTABLISHED does not contain TCPF_SYN_SENT, so a softirq entering after the wait cann
osv:CVE-2026-80849
Kernel
Fixed versions: 6.12.108, 6.18.49, 7.1.13, 7.2.3
Complete source record
{
"id": "05b25072ef12db08207ecc7529874605c2e70144cfe0f073e0da186f36934f63",
"url": "https://osv.dev/vulnerability/CVE-2026-80849",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "net/tcp-ao: fix use-after-free of current_key on reconnect to another peer",
"summary": "In the Linux kernel, the following vulnerability has been resolved: net/tcp-ao: fix use-after-free of current_key on reconnect to another peer tcp_inbound_ao_hash() is called before bh_lock_sock_nested() is taken, with only rcu_read_lock() held. On the fast path for established sockets, if the rnext_keyid sent by the peer differs from current_key->sndid, the key the peer asked for is looked up and stored in current_key. The lookup is inside the RCU read side, but current_key outlives it. When the socket is disconnected and connect() is called again for another peer, tcp_ao_connect_init() unlinks every key that does not match the new peer and frees it with call_rcu(). If current_key points at such a key, it is cleared to NULL. The fast path reads sk_state only once on entry, so a softirq that got into it while the socket was still established can update current_key after that loop has already run. The update is inside the RCU read side, so it comes before the call_rcu() callback, and once the callback frees the key, current_key is left pointing at freed memory. The next transmission picks that pointer up in tcp_get_current_key(). tcp_ao_transmit_skb() then reads the traffic key from the freed object, which is the use-after-free. Wait for one grace period before unlinking, and only if a key is going to be removed. By the time tcp_connect() runs the socket is already in TCP_SYN_SENT, and TCP_AO_ESTABLISHED does not contain TCPF_SYN_SENT, so a softirq entering after the wait cann",
"evidence": "osv:CVE-2026-80849",
"products": [
{
"name": {
"value": "Kernel",
"evidence": "/affected/1/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "6.12.108",
"evidence": "/affected/1/ranges"
},
{
"value": "6.18.49",
"evidence": "/affected/1/ranges"
},
{
"value": "7.1.13",
"evidence": "/affected/1/ranges"
},
{
"value": "7.2.3",
"evidence": "/affected/1/ranges"
}
],
"affected_versions": []
}
],
"severity": "unknown",
"structured": {
"id": "CVE-2026-80849",
"aliases": [
"CVE-2026-80849"
],
"affected": [
{
"ranges": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"type": "GIT",
"events": [
{
"introduced": "0a3a809089eb1d4a0a2fd0c16b520d603988c859"
},
{
"fixed": "84a93b4e012587d0a4a84ffb23ec6da18e9d85f9"
},
{
"fixed": "73fde8fe4469f4ed8f0afcc0b9d6413002a9e6b3"
},
{
"fixed": "e54ad693eddb40c595add013f545354c538e325b"
},
{
"fixed": "2857dcbd03cf3354af0fba1b65c6a260fb43811a"
},
{
"fixed": "da4471557f279d0f56605158a625bb6e49ef7d41"
}
]
}
],
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-80849.json"
}
},
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.7.0"
},
{
"fixed": "6.12.108"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.13.0"
},
{
"fixed": "6.18.49"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.19.0"
},
{
"fixed": "7.1.13"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "7.2.0"
},
{
"fixed": "7.2.3"
}
]
}
],
"package": {
"name": "Kernel",
"ecosystem": "Linux"
},
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-80849.json"
}
}
],
"modified": "2026-10-28T02:30:29.707367114Z",
"provider": "osv",
"references": [
"https://git.kernel.org/stable/c/2857dcbd03cf3354af0fba1b65c6a260fb43811a",
"https://git.kernel.org/stable/c/73fde8fe4469f4ed8f0afcc0b9d6413002a9e6b3",
"https://git.kernel.org/stable/c/84a93b4e012587d0a4a84ffb23ec6da18e9d85f9",
"https://git.kernel.org/stable/c/da4471557f279d0f56605158a625bb6e49ef7d41",
"https://git.kernel.org/stable/c/e54ad693eddb40c595add013f545354c538e325b",
"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/80xxx/CVE-2026-80849.json",
"https://nvd.nist.gov/vuln/detail/CVE-2026-80849",
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
],
"provider_metadata": {
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/80xxx/CVE-2026-80849.json"
}
},
"related_cves": [
{
"value": "CVE-2026-80849",
"evidence": "/id"
}
],
"security_relevant": true,
"severity_evidence": null
},
"source_id": "core-osv",
"document_id": 496758,
"published_at": "2026-09-04T15:54:59.412+00:00"
}