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