]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
staging: rtl8712: handle firmware load failure
authorRustam Kovhaev <rkovhaev@gmail.com>
Thu, 16 Jul 2020 15:13:26 +0000 (08:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Aug 2020 13:33:34 +0000 (15:33 +0200)
commit b4383c971bc5263efe2b0915ba67ebf2bf3f1ee5 upstream.

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>
drivers/staging/rtl8712/hal_init.c
drivers/staging/rtl8712/usb_intf.c

index 40145c0338e458290891f9e36c35cf2622805a2c..42c0a3c947f199c154d40db62cf1f2697b0278c6 100644 (file)
@@ -33,7 +33,6 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
 {
        struct _adapter *adapter = context;
 
-       complete(&adapter->rtl8712_fw_ready);
        if (!firmware) {
                struct usb_device *udev = adapter->dvobjpriv.pusbdev;
                struct usb_interface *usb_intf = adapter->pusb_intf;
@@ -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");
                usb_put_dev(udev);
                usb_set_intfdata(usb_intf, NULL);
+               complete(&adapter->rtl8712_fw_ready);
                return;
        }
        adapter->fw = firmware;
        /* firmware available - start netdev */
        register_netdev(adapter->pnetdev);
+       complete(&adapter->rtl8712_fw_ready);
 }
 
 static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
index a87562f632a7ff07a4f7fb405dbb66ad4764f0da..2fcd65260f4c18b1f9e2465aed024738a61acfc7 100644 (file)
@@ -595,13 +595,17 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
        if (pnetdev) {
                struct _adapter *padapter = netdev_priv(pnetdev);
 
-               usb_set_intfdata(pusb_intf, NULL);
-               release_firmware(padapter->fw);
                /* never exit with a firmware callback pending */
                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)
                        padapter->surprise_removed = true;
-               unregister_netdev(pnetdev); /* will call netdev_close() */
+               if (pnetdev->reg_state != NETREG_UNINITIALIZED)
+                       unregister_netdev(pnetdev); /* will call netdev_close() */
                flush_scheduled_work();
                udelay(1);
                /* Stop driver mlme relation timer */
@@ -614,6 +618,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
                 */
                usb_put_dev(udev);
        }
+firmware_load_fail:
        /* If we didn't unplug usb dongle and remove/insert module, driver
         * fails on sitesurvey for the first time when device is up.
         * Reset usb port for sitesurvey fail issue.