diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2016-04-15 09:41:35 +0200 |
---|---|---|
committer | Sasha Levin <alexander.levin@microsoft.com> | 2018-01-17 12:29:30 -0500 |
commit | 729cabd84d0fac2c5f7c25b6dcef5adf828a6e73 (patch) | |
tree | bbc6b4521024945d863ed821d41747dfdc55a4cd /arch/s390 | |
parent | 7f9ab5fb771ec358f6239d0c6541ebd1b266e621 (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.c | 16 |
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; } |