|
|
9bac43 |
From cb36a048eaf475d3184e5fbecfa669d5d645f943 Mon Sep 17 00:00:00 2001
|
|
|
9bac43 |
From: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
9bac43 |
Date: Fri, 20 Oct 2017 07:19:24 +0200
|
|
|
9bac43 |
Subject: [PATCH 02/19] vga: handle cirrus vbe mode wraparounds.
|
|
|
9bac43 |
|
|
|
9bac43 |
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
9bac43 |
Message-id: <20171020071925.9483-4-kraxel@redhat.com>
|
|
|
9bac43 |
Patchwork-id: 77391
|
|
|
9bac43 |
O-Subject: [RHV7.5 qemu-kvm-rhev PATCH 3/4] vga: handle cirrus vbe mode wraparounds.
|
|
|
9bac43 |
Bugzilla: 1501301
|
|
|
9bac43 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9bac43 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
9bac43 |
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
9bac43 |
|
|
|
9bac43 |
Commit "3d90c62548 vga: stop passing pointers to vga_draw_line*
|
|
|
9bac43 |
functions" is incomplete. It doesn't handle the case that the vga
|
|
|
9bac43 |
rendering code tries to create a shared surface, i.e. a pixman image
|
|
|
9bac43 |
backed by vga video memory. That can not work in case the guest display
|
|
|
9bac43 |
wraps from end of video memory to the start. So force shadowing in that
|
|
|
9bac43 |
case. Also adjust the snapshot region calculation.
|
|
|
9bac43 |
|
|
|
9bac43 |
Can trigger with cirrus only, when programming vbe modes using the bochs
|
|
|
9bac43 |
api (stdvga, also qxl and virtio-vga in vga compat mode) wrap arounds
|
|
|
9bac43 |
can't happen.
|
|
|
9bac43 |
|
|
|
9bac43 |
Fixes: CVE-2017-13672
|
|
|
9bac43 |
Fixes: 3d90c6254863693a6b13d918d2b8682e08bbc681
|
|
|
9bac43 |
Cc: P J P <ppandit@redhat.com>
|
|
|
9bac43 |
Reported-by: David Buchanan <d@vidbuchanan.co.uk>
|
|
|
9bac43 |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
9bac43 |
Message-id: 20171010141323.14049-3-kraxel@redhat.com
|
|
|
9bac43 |
(cherry picked from commit 28f77de26a4f9995458ddeb9d34bb06c0193bdc9)
|
|
|
9bac43 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9bac43 |
---
|
|
|
9bac43 |
hw/display/vga.c | 28 +++++++++++++++++++++-------
|
|
|
9bac43 |
1 file changed, 21 insertions(+), 7 deletions(-)
|
|
|
9bac43 |
|
|
|
9bac43 |
diff --git a/hw/display/vga.c b/hw/display/vga.c
|
|
|
9bac43 |
index 895e95c..06ca3da 100644
|
|
|
9bac43 |
--- a/hw/display/vga.c
|
|
|
9bac43 |
+++ b/hw/display/vga.c
|
|
|
9bac43 |
@@ -1465,13 +1465,13 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|
|
9bac43 |
DisplaySurface *surface = qemu_console_surface(s->con);
|
|
|
9bac43 |
int y1, y, update, linesize, y_start, double_scan, mask, depth;
|
|
|
9bac43 |
int width, height, shift_control, bwidth, bits;
|
|
|
9bac43 |
- ram_addr_t page0, page1;
|
|
|
9bac43 |
+ ram_addr_t page0, page1, region_start, region_end;
|
|
|
9bac43 |
DirtyBitmapSnapshot *snap = NULL;
|
|
|
9bac43 |
int disp_width, multi_scan, multi_run;
|
|
|
9bac43 |
uint8_t *d;
|
|
|
9bac43 |
uint32_t v, addr1, addr;
|
|
|
9bac43 |
vga_draw_line_func *vga_draw_line = NULL;
|
|
|
9bac43 |
- bool share_surface;
|
|
|
9bac43 |
+ bool share_surface, force_shadow = false;
|
|
|
9bac43 |
pixman_format_code_t format;
|
|
|
9bac43 |
#ifdef HOST_WORDS_BIGENDIAN
|
|
|
9bac43 |
bool byteswap = !s->big_endian_fb;
|
|
|
9bac43 |
@@ -1484,6 +1484,15 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|
|
9bac43 |
s->get_resolution(s, &width, &height);
|
|
|
9bac43 |
disp_width = width;
|
|
|
9bac43 |
|
|
|
9bac43 |
+ region_start = (s->start_addr * 4);
|
|
|
9bac43 |
+ region_end = region_start + s->line_offset * height;
|
|
|
9bac43 |
+ if (region_end > s->vbe_size) {
|
|
|
9bac43 |
+ /* wraps around (can happen with cirrus vbe modes) */
|
|
|
9bac43 |
+ region_start = 0;
|
|
|
9bac43 |
+ region_end = s->vbe_size;
|
|
|
9bac43 |
+ force_shadow = true;
|
|
|
9bac43 |
+ }
|
|
|
9bac43 |
+
|
|
|
9bac43 |
shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
|
|
|
9bac43 |
double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
|
|
|
9bac43 |
if (shift_control != 1) {
|
|
|
9bac43 |
@@ -1523,7 +1532,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|
|
9bac43 |
format = qemu_default_pixman_format(depth, !byteswap);
|
|
|
9bac43 |
if (format) {
|
|
|
9bac43 |
share_surface = dpy_gfx_check_format(s->con, format)
|
|
|
9bac43 |
- && !s->force_shadow;
|
|
|
9bac43 |
+ && !s->force_shadow && !force_shadow;
|
|
|
9bac43 |
} else {
|
|
|
9bac43 |
share_surface = false;
|
|
|
9bac43 |
}
|
|
|
9bac43 |
@@ -1627,8 +1636,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|
|
9bac43 |
y1 = 0;
|
|
|
9bac43 |
|
|
|
9bac43 |
if (!full_update) {
|
|
|
9bac43 |
- ram_addr_t region_start = addr1;
|
|
|
9bac43 |
- ram_addr_t region_end = addr1 + s->line_offset * height;
|
|
|
9bac43 |
vga_sync_dirty_bitmap(s);
|
|
|
9bac43 |
if (s->line_compare < height) {
|
|
|
9bac43 |
/* split screen mode */
|
|
|
9bac43 |
@@ -1651,10 +1658,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
|
|
9bac43 |
addr = (addr & ~0x8000) | ((y1 & 2) << 14);
|
|
|
9bac43 |
}
|
|
|
9bac43 |
update = full_update;
|
|
|
9bac43 |
- page0 = addr;
|
|
|
9bac43 |
- page1 = addr + bwidth - 1;
|
|
|
9bac43 |
+ page0 = addr & s->vbe_size_mask;
|
|
|
9bac43 |
+ page1 = (addr + bwidth - 1) & s->vbe_size_mask;
|
|
|
9bac43 |
if (full_update) {
|
|
|
9bac43 |
update = 1;
|
|
|
9bac43 |
+ } else if (page1 < page0) {
|
|
|
9bac43 |
+ /* scanline wraps from end of video memory to the start */
|
|
|
9bac43 |
+ assert(force_shadow);
|
|
|
9bac43 |
+ update = memory_region_snapshot_get_dirty(&s->vram, snap,
|
|
|
9bac43 |
+ page0, 0);
|
|
|
9bac43 |
+ update |= memory_region_snapshot_get_dirty(&s->vram, snap,
|
|
|
9bac43 |
+ page1, 0);
|
|
|
9bac43 |
} else {
|
|
|
9bac43 |
update = memory_region_snapshot_get_dirty(&s->vram, snap,
|
|
|
9bac43 |
page0, page1 - page0);
|
|
|
9bac43 |
--
|
|
|
9bac43 |
1.8.3.1
|
|
|
9bac43 |
|