]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/CVE-2015-8818-exec-skip-MMIO-regions-correctly-in-cpu_physical_mem.patch
Fix CVE-2015-8817 and CVE-2015-8818
[pve-qemu-kvm.git] / debian / patches / CVE-2015-8818-exec-skip-MMIO-regions-correctly-in-cpu_physical_mem.patch
1 From 56daf5912f942155224af873b056f981fca2de8b Mon Sep 17 00:00:00 2001
2 From: Paolo Bonzini <pbonzini@redhat.com>
3 Date: Sat, 4 Jul 2015 00:24:51 +0200
4 Subject: [PATCH 3/4] exec: skip MMIO regions correctly in
5 cpu_physical_memory_write_rom_internal
6
7 Loading the BIOS in the mac99 machine is interesting, because there is a
8 PROM in the middle of the BIOS region (from 16K to 32K). Before memory
9 region accesses were clamped, when QEMU was asked to load a BIOS from
10 0xfff00000 to 0xffffffff it would put even those 16K from the BIOS file
11 into the region. This is weird because those 16K were not actually
12 visible between 0xfff04000 and 0xfff07fff. However, it worked.
13
14 After clamping was added, this also worked. In this case, the
15 cpu_physical_memory_write_rom_internal function split the write in
16 three parts: the first 16K were copied, the PROM area (second 16K) were
17 ignored, then the rest was copied.
18
19 Problems then started with commit 965eb2f (exec: do not clamp accesses
20 to MMIO regions, 2015-06-17). Clamping accesses is not done for MMIO
21 regions because they can overlap wildly, and MMIO registers can be
22 expected to perform full-width accesses based only on their address
23 (with no respect for adjacent registers that could decode to completely
24 different MemoryRegions). However, this lack of clamping also applied
25 to the PROM area! cpu_physical_memory_write_rom_internal thus failed
26 to copy the third range above, i.e. only copied the first 16K of the BIOS.
27
28 In effect, address_space_translate is expecting _something else_ to do
29 the clamping for MMIO regions if the incoming length is large. This
30 "something else" is memory_access_size in the case of address_space_rw,
31 so use the same logic in cpu_physical_memory_write_rom_internal.
32
33 Reported-by: Alexander Graf <agraf@redhat.com>
34 Reviewed-by: Laurent Vivier <lvivier@redhat.com>
35 Tested-by: Laurent Vivier <lvivier@redhat.com>
36 Fixes: 965eb2f
37 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
38 ---
39 exec.c | 14 +++++++++++++-
40 1 file changed, 13 insertions(+), 1 deletion(-)
41
42 diff --git a/exec.c b/exec.c
43 index 03c9995..80c9d79 100644
44 --- a/exec.c
45 +++ b/exec.c
46 @@ -341,6 +341,18 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
47 *xlat = addr + section->offset_within_region;
48
49 mr = section->mr;
50 +
51 + /* MMIO registers can be expected to perform full-width accesses based only
52 + * on their address, without considering adjacent registers that could
53 + * decode to completely different MemoryRegions. When such registers
54 + * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO
55 + * regions overlap wildly. For this reason we cannot clamp the accesses
56 + * here.
57 + *
58 + * If the length is small (as is the case for address_space_ldl/stl),
59 + * everything works fine. If the incoming length is large, however,
60 + * the caller really has to do the clamping through memory_access_size.
61 + */
62 if (memory_region_is_ram(mr)) {
63 diff = int128_sub(mr->size, int128_make64(addr));
64 *plen = int128_get64(int128_min(diff, int128_make64(*plen)));
65 @@ -2236,7 +2248,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
66
67 if (!(memory_region_is_ram(mr) ||
68 memory_region_is_romd(mr))) {
69 - /* do nothing */
70 + l = memory_access_size(mr, l, addr1);
71 } else {
72 addr1 += memory_region_get_ram_addr(mr);
73 /* ROM/RAM case */
74 --
75 2.1.4
76