CVE-2026-17050 Overview
CVE-2026-17050 is a double-free vulnerability [CWE-415] in the experimental USB host stack of the Zephyr real-time operating system. The flaw resides in usbh_device_set_configuration() within subsys/usb/host/usbh_device.c. On three failure paths, the per-device configuration-descriptor buffer udev->cfg_desc is released with k_heap_free() but the pointer is left dangling. A later cleanup in usbh_device_free() frees the same block a second time because its guard only checks for a non-NULL pointer. The condition is triggered entirely by an attached USB peripheral responding with malformed descriptor data.
Critical Impact
A malicious USB peripheral can deterministically crash the USB host through k_panic() on hardened builds, or corrupt the usb_device_heap free list on unhardened builds, potentially yielding overlapping allocations.
Affected Products
- Zephyr RTOS v4.4.x with CONFIG_USB_HOST_STACK enabled (double free during enumeration)
- Zephyr RTOS v4.1.0 through v4.3.x with CONFIG_USB_HOST_STACK enabled (double free via removal or duplicate-connect events)
- Builds compiled with CONFIG_SYS_HEAP_HARDENING_NONE are subject to heap free-list corruption rather than a controlled panic
Discovery Timeline
- 2026-09-21 - CVE-2026-17050 published to NVD
- 2026-09-22 - Last updated in NVD database
Technical Details for CVE-2026-17050
Vulnerability Analysis
The experimental USB host stack allocates udev->cfg_desc from the dedicated usb_device_heap during device enumeration. Three failure paths in usbh_device_set_configuration() release this buffer without clearing the pointer: a failed full-length GET_DESCRIPTOR(CONFIGURATION) read, a mismatch between the short and full descriptor reads, and a rejected descriptor in parse_configuration_descriptor().
When usbh_device_connect() observes the failure, it calls usbh_device_free(). That cleanup routine only checks if (udev->cfg_desc != NULL) before calling k_heap_free() again on the stale pointer. The result is a double free against usb_device_heap.
On builds with the current default CONFIG_SYS_HEAP_HARDENING_BASIC, sys_heap_free() detects the already-free chunk and invokes k_panic(), producing a peripheral-triggered denial of service. On builds without that detection, the second free manipulates a chunk already on the free list, corrupting the allocator so that later allocations may return overlapping or invalid blocks.
Root Cause
The root cause is missing state hygiene after k_heap_free(). The three error paths in usbh_device_set_configuration() do not set udev->cfg_desc = NULL, so the subsequent NULL check in usbh_device_free() fails to detect the already-released buffer.
Attack Vector
Exploitation requires physical access to attach a malicious or malformed USB device to a Zephyr host. The device answers the initial 9-byte configuration-descriptor request with a well-formed header, then fails one of the three checks. Examples include returning a full descriptor whose interface count disagrees with bNumInterfaces, or answering the second read with different bytes than the first. On v4.4.x the double free occurs within a single enumeration. On v4.1.0 through v4.3.x it arrives via dev_removed_handler() or dev_connected_handler() in subsys/usb/host/usbh_core.c, requiring a subsequent removal or duplicate-connect event.
// Security patch in subsys/usb/host/usbh_device.c
// Source: https://github.com/zephyrproject-rtos/zephyr/commit/d46a8c1f8fb65e1f80b44bd651a6dafea747602e
sys_dlist_remove(&udev->node);
if (udev->cfg_desc != NULL) {
k_heap_free(&usb_device_heap, udev->cfg_desc);
+ udev->cfg_desc = NULL;
}
k_mem_slab_free(&usb_device_slab, (void *)udev);
The patch nulls udev->cfg_desc after every k_heap_free(), making the cleanup guard sound.
Detection Methods for CVE-2026-17050
Indicators of Compromise
- Kernel panic messages from sys_heap_free() on hardened builds, correlated with USB device connect events
- USB enumeration failures immediately followed by device removal or reconnect events referencing the same port
- Anomalous or malformed configuration descriptors where bNumInterfaces disagrees with the actual descriptor payload
Detection Strategies
- Enable CONFIG_SYS_HEAP_HARDENING_BASIC or stronger to convert silent heap corruption into a deterministic k_panic() that can be logged
- Instrument usbh_device_connect() and usbh_device_free() with debug tracing to capture peripheral VID/PID and descriptor payloads on enumeration failure
- Audit devices connecting to Zephyr hosts running CONFIG_USB_HOST_STACK for unexpected disconnect and reconnect patterns
Monitoring Recommendations
- Ship kernel panic logs and USB subsystem traces to a centralized log aggregator for correlation with device attach events
- Track firmware crash telemetry from embedded Zephyr fleets to identify clusters of USB-triggered restarts
- Monitor build inventories to identify devices shipping with CONFIG_USB_HOST_STACK enabled and prioritize patch rollout
How to Mitigate CVE-2026-17050
Immediate Actions Required
- Apply the upstream commit d46a8c1f8fb65e1f80b44bd651a6dafea747602e from the Zephyr project to any firmware image that enables CONFIG_USB_HOST_STACK
- Disable CONFIG_USB_HOST_STACK on production images where USB host functionality is not required, since it is experimental and off by default
- Restrict physical access to USB host ports on affected devices until patched firmware is deployed
Patch Information
The fix is available in the upstream Zephyr repository. Refer to the Zephyr commit d46a8c1 and the GitHub Security Advisory GHSA-r7xw-9jhg-88cm for details. The patch adds udev->cfg_desc = NULL after k_heap_free() in usbh_device_free() and on the failure paths in usbh_device_set_configuration().
Workarounds
- Set CONFIG_SYS_HEAP_HARDENING_BASIC (default in current releases) so the second free triggers k_panic() instead of silently corrupting the free list
- Reduce or isolate CONFIG_USBH_USB_DEVICE_HEAP to bound impact to the small dedicated heap whose only client is the descriptor buffer
- Enforce a USB device allow-list at the application layer to reject peripherals whose descriptors do not match expected VID/PID pairs
# Disable the experimental USB host stack in Kconfig if not required
CONFIG_USB_HOST_STACK=n
# Or, if the stack must remain enabled, ensure heap hardening is active
CONFIG_SYS_HEAP_HARDENING_BASIC=y
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.