CVE-2024-36894 in Linux
Summary
by MITRE • 05/30/2024
In the Linux kernel, the following vulnerability has been resolved:
usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
FFS based applications can utilize the aio_cancel() callback to dequeue pending USB requests submitted to the UDC. There is a scenario where the FFS application issues an AIO cancel call, while the UDC is handling a soft disconnect. For a DWC3 based implementation, the callstack looks like the following:
DWC3 Gadget FFS Application dwc3_gadget_soft_disconnect() ... --> dwc3_stop_active_transfers() --> dwc3_gadget_giveback(-ESHUTDOWN) --> ffs_epfile_async_io_complete() ffs_aio_cancel() --> usb_ep_free_request() --> usb_ep_dequeue()
There is currently no locking implemented between the AIO completion handler and AIO cancel, so the issue occurs if the completion routine is running in parallel to an AIO cancel call coming from the FFS application. As the completion call frees the USB request (io_data->req) the FFS application is also referencing it for the usb_ep_dequeue() call. This can lead to accessing a stale/hanging pointer.
commit b566d38857fc ("usb: gadget: f_fs: use io_data->status consistently") relocated the usb_ep_free_request() into ffs_epfile_async_io_complete(). However, in order to properly implement locking to mitigate this issue, the spinlock can't be added to ffs_epfile_async_io_complete(), as usb_ep_dequeue() (if successfully dequeuing a USB request) will call the function driver's completion handler in the same context. Hence, leading into a deadlock.
Fix this issue by moving the usb_ep_free_request() back to ffs_user_copy_worker(), and ensuring that it explicitly sets io_data->req to NULL after freeing it within the ffs->eps_lock. This resolves the race condition above, as the ffs_aio_cancel() routine will not continue attempting to dequeue a request that has already been freed, or the ffs_user_copy_work() not freeing the USB request until the AIO cancel is done referencing it.
This fix depends on commit b566d38857fc ("usb: gadget: f_fs: use io_data->status consistently")
Be aware that VulDB is the high quality source for vulnerability data.
Analysis
by VulDB Data Team • 08/28/2025
The vulnerability described in CVE-2024-36894 affects the Linux kernel's USB gadget framework, specifically within the function filesystem (FFS) implementation that handles asynchronous I/O operations. This issue manifests as a race condition between the aio_cancel() function and the AIO request completion handler in USB gadget drivers, particularly impacting DWC3-based USB implementations. The problem occurs when an FFS application attempts to cancel pending USB requests while the USB device controller is processing a soft disconnect event, creating a scenario where concurrent execution paths attempt to access the same USB request structure. According to CWE-362, this represents a classic race condition vulnerability where multiple threads or processes access shared resources without proper synchronization, potentially leading to memory corruption or undefined behavior.
The technical flaw stems from the improper handling of USB request lifecycle management during asynchronous I/O operations. When the DWC3 gadget driver processes a soft disconnect, it calls dwc3_stop_active_transfers() which eventually invokes ffs_epfile_async_io_complete() to complete pending AIO requests. However, the AIO cancel operation initiated by the FFS application concurrently calls usb_ep_dequeue() which attempts to access the same USB request structure that the completion handler is in the process of freeing. This conflict occurs because usb_ep_free_request() was moved to the completion handler in commit b566d38857fc, but no proper locking mechanism was implemented to coordinate access between these two execution paths. The vulnerability falls under ATT&CK technique T1059.007 for execution through system commands and T1566 for initial access via network services, as it could potentially be exploited to compromise system integrity through USB-based attack vectors.
The operational impact of this vulnerability extends beyond simple memory access violations to potentially enable privilege escalation or system instability within embedded Linux systems that rely heavily on USB gadget functionality. Systems utilizing USB gadget drivers for device emulation, such as USB OTG configurations, network adapters, or storage devices, could experience crashes or unpredictable behavior when concurrent AIO cancellation and completion operations occur. The race condition creates a scenario where freed memory structures are accessed, leading to potential information disclosure or denial of service conditions that could affect the entire USB subsystem. This vulnerability particularly impacts devices running Linux kernels with DWC3 USB controllers, which are commonly found in mobile devices, embedded systems, and IoT platforms where USB gadget functionality is critical for device operation and communication.
The fix implemented addresses the root cause by reverting the placement of usb_ep_free_request() back to the ffs_user_copy_worker() function while introducing proper locking mechanisms. The solution ensures that the USB request is freed within the context of ffs->eps_lock, preventing concurrent access between the completion handler and cancellation routines. By explicitly setting io_data->req to NULL after freeing the request within the locked section, the fix prevents the aio_cancel() routine from attempting to operate on a freed structure, while also ensuring that the completion handler does not access stale pointers. This approach avoids the potential deadlock scenario that would occur if spinlocks were added to the completion handler, since the completion handler might be invoked from within the usb_ep_dequeue() path, creating a circular dependency. The mitigation strategy aligns with security best practices for concurrent programming and follows the principle of least privilege by ensuring proper resource management and synchronization in kernel space operations. The fix requires careful coordination with the existing commit that standardized io_data->status handling, ensuring that the solution maintains backward compatibility while providing the necessary synchronization guarantees to prevent the race condition from occurring.