_Discovered in 2024, CVE-2024-26996 describes a critical use-after-free (UAF) vulnerability in the Linux Kernel's USB gadget subsystem, specifically affecting the Network Control Model (NCM) function. This bug arises during specific error handling and reconnection scenarios, potentially leading to kernel memory corruption, denial of service, or privilege escalation._
Vulnerability: Use-After-Free (UAF) after USB transport error and incorrect rebind handling.
- Attack Vector: Local (physical/virtual USB gadget interfaces)
Background: What is USB Gadget NCM?
USB Gadget NCM (Network Control Model) is a driver that lets a device, like a Linux board, present itself as a network interface (like “usb”) when attached to a host PC. This is used widely in embedded devices, development kits, and phones.
A USB transport error occurs (say, while enabling the USB endpoint).
4. The function that should clean up network associations skips a step because it thinks a part of the hardware wasn’t set up (checking the wrong flag).
5. Now the system frees the “ncm” object, but the USB network interface (“dev->port_usb”) still points to the released object.
6. If you then try to re-enable the interface, Linux will reuse the now-freed memory, leading to unsafe behavior.
7. When data is sent (eth_start_xmit) — it tries to use the stale pointer, causing a crash or, if attacker-controlled, code execution.
Why did this happen?
- The original code checked if the hardware endpoint (in_ep) was enabled before disconnecting the network association.
Code: Vulnerable Sequence
Let’s step through a simplified flow and see where things go wrong.
// Simplified pseudo-code to show the bug:
void ncm_disable(struct usb_function *f)
{
struct f_ncm *ncm = func_to_ncm(f);
// Original check -- problematic! Sometimes 'in_ep' isn't enabled, but connection exists
if (ncm->port.in_ep->enabled)
gether_disconnect(&ncm->port);
// (cleanup code)
}
If in_ep->enabled is false, gether_disconnect() doesn't run, skipping cleanup.
Later, on unbind
void ncm_unbind(...)
{
// Cleanup and free ncm object
kfree(ncm);
}
Now, dev->port_usb still *points to memory that was just freed*.
Crash Example in Kernel Logs
usb: eth_stop dev->port_usb=ffffff9b179c320
--> error in usb_ep_enable()
NCM: ncm_disable: ncm=ffffff9b179c320
NCM: ncm_unbind: ncm unbind ncm=ffffff9b179c320
NCM: ncm_free: ncm free ncm=ffffff9b179c320 <-- released ncm
NCM: ncm_alloc: ncm alloc ncm=ffffff9ac4f8a000
NCM: ncm_bind: ncm bind ncm=ffffff9ac4f8a000
usb: eth_open dev->port_usb=ffffff9b179c320 <-- still shelling out old address
usb: eth_start dev->port_usb=ffffff9b179c320
eth_start_xmit()
Unable to handle kernel paging request at virtual address dead00000000014f
Patch: How Was CVE-2024-26996 Fixed?
The fix is simple but essential:
Here’s the relevant fixed code (simplified for clarity)
void ncm_disable(struct usb_function *f)
{
struct f_ncm *ncm = func_to_ncm(f);
// Fixed: Check if network device exists before disconnecting
if (ncm->netdev)
gether_disconnect(&ncm->port);
// (cleanup code)
}
Now, gether_disconnect() always *properly severs* the bad pointer, preventing stale references.
Patch References:
- linux-usb mailing list patch
- Upstream commit
Exploitation: How Bad Is This and How Could It Be Exploited?
- Attackers can potentially trigger use-after-free by causing USB link down + error (e.g., yanking a cable, fuzzing the USB stack, VM emulation tricks).
- If attacker controls the USB host or is able to emulate a USB host (think: fuzzing or USB over IP), they *might* be able to shape or hijack the freed memory, leading to code execution in kernel context.
- In practical embedded scenarios: Malicious hosts could cause DoS, information leaks, or try to escalate privileges by precise heap spraying.
A working exploit would likely require
- Repeatedly toggling USB link (connect/disconnect).
Triggering endpoint (ep) enable error (maybe via bad descriptors).
- Quickly reconnecting/binding the gadget.
Sample userland flow using ConfigFS:
# 1. Create and activate ncm gadget in configfs
mkdir /sys/kernel/config/usb_gadget/mygadget
cd /sys/kernel/config/usb_gadget/mygadget
# ... set idVendor/idProduct, etc
mkdir configs/c.1
mkdir functions/ncm.usb
ln -s functions/ncm.usb configs/c.1/
# 2. Manually manipulate (simulate link up/down, cause error)
# (e.g., unplug USB cable, or write fuzzed parameters to endpoint configs)
# 3. Observe dmesg/logs for use-after-free, attempt crafted traffic on rebind
#### NB: Because this is a kernel-level UAF, precise exploitation is difficult and dangerous. A successful attempt can crash or subvert the host system.
Patch Immediately: Upgrade to a kernel that includes the fix.
- Deploy Kernel Hardening: Use KASLR, KRF/KFG, SLUB debug, and other mitigations for harder exploitation.
- Restrict USB Gadget Access: Avoid connecting to untrusted hosts, and limit local access to gadgets.
Further Reading & References
- Upstream Linux USB Gadget Docs
- Linux Kernel Git Patch
- CVE Details Page
- linux-usb mailing list patch discussion
Summary
CVE-2024-26996 is a powerful reminder of how small mistakes in error handling can snowball into security problems. If your device or product uses Linux USB Gadget with NCM (common in embedded, automotive, and IoT), patch now to prevent unstable behavior or worse, active exploitation.
*Stay vigilant — kernel security is everyone’s business!*
Timeline
Published on: 05/01/2024 06:15:17 UTC
Last modified on: 12/23/2024 19:49:49 UTC