Commit b4383c97 authored by Rustam Kovhaev's avatar Rustam Kovhaev Committed by Greg Kroah-Hartman

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=80899a8a8efe8968cde7Signed-off-by: default avatarRustam Kovhaev <rkovhaev@gmail.com>
Cc: stable <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200716151324.1036204-1-rkovhaev@gmail.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c4283950
...@@ -33,7 +33,6 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) ...@@ -33,7 +33,6 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
{ {
struct _adapter *adapter = context; struct _adapter *adapter = context;
complete(&adapter->rtl8712_fw_ready);
if (!firmware) { if (!firmware) {
struct usb_device *udev = adapter->dvobjpriv.pusbdev; struct usb_device *udev = adapter->dvobjpriv.pusbdev;
struct usb_interface *usb_intf = adapter->pusb_intf; struct usb_interface *usb_intf = adapter->pusb_intf;
...@@ -41,11 +40,13 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) ...@@ -41,11 +40,13 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
dev_err(&udev->dev, "r8712u: Firmware request failed\n"); dev_err(&udev->dev, "r8712u: Firmware request failed\n");
usb_put_dev(udev); usb_put_dev(udev);
usb_set_intfdata(usb_intf, NULL); usb_set_intfdata(usb_intf, NULL);
complete(&adapter->rtl8712_fw_ready);
return; return;
} }
adapter->fw = firmware; adapter->fw = firmware;
/* firmware available - start netdev */ /* firmware available - start netdev */
register_netdev(adapter->pnetdev); register_netdev(adapter->pnetdev);
complete(&adapter->rtl8712_fw_ready);
} }
static const char firmware_file[] = "rtlwifi/rtl8712u.bin"; static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
......
...@@ -595,12 +595,16 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) ...@@ -595,12 +595,16 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
if (pnetdev) { if (pnetdev) {
struct _adapter *padapter = netdev_priv(pnetdev); struct _adapter *padapter = netdev_priv(pnetdev);
usb_set_intfdata(pusb_intf, NULL);
release_firmware(padapter->fw);
/* never exit with a firmware callback pending */ /* never exit with a firmware callback pending */
wait_for_completion(&padapter->rtl8712_fw_ready); wait_for_completion(&padapter->rtl8712_fw_ready);
pnetdev = usb_get_intfdata(pusb_intf);
usb_set_intfdata(pusb_intf, NULL);
if (!pnetdev)
goto firmware_load_fail;
release_firmware(padapter->fw);
if (drvpriv.drv_registered) if (drvpriv.drv_registered)
padapter->surprise_removed = true; padapter->surprise_removed = true;
if (pnetdev->reg_state != NETREG_UNINITIALIZED)
unregister_netdev(pnetdev); /* will call netdev_close() */ unregister_netdev(pnetdev); /* will call netdev_close() */
flush_scheduled_work(); flush_scheduled_work();
udelay(1); udelay(1);
...@@ -614,6 +618,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) ...@@ -614,6 +618,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
*/ */
usb_put_dev(udev); usb_put_dev(udev);
} }
firmware_load_fail:
/* If we didn't unplug usb dongle and remove/insert module, driver /* If we didn't unplug usb dongle and remove/insert module, driver
* fails on sitesurvey for the first time when device is up. * fails on sitesurvey for the first time when device is up.
* Reset usb port for sitesurvey fail issue. * Reset usb port for sitesurvey fail issue.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment