Skip to content

Commit 1739c70

Browse files
agrafbonzini
authored andcommitted
KVM: x86: Add compat handler for KVM_X86_SET_MSR_FILTER
The KVM_X86_SET_MSR_FILTER ioctls contains a pointer in the passed in struct which means it has a different struct size depending on whether it gets called from 32bit or 64bit code. This patch introduces compat code that converts from the 32bit struct to its 64bit counterpart which then gets used going forward internally. With this applied, 32bit QEMU can successfully set MSR bitmaps when running on 64bit kernels. Reported-by: Andrew Randrianasulu <[email protected]> Fixes: 1a15525 ("KVM: x86: Introduce MSR filtering") Signed-off-by: Alexander Graf <[email protected]> Message-Id: <[email protected]> Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 2e3272b commit 1739c70

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

arch/x86/kvm/x86.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6489,6 +6489,62 @@ static int kvm_vm_ioctl_set_msr_filter(struct kvm *kvm,
64896489
return 0;
64906490
}
64916491

6492+
#ifdef CONFIG_KVM_COMPAT
6493+
/* for KVM_X86_SET_MSR_FILTER */
6494+
struct kvm_msr_filter_range_compat {
6495+
__u32 flags;
6496+
__u32 nmsrs;
6497+
__u32 base;
6498+
__u32 bitmap;
6499+
};
6500+
6501+
struct kvm_msr_filter_compat {
6502+
__u32 flags;
6503+
struct kvm_msr_filter_range_compat ranges[KVM_MSR_FILTER_MAX_RANGES];
6504+
};
6505+
6506+
#define KVM_X86_SET_MSR_FILTER_COMPAT _IOW(KVMIO, 0xc6, struct kvm_msr_filter_compat)
6507+
6508+
long kvm_arch_vm_compat_ioctl(struct file *filp, unsigned int ioctl,
6509+
unsigned long arg)
6510+
{
6511+
void __user *argp = (void __user *)arg;
6512+
struct kvm *kvm = filp->private_data;
6513+
long r = -ENOTTY;
6514+
6515+
switch (ioctl) {
6516+
case KVM_X86_SET_MSR_FILTER_COMPAT: {
6517+
struct kvm_msr_filter __user *user_msr_filter = argp;
6518+
struct kvm_msr_filter_compat filter_compat;
6519+
struct kvm_msr_filter filter;
6520+
int i;
6521+
6522+
if (copy_from_user(&filter_compat, user_msr_filter,
6523+
sizeof(filter_compat)))
6524+
return -EFAULT;
6525+
6526+
filter.flags = filter_compat.flags;
6527+
for (i = 0; i < ARRAY_SIZE(filter.ranges); i++) {
6528+
struct kvm_msr_filter_range_compat *cr;
6529+
6530+
cr = &filter_compat.ranges[i];
6531+
filter.ranges[i] = (struct kvm_msr_filter_range) {
6532+
.flags = cr->flags,
6533+
.nmsrs = cr->nmsrs,
6534+
.base = cr->base,
6535+
.bitmap = (__u8 *)(ulong)cr->bitmap,
6536+
};
6537+
}
6538+
6539+
r = kvm_vm_ioctl_set_msr_filter(kvm, &filter);
6540+
break;
6541+
}
6542+
}
6543+
6544+
return r;
6545+
}
6546+
#endif
6547+
64926548
#ifdef CONFIG_HAVE_KVM_PM_NOTIFIER
64936549
static int kvm_arch_suspend_notifier(struct kvm *kvm)
64946550
{

0 commit comments

Comments
 (0)