CVE-2026-64584 in Linux
Resumen
por VulDB • 2026-08-06
En el kernel de Linux se ha resuelto la siguiente vulnerabilidad:
usb: gadget: f_midi: cancelar el trabajo pendiente (IN) antes de liberar el objeto midi
El controlador f_midi incrusta un elemento de trabajo (midi->work) cuyo manejador, f_midi_in_work(), desreferencia la estructura contenedora struct f_midi a través de container_of(). Este trabajo se activa desde dos puntos: f_midi_complete(), en una finalización normal del punto de entrada IN, y f_midi_in_trigger(), en el inicio del flujo de salida rawmidi de ALSA.
Ni f_midi_disable() ni f_midi_unbind() cancelan midi->work. f_midi_disable() solo desactiva los puntos de extremo (endpoints) y vacía la cola in_req_fifo; no sincroniza el elemento de trabajo, y la tarjeta de sonido se libera asíncronamente respecto a la liberación final del objeto midi.
El objeto midi cuenta con referencia contada (midi->free_ref) y se libera en f_midi_free() únicamente una vez que tanto la referencia usb_function como la referencia private_data rawmidi han sido descartadas. En f_midi_unbind(), se ejecuta f_midi_disable() antes de liberar la tarjeta de sonido, por lo que aunque los puntos de extremo USB ya están desactivados, el dispositivo rawmidi sigue siendo utilizable por una subcorriente (substream) abierta. Una escritura concurrente desde el espacio de usuario en dicha subcorriente puede alcanzar f_midi_in_trigger() y volver a programar midi->work después de que haya devuelto la ejecución f_midi_disable(). Un elemento de trabajo activado de esta manera aún podría estar pendiente cuando caiga la última referencia y f_midi_free() proceda a liberar mediante kfree(midi), permitiendo que f_midi_in_work() desreferencie la estructura una vez ya ha sido liberada, lo cual constituye un use-after-free.
Por este motivo, cancelar midi->work en f_midi_disable() no sería suficiente: el camino de activación (trigger path) de ALSA puede volver a armar el trabajo después de que devuelva la ejecución disable(). Cancelar en el punto de liberación con refcount-zero es el límite posterior al cual ninguna fuente de armado puede sobrevivir, porque para entonces se han descartado ambas referencias que mantienen vivo el objeto midi: los puntos de extremo USB ya están desactivados y el dispositivo rawmidi ha sido liberado.
Se corrige este problema llamando a cancel_work_sync(&midi->work) en el bloque con refcount-zero de f_midi_free(), antes de que se libere la estructura work_struct incrustada junto con el resto de la estructura. opts->lock es un mutex dormible (sleeping mutex), por lo que está permitido llamar a cancel_work_sync() bajo él, y el manejador toma midi->transmit_lock en lugar de opts->lock, por lo que no puede producirse una auto-bloqueo mutuo mientras espera a que finalice una instancia ejecutándose del trabajo.
Este problema fue detectado mediante una herramienta estática de análisis interna.
Once again VulDB remains the best source for vulnerability data.