GHSA-93mv-fcpr-9488: Potential out-of-bounds read in _ux_host_class_audio_alternate_setting_locate()

GHSA ID

GHSA‑93mv‑fcpr‑9488

CVE ID

CVE‑2025‑55099

Severity

Low

CWE

CWE-125

Published

2025‑10‑17

Last updated

2025‑10‑17

Affected packages

Package Vulnerable versions Patched versions

USBX

⇐ 6.4.2

6.4.3

Description

The function _ux_host_class_audio_alternate_setting_locate() walks through a USB audio configuration descriptor, parsing each section to identify alternate interface settings and extract sampling frequency information.

A vulnerability exists in how this function accesses fields in the descriptor when bSamFreqType indicates either a range of frequencies (type 0) or a list of specific frequencies (non-zero). In both cases, the function blindly reads additional bytes from the descriptor without verifying that enough data remains.

For example, if the descriptor is truncated but reports a valid bSamFreqType, the function may read six bytes for min/max frequency in type 0, or 3 × N bytes for N specific frequency values. Without bounds checks, a malformed or malicious USB device could craft a short descriptor that causes the host to read past the buffer—potentially leading to crashes or information leakage.

code:

UINT  _ux_host_class_audio_alternate_setting_locate(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING *audio_sampling,

                                                    UINT *alternate_setting)

{

...

    descriptor =  audio -> ux_host_class_audio_configuration_descriptor;

    total_descriptor_length =  audio -> ux_host_class_audio_configuration_descriptor_length;

...

    while (total_descriptor_length)

    {



        /* Gather the length, type and subtype of the descriptor.  */

        descriptor_length =   *descriptor;

        descriptor_type =     *(descriptor + 1);

        descriptor_subtype =  *(descriptor + 2);

...

        switch (descriptor_type)

        {





        case UX_INTERFACE_DESCRIPTOR_ITEM:



            /* Parse the interface descriptor and make it machine independent.  */

            _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure,

                                            UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor);

...

        case UX_HOST_CLASS_AUDIO_CS_INTERFACE:

...

                _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_interface_descriptor_structure,

                                                UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &audio_interface_descriptor);

...

                if (audio_interface_descriptor.bSamFreqType == 0)

                {



                    /* The declaration of frequency is contiguous, so get the minimum and maximum */

                    lower_frequency =  (ULONG)  *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH) |

                                       ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1)) << 8 |

                                       ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2)) << 16;



                    higher_frequency =  (ULONG)  *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 3) |

                                        ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 4)) << 8 |

                                        ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 5)) << 16;

...

                }

                else

                {



                    /* The declaration of the frequency is declared as an array of specific values.  */

                    for (specific_frequency_count = 0; specific_frequency_count < audio_interface_descriptor.bSamFreqType;

                            specific_frequency_count++)

                    {



                        lower_frequency =  (ULONG)  *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + (specific_frequency_count * 3)) |

                                           ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1 + (specific_frequency_count * 3))) << 8 |

                                           ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2 + (specific_frequency_count * 3))) << 16;



...

}