CVE-2022-49299 - Linux Kernel usb:dwc2 Gadget Vulnerability Explained
A vulnerability identified as CVE-2022-49299 was found and fixed in the Linux kernel's dwc2 USB gadget driver. This bug occurred because the driver was incorrectly resetting an internal field (driver->bus) inside the USB gadget structure. This mistake became critical after the USB gadget subsystem got its own bus system, leading to dangerous NULL pointer dereferences and kernel crashes on affected devices.
In this post, we'll explain how the vulnerability happened, show the exploit details, and walk through the patch that fixed it.
What Happened? The Technical Root
The Linux USB gadget framework lets your device act as a USB device (e.g., mass storage, network). Gadget drivers plug into this system. The Dual Role Controller (dwc2) is a specific USB controller driver used by many embedded systems (e.g., Samsung's Exynos SoC).
The bug: the dwc2 gadget code manipulated the gadget subsystem's internal pointer:
driver->bus
This is not something a USB controller driver should touch–it’s owned by the higher-level gadget core code.
Why didn’t it break before?
Historically, gadget drivers and buses were less strictly isolated. But, after commit fc274c1e9973 ("USB: gadget: Add a new bus for gadgets"), gadgets were organized behind a proper bus subsystem.
With this change, if the dwc2 code resets driver->bus, it risks making it NULL where core gadget code expects a valid pointer.
This resulted in kernel NULL pointer dereferences and system crashes during driver loading.
Suppose you load a gadget driver like g_ether on a Samsung Exynos device. You might see this crash
dwc2 12480000.hsotg: bound driver g_ether
8<--- cut here ---
Unable to handle kernel NULL pointer dereference at virtual address 00000000
[00000000] *pgd=00000000
Internal error: Oops: 5 [#1] SMP ARM
Modules linked in: ...
CPU: PID: 620 Comm: modprobe Not tainted 5.18.-rc5-next-20220504 #11862
Hardware name: Samsung Exynos (Flattened Device Tree)
PC is at module_add_driver+x44/xe8
...
dwc2 12480000.hsotg: new device is high-speed
---[ end trace 000000000000000 ]---
What went wrong:
The kernel code dereferenced a NULL pointer while trying to add the driver to its bus during probe/binding. The bus pointer had been reset unexpectedly by the UDC (dwc2) driver.
Here's an *approximate* snippet of the vulnerable logic
static int dwc2_udc_remove(struct platform_device *pdev)
{
if (udc->gadget.driver) {
// BAD: This resets gadget core internals!
udc->gadget.driver->bus = NULL;
udc->gadget.driver = NULL;
}
...
}
After the gadget subsystem rework, this line
udc->gadget.driver->bus = NULL;
meant that the gadget didn't know which USB bus it belonged to anymore, causing failures anywhere that pointer was needed.
Patched code
static int dwc2_udc_remove(struct platform_device *pdev)
{
if (udc->gadget.driver) {
// DON'T touch gadget core's internal bus pointer!
// udc->gadget.driver->bus = NULL; <-- REMOVED
udc->gadget.driver = NULL;
}
...
}
Summary:
*The UDC (controller) driver should never modify driver->bus. Only the USB gadget core is responsible for it.*
Local Exploitation:
An attacker with the ability to load gadget modules (for example, via modprobe g_ether) could trigger a kernel crash, causing Denial-of-Service (DoS).
Remote Exploitation:
Not possible, unless somehow remote users can control which USB gadget is loaded (unlikely, but possible in some weird setups).
Platforms Affected:
ARM devices using the dwc2 controller (Samsung Exynos, some Broadcom SoCs, and others)
- Linux kernels after the gadget bus rework (commit fc274c1e9973) and before the fix.
Checking If You're Affected
1. Check your kernel version:
If you’re on Linux 5.18-rc5 next and earlier, especially on ARM platforms, you might be vulnerable.
2. Are you using dwc2 for USB device mode?
If your hardware has this controller and you’re using gadget functionality (USB device), check if your vendor kernel includes the fix.
3. Test by loading a gadget module:
If you can, try this only on non-mission-critical devices
sudo modprobe g_ether # or g_mass_storage
If you observe a kernel crash or oops similar to the one above, you’re likely affected.
## How to Patch / Mitigation
- Update your kernel to include the fix, which is committed upstream (May 2022).
References
- Linux kernel commit fixing CVE-2022-49299
- Commit "USB: gadget: Add a new bus for gadgets"
- CVE-2022-49299 at cve.org
- dwc2 UDC driver upstream source
Conclusion
CVE-2022-49299 is a good example of how subtle Linux kernel API changes can make legacy code suddenly unsafe. Never touch subsystem internal pointers unless the API *specifically* says you can! If you use USB gadget mode on ARM (or any platform with dwc2), make sure you have this patch to avoid nasty crashes.
Timeline
Published on: 02/26/2025 07:01:06 UTC
Last modified on: 04/14/2025 19:49:30 UTC