CVE-2024-26995 - Linux Kernel USB Type-C pd_set Off-By-One Overflow Vulnerability Explained
In the world of Linux kernel security, even the smallest code mistake can have big effects. Today, we’ll break down CVE-2024-26995, a vulnerability in the USB Type-C Port Controller Manager (tcpm), explain how it happened, show you the code, and help you understand why it’s a risk to your devices.
What is CVE-2024-26995?
CVE-2024-26995 is a vulnerability in the Linux kernel’s USB Type-C tcpm driver, uncovered and patched in early 2024. It involves an off-by-one error in handling PDO (Power Data Object) counting during USB Power Delivery (PD) negotiation, which could lead to wrong power contracts such as overvoltage or overcurrent situations. In simpler words, because of a small counting mistake, a device could try to draw or deliver the wrong kind of power — not ideal for sensitive electronics.
Affected Component:
drivers/usb/typec/tcpm/tcpm.c in the Linux kernel
Technical Details (Explained Simply)
During PD negotiation (when two USB-C devices agree on how much power to send), the tcpm driver keeps track of the number of PDOs — these are basically descriptions of available power options (like “I can send 5V/3A”).
The code counted the number of these objects by incrementing the loop variable one extra time, causing it to sometimes claim one more power profile than really available.
Negotiating a power profile that isn’t really supported
- Sending the wrong "Request Data Object" (RDO), resulting in overcurrent/overvoltage
Here’s an excerpt showing the off-by-one problem (simplified for clarity)
unsigned int nr_snk_pdo = ;
for (i = ; i < ARRAY_SIZE(snk_pdo); i++) {
if (local_snk_pdo[i] == )
break;
snk_pdo[i] = local_snk_pdo[i];
}
nr_snk_pdo = i + 1; // Off-by-one! Should just be i.
The Patch
The fix is simple: Don’t add one to the index! The loop variable already represents the right count after leaving the loop.
Fixed Version
unsigned int nr_snk_pdo = ;
for (i = ; i < ARRAY_SIZE(snk_pdo); i++) {
if (local_snk_pdo[i] == )
break;
snk_pdo[i] = local_snk_pdo[i];
}
nr_snk_pdo = i; // Correct: no "+ 1"
Exploit Details: What Could Go Wrong?
If an attacker can influence the kernel’s power negotiation (for example by connecting a malicious USB PD device), they might:
Potentially leverage this as part of a chain for further attacks
This is mostly a problem for physical attacks (plugging in a tricky device), but the consequences can be serious for laptops, phones, or any device using USB-C PD with Linux.
How Was This Found and Fixed?
The issue was found by USB/Type-C developers and patched with this commit:
> usb: typec: tcpm: Correct the PDO counting in pd_set
>
> Off-by-one errors happen because nr_snk_pdo and nr_src_pdo are incorrectly added one. [...] This could potentially cause over current or port resets.
See the patch here:
linux.git commit df32e08
Ubuntu, Fedora, and other major distributions have rolled out fixes as of March-April 2024.
Should I Worry?
- If you use a Linux device with USB-C Power Delivery (laptops, tablets, devboards): update your kernel as soon as your distro provides a patch
References
- CVE Record - CVE-2024-26995
- Linux kernel git commit df32e08
- USB Power Delivery Specification Overview (USB.org)
- LWN.net coverage of Type-C/PD kernel changes
Conclusion
CVE-2024-26995 shows that tiny off-by-one errors can lead to real power problems! If you’re maintaining or deploying Linux systems, always monitor kernel security updates — especially for low-level drivers like USB PD. Luckily, the fix is easy and patches are available.
Stay safe, keep your systems up to date, and be careful what you plug in.
*Authored for educational purposes — do not attempt to exploit or abuse this or similar vulnerabilities!*
Timeline
Published on: 05/01/2024 06:15:17 UTC
Last modified on: 12/23/2024 19:49:22 UTC