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