Quick Emulator (aka QEMU) is an open source systems emulator. It emulates various processors and their accompanying hardware peripherals like disc, serial ports, NIC et al. A serious vulnerability of out-of-bounds r/w access through the Video Graphics Array (VGA) emulator was discovered and reported by Mr Wei Xiao and Qinghao Tang of Marvel Team at 360.cn Inc. This vulnerability is formally known as Dark Portal. In this post we’ll see how Dark Portal works and its mitigation.
VGA is a hardware component primarily responsible for drawing content on a display device. This content could be text or images at various resolutions. The VGA controller comes with its own processor (GPU) and its own RAM. Size of this RAM varies from device to device. The VGA emulator in QEMU comes with the default memory of 16 MB. The systems’ CPU maps this memory, or parts of it, to supply graphical data to the GPU.
The VGA standard has evolved and many extensions to it have been devised to support higher resolutions or new hardware. The VESA BIOS Extensions (VBE) is a software interface implemented in VGA BIOS and Boch VBE exntension is a set of registers designed to support Super VGA (SVGA) hardware. QEMU VGA emulator implements both VBE and Boch VBE extensions. It provides two ways to access its video memory:
- Linear Frame buffer: In this, entire video RAM is accessed by the CPU like a byte addressed array in C.
- Bank Switching: A chunk (or bank) of 64 KB of video memory is mapped into host’s memory. Host CPU could slide this 64KB window, to access other parts of the video memory.
VBE has numerous registers to hold information about memory bank’s size, offset etc. parameters. These registers can be manipulated using VGA I/O port r/w functions. A register VBE_DISPI_INDEX_BANK holds the offset address in the currently used bank (or window) of the VGA memory. In order to update the display pixel, GPU must calculate its location on the screen and its offset within current memory bank.
QEMU VGA emulator in action:
In QEMU’s VGA emulator, user could set the offset VBE_DISPI_INDEX_BANK register via vbe_ioport_write_data() routine
void vbe_ioport_write_data() {
...
case VBE_DISPI_INDEX_BANK:
...
s->bank_offset = (val << 16);
}
The VGA read/write functions vga_mem_readb() and vga_mem_writeb() compute the pixel location using the supplied address and bank_offset values
uint32_t vga_mem_readb/writeb(VGACommonState *s, hwaddr addr, ...) {
...
switch(memory_map_mode) {
case 1:
...
addr += s->bank_offset;
break;
...
/* standard VGA latched access */
s->latch = ((uint32_t *)s->vram_ptr)[addr];
}
The said out-of-bounds r/w access issue occurs because it accesses the byte(uint8_t *) addressed video memory, as double word(uint32_t *) type. This type promotion throws the given pixel location address beyond the 16 MB VGA memory.
Impact:
This issue affects all QEMU/KVM and Xen guests wherein VGA emulator is enabled. Depending on where the OOB access lands in host memory, it could lead to information disclosure OR crash the QEMU process resulting in DoS. It could potentially be leveraged to execute arbitrary code with privileges of the QEMU process on the host.
Mitigation:
The sVirt and Seccomp functionalities used to restrict host’s QEMU process privileges and resource access might mitigate the impact of successful exploitation of this issue. Also a possible policy-based workaround is to avoid granting untrusted users administrator privileges within guests.
Conclusion:
VGA VBE registers can be manipulated by a privileged user inside guest. It leads to an out-of-bounds memory access in QEMU process on the host, essentially making it an attack on the virtualisation host by a guest.
Product
Red Hat Enterprise Linux
Component
kvm