[PATCH] hostap: Do not free local->hw_priv before unregistering netdev
local->hw_priv was being freed and set to NULL just before calling prism2_free_local_data(). However, this may expose a race condition in which something ends up trying to use hw_priv during shutdown. I haven't noticed this happening, but better be safe than sorry, so let's postpone hw_priv freeing to happen only after prism2_free_local_data() has returned. Signed-off-by: Jouni Malinen <jkmaline@cc.hut.fi> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
committed by
Jeff Garzik
parent
f7a7444755
commit
c355184cd3
@@ -565,13 +565,14 @@ static void prism2_detach(dev_link_t *link)
|
|||||||
*linkp = link->next;
|
*linkp = link->next;
|
||||||
/* release net devices */
|
/* release net devices */
|
||||||
if (link->priv) {
|
if (link->priv) {
|
||||||
|
struct hostap_cs_priv *hw_priv;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct hostap_interface *iface;
|
struct hostap_interface *iface;
|
||||||
dev = link->priv;
|
dev = link->priv;
|
||||||
iface = netdev_priv(dev);
|
iface = netdev_priv(dev);
|
||||||
kfree(iface->local->hw_priv);
|
hw_priv = iface->local->hw_priv;
|
||||||
iface->local->hw_priv = NULL;
|
|
||||||
prism2_free_local_data(dev);
|
prism2_free_local_data(dev);
|
||||||
|
kfree(hw_priv);
|
||||||
}
|
}
|
||||||
kfree(link);
|
kfree(link);
|
||||||
}
|
}
|
||||||
|
@@ -358,8 +358,6 @@ static int prism2_pci_probe(struct pci_dev *pdev,
|
|||||||
return hostap_hw_ready(dev);
|
return hostap_hw_ready(dev);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
kfree(hw_priv);
|
|
||||||
|
|
||||||
if (irq_registered && dev)
|
if (irq_registered && dev)
|
||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
|
|
||||||
@@ -370,10 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
|
|||||||
|
|
||||||
err_out_disable:
|
err_out_disable:
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
kfree(hw_priv);
|
|
||||||
if (local)
|
|
||||||
local->hw_priv = NULL;
|
|
||||||
prism2_free_local_data(dev);
|
prism2_free_local_data(dev);
|
||||||
|
kfree(hw_priv);
|
||||||
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@@ -398,9 +394,8 @@ static void prism2_pci_remove(struct pci_dev *pdev)
|
|||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
|
|
||||||
mem_start = hw_priv->mem_start;
|
mem_start = hw_priv->mem_start;
|
||||||
kfree(hw_priv);
|
|
||||||
iface->local->hw_priv = NULL;
|
|
||||||
prism2_free_local_data(dev);
|
prism2_free_local_data(dev);
|
||||||
|
kfree(hw_priv);
|
||||||
|
|
||||||
iounmap(mem_start);
|
iounmap(mem_start);
|
||||||
|
|
||||||
|
@@ -568,10 +568,8 @@ static int prism2_plx_probe(struct pci_dev *pdev,
|
|||||||
return hostap_hw_ready(dev);
|
return hostap_hw_ready(dev);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
kfree(hw_priv);
|
|
||||||
if (local)
|
|
||||||
local->hw_priv = NULL;
|
|
||||||
prism2_free_local_data(dev);
|
prism2_free_local_data(dev);
|
||||||
|
kfree(hw_priv);
|
||||||
|
|
||||||
if (irq_registered && dev)
|
if (irq_registered && dev)
|
||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
@@ -604,9 +602,8 @@ static void prism2_plx_remove(struct pci_dev *pdev)
|
|||||||
if (dev->irq)
|
if (dev->irq)
|
||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
|
|
||||||
kfree(iface->local->hw_priv);
|
|
||||||
iface->local->hw_priv = NULL;
|
|
||||||
prism2_free_local_data(dev);
|
prism2_free_local_data(dev);
|
||||||
|
kfree(hw_priv);
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user