Recently, a critical bug in the Linux kernel's clock framework has been identified and fixed. Labeled as CVE-2024-27038, this vulnerability exposes systems using affected Linux kernels to potential crashes due to a NULL pointer dereference in the clk_core_get function.
This post breaks down what happened, why it’s risky, how it was fixed, and all the technical details you need to understand this kernel issue.
👾 What is CVE-2024-27038?
The Linux kernel manages hardware clocks using various "clk" (clock) APIs. The function clk_core_get() is central to this subsystem. Due to improper error handling, the kernel could try to access memory through a NULL pointer, causing the system to crash or, in some user scenarios, be open to further exploitation.
It all comes down to this code path
clk_core_get()
of_clk_get_hw_from_clkspec()
__of_clk_get_hw_from_provider()
__clk_get_hw() // <-- can return NULL
In the above call chain, __clk_get_hw() can return NULL. If it does, clk_core_get() will attempt to dereference hw->core, leading to a kernel panic or Oops.
Originally, there was a safeguard check
if (IS_ERR_OR_NULL(hw))
return NULL;
This would catch both error pointers _and_ NULL before dereferencing. But after changes introduced in commit dde4eff47c82 ("clk: Look for parents with clkdev based clk_lookups"), this check was dropped:
core = hw->core;
If hw is actually NULL, this line will crash the kernel.
#### Real-world impact:
- Any driver/subsystem calling clk_core_get() with an unresolved clock description could potentially crash the system.
- This is a local denial of service vulnerability: it doesn't lead to privilege escalation or arbitrary code execution, but could be exploited by local users or misconfigured device trees.
---
## 💣 Exploit Example
Below is a minimal example showing how a faulty or missing clock configuration in a device tree could lead to a NULL pointer dereference, triggering this bug.
Exploit scenario:
1. A device tree node tries to request a clock that doesn't exist.
2. The kernel code hits clk_core_get() via a driver.
3. __clk_get_hw() returns NULL.
4. Kernel dereferences hw->core. System crash.
Crashing the kernel (pseudocode):
c
// Suppose this is in a driver probe function
struct clk *clk;
clk = devm_clk_get(dev, "bogus-clock");
if (IS_ERR(clk)) {
return PTR_ERR(clk);
}
// If clk is returned as NULL, leading to later use …
If the driver's error handling is not robust, and the kernel didn’t do the right check in clk_core_get(), a NULL pointer dereference occurs at a low level.
Kernel panic snippet (simulated log):
BUG: kernel NULL pointer dereference, address: 000000000000000
...
IP: clk_core_get+x20/x60
---
## 🛠️ The Fix
The fix simply restores proper error checking before dereferencing the pointer:
### Before (vulnerable):
c
struct clk_core *clk_core_get(...) {
hw = __clk_get_hw(...);
core = hw->core; // <-- CRASHES if hw is NULL!
...
}
### After (patched):
c
struct clk_core *clk_core_get(...) {
if (!hw)
return NULL; // Safely bail out
...
}
`
Commit Link:
- clk: fix clk_core_get NULL dereference
Upstream fix included in:
- Linux mainline after June 2024 (check your distro for backports!)
---
## 🛡️ How to Stay Safe
- Check your distribution’s kernel changelog! Make sure the fix for CVE-2024-27038 is included.
- Update kernels on embedded and server systems if you use device trees and custom clocks.
- Review device tree source files to ensure all required clocks are properly defined.
---
## 📚 References
- CVE-2024-27038 at NVD
- Upstream commit fix
- Linux kernel clock documentation
- Related changes: clk: Look for parents with clkdev based clk_lookups
---
## 📝 Summary
CVE-2024-27038 is a classic lesson in the importance of defensive programming in the kernel. Even the smallest oversight — forgetting to check for NULL — can lead to system-wide crashes.
Keep your kernels patched, and always double-check pointers! 🐧💻
---
Please share this post to help others stay secure!
Timeline
Published on: 05/01/2024 13:15:49 UTC
Last modified on: 12/23/2024 14:11:28 UTC