Commit 1e52db69 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'vfio-v3.12-rc5' of git://github.com/awilliam/linux-vfio

Pull vfio fix from Alex Williamson:
 "Fix an incorrect break out of nested loop in iommu mapping code"

* tag 'vfio-v3.12-rc5' of git://github.com/awilliam/linux-vfio:
  VFIO: vfio_iommu_type1: fix bug caused by break in nested loop
parents ed8ada39 d93b3ac0
...@@ -545,6 +545,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, ...@@ -545,6 +545,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
long npage; long npage;
int ret = 0, prot = 0; int ret = 0, prot = 0;
uint64_t mask; uint64_t mask;
struct vfio_dma *dma = NULL;
unsigned long pfn;
end = map->iova + map->size; end = map->iova + map->size;
...@@ -587,8 +589,6 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, ...@@ -587,8 +589,6 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
} }
for (iova = map->iova; iova < end; iova += size, vaddr += size) { for (iova = map->iova; iova < end; iova += size, vaddr += size) {
struct vfio_dma *dma = NULL;
unsigned long pfn;
long i; long i;
/* Pin a contiguous chunk of memory */ /* Pin a contiguous chunk of memory */
...@@ -597,16 +597,15 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, ...@@ -597,16 +597,15 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
if (npage <= 0) { if (npage <= 0) {
WARN_ON(!npage); WARN_ON(!npage);
ret = (int)npage; ret = (int)npage;
break; goto out;
} }
/* Verify pages are not already mapped */ /* Verify pages are not already mapped */
for (i = 0; i < npage; i++) { for (i = 0; i < npage; i++) {
if (iommu_iova_to_phys(iommu->domain, if (iommu_iova_to_phys(iommu->domain,
iova + (i << PAGE_SHIFT))) { iova + (i << PAGE_SHIFT))) {
vfio_unpin_pages(pfn, npage, prot, true);
ret = -EBUSY; ret = -EBUSY;
break; goto out_unpin;
} }
} }
...@@ -616,8 +615,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, ...@@ -616,8 +615,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
if (ret) { if (ret) {
if (ret != -EBUSY || if (ret != -EBUSY ||
map_try_harder(iommu, iova, pfn, npage, prot)) { map_try_harder(iommu, iova, pfn, npage, prot)) {
vfio_unpin_pages(pfn, npage, prot, true); goto out_unpin;
break;
} }
} }
...@@ -672,9 +670,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, ...@@ -672,9 +670,8 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
dma = kzalloc(sizeof(*dma), GFP_KERNEL); dma = kzalloc(sizeof(*dma), GFP_KERNEL);
if (!dma) { if (!dma) {
iommu_unmap(iommu->domain, iova, size); iommu_unmap(iommu->domain, iova, size);
vfio_unpin_pages(pfn, npage, prot, true);
ret = -ENOMEM; ret = -ENOMEM;
break; goto out_unpin;
} }
dma->size = size; dma->size = size;
...@@ -685,17 +682,22 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, ...@@ -685,17 +682,22 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
} }
} }
if (ret) { WARN_ON(ret);
struct vfio_dma *tmp; mutex_unlock(&iommu->lock);
return ret;
out_unpin:
vfio_unpin_pages(pfn, npage, prot, true);
out:
iova = map->iova; iova = map->iova;
size = map->size; size = map->size;
while ((tmp = vfio_find_dma(iommu, iova, size))) { while ((dma = vfio_find_dma(iommu, iova, size))) {
int r = vfio_remove_dma_overlap(iommu, iova, int r = vfio_remove_dma_overlap(iommu, iova,
&size, tmp); &size, dma);
if (WARN_ON(r || !size)) if (WARN_ON(r || !size))
break; break;
} }
}
mutex_unlock(&iommu->lock); mutex_unlock(&iommu->lock);
return ret; return ret;
......
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