CVE-2026-31721 Overview
CVE-2026-31721 is a Linux kernel vulnerability in the USB gadget HID function driver (f_hid). The flaw stems from improper lifecycle management of wait queues and spinlocks initialized inside hidg_bind instead of hidg_alloc. When a userspace process opens /dev/hidg0, registers the file descriptor with epoll, and triggers an unbind/rebind cycle of the USB Device Controller (UDC), the bind path re-initializes wait queues that still contain pending entries. This produces list corruption detectable when CONFIG_DEBUG_LIST is enabled. The vulnerability affects multiple Linux kernel branches, including 7.0 release candidates, and impacts system availability through kernel-level data structure corruption.
Critical Impact
A local user with access to /dev/hidg0 and the ability to trigger UDC bind cycles can corrupt kernel wait queue lists, leading to denial of service through kernel instability.
Affected Products
- Linux Kernel (multiple stable branches)
- Linux Kernel 7.0-rc1 through 7.0-rc6
- Systems using USB gadget HID function (f_hid) with configurable UDC binding
Discovery Timeline
- 2026-05-01 - CVE-2026-31721 published to NVD
- 2026-05-06 - Last updated in NVD database
Technical Details for CVE-2026-31721
Vulnerability Analysis
The vulnerability resides in drivers/usb/gadget/function/f_hid.c. The hidg_bind function calls init_waitqueue_head to initialize wait queues used by the HID gadget's poll/epoll interface. These queues live on the function instance that exists across bind and unbind cycles. When userspace opens /dev/hidg0 and registers the descriptor through EPOLL_CTL_ADD, the kernel inserts entries into these wait queues via poll_wait.
If an administrator unbinds and rebinds the UDC while the file descriptor remains open, hidg_bind re-initializes the same wait queue heads. The previously registered epoll entries are still linked to the old list state. A subsequent EPOLL_CTL_DEL triggers remove_wait_queue and ep_remove_wait_queue, which traverses corrupted list pointers. With CONFIG_DEBUG_LIST enabled, the kernel detects the inconsistency and reports list_del corruption. Without that debug option, the kernel may silently dereference invalid pointers.
Root Cause
The root cause is a lifetime mismatch between the wait queue data structures and the function instance that owns them. Wait queue heads, list heads, and spinlocks belong to the lifetime of the gadget function (hidg_alloc), but were repeatedly re-initialized in hidg_bind. This violates the invariant that initialization must occur exactly once per object lifetime [CWE-665].
Attack Vector
Exploitation requires local access with permissions to open /dev/hidg0 and trigger UDC bind/unbind operations through configfs. The reproduction sequence is:
- Configure and bind an HID gadget through configfs.
- Open /dev/hidg0 from userspace.
- Add the descriptor to an epoll instance with EPOLL_CTL_ADD.
- Unbind the UDC, then rebind it.
- Call EPOLL_CTL_DEL on the descriptor to trigger list traversal.
The resulting list corruption can panic the kernel or destabilize the system, denying service to all users on the host.
Detection Methods for CVE-2026-31721
Indicators of Compromise
- Kernel log entries containing list_del corruption originating from remove_wait_queue or ep_remove_wait_queue
- Unexpected kernel oops or panic traces referencing f_hid functions during USB gadget reconfiguration
- System hangs or crashes following UDC unbind/bind sequences while /dev/hidg0 file descriptors remain open
Detection Strategies
- Audit kernel ring buffer (dmesg) for list debugging warnings emitted by CONFIG_DEBUG_LIST builds
- Monitor configfs write activity under /sys/kernel/config/usb_gadget/ to identify processes performing repeated UDC bind cycles
- Correlate process audit logs of open calls on /dev/hidg* with subsequent UDC state changes
Monitoring Recommendations
- Enable kernel auditd rules to record access to /dev/hidg0 and writes to UDC configfs attributes
- Track non-root processes invoking USB gadget reconfiguration on production hosts
- Alert on kernel taint flags or Oops events on systems exposing USB gadget functionality
How to Mitigate CVE-2026-31721
Immediate Actions Required
- Apply the upstream Linux kernel patches that move list, wait queue, and spinlock initialization from hidg_bind to hidg_alloc
- Restrict access to /dev/hidg* device nodes and USB gadget configfs paths to trusted administrators only
- On systems that do not require USB gadget HID functionality, unload or disable the usb_f_hid module
Patch Information
The fix has been merged into multiple stable Linux kernel branches. Reference the upstream commits at Linux Kernel Commit 13440c0, Linux Kernel Commit 26a879a, Linux Kernel Commit 4e0a882, Linux Kernel Commit 5d1bb39, Linux Kernel Commit 81aee45, Linux Kernel Commit 8ec6a58, Linux Kernel Commit de93e08, and Linux Kernel Commit f7d00ee. Distribution maintainers ship the fix in updated kernel packages.
Workarounds
- Avoid unbinding and rebinding the UDC while userspace processes hold open file descriptors on /dev/hidg* nodes
- Remove or blacklist the usb_f_hid kernel module on hosts that do not act as USB HID gadgets
- Tighten file system permissions on /dev/hidg* and configfs USB gadget paths to prevent unprivileged manipulation
# Blacklist the f_hid module on systems that do not require USB HID gadget support
echo "blacklist usb_f_hid" | sudo tee /etc/modprobe.d/blacklist-usb-f-hid.conf
sudo update-initramfs -u
# Restrict access to USB gadget configfs and HID device nodes
sudo chmod 0700 /sys/kernel/config/usb_gadget
sudo chmod 0600 /dev/hidg0
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

