[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [qemu-xen stable-4.6] vga: fix banked access bounds checking (CVE-2016-3710)



commit 96c04bb7e436254db27b6fa0b288c6fc154c6f14
Author:     Gerd Hoffmann <kraxel@xxxxxxxxxx>
AuthorDate: Tue Apr 26 08:49:10 2016 +0200
Commit:     Anthony PERARD <anthony.perard@xxxxxxxxxx>
CommitDate: Mon May 9 17:41:20 2016 +0100

    vga: fix banked access bounds checking (CVE-2016-3710)
    
    vga allows banked access to video memory using the window at 0xa00000
    and it supports a different access modes with different address
    calculations.
    
    The VBE bochs extentions support banked access too, using the
    VBE_DISPI_INDEX_BANK register.  The code tries to take the different
    address calculations into account and applies different limits to
    VBE_DISPI_INDEX_BANK depending on the current access mode.
    
    Which is probably effective in stopping misprogramming by accident.
    But from a security point of view completely useless as an attacker
    can easily change access modes after setting the bank register.
    
    Drop the bogus check, add range checks to vga_mem_{readb,writeb}
    instead.
    
    upstream-commit-id: 3bf1817079bb0d80c0d8a86a7c7dd0bfe90eb82e
    
    Fixes: CVE-2016-3710
    Reported-by: Qinghao Tang <luodalongde@xxxxxxxxx>
    Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx>
    Signed-off-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
---
 hw/display/vga.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 52eaf05..b577712 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -178,6 +178,7 @@ static void vga_update_memory_access(VGACommonState *s)
             break;
         }
         base += isa_mem_base;
+        assert(offset + size <= s->vram_size);
         memory_region_init_alias(&s->chain4_alias, 
memory_region_owner(&s->vram),
                                  "vga.chain4", &s->vram, offset, size);
         memory_region_add_subregion_overlap(s->legacy_address_space, base,
@@ -715,11 +716,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, 
uint32_t val)
             vbe_fixup_regs(s);
             break;
         case VBE_DISPI_INDEX_BANK:
-            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
-              val &= (s->vbe_bank_mask >> 2);
-            } else {
-              val &= s->vbe_bank_mask;
-            }
+            val &= s->vbe_bank_mask;
             s->vbe_regs[s->vbe_index] = val;
             s->bank_offset = (val << 16);
             vga_update_memory_access(s);
@@ -818,13 +815,21 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
 
     if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
         /* chain 4 mode : simplest access */
+        assert(addr < s->vram_size);
         ret = s->vram_ptr[addr];
     } else if (s->gr[VGA_GFX_MODE] & 0x10) {
         /* odd/even mode (aka text mode mapping) */
         plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
-        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
+        addr = ((addr & ~1) << 1) | plane;
+        if (addr >= s->vram_size) {
+            return 0xff;
+        }
+        ret = s->vram_ptr[addr];
     } else {
         /* standard VGA latched access */
+        if (addr * sizeof(uint32_t) >= s->vram_size) {
+            return 0xff;
+        }
         s->latch = ((uint32_t *)s->vram_ptr)[addr];
 
         if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
@@ -881,6 +886,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, 
uint32_t val)
         plane = addr & 3;
         mask = (1 << plane);
         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
+            assert(addr < s->vram_size);
             s->vram_ptr[addr] = val;
 #ifdef DEBUG_VGA_MEM
             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
@@ -894,6 +900,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, 
uint32_t val)
         mask = (1 << plane);
         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
             addr = ((addr & ~1) << 1) | plane;
+            if (addr >= s->vram_size) {
+                return;
+            }
             s->vram_ptr[addr] = val;
 #ifdef DEBUG_VGA_MEM
             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
@@ -967,6 +976,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, 
uint32_t val)
         mask = s->sr[VGA_SEQ_PLANE_WRITE];
         s->plane_updated |= mask; /* only used to detect font change */
         write_mask = mask16[mask];
+        if (addr * sizeof(uint32_t) >= s->vram_size) {
+            return;
+        }
         ((uint32_t *)s->vram_ptr)[addr] =
             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
             (val & write_mask);
--
generated by git-patchbot for /home/xen/git/qemu-xen.git#stable-4.6

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.