| From d1e61a353f9049a9192a1d08cdb18cedfc336783 Mon Sep 17 00:00:00 2001 |
| From: Marc Zyngier <marc.zyngier@arm.com> |
| Date: Thu, 16 Mar 2017 18:20:50 +0000 |
| Subject: [PATCH] arm/arm64: KVM: Take mmap_sem in |
| kvm_arch_prepare_memory_region |
| |
| commit 72f310481a08db821b614e7b5d00febcc9064b36 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c |
| index 7bc33138c746..b3063ee63593 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, |
| (KVM_PHYS_SIZE >> PAGE_SHIFT)) |
| return -EFAULT; |
| |
| + down_read(¤t->mm->mmap_sem); |
| /* |
| * A memory region could potentially cover multiple VMAs, and any holes |
| * 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, |
| pa += vm_start - vma->vm_start; |
| |
| /* IO region dirty page logging not allowed */ |
| - if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) |
| - return -EINVAL; |
| + if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) { |
| + ret = -EINVAL; |
| + goto out; |
| + } |
| |
| ret = kvm_phys_addr_ioremap(kvm, gpa, pa, |
| vm_end - vm_start, |
| @@ -1859,7 +1862,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, |
| } while (hva < reg_end); |
| |
| if (change == KVM_MR_FLAGS_ONLY) |
| - return ret; |
| + goto out; |
| |
| spin_lock(&kvm->mmu_lock); |
| if (ret) |
| @@ -1867,6 +1870,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, |
| else |
| stage2_flush_memslot(kvm, memslot); |
| spin_unlock(&kvm->mmu_lock); |
| +out: |
| + up_read(¤t->mm->mmap_sem); |
| return ret; |
| } |
| |
| -- |
| 2.12.0 |
| |