Commit d4ad442b 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 8e888061
...@@ -1761,6 +1761,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1761,6 +1761,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
...@@ -1804,8 +1805,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1804,8 +1805,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,
...@@ -1817,7 +1820,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1817,7 +1820,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)
...@@ -1825,6 +1828,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, ...@@ -1825,6 +1828,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