aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2016-06-01 08:09:19 -0400
committerRadim Krčmář <rkrcmar@redhat.com>2016-06-02 11:38:50 -0400
commit83676e923895adf2af392cfd36a05709950aaeef (patch)
tree5c462f932fa0d899a0b37c3187f76a8fd9b31ca1
parentb21629da120dd6145d14dbd6d028e1bba680a92b (diff)
KVM: x86: avoid vmalloc(0) in the KVM_SET_CPUID
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: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
-rw-r--r--arch/x86/kvm/cpuid.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 769af907f824..7597b42a8a88 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -181,19 +181,22 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
181 struct kvm_cpuid_entry __user *entries) 181 struct kvm_cpuid_entry __user *entries)
182{ 182{
183 int r, i; 183 int r, i;
184 struct kvm_cpuid_entry *cpuid_entries; 184 struct kvm_cpuid_entry *cpuid_entries = NULL;
185 185
186 r = -E2BIG; 186 r = -E2BIG;
187 if (cpuid->nent > KVM_MAX_CPUID_ENTRIES) 187 if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
188 goto out; 188 goto out;
189 r = -ENOMEM; 189 r = -ENOMEM;
190 cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent); 190 if (cpuid->nent) {
191 if (!cpuid_entries) 191 cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) *
192 goto out; 192 cpuid->nent);
193 r = -EFAULT; 193 if (!cpuid_entries)
194 if (copy_from_user(cpuid_entries, entries, 194 goto out;
195 cpuid->nent * sizeof(struct kvm_cpuid_entry))) 195 r = -EFAULT;
196 goto out_free; 196 if (copy_from_user(cpuid_entries, entries,
197 cpuid->nent * sizeof(struct kvm_cpuid_entry)))
198 goto out;
199 }
197 for (i = 0; i < cpuid->nent; i++) { 200 for (i = 0; i < cpuid->nent; i++) {
198 vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function; 201 vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function;
199 vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax; 202 vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
@@ -212,9 +215,8 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
212 kvm_x86_ops->cpuid_update(vcpu); 215 kvm_x86_ops->cpuid_update(vcpu);
213 r = kvm_update_cpuid(vcpu); 216 r = kvm_update_cpuid(vcpu);
214 217
215out_free:
216 vfree(cpuid_entries);
217out: 218out:
219 vfree(cpuid_entries);
218 return r; 220 return r;
219} 221}
220 222