ipack: tpci200: fix many double free issues in tpci200_pci_probe
[ Upstream commit 57a1681095f912239c7fb4d66683ab0425973838 ] 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 9272e5d0028d ("ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe"). Fixes: 9272e5d0028d ("ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe") Cc: stable@vger.kernel.org Reported-by: Dongliang Mu <mudongliangabcd@gmail.com> Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com> Link: https://lore.kernel.org/r/20210810100323.3938492-1-mudongliangabcd@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
cb7aa51031
commit
280d66b317
@ -91,16 +91,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,
|
||||||
@ -529,7 +526,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);
|
||||||
@ -540,7 +537,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_nocache(
|
tpci200->info->cfg_regs = ioremap_nocache(
|
||||||
pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
|
pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
|
||||||
@ -548,7 +545,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
|
||||||
@ -571,7 +568,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 */
|
||||||
@ -583,7 +580,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 */
|
||||||
@ -594,19 +591,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;
|
||||||
}
|
}
|
||||||
@ -616,6 +610,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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user