CVE-2026-80947
High · 7.8CVSS
7.8
EPSS
0.2%
Published
Sep 11, 2026
CISA due date
—
Cloudanix analysis
A bug in a USB Wi-Fi driver can crash a Linux computer or let a logged-in user take it over when the wireless adapter is disconnected while busy, and installing the latest system updates fixes it.
- Exploitation
- Local Privilege
- Attacker needs
- Local User
- Complexity
- Moderate
- Impact
- Privilege Gain
- Component
- OS kernel
- Class
- Use After Free
- Remediation
- Patch
- Effort
- Medium
- Patch risk
- Low
What it actually does
A use-after-free in the Linux kernel rtl8xxxu USB Wi-Fi driver lets a deferred RX URB work item (rx_urb_wq) run after driver private state (priv) has already been freed during interface stop or disconnect. RX completion can queue work after shutdown because schedule_work() was not atomic with the shutdown check, and a still-running worker can resubmit URBs after usb_kill_anchored_urbs() returns. The dangling priv pointer is recovered via container_of and then dereferenced (including priv->udev), producing kernel memory corruption with crash or local privilege-escalation potential.
Why it matters to the business
Linux hosts that use Realtek RTL8xxx-family USB Wi-Fi adapters can suffer kernel panics, loss of wireless connectivity, or—worst case—local privilege escalation by a logged-in low-privilege user during adapter teardown under receive load. The issue is not on the CISA KEV list, is not associated with ransomware, has exploit maturity None, and an EPSS of 0.0017 that has been unchanged for 30 days, so this is not an internet-wide emergency; prioritize multi-user laptops, kiosks, and embedded devices that actually load rtl8xxxu. The report is about 20 days old and was found by static analysis, not in-the-wild abuse.
How an attack unfolds
A local, low-privilege actor on a machine with an rtl8xxxu-backed USB adapter needs the wireless interface to be receiving traffic so RX URBs sit on the pending list and rx_urb_wq can be armed, then needs the driver to stop or the USB device to disconnect while that work is still queued or running. Because stop did not cancel rx_urb_wq, the worker can execute after ieee80211_free_hw() frees priv. A second race allows a completion that saw shutdown as false to schedule work after cancel_work_sync() has already returned. The result is a kernel use-after-free that typically panics the host and, in principle, can be turned into local privilege escalation. No public exploit, named threat actor, or campaign activity is known.
How to fix it
Install a Linux kernel update from the OS vendor that includes the rtl8xxxu teardown fix: cancel_work_sync() on rx_urb_wq in rtl8xxxu_stop() before killing anchored URBs, and call schedule_work() only under rx_urb_lock in the !shutdown path so arming cannot outlive shutdown. This record does not list exact fixed kernel versions; use distro/security advisories for the package that contains the fix. Until patched, restrict untrusted local users, avoid hot-unplug or module unload of affected USB Wi-Fi adapters under load, and prefer patched kernels or non-rtl8xxxu adapters where feasible.
How to confirm the fix worked
Confirm the installed kernel changelog or vendor advisory includes the rtl8xxxu rx_urb_wq cancel and shutdown-atomic schedule_work change. Inventory whether rtl8xxxu is loaded and whether Realtek RTL8xxx USB 802.11 devices are attached. After patching, bring the interface down/up and perform USB disconnect and suspend/resume under normal receive traffic and verify dmesg/journal show no oops, KASAN use-after-free, or workqueue warnings in rtl8xxxu. Unpatched kernels remain theoretically exposed whenever the module is present; the race itself requires teardown concurrent with RX work.
Typical attack path
- Gain local low-privilege access on a Linux host whose wireless adapter is driven by rtl8xxxu
- Have the interface up and receiving frames so RX URB work can be queued
- Cause driver stop, USB removal, or equivalent teardown while that work may still run
- Trigger the worker against already-freed driver private state
- Use the kernel use-after-free for a crash or, if further abused, local privilege escalation
How to detect it
There is no known malware, C2, or attributed actor activity. Hunt for evidence the bug fired (accidental or malicious) in kernel logs, journald, kdump/vmcore, and ftrace/kwork artifacts: oops or BUG during or just after USB Wi-Fi disconnect, interface down, or module teardown; KASAN or KFENCE slab-use-after-free attributed to rtl8xxxu RX URB work or submit paths; workqueue execution of rx_urb_wq after the device is gone. Correlate with USB disconnect/remove events and ieee80211 unregister. Absence of these crashes does not prove the race was never hit on a non-debug kernel.
- rtl8xxxu_rx_urb_work
- rtl8xxxu_submit_rx_urb
- rtl8xxxu_queue_rx_urb
- rtl8xxxu_rx_complete
- rtl8xxxu_stop
- KASAN: slab-use-after-free
- use-after-free in rtl8xxxu
- Unable to handle kernel paging request
- workqueue: rtl8xxxu
What your security team should do
- Inventory Linux endpoints and appliances that load rtl8xxxu or use Realtek RTL8xxx USB Wi-Fi NICs and patch those first
- Apply vendor kernel updates; treat as high on multi-user and kiosk systems with this hardware, routine elsewhere given EPSS 0.0017, no KEV listing, and no known exploits
- Until patched, limit untrusted local logins and USB Wi-Fi hotplug on affected hosts
- Watch kernel logs and crash dumps for rtl8xxxu use-after-free or oops around disconnect/stop
- Do not run a KEV-style emergency SLA; reassess if exploit code or in-the-wild use appears
The record
In the Linux kernel, the following vulnerability has been resolved: wifi: rtl8xxxu: fix use-after-free from rx_urb_wq on stop rtl8xxxu arms rx_urb_wq from the RX completion path: rtl8xxxu_rx_complete() hands the URB to rtl8xxxu_queue_rx_urb(), which queues it on rx_urb_pending_list and, once the list grows past RTL8XXXU_RX_URB_PENDING_WATER, schedules rx_urb_wq. The worker rtl8xxxu_rx_urb_work() drains rx_urb_pending_list, recovers priv through container_of, and resubmits each URB through rtl8xxxu_submit_rx_urb(), which anchors it on rx_anchor and dereferences priv->udev. rtl8xxxu_stop() cancels the sibling work items (c2hcmd_work, ra_watchdog, update_beacon_work) but never cancels rx_urb_wq, so a worker armed during the last burst of RX traffic can run rtl8xxxu_rx_urb_work() after rtl8xxxu_disconnect() has called ieee80211_free_hw(), which frees priv, producing a use-after-free. The window opens under active RX traffic (pending count above the watermark) followed by a disconnect. There are two teardown races to close: * rtl8xxxu_queue_rx_urb() decided whether to enqueue under rx_urb_lock but called schedule_work() after dropping the lock. A completion that observed shutdown == false and released the lock could then call schedule_work() after rtl8xxxu_stop() had set shutdown and cancel_work_sync() had already returned, arming the worker to run after the teardown. Move schedule_work() under the same !shutdown branch so the arming decision is atomic with the shutdown check. * rtl8xxxu_rx_urb_work() anchors every URB it drained back onto rx_anchor through rtl8xxxu_submit_rx_urb(). A worker still running when usb_kill_anchored_urbs(&priv->rx_anchor) returned would submit a URB that escaped the kill. In rtl8xxxu_stop(), call cancel_work_sync(&priv->rx_urb_wq) before the kill so the worker is drained first. After priv->shutdown is set under rx_urb_lock, completions can no longer queue rx_urb_wq. cancel_work_sync() then drains the last queued or running worker, and the following usb_kill_anchored_urbs() kills the URBs it may have submitted. rtl8xxxu_disconnect() is covered because ieee80211_unregister_hw() guarantees .stop() runs for a live interface before ieee80211_free_hw() frees priv. The probe error path needs no cancel: rx_urb_wq is INIT_WORK()'d there but cannot have been scheduled, since no URB is submitted before ieee80211_register_hw() succeeds. This bug was found by static analysis.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|