diff options
Diffstat (limited to 'meta/recipes-devtools/qemu/qemu/11-xen-pt-unknown-PCI-config-space-fields-should-be-readonly-CVE-2015-4106.patch')
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/11-xen-pt-unknown-PCI-config-space-fields-should-be-readonly-CVE-2015-4106.patch | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu/11-xen-pt-unknown-PCI-config-space-fields-should-be-readonly-CVE-2015-4106.patch b/meta/recipes-devtools/qemu/qemu/11-xen-pt-unknown-PCI-config-space-fields-should-be-readonly-CVE-2015-4106.patch new file mode 100644 index 0000000000..5bfcf5e166 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/11-xen-pt-unknown-PCI-config-space-fields-should-be-readonly-CVE-2015-4106.patch | |||
@@ -0,0 +1,137 @@ | |||
1 | Upstream-Status: Backport | ||
2 | |||
3 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
4 | |||
5 | From c25bbf1545a53ac051f9e51d4140e397660c10ae Mon Sep 17 00:00:00 2001 | ||
6 | From: Jan Beulich <jbeulich@suse.com> | ||
7 | Date: Tue, 2 Jun 2015 15:07:01 +0000 | ||
8 | Subject: xen/pt: unknown PCI config space fields should be read-only | ||
9 | Bug-Debian: http://bugs.debian.org/787547 | ||
10 | |||
11 | ... by default. Add a per-device "permissive" mode similar to pciback's | ||
12 | to allow restoring previous behavior (and hence break security again, | ||
13 | i.e. should be used only for trusted guests). | ||
14 | |||
15 | This is part of XSA-131. | ||
16 | |||
17 | Signed-off-by: Jan Beulich <jbeulich@suse.com> | ||
18 | Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> | ||
19 | Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>) | ||
20 | --- | ||
21 | hw/xen/xen_pt.c | 32 +++++++++++++++++++++++++++++--- | ||
22 | hw/xen/xen_pt.h | 2 ++ | ||
23 | hw/xen/xen_pt_config_init.c | 4 ++++ | ||
24 | 3 files changed, 35 insertions(+), 3 deletions(-) | ||
25 | |||
26 | diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c | ||
27 | index 8923582..9afcda8 100644 | ||
28 | --- a/hw/xen/xen_pt.c | ||
29 | +++ b/hw/xen/xen_pt.c | ||
30 | @@ -239,6 +239,7 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, | ||
31 | XenPTReg *reg_entry = NULL; | ||
32 | uint32_t find_addr = addr; | ||
33 | XenPTRegInfo *reg = NULL; | ||
34 | + bool wp_flag = false; | ||
35 | |||
36 | if (xen_pt_pci_config_access_check(d, addr, len)) { | ||
37 | return; | ||
38 | @@ -278,6 +279,10 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, | ||
39 | |||
40 | /* pass directly to the real device for passthrough type register group */ | ||
41 | if (reg_grp_entry == NULL) { | ||
42 | + if (!s->permissive) { | ||
43 | + wb_mask = 0; | ||
44 | + wp_flag = true; | ||
45 | + } | ||
46 | goto out; | ||
47 | } | ||
48 | |||
49 | @@ -298,12 +303,15 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, | ||
50 | uint32_t real_offset = reg_grp_entry->base_offset + reg->offset; | ||
51 | uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3); | ||
52 | uint8_t *ptr_val = NULL; | ||
53 | + uint32_t wp_mask = reg->emu_mask | reg->ro_mask; | ||
54 | |||
55 | valid_mask <<= (find_addr - real_offset) << 3; | ||
56 | ptr_val = (uint8_t *)&val + (real_offset & 3); | ||
57 | - if (reg->emu_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) { | ||
58 | - wb_mask &= ~((reg->emu_mask | ||
59 | - >> ((find_addr - real_offset) << 3)) | ||
60 | + if (!s->permissive) { | ||
61 | + wp_mask |= reg->res_mask; | ||
62 | + } | ||
63 | + if (wp_mask == (0xFFFFFFFF >> ((4 - reg->size) << 3))) { | ||
64 | + wb_mask &= ~((wp_mask >> ((find_addr - real_offset) << 3)) | ||
65 | << ((len - emul_len) << 3)); | ||
66 | } | ||
67 | |||
68 | @@ -347,6 +355,16 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, | ||
69 | } else { | ||
70 | /* nothing to do with passthrough type register, | ||
71 | * continue to find next byte */ | ||
72 | + if (!s->permissive) { | ||
73 | + wb_mask &= ~(0xff << ((len - emul_len) << 3)); | ||
74 | + /* Unused BARs will make it here, but we don't want to issue | ||
75 | + * warnings for writes to them (bogus writes get dealt with | ||
76 | + * above). | ||
77 | + */ | ||
78 | + if (index < 0) { | ||
79 | + wp_flag = true; | ||
80 | + } | ||
81 | + } | ||
82 | emul_len--; | ||
83 | find_addr++; | ||
84 | } | ||
85 | @@ -358,6 +376,13 @@ static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, | ||
86 | memory_region_transaction_commit(); | ||
87 | |||
88 | out: | ||
89 | + if (wp_flag && !s->permissive_warned) { | ||
90 | + s->permissive_warned = true; | ||
91 | + xen_pt_log(d, "Write-back to unknown field 0x%02x (partially) inhibited (0x%0*x)\n", | ||
92 | + addr, len * 2, wb_mask); | ||
93 | + xen_pt_log(d, "If the device doesn't work, try enabling permissive mode\n"); | ||
94 | + xen_pt_log(d, "(unsafe) and if it helps report the problem to xen-devel\n"); | ||
95 | + } | ||
96 | for (index = 0; wb_mask; index += len) { | ||
97 | /* unknown regs are passed through */ | ||
98 | while (!(wb_mask & 0xff)) { | ||
99 | @@ -824,6 +849,7 @@ static void xen_pt_unregister_device(PCIDevice *d) | ||
100 | |||
101 | static Property xen_pci_passthrough_properties[] = { | ||
102 | DEFINE_PROP_PCI_HOST_DEVADDR("hostaddr", XenPCIPassthroughState, hostaddr), | ||
103 | + DEFINE_PROP_BOOL("permissive", XenPCIPassthroughState, permissive, false), | ||
104 | DEFINE_PROP_END_OF_LIST(), | ||
105 | }; | ||
106 | |||
107 | diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h | ||
108 | index f9795eb..4bba559 100644 | ||
109 | --- a/hw/xen/xen_pt.h | ||
110 | +++ b/hw/xen/xen_pt.h | ||
111 | @@ -197,6 +197,8 @@ struct XenPCIPassthroughState { | ||
112 | |||
113 | PCIHostDeviceAddress hostaddr; | ||
114 | bool is_virtfn; | ||
115 | + bool permissive; | ||
116 | + bool permissive_warned; | ||
117 | XenHostPCIDevice real_device; | ||
118 | XenPTRegion bases[PCI_NUM_REGIONS]; /* Access regions */ | ||
119 | QLIST_HEAD(, XenPTRegGroup) reg_grps; | ||
120 | diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c | ||
121 | index 19f926b..f3cf069 100644 | ||
122 | --- a/hw/xen/xen_pt_config_init.c | ||
123 | +++ b/hw/xen/xen_pt_config_init.c | ||
124 | @@ -101,6 +101,10 @@ static uint32_t get_throughable_mask(const XenPCIPassthroughState *s, | ||
125 | { | ||
126 | uint32_t throughable_mask = ~(reg->emu_mask | reg->ro_mask); | ||
127 | |||
128 | + if (!s->permissive) { | ||
129 | + throughable_mask &= ~reg->res_mask; | ||
130 | + } | ||
131 | + | ||
132 | return throughable_mask & valid_mask; | ||
133 | } | ||
134 | |||
135 | -- | ||
136 | 2.1.4 | ||
137 | |||