GHSA-r7xw-9jhg-88cm: Double free of the USB host configuration descriptor when device enumeration fails

Published Sep 21, 2026
·
Updated

The experimental USB host stack allocates a per-device configuration-descriptor buffer, udev->cfgdesc, from the dedicated usbdeviceheap in usbhdevicesetconfiguration() (subsys/usb/host/usbhdevice.c). On three failure paths — a failed full-length GETDESCRIPTOR(CONFIGURATION) read, a mismatch between the short and full descriptor reads, and a rejected descriptor in parseconfigurationdescriptor() — the buffer was released with kheapfree() but the pointer was left dangling. The cleanup in usbhdevicefree() is guarded only by if (udev->cfgdesc != NULL), so it frees the same block a second time.

The path is driven entirely by the attached peripheral: usbhdeviceconnect() calls usbhdeviceinit(), which ends in usbhdevicesetconfiguration(), and on failure usbhdeviceconnect() calls usbhdevicefree(). On v4.4.x this happens during the same enumeration, with no unplug required; on v4.1.0–v4.3.x the second free instead arrives via devremovedhandler()/devconnectedhandler() in subsys/usb/host/usbhcore.c, so it requires a removal or duplicate-connect event after the failed enumeration — a sequence the attached device fully controls. A malicious or malformed USB device only has to answer the first 9-byte configuration-descriptor request with a well-formed header and then fail any of the three checks, for example by returning a full descriptor whose interface count disagrees with bNumInterfaces, or by answering the second read with different bytes.

The result is a double free on usbdeviceheap. On builds where lib/heap hardening is active (the current default CONFIGSYSHEAPHARDENINGBASIC), sysheapfree() detects the already-free chunk and calls kpanic(), giving a deterministic, peripheral-triggered denial of service of the USB host. On builds without that detection — earlier releases, or CONFIGSYSHEAPHARDENINGNONE — the second free manipulates a chunk already on the free list, corrupting the heap's free list so that later allocations can return overlapping or invalid blocks.

Exploitation beyond denial of service is bounded by the fact that usbdeviceheap is a small dedicated heap (CONFIGUSBHUSBDEVICEHEAP, default 1024 bytes) whose only client is this descriptor buffer, and by CONFIGUSBHOSTSTACK being marked experimental and disabled by default. The fix sets udev->cfgdesc = NULL after every kheapfree(), making the cleanup guard sound.

Affected Software

1 affected component
Zephyr Project Zephyr RTOS>=4.1.0<=4.4.x

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Configuration

    Set udev->cfg_desc = NULL after every k_heap_free() of the configuration-descriptor buffer so usbh_device_free() cannot free the same block a second time.

    Zephyr USB host stack udev->cfg_desc = NULL

Event History

Sep 21, 2026
CVE Published
via OSV·04:41 PM
Data Sourced
via OSV·04:41 PM
DescriptionSeverityWeakness

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203