qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] target-i386: kvm: prevent buffer overflow if -cpu f


From: Igor Mammedov
Subject: [Qemu-devel] [PATCH] target-i386: kvm: prevent buffer overflow if -cpu foo, [x]level is too big
Date: Thu, 24 Jan 2013 00:05:48 +0100

Stack corruption may occur if too big 'level' or 'xlevel' values passed
on command line with KVM enabled, due to limited size of cpuid_data
in kvm_arch_init_vcpu().

reproduces with:
 qemu -enable-kvm -cpu qemu64,level=4294967295
or
 qemu -enable-kvm -cpu qemu64,xlevel=4294967295

Check if there is space in cpuid_data before passing it to cpu_x86_cpuid()
or abort() if there is not space.

Signed-off-by: Igor Mammedov <address@hidden>
---
 target-i386/kvm.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 3acff40..8885b22 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -413,10 +413,13 @@ static void cpu_update_state(void *opaque, int running, 
RunState state)
 
 int kvm_arch_init_vcpu(CPUState *cs)
 {
+    const int max_cpuid_entries = 100;
     struct {
         struct kvm_cpuid2 cpuid;
-        struct kvm_cpuid_entry2 entries[100];
+        struct kvm_cpuid_entry2 entries[max_cpuid_entries];
     } QEMU_PACKED cpuid_data;
+    const struct kvm_cpuid_entry2 *cpuid_last_entry =
+        &cpuid_data.entries[max_cpuid_entries - 1];
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
     uint32_t limit, i, j, cpuid_i;
@@ -503,6 +506,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
 
     for (i = 0; i <= limit; i++) {
         c = &cpuid_data.entries[cpuid_i++];
+        if (c > cpuid_last_entry) {
+            fprintf(stderr, "unsupported level value: 0x%x\n", limit);
+            abort();
+        }
 
         switch (i) {
         case 2: {
@@ -517,6 +524,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
 
             for (j = 1; j < times; ++j) {
                 c = &cpuid_data.entries[cpuid_i++];
+                if (c > cpuid_last_entry) {
+                    fprintf(stderr, "cpuid_data is full, no space for "
+                            "cpuid(eax:2):eax & 0xf = 0x%x\n", times);
+                    abort();
+                }
                 c->function = i;
                 c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC;
                 cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
@@ -545,6 +557,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
                     continue;
                 }
                 c = &cpuid_data.entries[cpuid_i++];
+                if (c > cpuid_last_entry) {
+                    fprintf(stderr, "cpuid_data is full, no space for "
+                            "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
+                    abort();
+                }
             }
             break;
         default:
@@ -558,6 +575,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
 
     for (i = 0x80000000; i <= limit; i++) {
         c = &cpuid_data.entries[cpuid_i++];
+        if (c > cpuid_last_entry) {
+            fprintf(stderr, "unsupported xlevel value: 0x%x\n", limit);
+            abort();
+        }
 
         c->function = i;
         c->flags = 0;
@@ -570,6 +591,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
 
         for (i = 0xC0000000; i <= limit; i++) {
             c = &cpuid_data.entries[cpuid_i++];
+            if (c > cpuid_last_entry) {
+                fprintf(stderr, "unsupported xlevel2 value: 0x%x\n", limit);
+                abort();
+            }
 
             c->function = i;
             c->flags = 0;
-- 
1.7.11.7




reply via email to

[Prev in Thread] Current Thread [Next in Thread]