diff options
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 5113cbf75674..a044856bd02b 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -660,7 +660,7 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
660 | goto out; | 660 | goto out; |
661 | if (mem->guest_phys_addr & (PAGE_SIZE - 1)) | 661 | if (mem->guest_phys_addr & (PAGE_SIZE - 1)) |
662 | goto out; | 662 | goto out; |
663 | if (mem->slot >= KVM_MEMORY_SLOTS) | 663 | if (mem->slot >= KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS) |
664 | goto out; | 664 | goto out; |
665 | if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) | 665 | if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) |
666 | goto out; | 666 | goto out; |
@@ -797,6 +797,8 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, | |||
797 | kvm_userspace_memory_region *mem, | 797 | kvm_userspace_memory_region *mem, |
798 | int user_alloc) | 798 | int user_alloc) |
799 | { | 799 | { |
800 | if (mem->slot >= KVM_MEMORY_SLOTS) | ||
801 | return -EINVAL; | ||
800 | return kvm_set_memory_region(kvm, mem, user_alloc); | 802 | return kvm_set_memory_region(kvm, mem, user_alloc); |
801 | } | 803 | } |
802 | 804 | ||
@@ -1010,6 +1012,22 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) | |||
1010 | return __gfn_to_memslot(kvm, gfn); | 1012 | return __gfn_to_memslot(kvm, gfn); |
1011 | } | 1013 | } |
1012 | 1014 | ||
1015 | int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) | ||
1016 | { | ||
1017 | int i; | ||
1018 | |||
1019 | gfn = unalias_gfn(kvm, gfn); | ||
1020 | for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { | ||
1021 | struct kvm_memory_slot *memslot = &kvm->memslots[i]; | ||
1022 | |||
1023 | if (gfn >= memslot->base_gfn | ||
1024 | && gfn < memslot->base_gfn + memslot->npages) | ||
1025 | return 1; | ||
1026 | } | ||
1027 | return 0; | ||
1028 | } | ||
1029 | EXPORT_SYMBOL_GPL(kvm_is_visible_gfn); | ||
1030 | |||
1013 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) | 1031 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) |
1014 | { | 1032 | { |
1015 | struct kvm_memory_slot *slot; | 1033 | struct kvm_memory_slot *slot; |
@@ -3087,6 +3105,8 @@ static struct page *kvm_vm_nopage(struct vm_area_struct *vma, | |||
3087 | struct page *page; | 3105 | struct page *page; |
3088 | 3106 | ||
3089 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; | 3107 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; |
3108 | if (!kvm_is_visible_gfn(kvm, pgoff)) | ||
3109 | return NOPAGE_SIGBUS; | ||
3090 | page = gfn_to_page(kvm, pgoff); | 3110 | page = gfn_to_page(kvm, pgoff); |
3091 | if (is_error_page(page)) { | 3111 | if (is_error_page(page)) { |
3092 | kvm_release_page(page); | 3112 | kvm_release_page(page); |