Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

[Bug] legacy USB host trusts device-controlled bNumInterfaces and can trigger out-of-bounds access in fixed interface array

未關閉
#11,288 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

@manyangshen 已經在處理了。

開始於 2026年9月22日。

  • #11822 來自 @manyangshen —— 未關閉

評估

難度
4/5
預估耗時
3-5 天
新手友好度
48/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
冷清
技術堆疊
c

研究方向

從 components/legacy/usb/usbhost/core/usbhost_core.c 中的 USB_MAX_INTERFACE 和 struct uinstance 開始,接著檢查所引用位置的 attach 和 detach 迴圈,以及 hub.c:452 中的 hub 路徑。確認 bNumInterfaces 如何在列舉和清理過程中傳遞。完成的標準是兩條路徑都能安全處理超過固定陣列容量的數量,包括部分 attach 失敗的情況。

由索引模型根據 Issue 內容生成。

描述

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:22
  • components/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:190
  • components/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
  1. Enable RT-Thread legacy USB host support.
  2. Connect a malicious USB device.
  3. 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
  4. Trigger disconnect / reconnect or any path that causes cleanup / detach.
  5. Observe that the detach logic iterates up to the untrusted bNumInterfaces value and reads device->intf[i] past the 8-entry array.
Stronger Out-of-Bounds Write PoC
  1. Provide a crafted configuration descriptor with:
    • bNumInterfaces > 8
    • Actual interface descriptors for indices 0..8 or higher
    • Interface class/subclass values that match enabled host class drivers
  2. Let the host enumerate the device normally.
  3. When i >= 8, the attach logic writes to device->intf[i] even though the fixed array ends at intf[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] unless i < 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->bNumInterfaces if it exceeds USB_MAX_INTERFACE
  • Do not allocate or access device->intf[i] unless i < 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

主要語言
C
星號
12.3k
分支
5.5k
平均合併
3 天 8 小時
30 天內合併 PR
27

環境準備

在 Codespaces 中開啟

在瀏覽器裡用你自己的 GitHub 帳號啟動這個專案的開發容器。

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

RT-Thread/rt-thread 的其他 Issue

查看 RT-Thread/rt-thread 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。