CVE-2024-36904 - Linux Kernel Use-After-Free in tcp_twsk_unique() – Analysis, Exploitation & Patching
---
TL;DR
A critical use-after-free vulnerability (CVE-2024-36904) was identified in the Linux kernel’s TCP/IP stack, specifically in the way it handles TCP TIME_WAIT sockets. This flaw can be triggered under rare, but realistic, race conditions leading to kernel memory corruption and possible privilege escalation. The vulnerability was responsibly reported by Anderson Nascimento, and is now patched via smarter reference count handling.
What is CVE-2024-36904?
CVE-2024-36904 is a race condition in the Linux kernel's TCP code. When a TCP connection ends, it often enters the TIME_WAIT state for a few minutes to ensure straggling packets don’t interfere with new connections on the same port. There’s a fast path for “port reuse” (think: for high-performance apps that open lots of connections). The affected code tries to bump (sock_hold()) the reference counter on a TIME_WAIT socket, but a race condition can result in taking a reference after the count already hit zero – leading to a use-after-free (UAF) bug.
Affected Versions
- Mainline kernel since: ec94c2696fb (change in tcp/dccp reducing atomic increments for performance, merged late 2023).
Exploitable in: All kernels with this patch before May 2024.
- Fixed in: Upstream commit
Thread B (perhaps another app or attacker) quickly tries to reuse that port.
3. Because the reference counter is briefly zero _after_ insertion into a hash bucket but _before_ it’s properly incremented, sock_hold() can act on a socket whose memory is already being reclaimed.
You may notice the classic refcount error in logs
WARNING: CPU: ... at lib/refcount.c:25 refcount_warn_saturate
...
tcp_twsk_unique+x186/x190
...
This means an attempt was made to increment a refcount that was already zero—an instant red flag for UAF!
Here’s what the old code looked like in simplified C
// vulnerable: may increment refcount even if it's already
void tcp_twsk_unique(...) {
...
sock_hold(sk_tw); // <-- The troublemaker
...
}
If two threads race, this increments a dead socket’s refcount.
While this bug is a tight race to win, a “hammer” could look like this (pseudocode)
# 1. Launch thousands of TCP connections, forcing some to hit TIME_WAIT
for i in range(10000):
s = socket()
s.connect(addr)
s.close()
# 2. Spawn parallel threads rapidly reconnecting to the same port
# This attempts to win the race after the TIME_WAIT has dropped to zero
A sophisticated exploitation would also need to heap spray the kernel to occupy freed memory with attacker-controlled data.
The kernel fix changes
// old: always increment refcount (even if )
sock_hold(sk_tw);
// new: increment only if not already , otherwise fail safely
if (!refcount_inc_not_zero(&sk_tw->sk_refcnt)) {
// Give up and don't reuse
return -1;
}
See the fix: commit 9fae4b99
This means the socket reuse path _fails safely_ instead of risking a UAF.
References
- Kernel Patch Commit
- Bug Report / Analysis
- CVE Details page
- Discussion on oss-sec
Am I Affected? (and How to Patch)
Run:
uname -r
If you’re running a kernel before 5.19. _and_ patch ec94c2696fb is present, you are at risk.
- Servers exposed to the Internet are most at risk, especially multi-user/multi-tenant environments.
Red Hat, Ubuntu, Debian have ongoing updates.
How To Fix:
Conclusion
CVE-2024-36904 is a sneaky race—easy to miss, potentially devastating. It shows why even “harmless” reference counting changes must be handled with extreme care in high-concurrency areas like the kernel! Update now, and keep an eye on your kernel logs for refcount warnings in the wild.
*Stay safe, keep your servers up to date, and happy hacking!*
Timeline
Published on: 05/30/2024 16:15:13 UTC
Last modified on: 05/04/2025 09:11:46 UTC