In the Linux kernel, an issue has been resolved which previously caused a hung task with uevent_show() on the stack trace. The vulnerability is related to the wifi: rtlwifi driver and the fix involves drastically reducing the attempts to read efuse in case of failures. Syzkaller, a bug-finding tool for Linux kernels, reported this issue, and although another commit [] addressed the specific problem, another type of hung task emerged when running v6.12-rc5 [1].

The issue can be traced along this path

(a) Syzkaller emulates a Realtek USB WiFi adapter using raw-gadget and dummy_hcd infrastructure.

(b) During the probe of rtl8192cu, the driver performs an efuse read procedure (related to EEPROM load), and here lies the problem: the function read_efuse() calls read_efuse_byte() many times, with loop iterations depending on the efuse size (in our example, 512 in total).

This procedure for reading efuse bytes relies on a loop that performs an I/O read up to *10k* times in case of failures. In the reproducer (involving the dummy_hcd emulation layer), it takes 15 seconds each loop, causing the driver to be stuck in its probe routine for an extended period. As a result, when attempting to reboot the system, a stack trace similar to the one below is exposed:

task:kworker/:3 state:D stack: pid:662 tgid:662 ppid:2 flags:x00004000
Workqueue: usb_hub_wq hub_event
Call Trace:
 __schedule+xe22/xeb6
 schedule_timeout+xe7/x132
 __wait_for_common+xb5/x12e
 usb_start_wait_urb+xc5/x1ef
 ? usb_alloc_urb+x95/xa4
 usb_control_msg+xff/x184
 _usbctrl_vendorreq_sync+xa/x161
 _usb_read_sync+xb3/xc5
 read_efuse_byte+x13c/x146
 read_efuse+x351/x5f
 efuse_read_all_map+x42/x52
 rtl_efuse_shadow_map_update+x60/xef
 rtl_get_hwinfo+x5d/x1c2
 rtl92cu_read_eeprom_info+x10a/x8d5
 ? rtl92c_read_chip_version+x14f/x17e
 rtl_usb_probe+x323/x851
 usb_probe_interface+x278/x34b
 really_probe+x202/x4a4
 __driver_probe_device+x166/x1b2
 driver_probe_device+x2f/xd8
 [...]

The proposed solution is to significantly reduce the attempts of performing I/O reads in case of failures for USB devices, as they are inherently slower than PCIe ones. By retrying up to 10 times instead of 10000, we can achieve responsiveness in the reproducer. It seems reasonable to believe that no USB device implementation requires this number of retries at every I/O read to function properly. Based on this assumption, it might be prudent to backport the fix to stable kernels, perhaps up to the 6.x series.

[] Commit 15fffc6a5624: "driver core: Fix uevent_show() vs driver detach race"

[1] To view details of the syzkaller report on this issue, check the entry from 2024/08/08 06:23 in the list of crashes; the C reproducer is available at https://syzkaller.appspot.com/text?tag=ReproC&x=1521fc83980000.

Timeline

Published on: 12/27/2024 14:15:26 UTC
Last modified on: 05/04/2025 09:55:21 UTC