On Mon, 19 Jul 2021 06:42:25 -0700 syzbot <syzbot+cc699626e48a6ebaf295@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote: > Hello, > > syzbot found the following issue on: > > HEAD commit: 8096acd7442e Merge tag 'net-5.14-rc2' of > git://git.kernel... git tree: upstream > console output: > https://syzkaller.appspot.com/x/log.txt?x=167ca94a300000 kernel > config: https://syzkaller.appspot.com/x/.config?x=5294764a378649cb > dashboard link: > https://syzkaller.appspot.com/bug?extid=cc699626e48a6ebaf295 > compiler: Debian clang version 11.0.1-2 syz repro: > https://syzkaller.appspot.com/x/repro.syz?x=14d68024300000 C > reproducer: https://syzkaller.appspot.com/x/repro.c?x=16e4f180300000 > > IMPORTANT: if you fix the issue, please add the following tag to the > commit: Reported-by: > syzbot+cc699626e48a6ebaf295@xxxxxxxxxxxxxxxxxxxxxxxxx > > ================================================================== > BUG: KASAN: slab-out-of-bounds in debug_spin_lock_before > kernel/locking/spinlock_debug.c:83 [inline] BUG: KASAN: > slab-out-of-bounds in do_raw_spin_lock+0x4f5/0x8e0 > kernel/locking/spinlock_debug.c:112 Read of size 4 at addr > ffff88802b46ce14 by task kworker/0:6/8471 > I don't see any reason behind doing clean up stuff in firmware callback. In my prevoius patch to this driver I fixed memory leak and, I believed, that this approach won't trigger anything else... Let's just call device_release_driver() under parent lock in case of firmware load failure and see if it works. #syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master With regards, Pavel Skripkin
>From 754dff1a4e90cf0b41ab4dc3a06226738385476f Mon Sep 17 00:00:00 2001 From: Pavel Skripkin <paskripkin@xxxxxxxxx> Date: Tue, 20 Jul 2021 14:05:02 +0300 Subject: [PATCH] staging: rtl8712: rewrite error handling /* .... */ Signed-off-by: Pavel Skripkin <paskripkin@xxxxxxxxx> --- drivers/staging/rtl8712/hal_init.c | 30 ++++++++++++------ drivers/staging/rtl8712/usb_intf.c | 50 +++++++++++++----------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 22974277afa0..4eff3fdecdb8 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -29,21 +29,31 @@ #define FWBUFF_ALIGN_SZ 512 #define MAX_DUMP_FWSZ (48 * 1024) +static void rtl871x_load_fw_fail(struct _adapter *adapter) +{ + struct usb_device *udev = adapter->dvobjpriv.pusbdev; + struct device *dev = &udev->dev; + struct device *parent = dev->parent; + + complete(&adapter->rtl8712_fw_ready); + + dev_err(&udev->dev, "r8712u: Firmware request failed\n"); + + if (parent) + device_lock(parent); + + device_release_driver(dev); + + if (parent) + device_unlock(parent); +} + static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) { struct _adapter *adapter = context; if (!firmware) { - struct usb_device *udev = adapter->dvobjpriv.pusbdev; - struct usb_interface *usb_intf = adapter->pusb_intf; - - dev_err(&udev->dev, "r8712u: Firmware request failed\n"); - usb_put_dev(udev); - usb_set_intfdata(usb_intf, NULL); - r8712_free_drv_sw(adapter); - adapter->dvobj_deinit(adapter); - complete(&adapter->rtl8712_fw_ready); - free_netdev(adapter->pnetdev); + rtl871x_load_fw_fail(adapter); return; } adapter->fw = firmware; diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 2434b13c8b12..6440febfd08d 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -591,35 +591,29 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) { struct net_device *pnetdev = usb_get_intfdata(pusb_intf); struct usb_device *udev = interface_to_usbdev(pusb_intf); + struct _adapter *padapter = netdev_priv(pnetdev); + + /* never exit with a firmware callback pending */ + wait_for_completion(&padapter->rtl8712_fw_ready); + usb_set_intfdata(pusb_intf, NULL); + release_firmware(padapter->fw); + if (drvpriv.drv_registered) + padapter->surprise_removed = true; + if (pnetdev->reg_state != NETREG_UNINITIALIZED) + unregister_netdev(pnetdev); /* will call netdev_close() */ + flush_scheduled_work(); + udelay(1); + /* Stop driver mlme relation timer */ + r8712_stop_drv_timers(padapter); + r871x_dev_unload(padapter); + r8712_free_drv_sw(padapter); + free_netdev(pnetdev); + + /* decrease the reference count of the usb device structure + * when disconnect + */ + usb_put_dev(udev); - if (pnetdev) { - struct _adapter *padapter = netdev_priv(pnetdev); - - /* 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; - if (pnetdev->reg_state != NETREG_UNINITIALIZED) - unregister_netdev(pnetdev); /* will call netdev_close() */ - flush_scheduled_work(); - udelay(1); - /* Stop driver mlme relation timer */ - r8712_stop_drv_timers(padapter); - r871x_dev_unload(padapter); - r8712_free_drv_sw(padapter); - free_netdev(pnetdev); - - /* decrease the reference count of the usb device structure - * when disconnect - */ - 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. -- 2.32.0