[meta-freescale] [meta-fsl-ppc][PATCH] kvm-iommu: CVE-2014-3601, CVE-2014-8369

Sona Sarmadi sona.sarmadi at enea.com
Tue Jan 27 01:22:10 PST 2015


CVE-2014-3601
Fixes the third parameter of kvm_iommu_put_pages
The third parameter of kvm_iommu_put_pages is wrong,
It should be 'gfn - slot->base_gfn'.

CVE-2014-8369
Fixes excessive pages un-pinning in kvm_iommu_map error path.
(This vulnerability exists because of an incorrect fix for CVE-2014-3601

Reference:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3601
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-8369
https://bugzilla.redhat.com/show_bug.cgi?id=1156518
https://lkml.org/lkml/2014/10/24/460

Signed-off-by: Sona Sarmadi <sona.sarmadi at enea.com>
---
 .../linux/files/0001-kvm-iommu-CVE-2014-3601.patch | 94 ++++++++++++++++++++++
 .../linux/files/0002-kvm-iommu-CVE-2014-8369.patch | 86 ++++++++++++++++++++
 recipes-kernel/linux/linux-qoriq_3.12.bb           |  2 +
 3 files changed, 182 insertions(+)
 create mode 100644 recipes-kernel/linux/files/0001-kvm-iommu-CVE-2014-3601.patch
 create mode 100644 recipes-kernel/linux/files/0002-kvm-iommu-CVE-2014-8369.patch

diff --git a/recipes-kernel/linux/files/0001-kvm-iommu-CVE-2014-3601.patch b/recipes-kernel/linux/files/0001-kvm-iommu-CVE-2014-3601.patch
new file mode 100644
index 0000000..e19a3c1
--- /dev/null
+++ b/recipes-kernel/linux/files/0001-kvm-iommu-CVE-2014-3601.patch
@@ -0,0 +1,94 @@
+From e35b1e9f17e0567f96502f3a2a31dace727ed3da Mon Sep 17 00:00:00 2001
+From: "Michael S. Tsirkin" <mst at redhat.com>
+Date: Tue, 19 Aug 2014 19:14:50 +0800
+Subject: [PATCH] kvm: iommu: fix the third parameter of kvm_iommu_put_pages
+ (CVE-2014-3601)
+
+commit 350b8bdd689cd2ab2c67c8a86a0be86cfa0751a7 upstream.
+
+The third parameter of kvm_iommu_put_pages is wrong,
+It should be 'gfn - slot->base_gfn'.
+
+By making gfn very large, malicious guest or userspace can cause kvm to
+go to this error path, and subsequently to pass a huge value as size.
+Alternatively if gfn is small, then pages would be pinned but never
+unpinned, causing host memory leak and local DOS.
+
+Passing a reasonable but large value could be the most dangerous case,
+because it would unpin a page that should have stayed pinned, and thus
+allow the device to DMA into arbitrary memory.  However, this cannot
+happen because of the condition that can trigger the error:
+
+- out of memory (where you can't allocate even a single page)
+  should not be possible for the attacker to trigger
+
+- when exceeding the iommu's address space, guest pages after gfn
+  will also exceed the iommu's address space, and inside
+  kvm_iommu_put_pages() the iommu_iova_to_phys() will fail.  The
+  page thus would not be unpinned at all.
+
+Upstream-Status: Backport
+
+Reported-by: Jack Morgenstein <jackm at mellanox.com>
+Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+Signed-off-by: Jiri Slaby <jslaby at suse.cz>
+Signed-off-by: Sona Sarmadi <sona.sarmadi at enea.com>
+---
+ virt/kvm/iommu.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
+index c329c8f..dec9971 100644
+--- a/virt/kvm/iommu.c
++++ b/virt/kvm/iommu.c
+@@ -61,6 +61,14 @@ static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn,
+ 	return pfn;
+ }
+ 
++static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages)
++{
++	unsigned long i;
++
++	for (i = 0; i < npages; ++i)
++		kvm_release_pfn_clean(pfn + i);
++}
++
+ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+ {
+ 	gfn_t gfn, end_gfn;
+@@ -123,6 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+ 		if (r) {
+ 			printk(KERN_ERR "kvm_iommu_map_address:"
+ 			       "iommu failed to map pfn=%llx\n", pfn);
++			kvm_unpin_pages(kvm, pfn, page_size);
+ 			goto unmap_pages;
+ 		}
+ 
+@@ -134,7 +143,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+ 	return 0;
+ 
+ unmap_pages:
+-	kvm_iommu_put_pages(kvm, slot->base_gfn, gfn);
++	kvm_iommu_put_pages(kvm, slot->base_gfn, gfn - slot->base_gfn);
+ 	return r;
+ }
+ 
+@@ -272,14 +281,6 @@ out_unlock:
+ 	return r;
+ }
+ 
+-static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages)
+-{
+-	unsigned long i;
+-
+-	for (i = 0; i < npages; ++i)
+-		kvm_release_pfn_clean(pfn + i);
+-}
+-
+ static void kvm_iommu_put_pages(struct kvm *kvm,
+ 				gfn_t base_gfn, unsigned long npages)
+ {
+-- 
+1.9.1
+
diff --git a/recipes-kernel/linux/files/0002-kvm-iommu-CVE-2014-8369.patch b/recipes-kernel/linux/files/0002-kvm-iommu-CVE-2014-8369.patch
new file mode 100644
index 0000000..e43771c
--- /dev/null
+++ b/recipes-kernel/linux/files/0002-kvm-iommu-CVE-2014-8369.patch
@@ -0,0 +1,86 @@
+From 248541357433e3035d954435dafcdb9e70afee4e Mon Sep 17 00:00:00 2001
+From: Quentin Casasnovas <quentin.casasnovas at oracle.com>
+Date: Fri, 17 Oct 2014 22:55:59 +0200
+Subject: [PATCH] kvm: fix excessive pages un-pinning in kvm_iommu_map error
+ path.
+
+commit 3d32e4dbe71374a6780eaf51d719d76f9a9bf22f upstream.
+
+The third parameter of kvm_unpin_pages() when called from
+kvm_iommu_map_pages() is wrong, it should be the number of pages to un-pin
+and not the page size.
+
+This error was facilitated with an inconsistent API: kvm_pin_pages() takes
+a size, but kvn_unpin_pages() takes a number of pages, so fix the problem
+by matching the two.
+
+This was introduced by commit 350b8bd ("kvm: iommu: fix the third parameter
+of kvm_iommu_put_pages (CVE-2014-3601)"), which fixes the lack of
+un-pinning for pages intended to be un-pinned (i.e. memory leak) but
+unfortunately potentially aggravated the number of pages we un-pin that
+should have stayed pinned. As far as I understand though, the same
+practical mitigations apply.
+
+This issue was found during review of Red Hat 6.6 patches to prepare
+Ksplice rebootless updates.
+
+Thanks to Vegard for his time on a late Friday evening to help me in
+understanding this code.
+
+Fix for CVE-2014-8369
+
+Upstream-Status: Backport
+
+Fixes: 350b8bd ("kvm: iommu: fix the third parameter of... (CVE-2014-3601)")
+Signed-off-by: Quentin Casasnovas <quentin.casasnovas at oracle.com>
+Signed-off-by: Vegard Nossum <vegard.nossum at oracle.com>
+Signed-off-by: Jamie Iles <jamie.iles at oracle.com>
+Reviewed-by: Sasha Levin <sasha.levin at oracle.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+Signed-off-by: Jiri Slaby <jslaby at suse.cz>
+Signed-off-by: Sona Sarmadi <sona.sarmadi at enea.com>
+---
+ virt/kvm/iommu.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
+index dec9971..a650aa4 100644
+--- a/virt/kvm/iommu.c
++++ b/virt/kvm/iommu.c
+@@ -43,13 +43,13 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
+ 				gfn_t base_gfn, unsigned long npages);
+ 
+ static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn,
+-			   unsigned long size)
++			   unsigned long npages)
+ {
+ 	gfn_t end_gfn;
+ 	pfn_t pfn;
+ 
+ 	pfn     = gfn_to_pfn_memslot(slot, gfn);
+-	end_gfn = gfn + (size >> PAGE_SHIFT);
++	end_gfn = gfn + npages;
+ 	gfn    += 1;
+ 
+ 	if (is_error_noslot_pfn(pfn))
+@@ -119,7 +119,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+ 		 * Pin all pages we are about to map in memory. This is
+ 		 * important because we unmap and unpin in 4kb steps later.
+ 		 */
+-		pfn = kvm_pin_pages(slot, gfn, page_size);
++		pfn = kvm_pin_pages(slot, gfn, page_size >> PAGE_SHIFT);
+ 		if (is_error_noslot_pfn(pfn)) {
+ 			gfn += 1;
+ 			continue;
+@@ -131,7 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+ 		if (r) {
+ 			printk(KERN_ERR "kvm_iommu_map_address:"
+ 			       "iommu failed to map pfn=%llx\n", pfn);
+-			kvm_unpin_pages(kvm, pfn, page_size);
++			kvm_unpin_pages(kvm, pfn, page_size >> PAGE_SHIFT);
+ 			goto unmap_pages;
+ 		}
+ 
+-- 
+1.9.1
+
diff --git a/recipes-kernel/linux/linux-qoriq_3.12.bb b/recipes-kernel/linux/linux-qoriq_3.12.bb
index 195b477..5993b59 100644
--- a/recipes-kernel/linux/linux-qoriq_3.12.bb
+++ b/recipes-kernel/linux/linux-qoriq_3.12.bb
@@ -17,6 +17,8 @@ SRC_URI = "git://git.freescale.com/ppc/sdk/linux.git;nobranch=1 \
     file://0002-HID-CVE-2014-3182.patch \
     file://0003-HID-CVE-2014-3184.patch \
     file://0004-USB-CVE-2014-3185.patch \
+    file://0001-kvm-iommu-CVE-2014-3601.patch \
+    file://0002-kvm-iommu-CVE-2014-8369.patch \
 "
 SRCREV = "6619b8b55796cdf0cec04b66a71288edd3057229"
 
-- 
1.9.1



More information about the meta-freescale mailing list