Skip to content

Commit e9e6aa5

Browse files
pskrgaggregkh
authored andcommitted
staging: rtl8712: error handling refactoring
There was strange error handling logic in case of fw load failure. For some reason fw loader callback was doing clean up stuff when fw is not available. I don't see any reason behind doing this. Since this driver doesn't have EEPROM firmware let's just disconnect it in case of fw load failure. Doing clean up stuff in 2 different place which can run concurently is not good idea and syzbot found 2 bugs related to this strange approach. So, in this pacth I deleted all clean up code from fw callback and made a call to device_release_driver() under device_lock(parent) in case of fw load failure. This approach is more generic and it defend driver from UAF bugs, since all clean up code is moved to one place. Fixes: e02a3b9 ("staging: rtl8712: fix memory leak in rtl871x_load_fw_cb") Fixes: 8c213fa ("staging: r8712u: Use asynchronous firmware loading") Cc: stable <[email protected]> Reported-and-tested-by: [email protected] Reported-and-tested-by: [email protected] Signed-off-by: Pavel Skripkin <[email protected]> Link: https://lore.kernel.org/r/d49ecc56e97c4df181d7bd4d240b031f315eacc3.1626895918.git.paskripkin@gmail.com Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9be550e commit e9e6aa5

File tree

2 files changed

+43
-39
lines changed

2 files changed

+43
-39
lines changed

drivers/staging/rtl8712/hal_init.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,31 @@
2929
#define FWBUFF_ALIGN_SZ 512
3030
#define MAX_DUMP_FWSZ (48 * 1024)
3131

32+
static void rtl871x_load_fw_fail(struct _adapter *adapter)
33+
{
34+
struct usb_device *udev = adapter->dvobjpriv.pusbdev;
35+
struct device *dev = &udev->dev;
36+
struct device *parent = dev->parent;
37+
38+
complete(&adapter->rtl8712_fw_ready);
39+
40+
dev_err(&udev->dev, "r8712u: Firmware request failed\n");
41+
42+
if (parent)
43+
device_lock(parent);
44+
45+
device_release_driver(dev);
46+
47+
if (parent)
48+
device_unlock(parent);
49+
}
50+
3251
static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
3352
{
3453
struct _adapter *adapter = context;
3554

3655
if (!firmware) {
37-
struct usb_device *udev = adapter->dvobjpriv.pusbdev;
38-
struct usb_interface *usb_intf = adapter->pusb_intf;
39-
40-
dev_err(&udev->dev, "r8712u: Firmware request failed\n");
41-
usb_put_dev(udev);
42-
usb_set_intfdata(usb_intf, NULL);
43-
r8712_free_drv_sw(adapter);
44-
adapter->dvobj_deinit(adapter);
45-
complete(&adapter->rtl8712_fw_ready);
46-
free_netdev(adapter->pnetdev);
56+
rtl871x_load_fw_fail(adapter);
4757
return;
4858
}
4959
adapter->fw = firmware;

drivers/staging/rtl8712/usb_intf.c

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -591,36 +591,30 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
591591
{
592592
struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
593593
struct usb_device *udev = interface_to_usbdev(pusb_intf);
594+
struct _adapter *padapter = netdev_priv(pnetdev);
595+
596+
/* never exit with a firmware callback pending */
597+
wait_for_completion(&padapter->rtl8712_fw_ready);
598+
usb_set_intfdata(pusb_intf, NULL);
599+
release_firmware(padapter->fw);
600+
if (drvpriv.drv_registered)
601+
padapter->surprise_removed = true;
602+
if (pnetdev->reg_state != NETREG_UNINITIALIZED)
603+
unregister_netdev(pnetdev); /* will call netdev_close() */
604+
r8712_flush_rwctrl_works(padapter);
605+
r8712_flush_led_works(padapter);
606+
udelay(1);
607+
/* Stop driver mlme relation timer */
608+
r8712_stop_drv_timers(padapter);
609+
r871x_dev_unload(padapter);
610+
r8712_free_drv_sw(padapter);
611+
free_netdev(pnetdev);
612+
613+
/* decrease the reference count of the usb device structure
614+
* when disconnect
615+
*/
616+
usb_put_dev(udev);
594617

595-
if (pnetdev) {
596-
struct _adapter *padapter = netdev_priv(pnetdev);
597-
598-
/* never exit with a firmware callback pending */
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);
605-
if (drvpriv.drv_registered)
606-
padapter->surprise_removed = true;
607-
if (pnetdev->reg_state != NETREG_UNINITIALIZED)
608-
unregister_netdev(pnetdev); /* will call netdev_close() */
609-
r8712_flush_rwctrl_works(padapter);
610-
r8712_flush_led_works(padapter);
611-
udelay(1);
612-
/* Stop driver mlme relation timer */
613-
r8712_stop_drv_timers(padapter);
614-
r871x_dev_unload(padapter);
615-
r8712_free_drv_sw(padapter);
616-
free_netdev(pnetdev);
617-
618-
/* decrease the reference count of the usb device structure
619-
* when disconnect
620-
*/
621-
usb_put_dev(udev);
622-
}
623-
firmware_load_fail:
624618
/* If we didn't unplug usb dongle and remove/insert module, driver
625619
* fails on sitesurvey for the first time when device is up.
626620
* Reset usb port for sitesurvey fail issue.

0 commit comments

Comments
 (0)