When multiple concurrent requests are made for the same firmware name, the firmware loader batches them. The first request allocates a struct fw_priv and proceeds to load the firmware (e.g., via the sysfs fallback). Subsequent requests find the existing fw_priv and wait for the first request to finish. In the sysfs fallback mechanism, if user space writes 1 to the loading attribute and then immediately writes 0 without writing any data, fw_priv->size remains 0 and fw_priv->data remains NULL. The sysfs fallback mechanism completes and sets the state to FW_STATUS_DONE. The first request wakes up, explicitly checks for a 0-size firmware, and correctly returns -ENOENT. However, the batched requests wake up from fw_state_wait(), see the FW_STATUS_DONE state, and assume success. _request_firmware_prepare() then blindly copies the 0 size and NULL data pointer into the struct firmware and returns success. Drivers receiving this invalid firmware can crash when attempting to parse it. For example, the emi26 driver calls request_ihex_firmware(), which passes the 0-size, NULL-data firmware to ihex_validate_fw(). Because fw->size is 0, fw->size - sizeof(*end) underflows to a huge positive value, causing the loop condition to evaluate to true. The loop executes and attempts to read from the NULL pointer, resulting in a KASAN null-ptr-deref: Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 0 UID: 0 PID: 5720 Comm: kworker/0:3 Not tainted Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Workqueue: usb_hub_wq hub_event RIP: 0010:ihex_binrec_size include/linux/ihex.h:26 [inline] RIP: 0010:__ihex_next_binrec include/linux/ihex.h:35 [inline] RIP: 0010:ihex_validate_fw include/linux/ihex.h:54 [inline] RIP: 0010:request_ihex_firmware include/linux/ihex.h:74 [inline] RIP: 0010:emi26_load_firmware drivers/usb/misc/emi26.c:86 [inline] RIP: 0010:emi26_probe+0x283/0x1690 drivers/usb/misc/emi26.c:232 Call Trace: usb_probe_interface+0x653/0xc60 drivers/usb/core/driver.c:396 call_driver_probe drivers/base/dd.c:-1 [inline] really_probe+0x254/0xae0 drivers/base/dd.c:706 To fix this, enforce the same validation rules for batched requests as for the primary request. In _request_firmware_prepare(), after fw_state_wait() returns successfully, explicitly check if fw_priv->size is 0. If it is, return -ENOENT instead of blindly calling fw_set_page_data(). This properly aborts any remaining batched requests and cleans up the state. Fixes: 1f2b79599ee8 ("firmware loader: always let firmware_buf own the pages buffer") Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot Reported-by: syzbot+cb67625c47fe4d6dd7c8@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=cb67625c47fe4d6dd7c8 Link: https://syzkaller.appspot.com/ai_job?id=c8fc1a4f-643b-4169-a624-9871d2c011bd To: "Danilo Krummrich" To: To: "Greg Kroah-Hartman" To: "Luis Chamberlain" To: "Rafael J. Wysocki" To: "Russ Weight" To: "Ming Lei" Cc: --- diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 24213a0ea..b1521a1da 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -771,6 +771,8 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name, if (ret > 0) { ret = fw_state_wait(fw_priv); if (!ret) { + if (!fw_priv->size) + return -ENOENT; fw_set_page_data(fw_priv, firmware); return 0; /* assigned */ } base-commit: 075b74841bd0065a3bda3440873c747938e69b68 -- This is an AI-generated patch subject to moderation. Reply with '#syz upstream' to Sign-off the patch as a human author and send it to the upstream kernel mailing lists. Reply with '#syz reject' to reject it ('#syz unreject' to undo). See https://goo.gle/syzbot-ai-patches for information about AI-generated patches. You can comment on the patch as usual, syzbot will try to address the comments and send a new version of the patch if necessary. syzbot engineers can be reached at syzkaller@googlegroups.com.