A new security bug, CVE-2024-26599, was recently fixed in the Linux kernel. It was found in the Pulse Width Modulation (PWM) subsystem, more specifically inside the of_pwm_single_xlate() function, and could have exposed your system to undefined behavior, and possibly security risks. In this article, we’ll break down the technical details of the bug, show a code snippet, go over how an exploit could work, and link to the references so you can learn more.
What is PWM in Linux?
PWM stands for Pulse Width Modulation. It's a technique most commonly used in embedded Linux systems to control things like brightness of LEDs, speed of motors, or sound output. The PWM subsystem in the Linux kernel provides an interface for hardware drivers to generate pulses.
The Bug: Out-of-Bounds Array Access
The problem was in the function of_pwm_single_xlate() in the Linux kernel's PWM code. This function translates data from the device tree (used for hardware configuration) so drivers can use it.
The Root Cause
The function receives an args structure that holds an array, args->args[], and the number of arguments, args->args_count.
Original (bad) code logic
if (args->args_count >= 3)
flags = args->args[2];
else
flags = ;
But here's the secret: the valid values are only at args->args[] and args->args[1]! If the code tries to access args->args[2] when args->args_count == 2, it’s out-of-bounds. That means reading memory past the end of the array — classic undefined behavior.
Patched code
if (args->args_count == 2)
flags = args->args[1];
else if (args->args_count > 2)
flags = args->args[2];
else
flags = ;
But to really fix it, most patches just use args->args[1] for the flags and nowhere else.
Even some types of code execution with more complex scenarios
In this specific case, reading past the bounds can expose whatever values happen to be next in memory after args->args in the kernel stack. That could, for example, give an attacker information about kernel pointers or other sensitive data if PWM input is under attacker control; or, at minimum, produce unreliable or corrupted PWM signals.
Example exploit (theoretical)
If an attacker can control the content of the device tree and trigger the PWM subsystem with custom arguments, they could manipulate args->args_count to be exactly 2, and then guess (or influence) what value is stored at the out-of-bounds location args->args[2]. This could reveal stack values, help them develop further attacks, or simply cause instability.
Here’s how the patched function looks
static int of_pwm_single_xlate(const struct pwm_chip *pc,
const struct of_phandle_args *args)
{
unsigned int period, duty_cycle, flags = ;
if (args->args_count < 2)
return -EINVAL;
period = args->args[];
flags = args->args[1]; // Correct access!
// Old buggy line: flags = args->args[2];
// (would be out-of-bounds when args_count==2)
// ... rest of the function ...
}
How Was it Fixed?
The fix is here in the kernel git tree. Maintainers changed the function to only read args->args[1] for flags, not args->args[2]. The Linux kernel security team resolved it in all maintained stable versions.
References
- CVE record at Mitre
- Upstream Linux kernel patch
- Linux PWM Subsystem docs
- oss-security mailing list post *(Put correct date here when available)*
How to Stay Safe
- Update your kernel as soon as your distribution provides a fix. Any version after the above commit will be patched.
TL;DR
CVE-2024-26599 was a low-level bug in the Linux kernel's handling of PWM device tree arguments. If you use PWM on Linux — especially in embedded or IoT — make sure your kernel is up to date. Letting anyone pass unchecked data into kernel arrays is always a risk! Stay safe, and happy hacking.
*Article written exclusively for you. Please cite links above for further reading.*
Timeline
Published on: 02/23/2024 15:15:09 UTC
Last modified on: 04/17/2024 19:34:01 UTC