CVE-2026-90001 Overview
CVE-2026-90001 is a race condition vulnerability in the Linux kernel's Human Interface Device (HID) Berkeley Packet Filter (BPF) subsystem. The flaw exists in the struct_ops destroy path, where __hid_bpf_ops_destroy_device() and hid_bpf_unreg() can race on the same registration reference. This race causes a double put_device() on struct hid_device, freeing the structure while hid_destroy_device() still references it. The resulting use-after-free condition allows a local attacker with low privileges to corrupt kernel memory. Successful exploitation can lead to privilege escalation, kernel information disclosure, or denial of service.
Critical Impact
A local, low-privileged attacker can trigger a use-after-free in kernel memory, potentially leading to privilege escalation or system compromise.
Affected Products
- Linux kernel versions containing the HID BPF struct_ops implementation
- Distributions shipping affected upstream kernels prior to the fix commits
- Systems where unprivileged users can load or attach BPF programs to HID devices
Discovery Timeline
- 2026-09-16 - CVE-2026-90001 published to the National Vulnerability Database (NVD)
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-90001
Vulnerability Analysis
The vulnerability resides in the HID BPF struct_ops teardown logic. Each successful attach via hid_bpf_ops_reg() acquires one device reference through hid_get_device(). Two independent code paths can release that reference. The first path runs during device destruction: hid_destroy_device() invokes hid_bpf_destroy_device(), which calls __hid_bpf_ops_destroy_device(). That function walks hdev->bpf.prog_list under rcu_read_lock() and drops one reference per attached program. The second path runs during BPF link release: a BPF map delete without BPF_F_LINK synchronously calls st_ops->unreg(), which invokes hid_bpf_unreg() and drops the registration reference.
Root Cause
The two paths execute under different lock domains, rcu_read_lock() versus prog_list_lock. The coordination handshake based on e->hdev = NULL on the destroy side and if (!hdev) return on the unreg side is a Time-of-Check Time-of-Use (TOCTOU) pattern. A concurrent unregister can read ops->hdev as non-NULL, block on prog_list_lock, and then proceed while the destroy traversal executes. Both paths then drop the same device reference. Because each decrement is individually valid, the refcount_t saturation check does not fire.
Attack Vector
A local attacker with the ability to attach BPF programs to a HID device can race the BPF link release against device teardown. Triggering unplug events or destroying BPF maps at precise moments causes the reference count to reach zero prematurely. The hid_device structure is freed while hid_destroy_device() continues executing on it. Subsequent teardown operations dereference freed memory, enabling kernel memory corruption primitives typically leveraged for privilege escalation.
No verified public exploit code is available. The vulnerability mechanism is documented in the upstream fix commits. See the Kernel Git Commit c7f927a for technical details.
Detection Methods for CVE-2026-90001
Indicators of Compromise
- Kernel oops or panic messages referencing hid_destroy_device, hid_bpf_unreg, or __hid_bpf_ops_destroy_device in dmesg or journalctl output
- KASAN use-after-free reports involving struct hid_device on kernels built with CONFIG_KASAN
- Unexpected process termination or system instability following BPF program attach or detach operations on HID devices
Detection Strategies
- Audit kernel logs for slab-use-after-free warnings tied to HID subsystem addresses
- Monitor bpf() syscall activity from non-root users, particularly BPF_LINK_CREATE and BPF_MAP_DELETE_ELEM operations targeting struct_ops maps
- Correlate USB device plug and unplug events with concurrent BPF map deletions from the same process context
Monitoring Recommendations
- Enable kernel auditing for bpf() syscalls and record process, user, and program type metadata
- Deploy runtime kernel integrity monitoring to identify anomalous kernel memory access patterns
- Track loaded BPF programs via bpftool prog list and alert on unexpected struct_ops attachments to HID devices
How to Mitigate CVE-2026-90001
Immediate Actions Required
- Apply the upstream kernel patches referenced in the vendor advisories as soon as vendor-supported builds are available
- Restrict CAP_BPF and CAP_SYS_ADMIN capabilities to trusted service accounts only
- Set kernel.unprivileged_bpf_disabled=1 via sysctl to prevent unprivileged BPF program loading
- Inventory systems running vulnerable kernels and prioritize patching for multi-tenant hosts
Patch Information
The fix serializes the remove and NULL decision under hdev->bpf.prog_list_lock on both sides. It moves the destroy-side put_device() calls outside the lock. The unregister path re-checks ops->hdev under the lock and returns without releasing the reference when the destroy path has already cleared it. Patches are available in the following upstream commits: Kernel Git Commit 4013596, Kernel Git Commit 9cdc7e6, Kernel Git Commit bfb7939, and Kernel Git Commit c7f927a.
Workarounds
- Disable unprivileged BPF program loading system-wide until patched kernels are deployed
- Blocklist the hid_bpf kernel module on systems that do not require HID BPF functionality
- Enforce mandatory access control policies via SELinux or AppArmor to restrict BPF syscall access
# Configuration example
# Disable unprivileged BPF at runtime
sudo sysctl -w kernel.unprivileged_bpf_disabled=1
# Persist across reboots
echo 'kernel.unprivileged_bpf_disabled=1' | sudo tee /etc/sysctl.d/10-disable-unpriv-bpf.conf
# Optional: blocklist hid_bpf module if unused
echo 'blacklist hid_bpf' | sudo tee /etc/modprobe.d/blacklist-hid-bpf.conf
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.