View | Details | Raw Unified | Return to bug 40920
Collapse All | Expand All

(-)qemu-2.1+dfsg.orig/debian/patches/series (+9 lines)
 Lines 93-95    Link Here 
93
i386-avoid-null-pointer-dereference-CVE-2016-1922.patch
93
i386-avoid-null-pointer-dereference-CVE-2016-1922.patch
94
e1000-eliminate-infinite-loops-on-out-of-bounds-start-CVE-2016-1981.patch
94
e1000-eliminate-infinite-loops-on-out-of-bounds-start-CVE-2016-1981.patch
95
hmp-fix-sendkey-out-of-bounds-write-CVE-2015-8619.patch
95
hmp-fix-sendkey-out-of-bounds-write-CVE-2015-8619.patch
96
97
# CVE-2016-3710
98
vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch
99
100
# CVE-2016-3712
101
vga-add-vbe_enabled-helper.patch
102
vga-factor-out-vga-register-setup.patch
103
vga-update-vga-register-setup-on-vbe-changes.patch
104
vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch
(-)qemu-2.1+dfsg.orig/debian/patches/vga-add-vbe_enabled-helper.patch (+68 lines)
Line 0    Link Here 
1
From 294a6c15a38669f80920b885287191514ab7d9ff Mon Sep 17 00:00:00 2001
2
From: Gerd Hoffmann <kraxel@redhat.com>
3
Date: Tue, 26 Apr 2016 14:11:34 +0200
4
Subject: [PATCH 2/5] vga: add vbe_enabled() helper
5
6
Makes code a bit easier to read.
7
8
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
9
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
10
---
11
 hw/display/vga.c | 13 +++++++++----
12
 1 file changed, 9 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/display/vga.c b/hw/display/vga.c
15
index 69e2554..da1eb4a 100644
16
--- a/hw/display/vga.c
17
+++ b/hw/display/vga.c
18
@@ -166,6 +166,11 @@ static uint32_t expand4[256];
19
 static uint16_t expand2[256];
20
 static uint8_t expand4to8[16];
21
 
22
+static inline bool vbe_enabled(VGACommonState *s)
23
+{
24
+    return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
25
+}
26
+
27
 static void vga_update_memory_access(VGACommonState *s)
28
 {
29
     MemoryRegion *region, *old_region = s->chain4_alias;
30
@@ -593,7 +598,7 @@ static void vbe_fixup_regs(VGACommonState *s)
31
     uint16_t *r = s->vbe_regs;
32
     uint32_t bits, linelength, maxy, offset;
33
 
34
-    if (!(r[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
35
+    if (!vbe_enabled(s)) {
36
         /* vbe is turned off -- nothing to do */
37
         return;
38
     }
39
@@ -1174,7 +1179,7 @@ static void vga_get_offsets(VGACommonState *s,
40
 {
41
     uint32_t start_addr, line_offset, line_compare;
42
 
43
-    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
44
+    if (vbe_enabled(s)) {
45
         line_offset = s->vbe_line_offset;
46
         start_addr = s->vbe_start_addr;
47
         line_compare = 65535;
48
@@ -1627,7 +1632,7 @@ static int vga_get_bpp(VGACommonState *s)
49
 {
50
     int ret;
51
 
52
-    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
53
+    if (vbe_enabled(s)) {
54
         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
55
     } else {
56
         ret = 0;
57
@@ -1639,7 +1644,7 @@ static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
58
 {
59
     int width, height;
60
 
61
-    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
62
+    if (vbe_enabled(s)) {
63
         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
64
         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
65
     } else {
66
-- 
67
1.9.1
68
(-)qemu-2.1+dfsg.orig/debian/patches/vga-factor-out-vga-register-setup.patch (+128 lines)
Line 0    Link Here 
1
From d377918c23d85f64d01914b43bfabc0a46fe974a Mon Sep 17 00:00:00 2001
2
From: Gerd Hoffmann <kraxel@redhat.com>
3
Date: Tue, 26 Apr 2016 15:24:18 +0200
4
Subject: [PATCH 3/5] vga: factor out vga register setup
5
6
When enabling vbe mode qemu will setup a bunch of vga registers to make
7
sure the vga emulation operates in correct mode for a linear
8
framebuffer.  Move that code to a separate function so we can call it
9
from other places too.
10
11
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
12
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
13
---
14
 hw/display/vga.c | 79 +++++++++++++++++++++++++++++++-------------------------
15
 1 file changed, 44 insertions(+), 35 deletions(-)
16
17
diff --git a/hw/display/vga.c b/hw/display/vga.c
18
index da1eb4a..cf5f97e 100644
19
--- a/hw/display/vga.c
20
+++ b/hw/display/vga.c
21
@@ -673,6 +673,49 @@ static void vbe_fixup_regs(VGACommonState *s)
22
     s->vbe_start_addr  = offset / 4;
23
 }
24
 
25
+/* we initialize the VGA graphic mode */
26
+static void vbe_update_vgaregs(VGACommonState *s)
27
+{
28
+    int h, shift_control;
29
+
30
+    if (!vbe_enabled(s)) {
31
+        /* vbe is turned off -- nothing to do */
32
+        return;
33
+    }
34
+
35
+    /* graphic mode + memory map 1 */
36
+    s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
37
+        VGA_GR06_GRAPHICS_MODE;
38
+    s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
39
+    s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
40
+    /* width */
41
+    s->cr[VGA_CRTC_H_DISP] =
42
+        (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
43
+    /* height (only meaningful if < 1024) */
44
+    h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
45
+    s->cr[VGA_CRTC_V_DISP_END] = h;
46
+    s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
47
+        ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
48
+    /* line compare to 1023 */
49
+    s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
50
+    s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
51
+    s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
52
+
53
+    if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
54
+        shift_control = 0;
55
+        s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
56
+    } else {
57
+        shift_control = 2;
58
+        /* set chain 4 mode */
59
+        s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
60
+        /* activate all planes */
61
+        s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
62
+    }
63
+    s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
64
+        (shift_control << 5);
65
+    s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
66
+}
67
+
68
 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
69
 {
70
     VGACommonState *s = opaque;
71
@@ -759,53 +802,19 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
72
         case VBE_DISPI_INDEX_ENABLE:
73
             if ((val & VBE_DISPI_ENABLED) &&
74
                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
75
-                int h, shift_control;
76
 
77
                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0;
78
                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
79
                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
80
                 s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;
81
                 vbe_fixup_regs(s);
82
+                vbe_update_vgaregs(s);
83
 
84
                 /* clear the screen (should be done in BIOS) */
85
                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
86
                     memset(s->vram_ptr, 0,
87
                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
88
                 }
89
-
90
-                /* we initialize the VGA graphic mode (should be done
91
-                   in BIOS) */
92
-                /* graphic mode + memory map 1 */
93
-                s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
94
-                    VGA_GR06_GRAPHICS_MODE;
95
-                s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
96
-                s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
97
-                /* width */
98
-                s->cr[VGA_CRTC_H_DISP] =
99
-                    (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
100
-                /* height (only meaningful if < 1024) */
101
-                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
102
-                s->cr[VGA_CRTC_V_DISP_END] = h;
103
-                s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
104
-                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
105
-                /* line compare to 1023 */
106
-                s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
107
-                s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
108
-                s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
109
-
110
-                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
111
-                    shift_control = 0;
112
-                    s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
113
-                } else {
114
-                    shift_control = 2;
115
-                    /* set chain 4 mode */
116
-                    s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
117
-                    /* activate all planes */
118
-                    s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
119
-                }
120
-                s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
121
-                    (shift_control << 5);
122
-                s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
123
             } else {
124
                 /* XXX: the bios should do that */
125
                 s->bank_offset = 0;
126
-- 
127
1.9.1
128
(-)qemu-2.1+dfsg.orig/debian/patches/vga-fix-banked-access-bounds-checking-CVE-2016-3710.patch (+108 lines)
Line 0    Link Here 
1
From 25935fd1ed3c4337aa4b61902ec580e17b130b63 Mon Sep 17 00:00:00 2001
2
From: Gerd Hoffmann <kraxel@redhat.com>
3
Date: Tue, 26 Apr 2016 08:49:10 +0200
4
Subject: [PATCH 1/5] vga: fix banked access bounds checking (CVE-2016-3710)
5
6
vga allows banked access to video memory using the window at 0xa00000
7
and it supports a different access modes with different address
8
calculations.
9
10
The VBE bochs extentions support banked access too, using the
11
VBE_DISPI_INDEX_BANK register.  The code tries to take the different
12
address calculations into account and applies different limits to
13
VBE_DISPI_INDEX_BANK depending on the current access mode.
14
15
Which is probably effective in stopping misprogramming by accident.
16
But from a security point of view completely useless as an attacker
17
can easily change access modes after setting the bank register.
18
19
Drop the bogus check, add range checks to vga_mem_{readb,writeb}
20
instead.
21
22
Fixes: CVE-2016-3710
23
Reported-by: Qinghao Tang <luodalongde@gmail.com>
24
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
25
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
26
---
27
 hw/display/vga.c | 24 ++++++++++++++++++------
28
 1 file changed, 18 insertions(+), 6 deletions(-)
29
30
diff --git a/hw/display/vga.c b/hw/display/vga.c
31
index 430e7ed..69e2554 100644
32
--- a/hw/display/vga.c
33
+++ b/hw/display/vga.c
34
@@ -197,6 +197,7 @@ static void vga_update_memory_access(VGACommonState *s)
35
             break;
36
         }
37
         base += isa_mem_base;
38
+        assert(offset + size <= s->vram_size);
39
         region = g_malloc(sizeof(*region));
40
         memory_region_init_alias(region, memory_region_owner(&s->vram),
41
                                  "vga.chain4", &s->vram, offset, size);
42
@@ -745,11 +746,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
43
             vbe_fixup_regs(s);
44
             break;
45
         case VBE_DISPI_INDEX_BANK:
46
-            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
47
-              val &= (s->vbe_bank_mask >> 2);
48
-            } else {
49
-              val &= s->vbe_bank_mask;
50
-            }
51
+            val &= s->vbe_bank_mask;
52
             s->vbe_regs[s->vbe_index] = val;
53
             s->bank_offset = (val << 16);
54
             vga_update_memory_access(s);
55
@@ -850,13 +847,21 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
56
 
57
     if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
58
         /* chain 4 mode : simplest access */
59
+        assert(addr < s->vram_size);
60
         ret = s->vram_ptr[addr];
61
     } else if (s->gr[VGA_GFX_MODE] & 0x10) {
62
         /* odd/even mode (aka text mode mapping) */
63
         plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
64
-        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
65
+        addr = ((addr & ~1) << 1) | plane;
66
+        if (addr >= s->vram_size) {
67
+            return 0xff;
68
+        }
69
+        ret = s->vram_ptr[addr];
70
     } else {
71
         /* standard VGA latched access */
72
+        if (addr * sizeof(uint32_t) >= s->vram_size) {
73
+            return 0xff;
74
+        }
75
         s->latch = ((uint32_t *)s->vram_ptr)[addr];
76
 
77
         if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
78
@@ -913,6 +918,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
79
         plane = addr & 3;
80
         mask = (1 << plane);
81
         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
82
+            assert(addr < s->vram_size);
83
             s->vram_ptr[addr] = val;
84
 #ifdef DEBUG_VGA_MEM
85
             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
86
@@ -926,6 +932,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
87
         mask = (1 << plane);
88
         if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
89
             addr = ((addr & ~1) << 1) | plane;
90
+            if (addr >= s->vram_size) {
91
+                return;
92
+            }
93
             s->vram_ptr[addr] = val;
94
 #ifdef DEBUG_VGA_MEM
95
             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
96
@@ -999,6 +1008,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
97
         mask = s->sr[VGA_SEQ_PLANE_WRITE];
98
         s->plane_updated |= mask; /* only used to detect font change */
99
         write_mask = mask16[mask];
100
+        if (addr * sizeof(uint32_t) >= s->vram_size) {
101
+            return;
102
+        }
103
         ((uint32_t *)s->vram_ptr)[addr] =
104
             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
105
             (val & write_mask);
106
-- 
107
1.9.1
108
(-)qemu-2.1+dfsg.orig/debian/patches/vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch (+75 lines)
Line 0    Link Here 
1
From f7926c73685c2bc7124265f567bafb502864c5dd Mon Sep 17 00:00:00 2001
2
From: Gerd Hoffmann <kraxel@redhat.com>
3
Date: Tue, 26 Apr 2016 14:48:06 +0200
4
Subject: [PATCH 5/5] vga: make sure vga register setup for vbe stays intact
5
 (CVE-2016-3712).
6
7
Call vbe_update_vgaregs() when the guest touches GFX, SEQ or CRT
8
registers, to make sure the vga registers will always have the
9
values needed by vbe mode.  This makes sure the sanity checks
10
applied by vbe_fixup_regs() are effective.
11
12
Without this guests can muck with shift_control, can turn on planar
13
vga modes or text mode emulation while VBE is active, making qemu
14
take code paths meant for CGA compatibility, but with the very
15
large display widths and heigts settable using VBE registers.
16
17
Which is good for one or another buffer overflow.  Not that
18
critical as they typically read overflows happening somewhere
19
in the display code.  So guests can DoS by crashing qemu with a
20
segfault, but it is probably not possible to break out of the VM.
21
22
Fixes: CVE-2016-3712
23
Reported-by: Zuozhi Fzz <zuozhi.fzz@alibaba-inc.com>
24
Reported-by: P J P <ppandit@redhat.com>
25
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
26
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
27
---
28
 hw/display/vga.c | 6 ++++++
29
 1 file changed, 6 insertions(+)
30
31
diff --git a/hw/display/vga.c b/hw/display/vga.c
32
index 63d1a70..dd61246 100644
33
--- a/hw/display/vga.c
34
+++ b/hw/display/vga.c
35
@@ -166,6 +166,8 @@ static uint32_t expand4[256];
36
 static uint16_t expand2[256];
37
 static uint8_t expand4to8[16];
38
 
39
+static void vbe_update_vgaregs(VGACommonState *s);
40
+
41
 static inline bool vbe_enabled(VGACommonState *s)
42
 {
43
     return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
44
@@ -513,6 +515,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
45
         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
46
 #endif
47
         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
48
+        vbe_update_vgaregs(s);
49
         if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
50
             s->update_retrace_info(s);
51
         }
52
@@ -544,6 +547,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
53
         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
54
 #endif
55
         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
56
+        vbe_update_vgaregs(s);
57
         vga_update_memory_access(s);
58
         break;
59
     case VGA_CRT_IM:
60
@@ -562,10 +566,12 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
61
             if (s->cr_index == VGA_CRTC_OVERFLOW) {
62
                 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
63
                     (val & 0x10);
64
+                vbe_update_vgaregs(s);
65
             }
66
             return;
67
         }
68
         s->cr[s->cr_index] = val;
69
+        vbe_update_vgaregs(s);
70
 
71
         switch(s->cr_index) {
72
         case VGA_CRTC_H_TOTAL:
73
-- 
74
1.9.1
75
(-)qemu-2.1+dfsg.orig/debian/patches/vga-update-vga-register-setup-on-vbe-changes.patch (+29 lines)
Line 0    Link Here 
1
From fbcff82cd7998f93556c28dfc63bbbd7b206c8ce Mon Sep 17 00:00:00 2001
2
From: Gerd Hoffmann <kraxel@redhat.com>
3
Date: Tue, 26 Apr 2016 15:39:22 +0200
4
Subject: [PATCH 4/5] vga: update vga register setup on vbe changes
5
6
Call the new vbe_update_vgaregs() function on vbe configuration
7
changes, to make sure vga registers are up-to-date.
8
9
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
10
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
11
---
12
 hw/display/vga.c | 1 +
13
 1 file changed, 1 insertion(+)
14
15
diff --git a/hw/display/vga.c b/hw/display/vga.c
16
index cf5f97e..63d1a70 100644
17
--- a/hw/display/vga.c
18
+++ b/hw/display/vga.c
19
@@ -792,6 +792,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
20
         case VBE_DISPI_INDEX_Y_OFFSET:
21
             s->vbe_regs[s->vbe_index] = val;
22
             vbe_fixup_regs(s);
23
+            vbe_update_vgaregs(s);
24
             break;
25
         case VBE_DISPI_INDEX_BANK:
26
             val &= s->vbe_bank_mask;
27
-- 
28
1.9.1
29

Return to bug 40920