9ae3a8
From 3c18025a495a2c105c2c33051ece0f3525d1e0c4 Mon Sep 17 00:00:00 2001
9ae3a8
From: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
Date: Thu, 28 Apr 2016 16:07:32 +0200
9ae3a8
Subject: [PATCH 27/27] vga: make sure vga register setup for vbe stays intact.
9ae3a8
9ae3a8
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
Message-id: <1461859652-20918-7-git-send-email-kraxel@redhat.com>
9ae3a8
Patchwork-id: 70297
9ae3a8
O-Subject: [virt-devel] [RHEL-7.3 qemu-kvm PATCH 6/6] vga: make sure vga register setup for vbe stays intact.
9ae3a8
Bugzilla: 1331413
9ae3a8
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9ae3a8
9ae3a8
Call vbe_update_vgaregs() when the guest touches GFX, SEQ or CRT
9ae3a8
registers, to make sure the vga registers will always have the
9ae3a8
values needed by vbe mode.  This makes sure the sanity checks
9ae3a8
applied by vbe_fixup_regs() are effective.
9ae3a8
9ae3a8
Without this guests can muck with shift_control, can turn on planar
9ae3a8
vga modes or text mode emulation while VBE is active, making qemu
9ae3a8
take code paths meant for CGA compatibility, but with the very
9ae3a8
large display widths and heigts settable using VBE registers.
9ae3a8
9ae3a8
Which is good for one or another buffer overflow.  Not that
9ae3a8
critical as they typically read overflows happening somewhere
9ae3a8
in the display code.  So guests can DoS by crashing qemu with a
9ae3a8
segfault, but it is probably not possible to break out of the VM.
9ae3a8
9ae3a8
Reported-by: Zuozhi Fzz <zuozhi.fzz@alibaba-inc.com>
9ae3a8
Reported-by: P J P <ppandit@redhat.com>
9ae3a8
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/display/vga.c | 6 ++++++
9ae3a8
 1 file changed, 6 insertions(+)
9ae3a8
9ae3a8
diff --git a/hw/display/vga.c b/hw/display/vga.c
9ae3a8
index ee3c0c0..f049b26 100644
9ae3a8
--- a/hw/display/vga.c
9ae3a8
+++ b/hw/display/vga.c
9ae3a8
@@ -166,6 +166,8 @@ static uint32_t expand4[256];
9ae3a8
 static uint16_t expand2[256];
9ae3a8
 static uint8_t expand4to8[16];
9ae3a8
 
9ae3a8
+static void vbe_update_vgaregs(VGACommonState *s);
9ae3a8
+
9ae3a8
 static inline bool vbe_enabled(VGACommonState *s)
9ae3a8
 {
9ae3a8
     return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
9ae3a8
@@ -511,6 +513,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
9ae3a8
         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
9ae3a8
 #endif
9ae3a8
         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
9ae3a8
+        vbe_update_vgaregs(s);
9ae3a8
         if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
9ae3a8
             s->update_retrace_info(s);
9ae3a8
         }
9ae3a8
@@ -542,6 +545,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
9ae3a8
         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
9ae3a8
 #endif
9ae3a8
         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
9ae3a8
+        vbe_update_vgaregs(s);
9ae3a8
         vga_update_memory_access(s);
9ae3a8
         break;
9ae3a8
     case VGA_CRT_IM:
9ae3a8
@@ -560,10 +564,12 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
9ae3a8
             if (s->cr_index == VGA_CRTC_OVERFLOW) {
9ae3a8
                 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
9ae3a8
                     (val & 0x10);
9ae3a8
+                vbe_update_vgaregs(s);
9ae3a8
             }
9ae3a8
             return;
9ae3a8
         }
9ae3a8
         s->cr[s->cr_index] = val;
9ae3a8
+        vbe_update_vgaregs(s);
9ae3a8
 
9ae3a8
         switch(s->cr_index) {
9ae3a8
         case VGA_CRTC_H_TOTAL:
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8