Skip to content

[Bug] out-of-bounds write due to unchecked format and frame indexes #11264

@XueDugu

Description

@XueDugu

RT-Thread Version

master (verified on commit 6a635e32d9f39ea015824927cee492620a05212f)

Hardware Type/Architectures

Any BSP enabling CherryUSB host video/UVC support

Develop Toolchain

GCC

Describe the bug

Affected Components

Field Detail
File 1 components/drivers/usb/cherryusb/class/video/usbh_video.c
File 2 components/drivers/usb/cherryusb/class/video/usbh_video.h
Path USB Host UVC device enumeration / descriptor parsing

Vulnerability Description

An out-of-bounds write/read vulnerability exists in the CherryUSB UVC host parser. Format and frame information are stored in fixed-size arrays:

struct usbh_video_format {
    struct usbh_video_resolution frame[12];
    uint8_t format_type;
    uint8_t num_of_frames;
};

struct usbh_video {
    ...
    uint8_t num_of_formats;
    struct usbh_video_format format[3];
    ...
};

During UVC descriptor parsing, the implementation directly trusts device-controlled descriptor fields such as bNumFormats, bFormatIndex, bNumFrameDescriptors, and bFrameIndex — with no bounds validation:

case VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE:
    video_class->num_of_formats = p[DESC_bNumFormats];
    break;

case VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_SUBTYPE:
    format_index = p[DESC_bFormatIndex];
    num_of_frames = p[DESC_bNumFrameDescriptors];
    video_class->format[format_index - 1].num_of_frames = num_of_frames;       // ← no bounds check
    video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_UNCOMPRESSED;
    break;

case VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE:
    frame_index = p[DESC_bFrameIndex];
    video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ...;    // ← no bounds check
    video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ...;
    video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ...;
    break;

The missing validations are:

  • bNumFormats <= 3
  • bFormatIndex is within 1..3
  • bNumFrameDescriptors <= 12
  • bFrameIndex is within 1..12

As a result:

  • Malformed descriptors can trigger immediate out-of-bounds writes into video_class->format[] or frame[].
  • Corrupted counts are later reused in iteration loops, causing additional out-of-bounds reads:
for (uint8_t i = 0; i < video_class->num_of_formats; i++) { ... }
for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) { ... }

Trigger Condition

This parser runs automatically during UVC device enumeration:

static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
{
    ...
    p = hport->raw_config_desc;
    while (p[DESC_bLength]) {
        ...
        /* parse video descriptors */
        p += p[DESC_bLength];
    }

    usbh_video_list_info(video_class);
    usbh_video_run(video_class);
}

Note: The memory corruption occurs before usbh_video_run(), so it is reachable even though the default weak usbh_video_run() implementation is empty. A malicious USB video/UVC device can trigger the bug immediately upon connection.


Proof of Concept

A PoC can be implemented with a programmable USB gadget/emulator such as Facedancer, LUNA, GreatFET, a Linux USB gadget setup, or any custom UVC firmware.

Trigger options:

  1. Set bNumFormats = 4 in the VideoStreaming input header descriptor (array capacity is format[3]).
  2. Provide a format descriptor with bFormatIndex = 4.
  3. Provide a frame descriptor with bFrameIndex = 13.
  4. Provide bNumFrameDescriptors > 12 and let later iteration walk beyond frame[12].

Expected result:

  • Enumeration reaches usbh_video_ctrl_connect().
  • Malformed descriptor indexes are written directly into fixed arrays.
  • Subsequent info-printing / selection logic may further read out-of-bounds memory.
  • The target may crash or show corrupted state during or immediately after enumeration.

Impact Analysis

Upstream

  • The vulnerable parser logic is present in current master.
  • The path is automatically reachable during stock USB host enumeration when CherryUSB UVC/video host support is enabled.
  • This is not a network-remote issue; it requires a malicious directly-connected USB video device.

Downstream

  • Any downstream RT-Thread product enabling CherryUSB host UVC/video support is affected when connected to an untrusted USB camera or USB video gadget.
  • Especially relevant for embedded hosts, kiosks, industrial panels, robotics devices, and edge gateways that accept third-party USB cameras.
  • No extra debug command or local user interaction is required once the malicious device is plugged in.

Suggested Fix

Add strict bounds checks before every write into video_class->format[] or frame[]:

if (format_index == 0 || format_index > RT_ARRAY_SIZE(video_class->format)) {
    return -USB_ERR_INVAL;
}

Apply the same pattern for frame_index and stored counts. The later iteration logic should also use validated bounded counts instead of raw descriptor values.

Please let us know if you intend to request a CVE ID upon confirmation of this vulnerability.

Other additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions