diff mbox series

net: can: fix use-after-free in ems_usb_disconnect

Message ID 20210617185130.5834-1-paskripkin@gmail.com (mailing list archive)
State Awaiting Upstream
Delegated to: Netdev Maintainers
Headers show
Series net: can: fix use-after-free in ems_usb_disconnect | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Guessed tree name to be net-next
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cc_maintainers fail 1 blamed authors not CCed: haas@ems-wuensche.com; 4 maintainers not CCed: socketcan@hartkopp.net mailhol.vincent@wanadoo.fr kuba@kernel.org haas@ems-wuensche.com
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 15 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link

Commit Message

Pavel Skripkin June 17, 2021, 6:51 p.m. UTC
In ems_usb_disconnect() dev pointer, which is
netdev private data, is used after free_candev() call:

	if (dev) {
		unregister_netdev(dev->netdev);
		free_candev(dev->netdev);

		unlink_all_urbs(dev);

		usb_free_urb(dev->intr_urb);

		kfree(dev->intr_in_buffer);
		kfree(dev->tx_msg_buffer);
	}

Fix it by simply moving free_candev() at the end of
the block.

Fail log:
 BUG: KASAN: use-after-free in ems_usb_disconnect
 Read of size 8 at addr ffff88804e041008 by task kworker/1:2/2895

 CPU: 1 PID: 2895 Comm: kworker/1:2 Not tainted 5.13.0-rc5+ #164
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a-rebuilt.opensuse.4
 Workqueue: usb_hub_wq hub_event
 Call Trace:
     dump_stack (lib/dump_stack.c:122)
     print_address_description.constprop.0.cold (mm/kasan/report.c:234)
     kasan_report.cold (mm/kasan/report.c:420 mm/kasan/report.c:436)
     ems_usb_disconnect (drivers/net/can/usb/ems_usb.c:683 drivers/net/can/usb/ems_usb.c:1058)

Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface")
Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
---
 drivers/net/can/usb/ems_usb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

Marc Kleine-Budde June 18, 2021, 7:04 a.m. UTC | #1
On 17.06.2021 21:51:30, Pavel Skripkin wrote:
> In ems_usb_disconnect() dev pointer, which is
> netdev private data, is used after free_candev() call:
> 
> 	if (dev) {
> 		unregister_netdev(dev->netdev);
> 		free_candev(dev->netdev);
> 
> 		unlink_all_urbs(dev);
> 
> 		usb_free_urb(dev->intr_urb);
> 
> 		kfree(dev->intr_in_buffer);
> 		kfree(dev->tx_msg_buffer);
> 	}
> 
> Fix it by simply moving free_candev() at the end of
> the block.
> 
> Fail log:
>  BUG: KASAN: use-after-free in ems_usb_disconnect
>  Read of size 8 at addr ffff88804e041008 by task kworker/1:2/2895
> 
>  CPU: 1 PID: 2895 Comm: kworker/1:2 Not tainted 5.13.0-rc5+ #164
>  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a-rebuilt.opensuse.4
>  Workqueue: usb_hub_wq hub_event
>  Call Trace:
>      dump_stack (lib/dump_stack.c:122)
>      print_address_description.constprop.0.cold (mm/kasan/report.c:234)
>      kasan_report.cold (mm/kasan/report.c:420 mm/kasan/report.c:436)
>      ems_usb_disconnect (drivers/net/can/usb/ems_usb.c:683 drivers/net/can/usb/ems_usb.c:1058)
> 
> Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface")
> Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>

Applied to linux-can/testing and added stable on Cc.

Thanks,
Marc
diff mbox series

Patch

diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 5af69787d9d5..0a37af4a3fa4 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -1053,7 +1053,6 @@  static void ems_usb_disconnect(struct usb_interface *intf)
 
 	if (dev) {
 		unregister_netdev(dev->netdev);
-		free_candev(dev->netdev);
 
 		unlink_all_urbs(dev);
 
@@ -1061,6 +1060,8 @@  static void ems_usb_disconnect(struct usb_interface *intf)
 
 		kfree(dev->intr_in_buffer);
 		kfree(dev->tx_msg_buffer);
+
+		free_candev(dev->netdev);
 	}
 }