Skip to content

Commit

Permalink
cirrus: fix patterncopy checks
Browse files Browse the repository at this point in the history
The blit_region_is_unsafe checks don't work correctly for the
patterncopy source.  It's a fixed-sized region, which doesn't
depend on cirrus_blt_{width,height}.  So go do the check in
cirrus_bitblt_common_patterncopy instead, then tell blit_is_unsafe that
it doesn't need to verify the source.  Also handle the case where we
blit from cirrus_bitbuf correctly.

This patch replaces 5858dd1.

Security impact:  I think for the most part error on the safe side this
time, refusing blits which should have been allowed.

Only exception is placing the blit source at the end of the video ram,
so cirrus_blt_srcaddr + 256 goes beyond the end of video memory.  But
even in that case I'm not fully sure this actually allows read access to
host memory.  To trick the commit 5858dd1 security checks one has to
pick very small cirrus_blt_{width,height} values, which in turn implies
only a fraction of the blit source will actually be used.

Cc: Wolfgang Bumiller <w.bumiller@proxmox.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
Message-id: 1486645341-5010-1-git-send-email-kraxel@redhat.com
  • Loading branch information
kraxel committed Feb 10, 2017
1 parent ec87f20 commit 95280c3
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions hw/display/cirrus_vga.c
Expand Up @@ -684,14 +684,39 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
}
}

static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
const uint8_t * src)
static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc)
{
uint32_t patternsize;
uint8_t *dst;
uint8_t *src;

dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr;

if (blit_is_unsafe(s, false, true)) {
if (videosrc) {
switch (s->vga.get_bpp(&s->vga)) {
case 8:
patternsize = 64;
break;
case 15:
case 16:
patternsize = 128;
break;
case 24:
case 32:
default:
patternsize = 256;
break;
}
s->cirrus_blt_srcaddr &= ~(patternsize - 1);
if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) {
return 0;
}
src = s->vga.vram_ptr + s->cirrus_blt_srcaddr;
} else {
src = s->cirrus_bltbuf;
}

if (blit_is_unsafe(s, true, true)) {
return 0;
}

Expand Down Expand Up @@ -732,8 +757,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)

static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
{
return cirrus_bitblt_common_patterncopy(s, s->vga.vram_ptr +
(s->cirrus_blt_srcaddr & ~7));
return cirrus_bitblt_common_patterncopy(s, true);
}

static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
Expand Down Expand Up @@ -832,7 +856,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)

if (s->cirrus_srccounter > 0) {
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
cirrus_bitblt_common_patterncopy(s, false);
the_end:
s->cirrus_srccounter = 0;
cirrus_bitblt_reset(s);
Expand Down

0 comments on commit 95280c3

Please sign in to comment.