Commit 750d62d4 authored by Paolo Bonzini's avatar Paolo Bonzini Committed by Juerg Haefliger

KVM: x86: avoid vmalloc(0) in the KVM_SET_CPUID

BugLink: https://bugs.launchpad.net/bugs/1811646

This causes an ugly dmesg splat.  Beautified syzkaller testcase:

    #include <unistd.h>
    #include <sys/syscall.h>
    #include <sys/ioctl.h>
    #include <fcntl.h>
    #include <linux/kvm.h>

    long r[8];

    int main()
    {
        struct kvm_cpuid2 c = { 0 };
        r[2] = open("/dev/kvm", O_RDWR);
        r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
        r[4] = ioctl(r[3], KVM_CREATE_VCPU, 0x8);
        r[7] = ioctl(r[4], KVM_SET_CPUID, &c);
        return 0;
    }
Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
(cherry picked from commit 83676e92)
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Acked-by: default avatarStefan Bader <stefan.bader@canonical.com>
Acked-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 11e04bcf
...@@ -169,19 +169,22 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, ...@@ -169,19 +169,22 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
struct kvm_cpuid_entry __user *entries) struct kvm_cpuid_entry __user *entries)
{ {
int r, i; int r, i;
struct kvm_cpuid_entry *cpuid_entries; struct kvm_cpuid_entry *cpuid_entries = NULL;
r = -E2BIG; r = -E2BIG;
if (cpuid->nent > KVM_MAX_CPUID_ENTRIES) if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
goto out; goto out;
r = -ENOMEM; r = -ENOMEM;
cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent); if (cpuid->nent) {
cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) *
cpuid->nent);
if (!cpuid_entries) if (!cpuid_entries)
goto out; goto out;
r = -EFAULT; r = -EFAULT;
if (copy_from_user(cpuid_entries, entries, if (copy_from_user(cpuid_entries, entries,
cpuid->nent * sizeof(struct kvm_cpuid_entry))) cpuid->nent * sizeof(struct kvm_cpuid_entry)))
goto out_free; goto out;
}
for (i = 0; i < cpuid->nent; i++) { for (i = 0; i < cpuid->nent; i++) {
vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function; vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function;
vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax; vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
...@@ -200,9 +203,8 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, ...@@ -200,9 +203,8 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
kvm_x86_ops->cpuid_update(vcpu); kvm_x86_ops->cpuid_update(vcpu);
r = kvm_update_cpuid(vcpu); r = kvm_update_cpuid(vcpu);
out_free:
vfree(cpuid_entries);
out: out:
vfree(cpuid_entries);
return r; return r;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment