From 876d516311c1538a7d29f2abec48b7cda0645eea Mon Sep 17 00:00:00 2001 From: Radim Krčmář Date: Tue, 17 Feb 2015 17:30:51 +0100 Subject: spice: fix invalid memory access to vga.vram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vga_common_init() doesn't allow more than 256 MiB vram size and silently shrinks any larger value. qxl_dirty_surfaces() used the unshrinked size via qxl->shadow_rom.surface0_area_size when accessing the memory, which resulted in segfault. Add a workaround for this case and an assert if it happens again. We have to bump the vga memory limit too, because 256 MiB wouldn't have allowed 8k (it requires more than 128 MiB). 1024 MiB doesn't work, but 512 MiB seems fine. Proposed-by: Gerd Hoffmann Signed-off-by: Radim Krčmář Signed-off-by: Gerd Hoffmann --- hw/display/vga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw/display/vga.c') diff --git a/hw/display/vga.c b/hw/display/vga.c index c8c49abc6e..6e4ca7e9ab 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2121,10 +2121,10 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) expand4to8[i] = v; } - /* valid range: 1 MB -> 256 MB */ + /* valid range: 1 MB -> 512 MB */ s->vram_size = 1024 * 1024; while (s->vram_size < (s->vram_size_mb << 20) && - s->vram_size < (256 << 20)) { + s->vram_size < (512 << 20)) { s->vram_size <<= 1; } s->vram_size_mb = s->vram_size >> 20; -- cgit 1.4.1 From 619616ce31a5a5d167bf26f40d920b26da0a7bfd Mon Sep 17 00:00:00 2001 From: Radim Krčmář Date: Tue, 17 Feb 2015 17:30:53 +0100 Subject: vga: refactor vram_size clamping and rounding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the code a bit more obvious. We don't have min/max, so a general helper for clamp probably isn't acceptable either. Signed-off-by: Radim Krčmář Signed-off-by: Gerd Hoffmann --- hw/display/vga.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'hw/display/vga.c') diff --git a/hw/display/vga.c b/hw/display/vga.c index 6e4ca7e9ab..c0f7b343bb 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2094,6 +2094,17 @@ static const GraphicHwOps vga_ops = { .text_update = vga_update_text, }; +static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax) +{ + if (val < vmin) { + return vmin; + } + if (val > vmax) { + return vmax; + } + return val; +} + void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) { int i, j, v, b; @@ -2121,13 +2132,10 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) expand4to8[i] = v; } - /* valid range: 1 MB -> 512 MB */ - s->vram_size = 1024 * 1024; - while (s->vram_size < (s->vram_size_mb << 20) && - s->vram_size < (512 << 20)) { - s->vram_size <<= 1; - } - s->vram_size_mb = s->vram_size >> 20; + s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512); + s->vram_size_mb = pow2ceil(s->vram_size_mb); + s->vram_size = s->vram_size_mb << 20; + if (!s->vbe_size) { s->vbe_size = s->vram_size; } -- cgit 1.4.1