Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [day] [month] [year] [list]
Date: Mon, 9 May 2016 17:33:28 +0530 (IST)
From: P J P <ppandit@...hat.com>
To: oss security list <oss-security@...ts.openwall.com>
cc: Michael Roth <mdroth@...ux.vnet.ibm.com>,
        Peter Maydell <peter.maydell@...aro.org>,
        Gerd Hoffmann <ghoffman@...hat.com>,
        Stefano Stabellini <sstabellini@...nel.org>,
        Qinghao Tang <luodalongde@...il.com>
Subject: CVE-2016-3710 Qemu: vga: out-of-bounds r/w access issue

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

    Hello,

An out-of-bounds r/w access issue was reported in the Qemu emulator's VGA 
module.

Qemu VGA module allows banked access to video memory using the window at 
0xa00000 and it supports different access modes with different address 
calculations. A privileged guest user could use this flaw to exceed the bank 
address window and write beyond the said memory area, potentially leading to 
arbitrary code execution with privileges of the Qemu process on a host. 
(Important)

'CVE-2016-3710' has been assigned to this issue by Red Hat Inc. Patch attached 
herein fixes this issue.

This issue was discovered and reported by "Wei Xiao and Qinghao Tang of 360 
Marvel Team" of 360.cn Inc.

They have named this issue as - "Dark Portal"

Thank you.
- --
Prasad J Pandit / Red Hat Product Security Team
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJXMHyQAAoJEN0TPTL+WwQfnnIQAImX2cxVTrPmGrPwFC66di8N
OIme91B7rFjFUQJ46Z+F3PmlsUsgDo9hwhg3VLOsQWeju06+C6fTV01dNvxL88re
mE7S5uQTRwOs9tR/ojxIYlwq6FnPek4yISRo9VsiQi/d8QD4+IPxg4mRH6nP9O4M
g9pYQrHAdKCGBsMmHUnIXJ5xamKO0oZMqJOfzZZUfZCDU3cy1p6pN6f2FVdgm7il
5/A5YJpC3Qvz9AM8DZ2jJOrEXMqIGucjt5fggOTzq3eNely6+Q1EV4i96+U08PrM
TeQqwNC1hEVSISpOKTM3V43XPnjpbbyb7SOMy2W4CCUq/NZTAQP9+HGzwarZ4IrF
xeVqJyyT9zewPRBuQX7XpG6cgKpHP3RuS4cYprMLccugd9fvYire7adRGeGfO25c
Rk3q1uSYWD4PkqalyprpjhXi85hQg2YbHRbc4Mjf1LAVExBYHoKb0vtZ0KnUXZTh
4h9HYPH1NnVKConQFXtSVEkcBgTAOtgKgHjDM/rZ0xNPnKsi4yVmJhBqSpmZ5c4b
VsnIggSpL0MtcDePKZN028a4bbkxdHUUCuADkBuNZSc5siBhzWFysO2CD5GaU7Qv
ZWV1IkxXbyZUXGgTzASvrsLtyXmBrB8EfQivZc2nVJCO3fHS1vGMPz6ccNKmRVnQ
T5mRyogkCnGI6B/lY8nj
=zy94
-----END PGP SIGNATURE-----
From 3bf1817079bb0d80c0d8a86a7c7dd0bfe90eb82e Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@...hat.com>
Date: Tue, 26 Apr 2016 08:49:10 +0200
Subject: [PATCH 1/5] 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.

Fixes: CVE-2016-3710
Reported-by: Qinghao Tang <luodalongde@...il.com>
Signed-off-by: Gerd Hoffmann <kraxel@...hat.com>
---
 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 657e9f1..b9191ca 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -179,6 +179,7 @@ static void vga_update_memory_access(VGACommonState *s)
             size = 0x8000;
             break;
         }
+        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,
@@ -716,11 +717,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);
@@ -819,13 +816,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)) {
@@ -882,6 +887,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);
@@ -895,6 +901,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);
@@ -968,6 +977,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);
-- 
1.8.3.1

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