summaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2016-04-15 09:41:35 +0200
committerSasha Levin <alexander.levin@microsoft.com>2018-01-17 12:29:30 -0500
commit729cabd84d0fac2c5f7c25b6dcef5adf828a6e73 (patch)
treebbc6b4521024945d863ed821d41747dfdc55a4cd /arch/s390
parent7f9ab5fb771ec358f6239d0c6541ebd1b266e621 (diff)
s390/pci: fix use after free in dma_init
[ Upstream commit dba599091c191d209b1499511a524ad9657c0e5a ] After a failure during registration of the dma_table (because of the function being in error state) we free its memory but don't reset the associated pointer to zero. When we then receive a notification from firmware (about the function being in error state) we'll try to walk and free the dma_table again. Fix this by resetting the dma_table pointer. In addition to that make sure that we free the iommu_bitmap when appropriate. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/pci/pci_dma.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 6fd8d5836138..888cc878efaa 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -432,7 +432,7 @@ int zpci_dma_init_device(struct zpci_dev *zdev)
zdev->dma_table = dma_alloc_cpu_table();
if (!zdev->dma_table) {
rc = -ENOMEM;
- goto out_clean;
+ goto out;
}
zdev->iommu_size = (unsigned long) high_memory - PAGE_OFFSET;
@@ -440,7 +440,7 @@ int zpci_dma_init_device(struct zpci_dev *zdev)
zdev->iommu_bitmap = vzalloc(zdev->iommu_pages / 8);
if (!zdev->iommu_bitmap) {
rc = -ENOMEM;
- goto out_reg;
+ goto free_dma_table;
}
rc = zpci_register_ioat(zdev,
@@ -449,12 +449,16 @@ int zpci_dma_init_device(struct zpci_dev *zdev)
zdev->start_dma + zdev->iommu_size - 1,
(u64) zdev->dma_table);
if (rc)
- goto out_reg;
- return 0;
+ goto free_bitmap;
-out_reg:
+ return 0;
+free_bitmap:
+ vfree(zdev->iommu_bitmap);
+ zdev->iommu_bitmap = NULL;
+free_dma_table:
dma_free_cpu_table(zdev->dma_table);
-out_clean:
+ zdev->dma_table = NULL;
+out:
return rc;
}