aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2017-03-16 14:20:50 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2017-03-20 06:48:35 -0400
commit72f310481a08db821b614e7b5d00febcc9064b36 (patch)
tree9de080bee8b65cb651087d7ec027ee3d59448423
parent90f6e150e44a0dc3883110eeb3ab35d1be42b6bb (diff)
arm/arm64: KVM: Take mmap_sem in kvm_arch_prepare_memory_region
We don't hold the mmap_sem while searching for VMAs (via find_vma), in kvm_arch_prepare_memory_region, which can end up in expected failures. Fixes: commit 8eef91239e57 ("arm/arm64: KVM: map MMIO regions at creation time") Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Eric Auger <eric.auger@rehat.com> Cc: stable@vger.kernel.org # v3.18+ Reviewed-by: Christoffer Dall <cdall@linaro.org> [ Handle dirty page logging failure case ] Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--arch/arm/kvm/mmu.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index f2e2e0c6d6fd..13b9c1fa8961 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1803,6 +1803,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
1803 (KVM_PHYS_SIZE >> PAGE_SHIFT)) 1803 (KVM_PHYS_SIZE >> PAGE_SHIFT))
1804 return -EFAULT; 1804 return -EFAULT;
1805 1805
1806 down_read(&current->mm->mmap_sem);
1806 /* 1807 /*
1807 * A memory region could potentially cover multiple VMAs, and any holes 1808 * A memory region could potentially cover multiple VMAs, and any holes
1808 * between them, so iterate over all of them to find out if we can map 1809 * between them, so iterate over all of them to find out if we can map
@@ -1846,8 +1847,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
1846 pa += vm_start - vma->vm_start; 1847 pa += vm_start - vma->vm_start;
1847 1848
1848 /* IO region dirty page logging not allowed */ 1849 /* IO region dirty page logging not allowed */
1849 if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) 1850 if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) {
1850 return -EINVAL; 1851 ret = -EINVAL;
1852 goto out;
1853 }
1851 1854
1852 ret = kvm_phys_addr_ioremap(kvm, gpa, pa, 1855 ret = kvm_phys_addr_ioremap(kvm, gpa, pa,
1853 vm_end - vm_start, 1856 vm_end - vm_start,
@@ -1859,7 +1862,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
1859 } while (hva < reg_end); 1862 } while (hva < reg_end);
1860 1863
1861 if (change == KVM_MR_FLAGS_ONLY) 1864 if (change == KVM_MR_FLAGS_ONLY)
1862 return ret; 1865 goto out;
1863 1866
1864 spin_lock(&kvm->mmu_lock); 1867 spin_lock(&kvm->mmu_lock);
1865 if (ret) 1868 if (ret)
@@ -1867,6 +1870,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
1867 else 1870 else
1868 stage2_flush_memslot(kvm, memslot); 1871 stage2_flush_memslot(kvm, memslot);
1869 spin_unlock(&kvm->mmu_lock); 1872 spin_unlock(&kvm->mmu_lock);
1873out:
1874 up_read(&current->mm->mmap_sem);
1870 return ret; 1875 return ret;
1871} 1876}
1872 1877