Look up another CVE · open CVE-2024-36971 in the interactive tracker
CVE-2024-36971
net: fix __dst_negative_advice() race
Published 2024-06-10 (2 years ago) by the Linux kernel CNA. Subsystem include/net. Debian urgency: not yet assigned.
What to do, per Debian release
Debian's own status for CVE-2024-36971 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source
| Release | Status | Version | What this means |
|---|---|---|---|
| Debian 12bookworm | fixed | 6.1.94-1 | Update the kernel and reboot. Fixed in 6.1.94-1. A running kernel keeps the old code until the machine restarts. |
| Debian 13trixie | fixed | 6.9.7-1 | Update the kernel and reboot. Fixed in 6.9.7-1. A running kernel keeps the old code until the machine restarts. |
| Debian 14forky | fixed | 6.9.7-1 | Update the kernel and reboot. Fixed in 6.9.7-1. A running kernel keeps the old code until the machine restarts. |
| Debian unstablesid | fixed | 6.9.7-1 | Update the kernel and reboot. Fixed in 6.9.7-1. A running kernel keeps the old code until the machine restarts. |
The vulnerability
What the bug is
__dst_negative_advice() does not enforce proper RCU rules when sk->dst_cache must be cleared, leading to possible UAF. RCU rules are that we must first clear sk->sk_dst_cache, then call dst_release(old_dst). Note that sk_dst_reset(sk) is implementing this protocol correctly, while __dst_negative_advice() uses the wrong order. Given that ip6_negative_advice() has special logic against RTF_CACHE, this means each of the three ->negative_advice() existing methods must perform the sk_dst_reset() themselves. Note the check against NULL dst is centralized in __dst_negative_advice(), there is no need to duplicate it in various callbacks. Many thanks to Clement Lecigne for tracking this issue. This old bug became visible after the blamed commit, using UDP sockets.
Where it lives
The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.
include/net/dst_ops.h
include/net/sock.h
net/ipv4/route.c
net/ipv6/route.c
net/xfrm/xfrm_policy.c
- What this is
- NETWORKING [GENERAL]MAINTAINERS section matched on include/net/ · netdev@vger.kernel.org · Maintained
Check it on the machine
grep -w CONFIG_INET /boot/config-$(uname -r)Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.
Show whether Debian builds this, per release
Debian builds this code. Every release below compiles the affected file into the kernels it ships.
- bookworm, trixie, forky, sidy
- y
- built into the kernel image on every flavour - only a patch removes it
- Build switch
- CONFIG_INET
From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages
Known to be exploited in the wild
- Added to KEV
- 2024-08-07
- Federal due date
- 2024-08-28
- Ransomware use
- unknown
- Required action
- Apply mitigations per vendor instructions or discontinue use of the product if mitigations are unavailable.
Signals
- Published
- 2024-06-10 (2 years ago)source
- CVSS
- 7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it - Attack vector
- local (AV:L)source
- EPSS
- 2.70%, higher than 85.7% of all CVEssource
- CISA KEV
- listedthe KEV catalogue
- Debian urgency
- not yet assignedsource
- Subsystem
- include/net
Upstream fixes
The versions the CNA records as introducing and fixing this, and the commit for each. source
| Introduced | Fixed in | Commit |
|---|---|---|
| 4.6 | 4.19.316 | 051c0bde9f04 |
| 4.6 | 5.4.278 | db0082825037 |
| 4.6 | 5.10.219 | 2295a7ef5c8c |
| 4.6 | 5.15.161 | eacb8b195579 |
| 4.6 | 6.1.94 | 81dd3c82a456 |
| 4.6 | 6.6.34 | 5af198c38712 |
| 4.6 | 6.9.4 | b8af8e6118a6 |
| 4.6 | 6.10 | 92f1655aa2b2 |
Debian advisories
| Advisory | Date | Shipped to | Debian |
|---|---|---|---|
| DSA-5730-1 | 2024-07-15 | bullseye 5.10.221-1 | tracker |
| DLA-3840-1 | 2024-06-25 | buster 4.19.316-1 | tracker |
Why the CNA scored it this way
Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source
- AV:LAttack vector, local
- The race must be driven by two concurrent local socket operations on the same fd — `setsockopt(SO_CNX_ADVICE)` and a lockless `udp_sendmsg()` — so the attacker needs local syscall access. A remote peer can drive only the free side (TCP retransmit timeouts, ICMP-induced PMTU/redirect exceptions), not the racing `sk_dst_cache` writer.
- AC:LAttack complexity, low
- The attacker controls both sides of the race (one thread calling `SO_CNX_ADVICE`, another calling `sendmsg()` on the same connected socket) and can create the required route-exception/obsolete-dst precondition at will, retrying indefinitely across many sockets; in-the-wild exploitation confirms it is reliably winnable.
- PR:LPrivileges required, low
- `SO_CNX_ADVICE` in `sock_setsockopt()` carries no capability check and a connected UDP socket needs no privileges, so any unprivileged local user — including a sandboxed Android app, as in the observed real-world exploit — can reach the code.
- UI:NUser interaction, none
- Exploitation is entirely self-driven through the attacker's own socket, timers and threads; no victim action is needed.
- S:UScope, unchanged
- The corrupted `dst_entry` and the resulting code execution are both within the kernel's own security authority — standard local privilege escalation, no VM/IOMMU boundary crossed.
- C:HConfidentiality impact, high
- The refcount underflow yields a use-after-free on a `dst_entry` whose contents (ops table, metrics, neighbour and function pointers) can be replaced by attacker-sprayed data, giving a kernel read primitive and full disclosure once escalated to root.
- I:HIntegrity impact, high
- `dst_entry` holds `ops`, `input()` and `output()` function pointers invoked on every transmit, so reclaiming the freed object gives direct control-flow hijack and arbitrary kernel write — this was weaponized as an in-the-wild Android privilege escalation.
- A:HAvailability impact, high
- Even unweaponized, the premature free and dangling `sk_dst_cache` dereference cause refcount WARNs, memory corruption and kernel oops/panic, and the trigger can be repeated freely by an unprivileged process.