CVE-2026-64584: usb: gadget: f_midi: cancel pending IN work before freeing the midi object
In the Linux kernel, the following vulnerability has been resolved:
usb: gadget: fmidi: cancel pending IN work before freeing the midi object
The fmidi driver embeds a work item (midi->work) whose handler, fmidiinwork(), dereferences the enclosing struct fmidi through containerof(). This work is armed from two sites: fmidicomplete(), on a normal IN-endpoint completion, and fmidiintrigger(), on an ALSA rawmidi output-stream start.
Neither fmididisable() nor fmidiunbind() cancels midi->work. fmididisable() only disables the endpoints and drains the inreqfifo; it does not synchronize the work item, and the sound card is released asynchronously to the final free of the midi object.
The midi object is reference-counted (midi->freeref) and is freed in fmidifree() only once both the usbfunction reference and the rawmidi privatedata reference have been dropped. In fmidiunbind(), fmididisable() runs before the sound card is released, so while the USB endpoints are already disabled the rawmidi device is still usable by an open substream. A concurrent userspace write on such a substream can reach fmidiintrigger() and queue midi->work again after fmididisable() has returned. A work item armed this way may still be pending when the last reference drops and fmidifree() proceeds to kfree(midi), letting fmidiinwork() dereference the struct after it has been freed, a use-after-free.
For this reason cancelling midi->work in fmididisable() would not be sufficient: the ALSA trigger path can rearm the work after disable() returns. Cancelling at the refcount-zero free site is the boundary after which neither arming source can survive, because by then both references that keep the midi object alive have been dropped: the USB endpoints are already disabled and the rawmidi device has been released.
Fix this by calling cancelworksync(&midi->work) in the refcount-zero block of fmidifree(), before the embedded workstruct is freed along with the rest of the structure. opts->lock is a sleeping mutex, so calling cancelworksync() under it is permitted, and the handler takes midi->transmitlock rather than opts->lock, so no self-deadlock can occur while it waits for a running instance of the work to finish.
This issue was found by an in-house static analysis tool.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
Fix the use-after-free by synchronizing the embedded work item: in the refcount-zero free path for the f_midi object, call cancel_work_sync(&midi->work) so f_midi_in_work() cannot dereference the enclosing struct after kfree(midi). The resolution described is: “Neither f_midi_disable() nor f_midi_unbind() cancels midi->work … Fix this by calling cancel_work_sync(&midi->work) in the refcount-zero.”
Linux kernel USB gadget f_midi driver Work cancellation in f_midi_free()/disable path = Call cancel_work_sync(&midi->work) when refcount reaches zero before embedded work_struct is freed
Event History
Frequently Asked Questions
What is the severity of CVE-2026-64584?
CVE-2026-64584 has a risk score of 38, indicating it is a moderate threat.
How do I fix CVE-2026-64584?
To fix CVE-2026-64584, ensure you update your Linux kernel to the latest version where this vulnerability has been resolved.
What type of vulnerability is CVE-2026-64584?
CVE-2026-64584 is classified as a Use After Free vulnerability affecting the Linux kernel's f_midi driver.
What impact does CVE-2026-64584 have on systems?
CVE-2026-64584 may allow an attacker to exploit the f_midi driver through invalid memory access, potentially leading to system instability.
Is CVE-2026-64584 present in all Linux kernel versions?
CVE-2026-64584 is specific to certain versions of the Linux kernel that include the f_midi driver and may not be present in all versions.