[kernel/stabilization] CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090)

Josh Boyer jwboyer at fedoraproject.org
Thu Dec 12 21:28:54 UTC 2013


commit 1515e1bf7185659de258695667d37c11d5ee4032
Author: Josh Boyer <jwboyer at fedoraproject.org>
Date:   Thu Dec 12 16:15:05 2013 -0500

    CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090)

 ...apic-synchronization-to-_cached-functions.patch |  247 ++++++++++++++++++++
 kernel.spec                                        |    7 +
 2 files changed, 254 insertions(+), 0 deletions(-)
---
diff --git a/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch b/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
new file mode 100644
index 0000000..a37d4cf
--- /dev/null
+++ b/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
@@ -0,0 +1,247 @@
+Bugzilla: 1042090
+Upstream-status: 3.13 and sent for stable                                                                                                                                                                                                                                                               
+Delivered-To: jwboyer at gmail.com
+Received: by 10.76.104.107 with SMTP id gd11csp361293oab;
+        Thu, 12 Dec 2013 12:41:12 -0800 (PST)
+X-Received: by 10.68.244.2 with SMTP id xc2mr15600217pbc.58.1386880872483;
+        Thu, 12 Dec 2013 12:41:12 -0800 (PST)
+Return-Path: <stable-owner at vger.kernel.org>
+Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67])
+        by mx.google.com with ESMTP id 5si8126292pbj.245.2013.12.12.12.40.49
+        for <multiple recipients>;
+        Thu, 12 Dec 2013 12:41:12 -0800 (PST)
+Received-SPF: pass (google.com: best guess record for domain of stable-owner at vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67;
+Authentication-Results: mx.google.com;
+       spf=pass (google.com: best guess record for domain of stable-owner at vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner at vger.kernel.org;
+       dkim=neutral (bad format) header.i=@gmail.com
+Received: (majordomo at vger.kernel.org) by vger.kernel.org via listexpand
+	id S1751901Ab3LLUiK (ORCPT <rfc822;kumadasu at gmail.com> + 64 others);
+	Thu, 12 Dec 2013 15:38:10 -0500
+Received: from mail-ea0-f169.google.com ([209.85.215.169]:43997 "EHLO
+	mail-ea0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
+	with ESMTP id S1751940Ab3LLUhR (ORCPT
+	<rfc822;stable at vger.kernel.org>); Thu, 12 Dec 2013 15:37:17 -0500
+Received: by mail-ea0-f169.google.com with SMTP id l9so411843eaj.0
+        for <multiple recipients>; Thu, 12 Dec 2013 12:37:15 -0800 (PST)
+DKIM-Signature:	v=1; a=rsa-sha256; c=relaxed/relaxed;
+        d=gmail.com; s=20120113;
+        h=sender:from:to:cc:subject:date:message-id;
+        bh=2MLmYgVGbv9FpnyP90yrPKk21SJoXFj93yQcaRn4G8Y=;
+        b=ouBadI22VTf1UuezbySC80FWJYdpF/8Ks6I8f5rq1/7SDQPTpScjOYjZX0UtIf1ihj
+         aeQ7IHqpmIYGKWadUbH2l88ZP1+rP7T+f2dZQeCb3HLNsPum0Ix8dzm/koeDnuS3dx75
+         50E9ZcFXO13Hx24tM8p0SAuYZ1DvbCNnPRK0yxHOmCtCWe+mQLBIgig1rg8TzSAazWm7
+         8LhpztDlIzNyZcfzKQvtdqTOBdnhadx5x39fxOe54Yw4JbppDa7R+BY5Jz6GOd3U0Op1
+         Nf97rU0pe/jeyOtjF0LVs/d9iyPPeRoSE+VAr91iT8qj9S2PFEN1QxxWL8sdvsDPZK6B
+         ZCmw==
+X-Received: by 10.14.182.199 with SMTP id o47mr10030582eem.7.1386880635352;
+        Thu, 12 Dec 2013 12:37:15 -0800 (PST)
+Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54])
+        by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.13
+        for <multiple recipients>
+        (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
+        Thu, 12 Dec 2013 12:37:14 -0800 (PST)
+From:	Paolo Bonzini <pbonzini at redhat.com>
+To:	linux-kernel at vger.kernel.org
+Cc:	gleb at redhat.com, kvm at vger.kernel.org, pmatouse at redhat.com,
+	Andy Honig <ahonig at google.com>, stable at vger.kernel.org
+Subject: [PATCH] KVM: x86: Convert vapic synchronization to _cached functions (CVE-2013-6368)
+Date:	Thu, 12 Dec 2013 21:36:53 +0100
+Message-Id: <1386880614-23300-3-git-send-email-pbonzini at redhat.com>
+X-Mailer: git-send-email 1.8.3.1
+Sender:	stable-owner at vger.kernel.org
+Precedence: bulk
+List-ID: <stable.vger.kernel.org>
+X-Mailing-List:	stable at vger.kernel.org
+
+From: Andy Honig <ahonig at google.com>
+
+In kvm_lapic_sync_from_vapic and kvm_lapic_sync_to_vapic there is the
+potential to corrupt kernel memory if userspace provides an address that
+is at the end of a page.  This patches concerts those functions to use
+kvm_write_guest_cached and kvm_read_guest_cached.  It also checks the
+vapic_address specified by userspace during ioctl processing and returns
+an error to userspace if the address is not a valid GPA.
+
+This is generally not guest triggerable, because the required write is
+done by firmware that runs before the guest.  Also, it only affects AMD
+processors and oldish Intel that do not have the FlexPriority feature
+(unless you disable FlexPriority, of course; then newer processors are
+also affected).
+
+Fixes: b93463aa59d6 ('KVM: Accelerated apic support')
+
+Reported-by: Andrew Honig <ahonig at google.com>
+Cc: stable at vger.kernel.org
+Signed-off-by: Andrew Honig <ahonig at google.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+---
+ arch/x86/kvm/lapic.c | 27 +++++++++++++++------------
+ arch/x86/kvm/lapic.h |  4 ++--
+ arch/x86/kvm/x86.c   | 40 +---------------------------------------
+ 3 files changed, 18 insertions(+), 53 deletions(-)
+
+diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
+index 89b52ec7d09c..b8bec45c1610 100644
+--- a/arch/x86/kvm/lapic.c
++++ b/arch/x86/kvm/lapic.c
+@@ -1692,7 +1692,6 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu,
+ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
+ {
+ 	u32 data;
+-	void *vapic;
+ 
+ 	if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention))
+ 		apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic);
+@@ -1700,9 +1699,8 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
+ 	if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
+ 		return;
+ 
+-	vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
+-	data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr));
+-	kunmap_atomic(vapic);
++	kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
++				sizeof(u32));
+ 
+ 	apic_set_tpr(vcpu->arch.apic, data & 0xff);
+ }
+@@ -1738,7 +1736,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
+ 	u32 data, tpr;
+ 	int max_irr, max_isr;
+ 	struct kvm_lapic *apic = vcpu->arch.apic;
+-	void *vapic;
+ 
+ 	apic_sync_pv_eoi_to_guest(vcpu, apic);
+ 
+@@ -1754,18 +1751,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
+ 		max_isr = 0;
+ 	data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
+ 
+-	vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
+-	*(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data;
+-	kunmap_atomic(vapic);
++	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
++				sizeof(u32));
+ }
+ 
+-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
+ {
+-	vcpu->arch.apic->vapic_addr = vapic_addr;
+-	if (vapic_addr)
++	if (vapic_addr) {
++		if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
++					&vcpu->arch.apic->vapic_cache,
++					vapic_addr, sizeof(u32)))
++			return -EINVAL;
+ 		__set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
+-	else
++	} else {
+ 		__clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
++	}
++
++	vcpu->arch.apic->vapic_addr = vapic_addr;
++	return 0;
+ }
+ 
+ int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
+index c730ac9fe801..c8b0d0d2da5c 100644
+--- a/arch/x86/kvm/lapic.h
++++ b/arch/x86/kvm/lapic.h
+@@ -34,7 +34,7 @@ struct kvm_lapic {
+ 	 */
+ 	void *regs;
+ 	gpa_t vapic_addr;
+-	struct page *vapic_page;
++	struct gfn_to_hva_cache vapic_cache;
+ 	unsigned long pending_events;
+ 	unsigned int sipi_vector;
+ };
+@@ -76,7 +76,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
+ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset);
+ void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector);
+ 
+-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
+ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
+ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
+ 
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 21ef1ba184ae..5d004da1e35d 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3214,8 +3214,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
+ 		r = -EFAULT;
+ 		if (copy_from_user(&va, argp, sizeof va))
+ 			goto out;
+-		r = 0;
+-		kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
++		r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
+ 		break;
+ 	}
+ 	case KVM_X86_SETUP_MCE: {
+@@ -5739,36 +5738,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
+ 			!kvm_event_needs_reinjection(vcpu);
+ }
+ 
+-static int vapic_enter(struct kvm_vcpu *vcpu)
+-{
+-	struct kvm_lapic *apic = vcpu->arch.apic;
+-	struct page *page;
+-
+-	if (!apic || !apic->vapic_addr)
+-		return 0;
+-
+-	page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
+-	if (is_error_page(page))
+-		return -EFAULT;
+-
+-	vcpu->arch.apic->vapic_page = page;
+-	return 0;
+-}
+-
+-static void vapic_exit(struct kvm_vcpu *vcpu)
+-{
+-	struct kvm_lapic *apic = vcpu->arch.apic;
+-	int idx;
+-
+-	if (!apic || !apic->vapic_addr)
+-		return;
+-
+-	idx = srcu_read_lock(&vcpu->kvm->srcu);
+-	kvm_release_page_dirty(apic->vapic_page);
+-	mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
+-	srcu_read_unlock(&vcpu->kvm->srcu, idx);
+-}
+-
+ static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+ {
+ 	int max_irr, tpr;
+@@ -6069,11 +6038,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
+ 	struct kvm *kvm = vcpu->kvm;
+ 
+ 	vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
+-	r = vapic_enter(vcpu);
+-	if (r) {
+-		srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
+-		return r;
+-	}
+ 
+ 	r = 1;
+ 	while (r > 0) {
+@@ -6132,8 +6096,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
+ 
+ 	srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
+ 
+-	vapic_exit(vcpu);
+-
+ 	return r;
+ }
+ 
+-- 
+1.8.3.1
+
+--
+To unsubscribe from this list: send the line "unsubscribe stable" in
+the body of a message to majordomo at vger.kernel.org
+More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff --git a/kernel.spec b/kernel.spec
index 8efaa4a..d26d744 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -741,6 +741,9 @@ Patch25171: elantech-Properly-differentiate-between-clickpads-an.patch
 #CVE-2013-6367 rhbz 1032207 1042081
 Patch25172: KVM-x86-Fix-potential-divide-by-0-in-lapic.patch
 
+#CVE-2013-6368 rhbz 1032210 1042090
+Patch25173: KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
+
 # END OF PATCH DEFINITIONS
 
 %endif
@@ -1446,6 +1449,9 @@ ApplyPatch elantech-Properly-differentiate-between-clickpads-an.patch
 #CVE-2013-6367 rhbz 1032207 1042081
 ApplyPatch KVM-x86-Fix-potential-divide-by-0-in-lapic.patch
 
+#CVE-2013-6368 rhbz 1032210 1042090
+ApplyPatch KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2250,6 +2256,7 @@ fi
 #                                    ||     ||
 %changelog
 * Thu Dec 12 2013 Josh Boyer <jwboyer at fedoraproject.org>
+- CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090)
 - CVE-2013-6367 kvm: division by 0 in apic_get_tmcct (rhbz 1032207 1042081)
 
 * Wed Dec 11 2013 Peter Robinson <pbrobinson at fedoraproject.org>


More information about the scm-commits mailing list