|
|
4f5da8 |
From 46da39c9f9a9a72cf9e833d46ce10d785581ce63 Mon Sep 17 00:00:00 2001
|
|
|
4f5da8 |
From: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
4f5da8 |
Date: Fri, 10 Feb 2017 08:30:13 +0100
|
|
|
4f5da8 |
Subject: [PATCH 1/3] cirrus: fix patterncopy checks
|
|
|
4f5da8 |
|
|
|
4f5da8 |
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
4f5da8 |
Message-id: <1486715415-3462-2-git-send-email-kraxel@redhat.com>
|
|
|
4f5da8 |
Patchwork-id: 73775
|
|
|
4f5da8 |
O-Subject: [virt-devel] [RHEL-7.4 qemu-kvm PATCH 1/3] cirrus: fix patterncopy checks
|
|
|
4f5da8 |
Bugzilla: 1420490
|
|
|
4f5da8 |
CVE: CVE-2017-2620/20170221
|
|
|
4f5da8 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
4f5da8 |
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
4f5da8 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
4f5da8 |
|
|
|
4f5da8 |
The blit_region_is_unsafe checks don't work correctly for the
|
|
|
4f5da8 |
patterncopy source. It's a fixed-sized region, which doesn't
|
|
|
4f5da8 |
depend on cirrus_blt_{width,height}. So go do the check in
|
|
|
4f5da8 |
cirrus_bitblt_common_patterncopy instead, then tell blit_is_unsafe that
|
|
|
4f5da8 |
it doesn't need to verify the source. Also handle the case where we
|
|
|
4f5da8 |
blit from cirrus_bitbuf correctly.
|
|
|
4f5da8 |
|
|
|
4f5da8 |
This patch replaces 5858dd1801883309bdd208d72ddb81c4e9fee30c.
|
|
|
4f5da8 |
|
|
|
4f5da8 |
Security impact: I think for the most part error on the safe side this
|
|
|
4f5da8 |
time, refusing blits which should have been allowed.
|
|
|
4f5da8 |
|
|
|
4f5da8 |
Only exception is placing the blit source at the end of the video ram,
|
|
|
4f5da8 |
so cirrus_blt_srcaddr + 256 goes beyond the end of video memory. But
|
|
|
4f5da8 |
even in that case I'm not fully sure this actually allows read access to
|
|
|
4f5da8 |
host memory. To trick the commit 5858dd18 security checks one has to
|
|
|
4f5da8 |
pick very small cirrus_blt_{width,height} values, which in turn implies
|
|
|
4f5da8 |
only a fraction of the blit source will actually be used.
|
|
|
4f5da8 |
|
|
|
4f5da8 |
Cc: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
|
|
4f5da8 |
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
4f5da8 |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
4f5da8 |
|
|
|
4f5da8 |
Upstream: WIP (https://patchwork.ozlabs.org/patch/726080/)
|
|
|
4f5da8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
4f5da8 |
---
|
|
|
4f5da8 |
hw/display/cirrus_vga.c | 36 ++++++++++++++++++++++++++++++------
|
|
|
4f5da8 |
1 file changed, 30 insertions(+), 6 deletions(-)
|
|
|
4f5da8 |
|
|
|
4f5da8 |
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
|
|
|
4f5da8 |
index e0e39ef..fff9bf0 100644
|
|
|
4f5da8 |
--- a/hw/display/cirrus_vga.c
|
|
|
4f5da8 |
+++ b/hw/display/cirrus_vga.c
|
|
|
4f5da8 |
@@ -678,14 +678,39 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
|
|
|
4f5da8 |
}
|
|
|
4f5da8 |
}
|
|
|
4f5da8 |
|
|
|
4f5da8 |
-static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
|
|
|
4f5da8 |
- const uint8_t * src)
|
|
|
4f5da8 |
+static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
|
|
|
4f5da8 |
{
|
|
|
4f5da8 |
+ uint32_t patternsize;
|
|
|
4f5da8 |
uint8_t *dst;
|
|
|
4f5da8 |
+ uint8_t *src;
|
|
|
4f5da8 |
|
|
|
4f5da8 |
dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr;
|
|
|
4f5da8 |
|
|
|
4f5da8 |
- if (blit_is_unsafe(s, false, true)) {
|
|
|
4f5da8 |
+ if (videosrc) {
|
|
|
4f5da8 |
+ switch (s->vga.get_bpp(&s->vga)) {
|
|
|
4f5da8 |
+ case 8:
|
|
|
4f5da8 |
+ patternsize = 64;
|
|
|
4f5da8 |
+ break;
|
|
|
4f5da8 |
+ case 15:
|
|
|
4f5da8 |
+ case 16:
|
|
|
4f5da8 |
+ patternsize = 128;
|
|
|
4f5da8 |
+ break;
|
|
|
4f5da8 |
+ case 24:
|
|
|
4f5da8 |
+ case 32:
|
|
|
4f5da8 |
+ default:
|
|
|
4f5da8 |
+ patternsize = 256;
|
|
|
4f5da8 |
+ break;
|
|
|
4f5da8 |
+ }
|
|
|
4f5da8 |
+ s->cirrus_blt_srcaddr &= ~(patternsize - 1);
|
|
|
4f5da8 |
+ if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) {
|
|
|
4f5da8 |
+ return 0;
|
|
|
4f5da8 |
+ }
|
|
|
4f5da8 |
+ src = s->vga.vram_ptr + s->cirrus_blt_srcaddr;
|
|
|
4f5da8 |
+ } else {
|
|
|
4f5da8 |
+ src = s->cirrus_bltbuf;
|
|
|
4f5da8 |
+ }
|
|
|
4f5da8 |
+
|
|
|
4f5da8 |
+ if (blit_is_unsafe(s, true, true)) {
|
|
|
4f5da8 |
return 0;
|
|
|
4f5da8 |
}
|
|
|
4f5da8 |
|
|
|
4f5da8 |
@@ -726,8 +751,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
|
|
|
4f5da8 |
|
|
|
4f5da8 |
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
|
|
4f5da8 |
{
|
|
|
4f5da8 |
- return cirrus_bitblt_common_patterncopy(s, s->vga.vram_ptr +
|
|
|
4f5da8 |
- (s->cirrus_blt_srcaddr & ~7));
|
|
|
4f5da8 |
+ return cirrus_bitblt_common_patterncopy(s, true);
|
|
|
4f5da8 |
}
|
|
|
4f5da8 |
|
|
|
4f5da8 |
static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
|
|
4f5da8 |
@@ -826,7 +850,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
|
|
|
4f5da8 |
|
|
|
4f5da8 |
if (s->cirrus_srccounter > 0) {
|
|
|
4f5da8 |
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
|
|
|
4f5da8 |
- cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
|
|
|
4f5da8 |
+ cirrus_bitblt_common_patterncopy(s, false);
|
|
|
4f5da8 |
the_end:
|
|
|
4f5da8 |
s->cirrus_srccounter = 0;
|
|
|
4f5da8 |
cirrus_bitblt_reset(s);
|
|
|
4f5da8 |
--
|
|
|
4f5da8 |
1.8.3.1
|
|
|
4f5da8 |
|