Commit 57a16810 authored by Dongliang Mu's avatar Dongliang Mu Committed by Greg Kroah-Hartman

ipack: tpci200: fix many double free issues in tpci200_pci_probe

The function tpci200_register called by tpci200_install and
tpci200_unregister called by tpci200_uninstall are in pair. However,
tpci200_unregister has some cleanup operations not in the
tpci200_register. So the error handling code of tpci200_pci_probe has
many different double free issues.

Fix this problem by moving those cleanup operations out of
tpci200_unregister, into tpci200_pci_remove and reverting
the previous commit 9272e5d0 ("ipack/carriers/tpci200:
Fix a double free in tpci200_pci_probe").

Fixes: 9272e5d0 ("ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe")
Cc: stable@vger.kernel.org
Reported-by: default avatarDongliang Mu <mudongliangabcd@gmail.com>
Signed-off-by: default avatarDongliang Mu <mudongliangabcd@gmail.com>
Link: https://lore.kernel.org/r/20210810100323.3938492-1-mudongliangabcd@gmail.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d7777253
...@@ -89,16 +89,13 @@ static void tpci200_unregister(struct tpci200_board *tpci200) ...@@ -89,16 +89,13 @@ static void tpci200_unregister(struct tpci200_board *tpci200)
free_irq(tpci200->info->pdev->irq, (void *) tpci200); free_irq(tpci200->info->pdev->irq, (void *) tpci200);
pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs); pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR); pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR); pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
pci_disable_device(tpci200->info->pdev); pci_disable_device(tpci200->info->pdev);
pci_dev_put(tpci200->info->pdev);
} }
static void tpci200_enable_irq(struct tpci200_board *tpci200, static void tpci200_enable_irq(struct tpci200_board *tpci200,
...@@ -527,7 +524,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev, ...@@ -527,7 +524,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL); tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
if (!tpci200->info) { if (!tpci200->info) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_err_info; goto err_tpci200;
} }
pci_dev_get(pdev); pci_dev_get(pdev);
...@@ -538,7 +535,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev, ...@@ -538,7 +535,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory"); dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
ret = -EBUSY; ret = -EBUSY;
goto out_err_pci_request; goto err_tpci200_info;
} }
tpci200->info->cfg_regs = ioremap( tpci200->info->cfg_regs = ioremap(
pci_resource_start(pdev, TPCI200_CFG_MEM_BAR), pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
...@@ -546,7 +543,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev, ...@@ -546,7 +543,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
if (!tpci200->info->cfg_regs) { if (!tpci200->info->cfg_regs) {
dev_err(&pdev->dev, "Failed to map PCI Configuration Memory"); dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
ret = -EFAULT; ret = -EFAULT;
goto out_err_ioremap; goto err_request_region;
} }
/* Disable byte swapping for 16 bit IP module access. This will ensure /* Disable byte swapping for 16 bit IP module access. This will ensure
...@@ -569,7 +566,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev, ...@@ -569,7 +566,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
if (ret) { if (ret) {
dev_err(&pdev->dev, "error during tpci200 install\n"); dev_err(&pdev->dev, "error during tpci200 install\n");
ret = -ENODEV; ret = -ENODEV;
goto out_err_install; goto err_cfg_regs;
} }
/* Register the carrier in the industry pack bus driver */ /* Register the carrier in the industry pack bus driver */
...@@ -581,7 +578,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev, ...@@ -581,7 +578,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
dev_err(&pdev->dev, dev_err(&pdev->dev,
"error registering the carrier on ipack driver\n"); "error registering the carrier on ipack driver\n");
ret = -EFAULT; ret = -EFAULT;
goto out_err_bus_register; goto err_tpci200_install;
} }
/* save the bus number given by ipack to logging purpose */ /* save the bus number given by ipack to logging purpose */
...@@ -592,19 +589,16 @@ static int tpci200_pci_probe(struct pci_dev *pdev, ...@@ -592,19 +589,16 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
tpci200_create_device(tpci200, i); tpci200_create_device(tpci200, i);
return 0; return 0;
out_err_bus_register: err_tpci200_install:
tpci200_uninstall(tpci200); tpci200_uninstall(tpci200);
/* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */ err_cfg_regs:
tpci200->info->cfg_regs = NULL; pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
out_err_install: err_request_region:
if (tpci200->info->cfg_regs)
iounmap(tpci200->info->cfg_regs);
out_err_ioremap:
pci_release_region(pdev, TPCI200_CFG_MEM_BAR); pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
out_err_pci_request: err_tpci200_info:
pci_dev_put(pdev);
kfree(tpci200->info); kfree(tpci200->info);
out_err_info: pci_dev_put(pdev);
err_tpci200:
kfree(tpci200); kfree(tpci200);
return ret; return ret;
} }
...@@ -614,6 +608,12 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200) ...@@ -614,6 +608,12 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200)
ipack_bus_unregister(tpci200->info->ipack_bus); ipack_bus_unregister(tpci200->info->ipack_bus);
tpci200_uninstall(tpci200); tpci200_uninstall(tpci200);
pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
pci_dev_put(tpci200->info->pdev);
kfree(tpci200->info); kfree(tpci200->info);
kfree(tpci200); kfree(tpci200);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment