In the Linux kernel, the following vulnerability has been resolved:
usb: gadget: f_midi: 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 fmidiin_trigger(), 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 fmidiin_work() 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.
{
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/64xxx/CVE-2026-64584.json",
"cna_assigner": "Linux"
}