| From 8750f9bbda115f3f79bfe43be85551ee5e12b6ff Mon Sep 17 00:00:00 2001 |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| Date: Tue, 27 Jul 2021 08:43:10 -0400 |
| Subject: KVM: add missing compat KVM_CLEAR_DIRTY_LOG |
| |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| |
| commit 8750f9bbda115f3f79bfe43be85551ee5e12b6ff upstream. |
| |
| The arguments to the KVM_CLEAR_DIRTY_LOG ioctl include a pointer, |
| therefore it needs a compat ioctl implementation. Otherwise, |
| 32-bit userspace fails to invoke it on 64-bit kernels; for x86 |
| it might work fine by chance if the padding is zero, but not |
| on big-endian architectures. |
| |
| Reported-by: Thomas Sattler |
| Cc: stable@vger.kernel.org |
| Fixes: 2a31b9db1535 ("kvm: introduce manual dirty log reprotect") |
| Reviewed-by: Peter Xu <peterx@redhat.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| virt/kvm/kvm_main.c | 28 ++++++++++++++++++++++++++++ |
| 1 file changed, 28 insertions(+) |
| |
| --- a/virt/kvm/kvm_main.c |
| +++ b/virt/kvm/kvm_main.c |
| @@ -3896,6 +3896,16 @@ struct compat_kvm_dirty_log { |
| }; |
| }; |
| |
| +struct compat_kvm_clear_dirty_log { |
| + __u32 slot; |
| + __u32 num_pages; |
| + __u64 first_page; |
| + union { |
| + compat_uptr_t dirty_bitmap; /* one bit per page */ |
| + __u64 padding2; |
| + }; |
| +}; |
| + |
| static long kvm_vm_compat_ioctl(struct file *filp, |
| unsigned int ioctl, unsigned long arg) |
| { |
| @@ -3905,6 +3915,24 @@ static long kvm_vm_compat_ioctl(struct f |
| if (kvm->mm != current->mm) |
| return -EIO; |
| switch (ioctl) { |
| +#ifdef CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT |
| + case KVM_CLEAR_DIRTY_LOG: { |
| + struct compat_kvm_clear_dirty_log compat_log; |
| + struct kvm_clear_dirty_log log; |
| + |
| + if (copy_from_user(&compat_log, (void __user *)arg, |
| + sizeof(compat_log))) |
| + return -EFAULT; |
| + log.slot = compat_log.slot; |
| + log.num_pages = compat_log.num_pages; |
| + log.first_page = compat_log.first_page; |
| + log.padding2 = compat_log.padding2; |
| + log.dirty_bitmap = compat_ptr(compat_log.dirty_bitmap); |
| + |
| + r = kvm_vm_ioctl_clear_dirty_log(kvm, &log); |
| + break; |
| + } |
| +#endif |
| case KVM_GET_DIRTY_LOG: { |
| struct compat_kvm_dirty_log compat_log; |
| struct kvm_dirty_log log; |