[kernel] r20100 - in dists/wheezy-security/linux/debian: . patches patches/bugfix/x86

Dann Frazier dannf at alioth.debian.org
Wed May 15 02:10:49 UTC 2013


Author: dannf
Date: Wed May 15 02:10:48 2013
New Revision: 20100

Log:
[x86] KVM: Allow cross page reads and writes from cached translations.
(fixes regression in fix for CVE-2013-1796)

Added:
   dists/wheezy-security/linux/debian/patches/bugfix/x86/KVM-Allow-cross-page-reads-and-writes-from-cached-tr.patch
Modified:
   dists/wheezy-security/linux/debian/changelog
   dists/wheezy-security/linux/debian/patches/series

Modified: dists/wheezy-security/linux/debian/changelog
==============================================================================
--- dists/wheezy-security/linux/debian/changelog	Wed May 15 01:55:49 2013	(r20099)
+++ dists/wheezy-security/linux/debian/changelog	Wed May 15 02:10:48 2013	(r20100)
@@ -1,5 +1,6 @@
 linux (3.2.41-2+deb7u1) UNRELEASED; urgency=high
 
+  [ dann frazier ]
   * perf: Treat attr.config as u64 in perf_swevent_init() (CVE-2013-2094)
   * TTY: fix timing leak with /dev/ptmx (CVE-2013-0160)
   * ext4: avoid hang when mounting non-journal filesystems with orphan list
@@ -19,6 +20,10 @@
   * rose: fix info leak via msg_name in rose_recvmsg() (CVE-2013-3234)
   * tipc: fix info leaks via msg_name in  recv_msg/recv_stream (CVE-2013-3235)
   * tracing: Fix possible NULL pointer dereferences (CVE-2013-3301)
+  
+  [ Ben Hutchings ]
+  * [x86] KVM: Allow cross page reads and writes from cached translations.
+    (fixes regression in fix for CVE-2013-1796)
 
  -- dann frazier <dannf at debian.org>  Tue, 14 May 2013 11:48:39 -0600
 

