| From 6b285a5587506bae084cf9a3ed5aa491d623b91b Mon Sep 17 00:00:00 2001 |
| From: Sean Christopherson <seanjc@google.com> |
| Date: Thu, 4 Nov 2021 00:25:03 +0000 |
| Subject: KVM: Disallow user memslot with size that exceeds "unsigned long" |
| |
| From: Sean Christopherson <seanjc@google.com> |
| |
| commit 6b285a5587506bae084cf9a3ed5aa491d623b91b upstream. |
| |
| Reject userspace memslots whose size exceeds the storage capacity of an |
| "unsigned long". KVM's uAPI takes the size as u64 to support large slots |
| on 64-bit hosts, but does not account for the size being truncated on |
| 32-bit hosts in various flows. The access_ok() check on the userspace |
| virtual address in particular casts the size to "unsigned long" and will |
| check the wrong number of bytes. |
| |
| KVM doesn't actually support slots whose size doesn't fit in an "unsigned |
| long", e.g. KVM's internal kvm_memory_slot.npages is an "unsigned long", |
| not a "u64", and misc arch specific code follows that behavior. |
| |
| Fixes: fa3d315a4ce2 ("KVM: Validate userspace_addr of memslot when registered") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Sean Christopherson <seanjc@google.com> |
| Reviewed-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com> |
| Message-Id: <20211104002531.1176691-3-seanjc@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| virt/kvm/kvm_main.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/virt/kvm/kvm_main.c |
| +++ b/virt/kvm/kvm_main.c |
| @@ -1297,7 +1297,8 @@ int __kvm_set_memory_region(struct kvm * |
| id = (u16)mem->slot; |
| |
| /* General sanity checks */ |
| - if (mem->memory_size & (PAGE_SIZE - 1)) |
| + if ((mem->memory_size & (PAGE_SIZE - 1)) || |
| + (mem->memory_size != (unsigned long)mem->memory_size)) |
| return -EINVAL; |
| if (mem->guest_phys_addr & (PAGE_SIZE - 1)) |
| return -EINVAL; |