GHSA-pp5m-jr2h-qp3f: Use-after-free in the MCTP over USB binding when the host disables the class while RX parsing is in progress
The MCTP over USB device class in subsys/pmci/mctp/mctpusb.c splits RX handling across two threads: the system workqueue runs mctpusbclassoutwork(), which parses host OUT data byte by byte and fills a packet buffer at usb->rxpkt, while the USB device stack thread runs mctpusbclassdisable(). The disable handler used kworkcancel(), which removes a queued work item but returns immediately without waiting for a handler that is already running, and then called mctpusbresetrxstate() to mctppktbuffree() the packet buffer the worker may still be using.
Both entry points into mctpusbclassdisable() are driven by the attached USB host: a SETCONFIGURATION request and a USB bus reset both reach it via usbdconfigreset() in subsys/usb/devicenext/usbdconfig.c. A host that streams partial MCTP frames on the bulk OUT endpoint and repeatedly forces a configuration change or bus reset therefore controls both the data being parsed and the moment the teardown runs, and can retry the race indefinitely without credentials or user interaction.
If the free lands while the worker holds the pointer, the worker writes host-supplied bytes into freed memory of the dedicated MCTP heap (CONFIGMCTPHEAPSIZE in subsys/pmci/mctp/mctpmemory.c), corrupting recycled buffers or sysheap free-block metadata; this window requires genuine parallelism, i.e. CONFIGSMP or a preemptible CONFIGSYSTEMWORKQUEUEPRIORITY. With the default cooperative workqueue the worker can still yield inside mctpbusrx() (application callback or a control-message reply blocking in mctpusbtx()), after which it resumes and calls mctppktbuffree(usb->rxpkt) on a pointer the teardown has NULLed, dereferencing NULL and faulting on targets with null-pointer detection.
The fix replaces the cancel with kworkcancelsync() plus a new struct kworksync outworksync, so disable waits for the RX worker to finish before draining the FIFO and freeing the packet buffer. The affected code is the MCTP subsystem, which is marked experimental, built only with CONFIGMCTPUSB.
Event History
Frequently Asked Questions
Who is exposed to this issue?
Devices using the MCTP over USB device class are exposed when connected to a USB host that can send bulk OUT traffic and trigger USB configuration changes or bus resets. The host does not need credentials or user interaction.
What does an attacker need to do to exploit the race?
An attacker needs to stream partial MCTP frames to the bulk OUT endpoint while repeatedly causing a SET_CONFIGURATION request or USB bus reset. This controls both the data being parsed and the timing of RX-state teardown, and the race can be retried indefinitely.
What is the likely impact if the race succeeds?
The RX worker can write host-supplied bytes into memory that has been freed from the dedicated MCTP heap. The provided severity vector indicates no confidentiality impact, low integrity impact, and high availability impact.
How can an affected device be identified?
Check whether the device enables the MCTP over USB device class implemented in subsys/pmci/mctp/mctp_usb.c. The vulnerable behavior involves mctp_usb_class_disable() cancelling RX work with k_work_cancel() and freeing the RX packet buffer while the work handler may still be running.