[Bug] legacy USB host trusts device-controlled bNumInterfaces and can trigger out-of-bounds access in fixed interface array
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- c
- Lĩnh vực
- embedded-iot, operating-systems, security
Hướng nghiên cứu
Bắt đầu với USB_MAX_INTERFACE và struct uinstance trong components/legacy/usb/usbhost/core/usbhost_core.c, sau đó kiểm tra các vòng lặp attach và detach tại các vị trí được nêu cũng như đường đi của hub trong hub.c:452. Xác minh cách bNumInterfaces được truyền qua quá trình enumeration và cleanup. Hoàn thành khi cả hai đường đi đều xử lý an toàn các số lượng lớn hơn sức chứa của mảng cố định, bao gồm cả các lỗi attach một phần.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
RT-Thread Version
master, verified on current worktree at commit 25295501c0cc7181d6a541a867fdf7214879ddf8
Hardware Type/Architectures
Any BSP enabling the legacy USB host stack and connecting to external USB devices
Develop Toolchain
GCC
Describe the bug
Summary
A memory-safety issue exists in RT-Thread's legacy USB host stack because it trusts the device-controlled bNumInterfaces field from the USB configuration descriptor, but stores interface state in a fixed-size internal array of only 8 entries.
USB_MAX_INTERFACE is fixed at 8, and struct uinstance contains only:
struct uhintf *intf[USB_MAX_INTERFACE];
However, the USB device's configuration descriptor field bNumInterfaces is attacker-controlled external input, and both attach and detach paths iterate directly up to device->cfg_desc->bNumInterfaces without comparing it against USB_MAX_INTERFACE.
This makes out-of-bounds access reachable from a malicious USB device.
Relevant Code
Internal capacity limit:
components/drivers/include/drivers/usb_host.h:22components/drivers/include/drivers/usb_host.h:66
#define USB_MAX_INTERFACE 0x08
struct uinstance
{
...
struct uhintf *intf[USB_MAX_INTERFACE];
...
};
Untrusted external field:
components/drivers/include/drivers/usb_common.h:294
rt_uint8_t bNumInterfaces;
Attach path:
components/legacy/usb/usbhost/core/usbhost_core.c:190components/legacy/usb/usbhost/core/usbhost_core.c:229
for (i = 0; i < device->cfg_desc->bNumInterfaces; i++)
{
...
device->intf[i] = (struct uhintf *)rt_malloc(sizeof(struct uhintf));
...
}
Detach path:
components/legacy/usb/usbhost/core/usbhost_core.c:276
for (i = 0; i < device->cfg_desc->bNumInterfaces; i++)
{
if (device->intf[i] == RT_NULL) continue;
...
}
Hub path that makes follow-on detach realistic even if attach fails partway:
components/legacy/usb/usbhost/core/hub.c:452
The attach return value is not handled in a way that prevents later detach-driven access from the same untrusted device lifecycle.
Correct Vulnerability Characterization
The issue is real, but the trigger conditions need to be stated precisely.
1. Out-of-bounds read is the easiest effect to reach
Because the detach path also trusts bNumInterfaces, a malicious USB device can cause the host to read past the 8-entry intf[] array during later disconnect / reconnect / cleanup flows.
2. Out-of-bounds write is also reachable
It is not enough to set only bNumInterfaces = 9. To actually reach the write at device->intf[i] = ... for i >= 8, the malicious USB device must also provide interface descriptors with indices beyond 7, and those descriptors must match an enabled host class driver so that the allocation path is taken.
If those conditions are met, device->intf[i] becomes a real out-of-bounds write.
3. Static storage makes corruption more dangerous
struct uinstance objects come from a static array:
components/legacy/usb/usbhost/core/usbhost_core.c:18
static struct uinstance dev[USB_MAX_DEVICE];
So writing beyond intf[7] is likely to corrupt adjacent fields of the same instance or neighboring device instances, not harmless padding.
Why This Is a Security Issue
This bug is reachable from an untrusted USB device during normal host-side enumeration.
A malicious USB peripheral can provide a crafted configuration descriptor with an oversized bNumInterfaces value and additional interface descriptors designed to drive the host into out-of-bounds access.
This is not just a robustness issue. It is a real memory-safety problem in the legacy USB host stack, with at least:
- Out-of-bounds read during detach / cleanup
- Out-of-bounds write during attach if enough matching interfaces are supplied
Depending on target layout and allocator behavior, the practical impact may include:
- Crash
- Denial of service
- Corruption of adjacent host USB state
- Undefined behavior during later device handling
Steps to Reproduce
A practical PoC should use a programmable USB device/emulator (for example a USB gadget setup, Facedancer-like platform, or custom firmware) and present a crafted configuration descriptor.
Minimal Out-of-Bounds Read PoC
- Enable RT-Thread legacy USB host support.
- Connect a malicious USB device.
- Provide a configuration descriptor with:
bNumInterfaces > 8- Enough malformed or unsupported interface layout so the attach path does not fully populate all
device->intf[]entries
- Trigger disconnect / reconnect or any path that causes cleanup / detach.
- Observe that the detach logic iterates up to the untrusted
bNumInterfacesvalue and readsdevice->intf[i]past the 8-entry array.
Stronger Out-of-Bounds Write PoC
- Provide a crafted configuration descriptor with:
bNumInterfaces > 8- Actual interface descriptors for indices
0..8or higher - Interface class/subclass values that match enabled host class drivers
- Let the host enumerate the device normally.
- When
i >= 8, the attach logic writes todevice->intf[i]even though the fixed array ends atintf[7].
Expected Behavior
RT-Thread should treat bNumInterfaces as untrusted input and reject or clamp any device that reports more interfaces than the internal host representation can store.
At minimum:
- Reject
bNumInterfaces > USB_MAX_INTERFACE - Avoid indexing
device->intf[i]unlessi < USB_MAX_INTERFACE - Apply the same validation consistently in both attach and detach paths
Actual Behavior
RT-Thread directly trusts bNumInterfaces from the device configuration descriptor and uses it to drive loops that index a fixed-size 8-entry internal array.
This allows a malicious USB device to cause out-of-bounds access in the legacy USB host stack.
Suggested Fix
The fix should be applied in all paths that use bNumInterfaces to index device->intf[], including both enumeration and detach/cleanup.
At minimum:
- Reject or clamp
device->cfg_desc->bNumInterfacesif it exceedsUSB_MAX_INTERFACE - Do not allocate or access
device->intf[i]unlessi < USB_MAX_INTERFACE - Ensure failure during attach cannot leave a later detach path iterating on the untrusted original interface count
Kindly let me know if you intend to request a CVE ID upon confirmation of the vulnerability.
Other additional context
No response
- Ngôn ngữ chính
- C
- Star
- 12.3k
- Fork
- 5.5k
- Merge trung bình
- 4 ngày 12 giờ
- Pull request đã merge (30 ngày)
- 32
Chuẩn bị môi trường
Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của RT-Thread/rt-thread
-
[Bug] [netdev] ping crashes the shell with a division by zero when the target is unreachable (received == 0)Có thể đã có người làm @r3wretrhy đã nhận 1 ngày trước. Đang mởbug Component component: net
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
RT-Thread/rt-thread#11852 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[bsp][stm32][bluepill] README「快速上手」缺少重新生成 MDK 工程这一步,按文档操作无法编译通过Có thể đã có người làm @moment-NEW đã nhận 4 ngày trước. Đang mởin progress
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
RT-Thread/rt-thread#11818 · 4 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
BSP BSP: Loongson bug RT-Smart
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
RT-Thread/rt-thread#11717 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Arch: RISC-V BSP BSP: HPMicro bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
RT-Thread/rt-thread#11687 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
RT-Thread/rt-thread#11472 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của RT-Thread/rt-thread
Issue tương tự
-
Discover carries headerEdges that nothing reads since #1914 moved E0507/E0517 to the compiler graphĐang mởtech-debt
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Maintainer thường phản hồi trong vòng 1 ngày
-
2个显示的问题Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
coolsnowwolf/lede#14209 ·
-
Cannot run pico-hsm-tool.pyĐang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 75/100
polhenarejos/pico-hsm#147 ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
OpenPrinting/cups#1746 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Status: Opened
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày