a056f3
From: linzhecheng <linzhecheng@huawei.com>
a056f3
Date: Thu, 11 Jan 2018 21:27:24 +0800
a056f3
Subject: [PATCH] vga: check the validation of memory addr when draw text
a056f3
a056f3
Start a vm with qemu-kvm -enable-kvm -vnc :66 -smp 1 -m 1024 -hda
a056f3
redhat_5.11.qcow2  -device pcnet -vga cirrus,
a056f3
then use VNC client to connect to VM, and excute the code below in guest
a056f3
OS will lead to qemu crash:
a056f3
a056f3
int main()
a056f3
 {
a056f3
    iopl(3);
a056f3
    srand(time(NULL));
a056f3
    int a,b;
a056f3
    while(1){
a056f3
	a = rand()%0x100;
a056f3
	b = 0x3c0 + (rand()%0x20);
a056f3
        outb(a,b);
a056f3
    }
a056f3
    return 0;
a056f3
}
a056f3
a056f3
The above code is writing the registers of VGA randomly.
a056f3
We can write VGA CRT controller registers index 0x0C or 0x0D
a056f3
(which is the start address register) to modify the
a056f3
the display memory address of the upper left pixel
a056f3
or character of the screen. The address may be out of the
a056f3
range of vga ram. So we should check the validation of memory address
a056f3
when reading or writing it to avoid segfault.
a056f3
a056f3
Signed-off-by: linzhecheng <linzhecheng@huawei.com>
a056f3
Message-id: 20180111132724.13744-1-linzhecheng@huawei.com
a056f3
Fixes: CVE-2018-5683
a056f3
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
a056f3
(cherry picked from commit 191f59dc17396bb5a8da50f8c59b6e0a430711a4)
a056f3
---
a056f3
 hw/display/vga.c | 3 +++
a056f3
 1 file changed, 3 insertions(+)
a056f3
a056f3
diff --git a/hw/display/vga.c b/hw/display/vga.c
a056f3
index 06ca3daa4c..b1cdf36cfa 100644
a056f3
--- a/hw/display/vga.c
a056f3
+++ b/hw/display/vga.c
a056f3
@@ -1280,6 +1280,9 @@ static void vga_draw_text(VGACommonState *s, int full_update)
a056f3
         cx_min = width;
a056f3
         cx_max = -1;
a056f3
         for(cx = 0; cx < width; cx++) {
a056f3
+            if (src + sizeof(uint16_t) > s->vram_ptr + s->vram_size) {
a056f3
+                break;
a056f3
+            }
a056f3
             ch_attr = *(uint16_t *)src;
a056f3
             if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
a056f3
                 if (cx < cx_min)