e0ce7fc
From 15268f91fbe75b38a851c458aef74e693d646ea5 Mon Sep 17 00:00:00 2001
e201061
From: Gerd Hoffmann <kraxel@redhat.com>
e0ce7fc
Date: Tue, 21 Feb 2017 10:54:59 -0800
e0ce7fc
Subject: [PATCH 2/2] cirrus: add blit_is_unsafe call to
e0ce7fc
 cirrus_bitblt_cputovideo
e201061
e201061
CIRRUS_BLTMODE_MEMSYSSRC blits do NOT check blit destination
e201061
and blit width, at all.  Oops.  Fix it.
e201061
e201061
Security impact: high.
e201061
e201061
The missing blit destination check allows to write to host memory.
e201061
Basically same as CVE-2014-8106 for the other blit variants.
e201061
e201061
The missing blit width check allows to overflow cirrus_bltbuf,
e201061
with the attractive target cirrus_srcptr (current cirrus_bltbuf write
e201061
position) being located right after cirrus_bltbuf in CirrusVGAState.
e201061
e201061
Due to cirrus emulation writing cirrus_bltbuf bytewise the attacker
e201061
hasn't full control over cirrus_srcptr though, only one byte can be
e201061
changed.  Once the first byte has been modified further writes land
e201061
elsewhere.
e201061
e201061
[ This is CVE-2017-2620 / XSA-209  - Ian Jackson ]
e201061
e201061
Reported-by: Gerd Hoffmann <ghoffman@redhat.com>
e201061
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
e201061
---
e201061
 hw/display/cirrus_vga.c | 8 ++++++++
e201061
 1 file changed, 8 insertions(+)
e201061
e201061
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
e0ce7fc
index 34a6900..5901250 100644
e201061
--- a/hw/display/cirrus_vga.c
e201061
+++ b/hw/display/cirrus_vga.c
e0ce7fc
@@ -865,6 +865,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
e201061
 {
e201061
     int w;
e201061
 
e201061
+    if (blit_is_unsafe(s, true)) {
e201061
+        return 0;
e201061
+    }
e201061
+
e201061
     s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
e201061
     s->cirrus_srcptr = &s->cirrus_bltbuf[0];
e201061
     s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
e0ce7fc
@@ -890,6 +894,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
e201061
 	}
e201061
         s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
e201061
     }
e201061
+
e201061
+    /* the blit_is_unsafe call above should catch this */
e201061
+    assert(s->cirrus_blt_srcpitch <= CIRRUS_BLTBUFSIZE);
e201061
+
e201061
     s->cirrus_srcptr = s->cirrus_bltbuf;
e201061
     s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
e201061
     cirrus_update_memory_access(s);
e201061
-- 
e0ce7fc
2.1.4
e201061