From 63ee86b476de63b02d7389afd6648c994efc1fed Mon Sep 17 00:00:00 2001 From: Wang Chen Date: Thu, 18 Dec 2008 19:36:46 -0800 Subject: [PATCH] netdevice zd1201: Use after free | commit 17b95c2a4add1cfe47388261356b19b6ff176002 | Author: John W. Linville | Date: Fri Oct 31 14:13:12 2008 -0400 | | netdevice zd1201: Convert directly reference of netdev->priv to netdev_priv() | | We have some reasons to kill netdev->priv: | 1. netdev->priv is equal to netdev_priv(). | 2. netdev_priv() wraps the calculation of netdev->priv's offset, obviously | netdev_priv() is more flexible than netdev->priv. | But we cann't kill netdev->priv, because so many drivers reference to it | directly. | | OK, becasue Dave S. Miller said, "every direct netdev->priv usage is a bug", | and I want to kill netdev->priv later, I decided to convert all the direct | reference of netdev->priv first. | | (Original patch posted by Wang Chen w/ above | changelog but using dev->ml_priv. That doesn't seem appropriate | to me for this driver, so I've revamped it to use netdev_priv() | instead. -- JWL) This commit changed the allocation of netdev, but didn't change the free method of it. This causes "zd" be used after the memory, which is pointed by "zd", being freed by free_netdev(). Signed-off-by: Wang Chen Signed-off-by: David S. Miller --- drivers/net/wireless/zd1201.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 3404807b3e127..b45c27d42fd83 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -1841,10 +1841,6 @@ static void zd1201_disconnect(struct usb_interface *interface) if (!zd) return; usb_set_intfdata(interface, NULL); - if (zd->dev) { - unregister_netdev(zd->dev); - free_netdev(zd->dev); - } hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { hlist_del_init(&frag->fnode); @@ -1860,7 +1856,11 @@ static void zd1201_disconnect(struct usb_interface *interface) usb_kill_urb(zd->rx_urb); usb_free_urb(zd->rx_urb); } - kfree(zd); + + if (zd->dev) { + unregister_netdev(zd->dev); + free_netdev(zd->dev); + } } #ifdef CONFIG_PM -- 2.39.5