Vendor: DENX Software Engineering Vendor URL: https://www.denx.de/wiki/U-Boot Versions affected: v2012.10-rc1 to v2023.01-rc1 Systems Affected: All systems with CONFIG_DFU_OVER_USB or CONFIG_SPL_DFU enabled Author: <Sultan Qasim Khan> <sultan.qasimkhan[at]nccgroup[dot]com> CVE Identifier: CVE-2022-2347 Risk: High 7.1 (CVSS:3.1/AV:P/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H)
U-Boot is a popular and feature-rich bootloader for embedded systems. It includes optional support for the USB Device Firmware Update (DFU) protocol, which can be used by devices to download new firmware, or upload their current firmware.
The U-Boot DFU implementation does not bound the length field in USB DFU download setup packets, and it does not verify that the transfer direction corresponds to the specified command. Consequently, if a physical attacker crafts a USB DFU download setup packet with a
wLength greater than 4096 bytes, they can write beyond the heap-allocated request buffer. It is also possible to read its content (and beyond it) if the direction bit for the setup packet indicates a device to host direction.
Functions: dfu_handle, state_dfu_idle, state_dfu_dnload_idle, handle_dnload
Data beyond the heap-allocated req->buf buffer may be corrupted or read by a connected USB host when a device running U-Boot is in DFU mode. This may enable a malicious host to gain code execution on the device running U-Boot or read sensitive data from the device.
USB DFU setup packets are handled by the
dfu_handle function. The DFU command is specified by the
ctrl->bRequest field, and the transfer direction for the data phase is specified by the direction bit
ctrl->bRequestType & USB_DIR_IN. The
dfu_handle function calls state-specific handlers such as
state_dfu_dnload_idle, and uses the value returned by the state handler as the length for the data phase of the transfer. The buffer that will be written to or read from in the data phase of the transfer is
req->buf, which is heap allocated as 4096 (
USB_BUFSIZ) bytes in
The request structure that is set up is then queued with the USB controller driver via a call to
usb_ep_queue. There are several USB controllers supported by U-Boot, such as the popular Designware DWC2 whose support is implemented in
drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c. These drivers are unaware of the allocated size for the request buffer (
req->buf), and assume the supplied length field (
req->length) is safe for the allocated buffer.
The DFU state handlers which support the download command (
state_dfu_dnload_idle) return the value returned by
USB_REQ_DFU_DNLOAD. No checking of the transfer direction is performed; DFU download requests are assumed to always be OUT transfers (host to device). However, a malicious or compromised host could issue a download request setup packet with the
USB_DIR_IN bit set (device to host). A DFU download request with the
USB_DIR_IN bit set would cause data in
req->buf to be sent to the host, rather than filling the buffer with data received from the host. Likewise, there no checks to verify that DFU upload operations are USB IN transfers.
handle_dnload function simply returns the length argument passed to it without any bounds checking. Both state handlers that call
handle_dnload pass it the
wLength field of the setup packet without any bounds checks. Consequently, a malicious host that sends a DFU setup packet with a length longer than 4096 bytes would result in a read or write beyond
req->buf. The DFU functional descriptor does declare a maximum
DFU_USB_BUFSIZ (4096 bytes), and compliant hosts would abide by not sending setup packets specifying lengths longer than this. However, a malicious or non-compliant host may send a DFU setup packet for a transfer longer than this.
Limit USB transfer lengths to a maximum of
DFU_USB_BUFSIZ before adding them to the endpoint transfer queue in
dfu_handle. In every DFU setup packet handler, also verify that the direction bit
ctrl->bRequestType & USB_DIR_IN matches the request type (such as upload or download).
- Feb 27, 2022 – Initial disclosure to security at denx.de – there was no response from this email address.
- April 30, 2022 – Follow up email sent to security at denx.de after 60 days to confirm receipt of the disclosure. Again, no response was received.
- June 3, 2022 – Disclosure to U-Boot founder Wolfgang Denk (wd at denx.de). This email bounced but provided alternative contacts, specifically Stefano Babic (sbabic at denx.de) and Stefan Roese (sr at denx.de).
- June 7, 2022 – Disclosure via email to Stefano Banic and Stefan Roese. Stefan Roese advised submitting the report to the public mailing list (u-boot at lists.denx.de), as all U-Boot development takes place in the open on that list.
- July 8, 2022 – Public disclosure via email to mailing list (u-boot at lists.denx.de).
- November 3, 2022 – Patch submitted by Venkatesh Yadav Abbarapu of AMD to mailing list.
- November 21, 2022 – Patch accepted and merged.
- November 21, 2022 – U-Boot v2023.01-rc2 tagged.
- November 28, 2022 – DFU functionality breakage reported on mailing list by Marek Vasut.
- November 29, 2022 – Cause of breakage due to error in patch identified and reported to the mailing list by Sultan Qasim Khan.
- November 30, 2022 – Patch to correct DFU breakage submitted by Hugo Simeliere of Witekio.
- December 8, 2022 – Patch accepted and merged.
- December 19, 2022 – U-Boot v2023.01-rc4 tagged.
- January 9, 2023 – U-Boot v2023.01 released.
- January 20, 2023 – Advisory published by NCC Group.
Jeremy Boone for providing feedback on this disclosure writeup.
About NCC Group
NCC Group is a global expert in cybersecurity and risk mitigation, working with businesses to protect their brand, value and reputation against the ever-evolving threat landscape. With our knowledge, experience and global footprint, we are best placed to help businesses identify, assess, mitigate & respond to the risks they face. We are passionate about making the Internet safer and revolutionizing the way in which organizations think about cybersecurity.