CVE-2024-56687

Source
https://nvd.nist.gov/vuln/detail/CVE-2024-56687
Import Source
https://storage.googleapis.com/osv-test-cve-osv-conversion/osv-output/CVE-2024-56687.json
JSON Data
https://api.test.osv.dev/v1/vulns/CVE-2024-56687
Related
Published
2024-12-28T10:15:12Z
Modified
2025-01-11T13:53:23.787292Z
Summary
[none]
Details

In the Linux kernel, the following vulnerability has been resolved:

usb: musb: Fix hardware lockup on first Rx endpoint request

There is a possibility that a request's callback could be invoked from usbepqueue() (call trace below, supplemented with missing calls):

req->complete from usbgadgetgivebackrequest (drivers/usb/gadget/udc/core.c:999) usbgadgetgivebackrequest from musbggiveback (drivers/usb/musb/musbgadget.c:147) musbggiveback from rxstate (drivers/usb/musb/musbgadget.c:784) rxstate from musbeprestart (drivers/usb/musb/musbgadget.c:1169) musbeprestart from musbeprestartresumework (drivers/usb/musb/musbgadget.c:1176) musbeprestartresumework from musbqueueresumework (drivers/usb/musb/musbcore.c:2279) musbqueueresumework from musbgadgetqueue (drivers/usb/musb/musbgadget.c:1241) musbgadgetqueue from usbepqueue (drivers/usb/gadget/udc/core.c:300)

According to the docstring of usbepqueue(), this should not happen:

"Note that @req's ->complete() callback must never be called from within usbepqueue() as that can create deadlock situations."

In fact, a hardware lockup might occur in the following sequence:

  1. The gadget is initialized using musbgadgetenable().
  2. Meanwhile, a packet arrives, and the RXPKTRDY flag is set, raising an interrupt.
  3. If IRQs are enabled, the interrupt is handled, but musbgrx() finds an empty queue (next_request() returns NULL). The interrupt flag has already been cleared by the glue layer handler, but the RXPKTRDY flag remains set.
  4. The first request is enqueued using usbepqueue(), leading to the call of req->complete(), as shown in the call trace above.
  5. If the callback enables IRQs and another packet is waiting, step (3) repeats. The request queue is empty because usbggiveback() removes the request before invoking the callback.
  6. The endpoint remains locked up, as the interrupt triggered by hardware setting the RXPKTRDY flag has been handled, but the flag itself remains set.

For this scenario to occur, it is only necessary for IRQs to be enabled at some point during the complete callback. This happens with the USB Ethernet gadget, whose rxcomplete() callback calls netifrx(). If called in the task context, netifrx() disables the bottom halves (BHs). When the BHs are re-enabled, IRQs are also enabled to allow soft IRQs to be processed. The gadget itself is initialized at module load (or at boot if built-in), but the first request is enqueued when the network interface is brought up, triggering rxcomplete() in the task context via ioctl(). If a packet arrives while the interface is down, it can prevent the interface from receiving any further packets from the USB host.

The situation is quite complicated with many parties involved. This particular issue can be resolved in several possible ways:

  1. Ensure that callbacks never enable IRQs. This would be difficult to enforce, as discovering how netifrx() interacts with interrupts was already quite challenging and uether is not the only function driver. Similar "bugs" could be hidden in other drivers as well.
  2. Disable MUSB interrupts in musbggiveback() before calling the callback and re-enable them afterwars (by calling musb{dis,en}ableinterrupts(), for example). This would ensure that MUSB interrupts are not handled during the callback, even if IRQs are enabled. In fact, it would allow IRQs to be enabled when releasing the lock. However, this feels like an inelegant hack.
  3. Modify the interrupt handler to clear the RXPKTRDY flag if the request queue is empty. While this approach also feels like a hack, it wastes CPU time by attempting to handle incoming packets when the software is not ready to process them.
  4. Flush the Rx FIFO instead of calling rxstate() in musbeprestart(). This ensures that the hardware can receive packets when there is at least one request in the queue. Once I ---truncated---
References

Affected packages

Debian:12 / linux

Package

