From patchwork Tue Jan 29 10:59:56 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 216504 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 98CE62C0098 for ; Tue, 29 Jan 2013 22:52:40 +1100 (EST) Received: from localhost ([::1]:42070 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U09jx-0007Q1-2r for incoming@patchwork.ozlabs.org; Tue, 29 Jan 2013 06:52:37 -0500 Received: from eggs.gnu.org ([208.118.235.92]:42768) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U09jj-0007P2-DG for qemu-devel@nongnu.org; Tue, 29 Jan 2013 06:52:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U09ji-0003u5-7Z for qemu-devel@nongnu.org; Tue, 29 Jan 2013 06:52:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:44594) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U09ji-0003tz-09 for qemu-devel@nongnu.org; Tue, 29 Jan 2013 06:52:22 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r0TBqJLf029757 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 29 Jan 2013 06:52:20 -0500 Received: from dhcp-1-237.tlv.redhat.com (dhcp-4-26.tlv.redhat.com [10.35.4.26]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r0TB04ME029849; Tue, 29 Jan 2013 06:00:05 -0500 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 13519) id 3D05D18D47B; Tue, 29 Jan 2013 13:00:04 +0200 (IST) From: Gleb Natapov To: Anthony Liguori Date: Tue, 29 Jan 2013 12:59:56 +0200 Message-Id: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org Subject: [Qemu-devel] [PATCH 2/2] target-i386: kvm: prevent buffer overflow if -cpu foo, [x]level is too big X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Igor Mammedov 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. Reviewed-by: Laszlo Ersek Reviewed-by: Andreas Faerber Signed-off-by: Igor Mammedov Signed-off-by: Gleb Natapov --- target-i386/kvm.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 3acff40..4ecb728 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -411,11 +411,12 @@ static void cpu_update_state(void *opaque, int running, RunState state) } } +#define KVM_MAX_CPUID_ENTRIES 100 int kvm_arch_init_vcpu(CPUState *cs) { struct { struct kvm_cpuid2 cpuid; - struct kvm_cpuid_entry2 entries[100]; + struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES]; } QEMU_PACKED cpuid_data; X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; @@ -502,6 +503,10 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused); for (i = 0; i <= limit; i++) { + if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { + fprintf(stderr, "unsupported level value: 0x%x\n", limit); + abort(); + } c = &cpuid_data.entries[cpuid_i++]; switch (i) { @@ -516,6 +521,11 @@ int kvm_arch_init_vcpu(CPUState *cs) times = c->eax & 0xff; for (j = 1; j < times; ++j) { + if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { + fprintf(stderr, "cpuid_data is full, no space for " + "cpuid(eax:2):eax & 0xf = 0x%x\n", times); + abort(); + } c = &cpuid_data.entries[cpuid_i++]; c->function = i; c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC; @@ -544,6 +554,11 @@ int kvm_arch_init_vcpu(CPUState *cs) if (i == 0xd && c->eax == 0) { continue; } + if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { + fprintf(stderr, "cpuid_data is full, no space for " + "cpuid(eax:0x%x,ecx:0x%x)\n", i, j); + abort(); + } c = &cpuid_data.entries[cpuid_i++]; } break; @@ -557,6 +572,10 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused); for (i = 0x80000000; i <= limit; i++) { + if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { + fprintf(stderr, "unsupported xlevel value: 0x%x\n", limit); + abort(); + } c = &cpuid_data.entries[cpuid_i++]; c->function = i; @@ -569,6 +588,10 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu_x86_cpuid(env, 0xC0000000, 0, &limit, &unused, &unused, &unused); for (i = 0xC0000000; i <= limit; i++) { + if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { + fprintf(stderr, "unsupported xlevel2 value: 0x%x\n", limit); + abort(); + } c = &cpuid_data.entries[cpuid_i++]; c->function = i;