summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2019-04-17 09:28:44 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2019-04-30 15:22:15 -0400
commit76d58e0f07ec203bbdfcaabd9a9fc10a5a3ed5ea (patch)
tree8cf55a1022132806b63cceb24b286514c2210e34 /virt
parent0699c64a4be6e4a6137240379a1f82c752e663d8 (diff)
KVM: fix KVM_CLEAR_DIRTY_LOG for memory slots of unaligned size
If a memory slot's size is not a multiple of 64 pages (256K), then the KVM_CLEAR_DIRTY_LOG API is unusable: clearing the final 64 pages either requires the requested page range to go beyond memslot->npages, or requires log->num_pages to be unaligned, and kvm_clear_dirty_log_protect requires log->num_pages to be both in range and aligned. To allow this case, allow log->num_pages not to be a multiple of 64 if it ends exactly on the last page of the slot. Reported-by: Peter Xu <peterx@redhat.com> Fixes: 98938aa8edd6 ("KVM: validate userspace input in kvm_clear_dirty_log_protect()", 2019-01-02) Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/kvm_main.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index dc8edc97ba85..a704d1f9bd96 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1240,7 +1240,7 @@ int kvm_clear_dirty_log_protect(struct kvm *kvm,
1240 if (as_id >= KVM_ADDRESS_SPACE_NUM || id >= KVM_USER_MEM_SLOTS) 1240 if (as_id >= KVM_ADDRESS_SPACE_NUM || id >= KVM_USER_MEM_SLOTS)
1241 return -EINVAL; 1241 return -EINVAL;
1242 1242
1243 if ((log->first_page & 63) || (log->num_pages & 63)) 1243 if (log->first_page & 63)
1244 return -EINVAL; 1244 return -EINVAL;
1245 1245
1246 slots = __kvm_memslots(kvm, as_id); 1246 slots = __kvm_memslots(kvm, as_id);
@@ -1253,8 +1253,9 @@ int kvm_clear_dirty_log_protect(struct kvm *kvm,
1253 n = kvm_dirty_bitmap_bytes(memslot); 1253 n = kvm_dirty_bitmap_bytes(memslot);
1254 1254
1255 if (log->first_page > memslot->npages || 1255 if (log->first_page > memslot->npages ||
1256 log->num_pages > memslot->npages - log->first_page) 1256 log->num_pages > memslot->npages - log->first_page ||
1257 return -EINVAL; 1257 (log->num_pages < memslot->npages - log->first_page && (log->num_pages & 63)))
1258 return -EINVAL;
1258 1259
1259 *flush = false; 1260 *flush = false;
1260 dirty_bitmap_buffer = kvm_second_dirty_bitmap(memslot); 1261 dirty_bitmap_buffer = kvm_second_dirty_bitmap(memslot);