Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: rtl8712: handle firmware load failure

when firmware fails to load we should not call unregister_netdev()
this patch fixes a race condition between rtl871x_load_fw_cb() and
r871xu_dev_remove() and fixes the bug reported by syzbot

Reported-by: syzbot+80899a8a8efe8968cde7@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=80899a8a8efe8968cde7
Signed-off-by: Rustam Kovhaev <rkovhaev@gmail.com>
Cc: stable <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200716151324.1036204-1-rkovhaev@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Rustam Kovhaev and committed by
Greg Kroah-Hartman
b4383c97 c4283950

+10 -4
+2 -1
drivers/staging/rtl8712/hal_init.c
··· 33 33 { 34 34 struct _adapter *adapter = context; 35 35 36 - complete(&adapter->rtl8712_fw_ready); 37 36 if (!firmware) { 38 37 struct usb_device *udev = adapter->dvobjpriv.pusbdev; 39 38 struct usb_interface *usb_intf = adapter->pusb_intf; ··· 40 41 dev_err(&udev->dev, "r8712u: Firmware request failed\n"); 41 42 usb_put_dev(udev); 42 43 usb_set_intfdata(usb_intf, NULL); 44 + complete(&adapter->rtl8712_fw_ready); 43 45 return; 44 46 } 45 47 adapter->fw = firmware; 46 48 /* firmware available - start netdev */ 47 49 register_netdev(adapter->pnetdev); 50 + complete(&adapter->rtl8712_fw_ready); 48 51 } 49 52 50 53 static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
+8 -3
drivers/staging/rtl8712/usb_intf.c
··· 595 595 if (pnetdev) { 596 596 struct _adapter *padapter = netdev_priv(pnetdev); 597 597 598 - usb_set_intfdata(pusb_intf, NULL); 599 - release_firmware(padapter->fw); 600 598 /* never exit with a firmware callback pending */ 601 599 wait_for_completion(&padapter->rtl8712_fw_ready); 600 + pnetdev = usb_get_intfdata(pusb_intf); 601 + usb_set_intfdata(pusb_intf, NULL); 602 + if (!pnetdev) 603 + goto firmware_load_fail; 604 + release_firmware(padapter->fw); 602 605 if (drvpriv.drv_registered) 603 606 padapter->surprise_removed = true; 604 - unregister_netdev(pnetdev); /* will call netdev_close() */ 607 + if (pnetdev->reg_state != NETREG_UNINITIALIZED) 608 + unregister_netdev(pnetdev); /* will call netdev_close() */ 605 609 flush_scheduled_work(); 606 610 udelay(1); 607 611 /* Stop driver mlme relation timer */ ··· 618 614 */ 619 615 usb_put_dev(udev); 620 616 } 617 + firmware_load_fail: 621 618 /* If we didn't unplug usb dongle and remove/insert module, driver 622 619 * fails on sitesurvey for the first time when device is up. 623 620 * Reset usb port for sitesurvey fail issue.