Name
linux
Purl
pkg:deb/debian/linux?arch=source

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
6.1.123-1

Affected versions

6.*

6.1.27-1
6.1.37-1
6.1.38-1
6.1.38-2~bpo11+1
6.1.38-2
6.1.38-3
6.1.38-4~bpo11+1
6.1.38-4
6.1.52-1
6.1.55-1~bpo11+1
6.1.55-1
6.1.64-1
6.1.66-1
6.1.67-1
6.1.69-1~bpo11+1
6.1.69-1
6.1.76-1~bpo11+1
6.1.76-1
6.1.82-1
6.1.85-1
6.1.90-1~bpo11+1
6.1.90-1
6.1.94-1~bpo11+1
6.1.94-1
6.1.98-1
6.1.99-1
6.1.106-1
6.1.106-2
6.1.106-3
6.1.112-1
6.1.115-1
6.1.119-1

Ecosystem specific

{
    "urgency": "not yet assigned"
}

Debian:13 / linux

Package

Name
linux
Purl
pkg:deb/debian/linux?arch=source

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
6.12.3-1

Affected versions

6.*

6.1.27-1
6.1.37-1
6.1.38-1
6.1.38-2~bpo11+1
6.1.38-2
6.1.38-3
6.1.38-4~bpo11+1
6.1.38-4
6.1.52-1
6.1.55-1~bpo11+1
6.1.55-1
6.1.64-1
6.1.66-1
6.1.67-1
6.1.69-1~bpo11+1
6.1.69-1
6.1.76-1~bpo11+1
6.1.76-1
6.1.82-1
6.1.85-1
6.1.90-1~bpo11+1
6.1.90-1
6.1.94-1~bpo11+1
6.1.94-1
6.1.98-1
6.1.99-1
6.1.106-1
6.1.106-2
6.1.106-3
6.1.112-1
6.1.115-1
6.1.119-1
6.1.123-1
6.3.1-1~exp1
6.3.2-1~exp1
6.3.4-1~exp1
6.3.5-1~exp1
6.3.7-1~bpo12+1
6.3.7-1
6.3.11-1
6.4~rc6-1~exp1
6.4~rc7-1~exp1
6.4.1-1~exp1
6.4.4-1~bpo12+1
6.4.4-1
6.4.4-2
6.4.4-3~bpo12+1
6.4.4-3
6.4.11-1
6.4.13-1
6.5~rc4-1~exp1
6.5~rc6-1~exp1
6.5~rc7-1~exp1
6.5.1-1~exp1
6.5.3-1~bpo12+1
6.5.3-1
6.5.6-1
6.5.8-1
6.5.10-1~bpo12+1
6.5.10-1
6.5.13-1
6.6.3-1~exp1
6.6.4-1~exp1
6.6.7-1~exp1
6.6.8-1
6.6.9-1
6.6.11-1
6.6.13-1~bpo12+1
6.6.13-1
6.6.15-1
6.6.15-2
6.7-1~exp1
6.7.1-1~exp1
6.7.4-1~exp1
6.7.7-1
6.7.9-1
6.7.9-2
6.7.12-1~bpo12+1
6.7.12-1
6.8.9-1
6.8.11-1
6.8.12-1~bpo12+1
6.8.12-1
6.9.2-1~exp1
6.9.7-1~bpo12+1
6.9.7-1
6.9.8-1
6.9.9-1
6.9.10-1~bpo12+1
6.9.10-1
6.9.11-1
6.9.12-1
6.10-1~exp1
6.10.1-1~exp1
6.10.3-1
6.10.4-1
6.10.6-1~bpo12+1
6.10.6-1
6.10.7-1
6.10.9-1
6.10.11-1~bpo12+1
6.10.11-1
6.10.12-1
6.11~rc4-1~exp1
6.11~rc5-1~exp1
6.11-1~exp1
6.11.2-1
6.11.4-1
6.11.5-1~bpo12+1
6.11.5-1
6.11.6-1
6.11.7-1
6.11.9-1
6.11.10-1~bpo12+1
6.11.10-1
6.12~rc6-1~exp1

Ecosystem specific

{
    "urgency": "not yet assigned"
}