diff options
Diffstat (limited to 'recipes-kernel/linux/files/0001-kvm-iommu-CVE-2014-3601.patch')
-rw-r--r-- | recipes-kernel/linux/files/0001-kvm-iommu-CVE-2014-3601.patch | 94 |
1 files changed, 94 insertions, 0 deletions
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 @@ | |||
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 | |||