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