KVM: add missing compat KVM_CLEAR_DIRTY_LOG
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: 2a31b9db15
("kvm: introduce manual dirty log reprotect")
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Родитель
7477565433
Коммит
8750f9bbda
|
@ -4391,6 +4391,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,
|
static long kvm_vm_compat_ioctl(struct file *filp,
|
||||||
unsigned int ioctl, unsigned long arg)
|
unsigned int ioctl, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -4400,6 +4410,24 @@ static long kvm_vm_compat_ioctl(struct file *filp,
|
||||||
if (kvm->mm != current->mm)
|
if (kvm->mm != current->mm)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
switch (ioctl) {
|
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: {
|
case KVM_GET_DIRTY_LOG: {
|
||||||
struct compat_kvm_dirty_log compat_log;
|
struct compat_kvm_dirty_log compat_log;
|
||||||
struct kvm_dirty_log log;
|
struct kvm_dirty_log log;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче