From: Rustam Kovhaev <rkovh...@gmail.com>

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+80899a8a8efe8968c...@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=80899a8a8efe8968cde7
Signed-off-by: Rustam Kovhaev <rkovh...@gmail.com>
Cc: stable <sta...@vger.kernel.org>
Link: https://lore.kernel.org/r/20200716151324.1036204-1-rkovh...@gmail.com
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 drivers/staging/rtl8712/hal_init.c |    3 ++-
 drivers/staging/rtl8712/usb_intf.c |   11 ++++++++---
 2 files changed, 10 insertions(+), 4 deletions(-)

--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -33,7 +33,6 @@ static void rtl871x_load_fw_cb(const str
 {
        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 str
                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";
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -595,13 +595,17 @@ static void r871xu_dev_remove(struct usb
        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
                 */
                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.


Reply via email to