Added: dists/wheezy-security/linux/debian/patches/bugfix/x86/KVM-Allow-cross-page-reads-and-writes-from-cached-tr.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/wheezy-security/linux/debian/patches/bugfix/x86/KVM-Allow-cross-page-reads-and-writes-from-cached-tr.patch	Wed May 15 02:10:48 2013	(r20100)
@@ -0,0 +1,177 @@
+From c471da1e3f5c6e43397dccf47cefd8edc86aa9f0 Mon Sep 17 00:00:00 2001
+From: Andrew Honig <ahonig at google.com>
+Date: Fri, 29 Mar 2013 09:35:21 -0700
+Subject: [PATCH] KVM: Allow cross page reads and writes from cached
+ translations.
+
+commit 8f964525a121f2ff2df948dac908dcc65be21b5b upstream.
+
+This patch adds support for kvm_gfn_to_hva_cache_init functions for
+reads and writes that will cross a page.  If the range falls within
+the same memslot, then this will be a fast operation.  If the range
+is split between two memslots, then the slower kvm_read_guest and
+kvm_write_guest are used.
+
+Tested: Test against kvm_clock unit tests.
+
+Signed-off-by: Andrew Honig <ahonig at google.com>
+Signed-off-by: Gleb Natapov <gleb at redhat.com>
+[bwh: Backported to 3.2:
+ - Drop change in lapic.c
+ - Keep using __gfn_to_memslot() in kvm_gfn_to_hva_cache_init()]
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ arch/x86/kvm/x86.c        |   13 ++++++-------
+ include/linux/kvm_host.h  |    2 +-
+ include/linux/kvm_types.h |    1 +
+ virt/kvm/kvm_main.c       |   47 +++++++++++++++++++++++++++++++++++----------
+ 4 files changed, 45 insertions(+), 18 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 2dd2e4e..e82a53a 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -1480,7 +1480,8 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
+ 		return 0;
+ 	}
+ 
+-	if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa))
++	if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
++					sizeof(u32)))
+ 		return 1;
+ 
+ 	vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS);
+@@ -1594,12 +1595,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+ 
+ 		gpa_offset = data & ~(PAGE_MASK | 1);
+ 
+-		/* Check that the address is 32-byte aligned. */
+-		if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1))
+-			break;
+-
+ 		if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+-		     &vcpu->arch.pv_time, data & ~1ULL))
++		     &vcpu->arch.pv_time, data & ~1ULL,
++		     sizeof(struct pvclock_vcpu_time_info)))
+ 			vcpu->arch.pv_time_enabled = false;
+ 		else
+ 			vcpu->arch.pv_time_enabled = true;
+@@ -1618,7 +1616,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+ 			return 1;
+ 
+ 		if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
+-							data & KVM_STEAL_VALID_BITS))
++						data & KVM_STEAL_VALID_BITS,
++						sizeof(struct kvm_steal_time)))
+ 			return 1;
+ 
+ 		vcpu->arch.st.msr_val = data;
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index 6136821..e6796c1 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -396,7 +396,7 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
+ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+ 			   void *data, unsigned long len);
+ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+-			      gpa_t gpa);
++			      gpa_t gpa, unsigned long len);
+ int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
+ int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
+ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
+diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
+index fa7cc72..b0bcce0 100644
+--- a/include/linux/kvm_types.h
++++ b/include/linux/kvm_types.h
+@@ -71,6 +71,7 @@ struct gfn_to_hva_cache {
+ 	u64 generation;
+ 	gpa_t gpa;
+ 	unsigned long hva;
++	unsigned long len;
+ 	struct kvm_memory_slot *memslot;
+ };
+ 
+diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
+index ec747dc..8bf05f0 100644
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -1401,21 +1401,38 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
+ }
+ 
+ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+-			      gpa_t gpa)
++			      gpa_t gpa, unsigned long len)
+ {
+ 	struct kvm_memslots *slots = kvm_memslots(kvm);
+ 	int offset = offset_in_page(gpa);
+-	gfn_t gfn = gpa >> PAGE_SHIFT;
++	gfn_t start_gfn = gpa >> PAGE_SHIFT;
++	gfn_t end_gfn = (gpa + len - 1) >> PAGE_SHIFT;
++	gfn_t nr_pages_needed = end_gfn - start_gfn + 1;
++	gfn_t nr_pages_avail;
+ 
+ 	ghc->gpa = gpa;
+ 	ghc->generation = slots->generation;
+-	ghc->memslot = __gfn_to_memslot(slots, gfn);
+-	ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL);
+-	if (!kvm_is_error_hva(ghc->hva))
++	ghc->len = len;
++	ghc->memslot = __gfn_to_memslot(slots, start_gfn);
++	ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
++	if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
+ 		ghc->hva += offset;
+-	else
+-		return -EFAULT;
+-
++	} else {
++		/*
++		 * If the requested region crosses two memslots, we still
++		 * verify that the entire region is valid here.
++		 */
++		while (start_gfn <= end_gfn) {
++			ghc->memslot = __gfn_to_memslot(slots, start_gfn);
++			ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn,
++						   &nr_pages_avail);
++			if (kvm_is_error_hva(ghc->hva))
++				return -EFAULT;
++			start_gfn += nr_pages_avail;
++		}
++		/* Use the slow path for cross page reads and writes. */
++		ghc->memslot = NULL;
++	}
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init);
+@@ -1426,8 +1443,13 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+ 	struct kvm_memslots *slots = kvm_memslots(kvm);
+ 	int r;
+ 
++	BUG_ON(len > ghc->len);
++
+ 	if (slots->generation != ghc->generation)
+-		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
++		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
++
++	if (unlikely(!ghc->memslot))
++		return kvm_write_guest(kvm, ghc->gpa, data, len);
+ 
+ 	if (kvm_is_error_hva(ghc->hva))
+ 		return -EFAULT;
+@@ -1447,8 +1469,13 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
+ 	struct kvm_memslots *slots = kvm_memslots(kvm);
+ 	int r;
+ 
++	BUG_ON(len > ghc->len);
++
+ 	if (slots->generation != ghc->generation)
+-		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
++		kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
++
++	if (unlikely(!ghc->memslot))
++		return kvm_read_guest(kvm, ghc->gpa, data, len);
+ 
+ 	if (kvm_is_error_hva(ghc->hva))
+ 		return -EFAULT;
+-- 
+1.7.10.4
+

Modified: dists/wheezy-security/linux/debian/patches/series
==============================================================================
--- dists/wheezy-security/linux/debian/patches/series	Wed May 15 01:55:49 2013	(r20099)
+++ dists/wheezy-security/linux/debian/patches/series	Wed May 15 02:10:48 2013	(r20100)
@@ -657,3 +657,4 @@
 bugfix/all/rose-fix-info-leak-via-msg_name-in-rose_recvmsg.patch
 bugfix/all/tipc-fix-info-leaks-via-msg_name-in-recv_msg-recv_st.patch
 bugfix/all/tracing-Fix-possible-NULL-pointer-dereferences.patch
+bugfix/x86/KVM-Allow-cross-page-reads-and-writes-from-cached-tr.patch



More information about the Kernel-svn-changes mailing list