提交 3bf18170 编写于 作者: G Gerd Hoffmann

vga: fix banked access bounds checking (CVE-2016-3710)

vga allows banked access to video memory using the window at 0xa00000
and it supports a different access modes with different address
calculations.

The VBE bochs extentions support banked access too, using the
VBE_DISPI_INDEX_BANK register.  The code tries to take the different
address calculations into account and applies different limits to
VBE_DISPI_INDEX_BANK depending on the current access mode.

Which is probably effective in stopping misprogramming by accident.
But from a security point of view completely useless as an attacker
can easily change access modes after setting the bank register.

Drop the bogus check, add range checks to vga_mem_{readb,writeb}
instead.

Fixes: CVE-2016-3710
Reported-by: NQinghao Tang <luodalongde@gmail.com>
Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
上级 277abf15
...@@ -179,6 +179,7 @@ static void vga_update_memory_access(VGACommonState *s) ...@@ -179,6 +179,7 @@ static void vga_update_memory_access(VGACommonState *s)
size = 0x8000; size = 0x8000;
break; break;
} }
assert(offset + size <= s->vram_size);
memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram), memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram),
"vga.chain4", &s->vram, offset, size); "vga.chain4", &s->vram, offset, size);
memory_region_add_subregion_overlap(s->legacy_address_space, base, memory_region_add_subregion_overlap(s->legacy_address_space, base,
...@@ -716,11 +717,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) ...@@ -716,11 +717,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
vbe_fixup_regs(s); vbe_fixup_regs(s);
break; break;
case VBE_DISPI_INDEX_BANK: case VBE_DISPI_INDEX_BANK:
if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { val &= s->vbe_bank_mask;
val &= (s->vbe_bank_mask >> 2);
} else {
val &= s->vbe_bank_mask;
}
s->vbe_regs[s->vbe_index] = val; s->vbe_regs[s->vbe_index] = val;
s->bank_offset = (val << 16); s->bank_offset = (val << 16);
vga_update_memory_access(s); vga_update_memory_access(s);
...@@ -819,13 +816,21 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) ...@@ -819,13 +816,21 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) { if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
/* chain 4 mode : simplest access */ /* chain 4 mode : simplest access */
assert(addr < s->vram_size);
ret = s->vram_ptr[addr]; ret = s->vram_ptr[addr];
} else if (s->gr[VGA_GFX_MODE] & 0x10) { } else if (s->gr[VGA_GFX_MODE] & 0x10) {
/* odd/even mode (aka text mode mapping) */ /* odd/even mode (aka text mode mapping) */
plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
ret = s->vram_ptr[((addr & ~1) << 1) | plane]; addr = ((addr & ~1) << 1) | plane;
if (addr >= s->vram_size) {
return 0xff;
}
ret = s->vram_ptr[addr];
} else { } else {
/* standard VGA latched access */ /* standard VGA latched access */
if (addr * sizeof(uint32_t) >= s->vram_size) {
return 0xff;
}
s->latch = ((uint32_t *)s->vram_ptr)[addr]; s->latch = ((uint32_t *)s->vram_ptr)[addr];
if (!(s->gr[VGA_GFX_MODE] & 0x08)) { if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
...@@ -882,6 +887,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) ...@@ -882,6 +887,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
plane = addr & 3; plane = addr & 3;
mask = (1 << plane); mask = (1 << plane);
if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) { if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
assert(addr < s->vram_size);
s->vram_ptr[addr] = val; s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM #ifdef DEBUG_VGA_MEM
printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr); printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
...@@ -895,6 +901,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) ...@@ -895,6 +901,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
mask = (1 << plane); mask = (1 << plane);
if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) { if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
addr = ((addr & ~1) << 1) | plane; addr = ((addr & ~1) << 1) | plane;
if (addr >= s->vram_size) {
return;
}
s->vram_ptr[addr] = val; s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM #ifdef DEBUG_VGA_MEM
printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr); printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
...@@ -968,6 +977,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) ...@@ -968,6 +977,9 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
mask = s->sr[VGA_SEQ_PLANE_WRITE]; mask = s->sr[VGA_SEQ_PLANE_WRITE];
s->plane_updated |= mask; /* only used to detect font change */ s->plane_updated |= mask; /* only used to detect font change */
write_mask = mask16[mask]; write_mask = mask16[mask];
if (addr * sizeof(uint32_t) >= s->vram_size) {
return;
}
((uint32_t *)s->vram_ptr)[addr] = ((uint32_t *)s->vram_ptr)[addr] =
(((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
(val & write_mask); (val & write_mask);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册