Linux Kernel vulnerabilities are critical—as millions of computers and devices depend on its stability. Recently, a flaw in the oxu_bus_suspend() function in the USB host driver was discovered. This post will walk you through what happened, why it’s dangerous, how the fix works, and, finally, what you need to do.
What Is CVE-2022-49313?
CVE-2022-49313 is a deadlock vulnerability found in certain Linux kernel versions in the drivers/usb/host/ subsystem, specifically in the oxu_bus_suspend() function. The issue could cause systems to become unresponsive when suspending the USB bus—brought on by a lock contention between the suspend and timer handler code paths.
Deadlock Race Diagram
(Thread 1) | (Thread 2)
oxu_bus_suspend() | timer_action()
spin_lock_irq() // (1) | mod_timer()
... | (wait for timer)
del_timer_sync() | oxu_watchdog()
(wait for timer to stop) | spin_lock_irq() // (2)
| ...
- Thread 1 (oxu_bus_suspend) locks oxu->lock, then calls del_timer_sync(), waiting for the timer handler to finish.
- But, if the timer is running, its handler (oxu_watchdog) needs the same lock (oxu->lock) to finish.
- Result: oxu_bus_suspend is waiting for the timer to release, but the timer handler can’t run because it can’t get the lock. Both are stuck — deadlock!
Here’s an example inspired by the real bug (simplified for clarity)
// oxu_bus_suspend: tries to suspend the bus
spin_lock_irq(&oxu->lock);
// ... other suspend logic ...
del_timer_sync(&oxu->timer); // <<--- waits for timer, still holding lock!
spin_unlock_irq(&oxu->lock);
Versus what could happen in the timer handler
// oxu_watchdog (timer handler)
spin_lock_irq(&oxu->lock);
// ... timer work ...
spin_unlock_irq(&oxu->lock);
With this order, del_timer_sync waits for the timer, but the timer can’t proceed because it can’t get the lock!
The Patch: How Was It Fixed?
The fix is simple but effective: move del_timer_sync() outside the locked section. This way, when waiting for the timer, the lock isn’t held, so the timer handler can finish.
Fixed Code Example
spin_lock_irq(&oxu->lock);
// ... (do what’s needed) ...
spin_unlock_irq(&oxu->lock);
del_timer_sync(&oxu->timer); // SAFE: lock not held
- Now, del_timer_sync() can confidently wait for the timer to finish, knowing the timer handler can get the lock.
Patch reference
- Kernel.org commit: drivers: usb: host: Fix deadlock in oxu_bus_suspend()
- NVD entry for CVE-2022-49313
- Original patch on lore.kernel.org
Exploiting the Vulnerability
Is it exploitable?
This bug is considered a denial-of-service risk. Any process or event that can trigger a USB bus suspend (such as a system suspend, device removal, or code triggering that path) could cause a system hang if the stars align and the timer is pending.
How could someone demonstrate it?
A simplified pseudocode exploit—just for understanding, actual exploitation depends on kernel versions and device context:
// In userspace, trigger suspend via sysfs or device API
system("echo suspend > /sys/bus/usb/devices/usbX/power/control");
// Or remove a device or put system to sleep externally
If the timer (oxu_watchdog) is pending, and the kernel is not patched, the system could freeze.
Takeaway:
- Even if not a remote code execution flaw, system hangs are critical, especially in embedded, server, or high-availability environments.
What Should You Do?
- Check Your Kernel Version: This bug affects certain Linux kernel series with the oxu USB host controller code.
References and More Information
- Linux kernel source code
- Original patch discussion on lore.kernel.org
- CVE-2022-49313 NVD entry
- Commit diff on kernel.org
Final Thoughts
CVE-2022-49313 is a great example of how complex locking and timing in kernel code can lead to deadly bugs—even with simple mistakes. Thankfully, the Linux community is quick to patch such incidents. As always, stay up to date and keep your systems safe!
If you want a deeper look at USB subsystem vulnerabilities or kernel race conditions, let me know in the comments.
Timeline
Published on: 02/26/2025 07:01:08 UTC
Last modified on: 04/14/2025 19:59:26 UTC