Commit a1ea3189 authored by Marc Zyngier's avatar Marc Zyngier Committed by Greg Kroah-Hartman

arm/arm64: KVM: Take mmap_sem in kvm_arch_prepare_memory_region

commit 72f31048 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 8eef9123 ("arm/arm64: KVM: map MMIO regions at creation time")
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Eric Auger <eric.auger@rehat.com>
Reviewed-by: default avatarChristoffer Dall <cdall@linaro.org>
[ Handle dirty page logging failure case ]
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 48f2825a
...@@ -1806,6 +1806,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1806,6 +1806,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
(KVM_PHYS_SIZE >> PAGE_SHIFT)) (KVM_PHYS_SIZE >> PAGE_SHIFT))
return -EFAULT; return -EFAULT;
down_read(&current->mm->mmap_sem);
/* /*
* A memory region could potentially cover multiple VMAs, and any holes * 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 * between them, so iterate over all of them to find out if we can map
...@@ -1849,8 +1850,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1849,8 +1850,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
pa += vm_start - vma->vm_start; pa += vm_start - vma->vm_start;
/* IO region dirty page logging not allowed */ /* IO region dirty page logging not allowed */
if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) {
return -EINVAL; ret = -EINVAL;
goto out;
}
ret = kvm_phys_addr_ioremap(kvm, gpa, pa, ret = kvm_phys_addr_ioremap(kvm, gpa, pa,
vm_end - vm_start, vm_end - vm_start,
...@@ -1862,7 +1865,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1862,7 +1865,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
} while (hva < reg_end); } while (hva < reg_end);
if (change == KVM_MR_FLAGS_ONLY) if (change == KVM_MR_FLAGS_ONLY)
return ret; goto out;
spin_lock(&kvm->mmu_lock); spin_lock(&kvm->mmu_lock);
if (ret) if (ret)
...@@ -1870,6 +1873,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1870,6 +1873,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
else else
stage2_flush_memslot(kvm, memslot); stage2_flush_memslot(kvm, memslot);
spin_unlock(&kvm->mmu_lock); spin_unlock(&kvm->mmu_lock);
out:
up_read(&current->mm->mmap_sem);
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