From: Paolo Bonzini <[email protected]> The VAPIC region is mapped as writable RAM, at very high priority, above existing memory. If the guest is allowed to map it everywhere, it can overlap PCI BARs or even SMRAM. Ensure that the whole region first in the 128K of low memory that are reserved to option ROMs.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4206 Reported-by: Artem Dinaburg <https://gitlab.com/artem35> Cc: [email protected] Reviewed-by: Philippe Mathieu-Daudé <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> (cherry picked from commit d61c8a6fb7388486353aa267ba0d75b098f16662) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/hw/i386/vapic.c b/hw/i386/vapic.c index 14de9b7a820..2069a4b962a 100644 --- a/hw/i386/vapic.c +++ b/hw/i386/vapic.c @@ -30,6 +30,10 @@ #define ROM_BLOCK_SIZE 512 #define ROM_BLOCK_MASK (~(ROM_BLOCK_SIZE - 1)) +/* Option ROM window on PC/Q35 machines; the vapic ROM must live in here. */ +#define OPTION_ROM_START 0xc0000 +#define OPTION_ROM_END 0xe0000 + typedef enum VAPICMode { VAPIC_INACTIVE = 0, VAPIC_ACTIVE = 1, @@ -586,6 +590,14 @@ static int vapic_map_rom_writable(VAPICROMState *s) size_t rom_size; uint8_t *ram; + /* + * The VAPIC region should be mapped in place, refuse mapping it + * outside of the option ROM window. + */ + if (rom_paddr < OPTION_ROM_START || rom_paddr >= OPTION_ROM_END) { + return -1; + } + if (s->rom_mapped_writable) { memory_region_del_subregion(mr, &s->rom); object_unparent(OBJECT(&s->rom)); @@ -600,9 +612,10 @@ static int vapic_map_rom_writable(VAPICROMState *s) } ram = memory_region_get_ram_ptr(section.mr); rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE; - if (rom_size == 0) { + if (rom_size == 0 || rom_size > OPTION_ROM_END - rom_paddr) { return -1; } + s->rom_size = rom_size; /* We need to round to avoid creating subpages @@ -610,6 +623,7 @@ static int vapic_map_rom_writable(VAPICROMState *s) rom_size += rom_paddr & ~TARGET_PAGE_MASK; rom_paddr &= TARGET_PAGE_MASK; rom_size = TARGET_PAGE_ALIGN(rom_size); + assert(rom_paddr >= OPTION_ROM_START && rom_paddr + rom_size <= OPTION_ROM_END); memory_region_init_alias(&s->rom, OBJECT(s), "kvmvapic-rom", section.mr, rom_paddr, rom_size); -- 2.47.3
