]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/extra/0001-vga-add-sr_vbe-register-set.patch
Fix CVE-2016-6490: virtio: check vring descriptor buffer length
[pve-qemu-kvm.git] / debian / patches / extra / 0001-vga-add-sr_vbe-register-set.patch
1 From 838ff135013302a85478ec3dd96d8ad985d1f01d Mon Sep 17 00:00:00 2001
2 From: Gerd Hoffmann <kraxel@redhat.com>
3 Date: Tue, 17 May 2016 10:54:54 +0200
4 Subject: [PATCH] vga: add sr_vbe register set
5
6 Commit "fd3c136 vga: make sure vga register setup for vbe stays intact
7 (CVE-2016-3712)." causes a regression. The win7 installer is unhappy
8 because it can't freely modify vga registers any more while in vbe mode.
9
10 This patch introduces a new sr_vbe register set. The vbe_update_vgaregs
11 will fill sr_vbe[] instead of sr[]. Normal vga register reads and
12 writes go to sr[]. Any sr register read access happens through a new
13 sr() helper function which will read from sr_vbe[] with vbe active and
14 from sr[] otherwise.
15
16 This way we can allow guests update sr[] registers as they want, without
17 allowing them disrupt vbe video modes that way.
18
19 Reported-by: Thomas Lamprecht <thomas@lamprecht.org>
20 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
21 ---
22 hw/display/vga.c | 50 ++++++++++++++++++++++++++++----------------------
23 hw/display/vga_int.h | 1 +
24 2 files changed, 29 insertions(+), 22 deletions(-)
25
26 diff --git a/hw/display/vga.c b/hw/display/vga.c
27 index 679070e..25d8bff 100644
28 --- a/hw/display/vga.c
29 +++ b/hw/display/vga.c
30 @@ -147,6 +147,11 @@ static inline bool vbe_enabled(VGACommonState *s)
31 return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
32 }
33
34 +static inline uint8_t sr(VGACommonState *s, int idx)
35 +{
36 + return vbe_enabled(s) ? s->sr_vbe[idx] : s->sr[idx];
37 +}
38 +
39 static void vga_update_memory_access(VGACommonState *s)
40 {
41 hwaddr base, offset, size;
42 @@ -161,8 +166,8 @@ static void vga_update_memory_access(VGACommonState *s)
43 s->has_chain4_alias = false;
44 s->plane_updated = 0xf;
45 }
46 - if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
47 - VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
48 + if ((sr(s, VGA_SEQ_PLANE_WRITE) & VGA_SR02_ALL_PLANES) ==
49 + VGA_SR02_ALL_PLANES && sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
50 offset = 0;
51 switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
52 case 0:
53 @@ -232,7 +237,7 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
54 ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
55 vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
56
57 - clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
58 + clocking_mode = (sr(s, VGA_SEQ_CLOCK_MODE) >> 3) & 1;
59 clock_sel = (s->msr >> 2) & 3;
60 dots = (s->msr & 1) ? 8 : 9;
61
62 @@ -484,7 +489,6 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
63 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
64 #endif
65 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
66 - vbe_update_vgaregs(s);
67 if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
68 s->update_retrace_info(s);
69 }
70 @@ -678,13 +682,13 @@ static void vbe_update_vgaregs(VGACommonState *s)
71
72 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
73 shift_control = 0;
74 - s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
75 + s->sr_vbe[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
76 } else {
77 shift_control = 2;
78 /* set chain 4 mode */
79 - s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
80 + s->sr_vbe[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
81 /* activate all planes */
82 - s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
83 + s->sr_vbe[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
84 }
85 s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
86 (shift_control << 5);
87 @@ -834,7 +838,7 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
88 break;
89 }
90
91 - if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
92 + if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
93 /* chain 4 mode : simplest access */
94 assert(addr < s->vram_size);
95 ret = s->vram_ptr[addr];
96 @@ -902,11 +906,11 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
97 break;
98 }
99
100 - if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
101 + if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
102 /* chain 4 mode : simplest access */
103 plane = addr & 3;
104 mask = (1 << plane);
105 - if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
106 + if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
107 assert(addr < s->vram_size);
108 s->vram_ptr[addr] = val;
109 #ifdef DEBUG_VGA_MEM
110 @@ -919,7 +923,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
111 /* odd/even mode (aka text mode mapping) */
112 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
113 mask = (1 << plane);
114 - if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
115 + if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
116 addr = ((addr & ~1) << 1) | plane;
117 if (addr >= s->vram_size) {
118 return;
119 @@ -994,7 +998,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
120
121 do_write:
122 /* mask data according to sr[2] */
123 - mask = s->sr[VGA_SEQ_PLANE_WRITE];
124 + mask = sr(s, VGA_SEQ_PLANE_WRITE);
125 s->plane_updated |= mask; /* only used to detect font change */
126 write_mask = mask16[mask];
127 if (addr * sizeof(uint32_t) >= s->vram_size) {
128 @@ -1150,10 +1154,10 @@ static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight
129 /* total width & height */
130 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
131 cwidth = 8;
132 - if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
133 + if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
134 cwidth = 9;
135 }
136 - if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
137 + if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
138 cwidth = 16; /* NOTE: no 18 pixel wide */
139 }
140 width = (s->cr[VGA_CRTC_H_DISP] + 1);
141 @@ -1195,7 +1199,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
142 int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
143
144 /* compute font data address (in plane 2) */
145 - v = s->sr[VGA_SEQ_CHARACTER_MAP];
146 + v = sr(s, VGA_SEQ_CHARACTER_MAP);
147 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
148 if (offset != s->font_offsets[0]) {
149 s->font_offsets[0] = offset;
150 @@ -1504,11 +1508,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
151 }
152
153 if (shift_control == 0) {
154 - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
155 + if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
156 disp_width <<= 1;
157 }
158 } else if (shift_control == 1) {
159 - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
160 + if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
161 disp_width <<= 1;
162 }
163 }
164 @@ -1572,7 +1576,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
165
166 if (shift_control == 0) {
167 full_update |= update_palette16(s);
168 - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
169 + if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
170 v = VGA_DRAW_LINE4D2;
171 } else {
172 v = VGA_DRAW_LINE4;
173 @@ -1580,7 +1584,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
174 bits = 4;
175 } else if (shift_control == 1) {
176 full_update |= update_palette16(s);
177 - if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
178 + if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
179 v = VGA_DRAW_LINE2D2;
180 } else {
181 v = VGA_DRAW_LINE2;
182 @@ -1627,7 +1631,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
183 #if 0
184 printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
185 width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
186 - s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
187 + s->line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
188 #endif
189 addr1 = (s->start_addr * 4);
190 bwidth = (width * bits + 7) / 8;
191 @@ -1779,6 +1783,7 @@ void vga_common_reset(VGACommonState *s)
192 {
193 s->sr_index = 0;
194 memset(s->sr, '\0', sizeof(s->sr));
195 + memset(s->sr_vbe, '\0', sizeof(s->sr_vbe));
196 s->gr_index = 0;
197 memset(s->gr, '\0', sizeof(s->gr));
198 s->ar_index = 0;
199 @@ -1881,10 +1886,10 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
200 /* total width & height */
201 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
202 cw = 8;
203 - if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
204 + if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
205 cw = 9;
206 }
207 - if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
208 + if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
209 cw = 16; /* NOTE: no 18 pixel wide */
210 }
211 width = (s->cr[VGA_CRTC_H_DISP] + 1);
212 @@ -2050,6 +2055,7 @@ static int vga_common_post_load(void *opaque, int version_id)
213
214 /* force refresh */
215 s->graphic_mode = -1;
216 + vbe_update_vgaregs(s);
217 return 0;
218 }
219
220 diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
221 index 40ba6a4..103cac2 100644
222 --- a/hw/display/vga_int.h
223 +++ b/hw/display/vga_int.h
224 @@ -99,6 +99,7 @@ typedef struct VGACommonState {
225 MemoryRegion chain4_alias;
226 uint8_t sr_index;
227 uint8_t sr[256];
228 + uint8_t sr_vbe[256];
229 uint8_t gr_index;
230 uint8_t gr[256];
231 uint8_t ar_index;
232 --
233 2.1.4
234