aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-05-22 15:41:20 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-22 15:41:20 -0400
commita3431acf742455ba738c9fb143802d4ad6937164 (patch)
treec4b61cc3e213d5d6592d74000fc43e8eb732ce98
parentb0db5cdf3975134ca967e8b8370a8f0c91ce2329 (diff)
parent0b5a958cf4df3a5cd578b861471e62138f55c85e (diff)
downloadlinux-a3431acf742455ba738c9fb143802d4ad6937164.tar.gz
Merge tag 'linux-can-fixes-for-3.15-20140521' of git://gitorious.org/linux-can/linux-can
Marc Kleine-Budde says: ==================== pull-request: can 2014-05-21 this is a pull request for net/master, for the v3.15 release cycle, with a single patch. Christopher R. Baker found a use after free during unloading of the peak_pci driver. This is fixes in a patch by Stephane Grosjean. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/can/sja1000/peak_pci.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index c540e3d12e3d..564933ae218c 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -551,7 +551,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct sja1000_priv *priv;
struct peak_pci_chan *chan;
- struct net_device *dev;
+ struct net_device *dev, *prev_dev;
void __iomem *cfg_base, *reg_base;
u16 sub_sys_id, icr;
int i, err, channels;
@@ -688,11 +688,13 @@ failure_remove_channels:
writew(0x0, cfg_base + PITA_ICR + 2);
chan = NULL;
- for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
- unregister_sja1000dev(dev);
- free_sja1000dev(dev);
+ for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
priv = netdev_priv(dev);
chan = priv->priv;
+ prev_dev = chan->prev_dev;
+
+ unregister_sja1000dev(dev);
+ free_sja1000dev(dev);
}
/* free any PCIeC resources too */
@@ -726,10 +728,12 @@ static void peak_pci_remove(struct pci_dev *pdev)
/* Loop over all registered devices */
while (1) {
+ struct net_device *prev_dev = chan->prev_dev;
+
dev_info(&pdev->dev, "removing device %s\n", dev->name);
unregister_sja1000dev(dev);
free_sja1000dev(dev);
- dev = chan->prev_dev;
+ dev = prev_dev;
if (!dev) {
/* do that only for first channel */