Look up another CVE · open CVE-2024-41045 in the interactive tracker
CVE-2024-41045
bpf: Defer work in bpf_timer_cancel_and_free
Published 2024-07-29 (2 years ago) by the Linux kernel CNA. Subsystem kernel/bpf. Debian urgency: not yet assigned.
What to do, per Debian release
Debian's own status for CVE-2024-41045 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 | vulnerable | 6.1.190-1 | No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication. |
| Debian 13trixie | fixed | 6.9.10-1 | Update the kernel and reboot. Fixed in 6.9.10-1. A running kernel keeps the old code until the machine restarts. |
| Debian 14forky | fixed | 6.9.10-1 | Update the kernel and reboot. Fixed in 6.9.10-1. A running kernel keeps the old code until the machine restarts. |
| Debian unstablesid | fixed | 6.9.10-1 | Update the kernel and reboot. Fixed in 6.9.10-1. A running kernel keeps the old code until the machine restarts. |
The vulnerability
What the bug is
Currently, the same case as previous patch (two timer callbacks trying to cancel each other) can be invoked through bpf_map_update_elem as well, or more precisely, freeing map elements containing timers. Since this relies on hrtimer_cancel as well, it is prone to the same deadlock situation as the previous patch. It would be sufficient to use hrtimer_try_to_cancel to fix this problem, as the timer cannot be enqueued after async_cancel_and_free. Once async_cancel_and_free has been done, the timer must be reinitialized before it can be armed again. The callback running in parallel trying to arm the timer will fail, and freeing bpf_hrtimer without waiting is sufficient (given kfree_rcu), and bpf_timer_cb will return HRTIMER_NORESTART, preventing the timer from being rearmed again. However, there exists a UAF scenario where the callback arms the timer before entering this function, such that if cancellation fails (due to timer callback invoking this routine, or the target timer callback running concurrently). In such a case, if the timer expiration is significantly far in the future, the RCU grace period expiration happening before it will free the bpf_hrtimer state and along with it the struct hrtimer, that is enqueued. Hence, it is clear cancellation needs to occur after async_cancel_and_free, and yet it cannot be done inline due to deadlock issues. We thus modify bpf_timer_cancel_and_free to defer work to the global workqueue, adding a work_struct alongside rcu_head (both used at _different_ points of time, so can share space). Update existing code comments to reflect the new state of affairs.
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.
kernel/bpf/helpers.c
- What this is
- BPF [GENERAL] (Safe Dynamic Programs and Tools)MAINTAINERS section matched on kernel/bpf/ · bpf@vger.kernel.org · Supported
Check it on the machine
grep -wE 'CONFIG_BPF|CONFIG_BPF_SYSCALL' /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 switches
- CONFIG_BPF, CONFIG_BPF_SYSCALL
- Reads as
- all on means the file is compiled; any one off means it is not.
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
Signals
- Published
- 2024-07-29 (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
- 0.29%, higher than 19.6% of all CVEssource
- CISA KEV
- not listedthe KEV catalogue
- Debian urgency
- not yet assignedsource
- Subsystem
- kernel/bpf
Upstream fixes
The versions the CNA records as introducing and fixing this, and the commit for each. source
| Introduced | Fixed in | Commit |
|---|---|---|
| 5.15 | 6.6.158 | 5eaa11c500ed |
| 5.15 | 6.9.10 | 7aa5a19279c3 |
| 5.15 | 6.10 | a6fcd19d7eac |
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 vulnerability is reached by loading and running an attacker-authored BPF program via the bpf() syscall, which requires local access to the system. BPF is explicitly classified as a local attack vector in kernel scoring guidance.
- AC:LAttack complexity, low
- The UAF is deterministic and fully attacker-scripted: the BPF callback arms its own timer with a far-future expiry and then deletes its own map element, guaranteeing the freed-while-enqueued hrtimer; no race the attacker cannot control is involved, and the deadlock variant is likewise attacker-orchestrated across two CPUs.
- PR:LPrivileges required, low
- The bpf_timer_* helpers are gated by bpf_token_capable(CAP_BPF), which resolves to ns_capable() in a BPF-token user namespace, so an unprivileged user with a delegated bpffs token (common in container environments) can reach it. This matches established scoring for BPF verifier/helper CVEs.
- UI:NUser interaction, none
- The attacker loads and triggers the BPF timer entirely on their own; no victim action of any kind is needed.
- S:UScope, unchanged
- The freed object and the corrupted hrtimer state are both kernel-internal; the impact stays within the kernel's own security authority with no crossing into a hypervisor or IOMMU boundary.
- C:HConfidentiality impact, high
- The freed bpf_hrtimer remains linked in the per-CPU hrtimer rbtree, so the timer subsystem keeps reading from reallocated heap memory, and controlling the freed slot gives an attacker a reliable kernel-memory read primitive enabling arbitrary disclosure.
- I:HIntegrity impact, high
- Enqueue/rebalance operations write rb_node and expiry fields into the freed object, and __run_hrtimer() calls a function pointer fetched from that freed memory, yielding both arbitrary write and control-flow hijack primitives after a heap spray.
- A:HAvailability impact, high
- Both defects reliably take down the machine — the UAF corrupts the per-CPU hrtimer queue causing panics, and the mutual hrtimer_cancel() deadlock between two timer callbacks wedges CPUs in softirq context permanently.