From 9de67411be20d63f844a9eed9adb9ab41b680b22 Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Wed, 3 Jul 2024 17:56:33 +0200 Subject: [PATCH] hw/display/sm501: Validate local memory size index in sm501_system_config_write Ensure that the local_mem_size_index is within valid bounds and does not exceed the allocated memory size before updating it in sm501_system_config_write to prevent out-of-bounds read. ASAN log: ==3067247==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55c6586e4d3c at pc 0x55c655d4e0ac bp 0x7ffc9d5c6a10 sp 0x7ffc9d5c6a08 READ of size 4 at 0x55c6586e4d3c thread T0 #0 0x55c655d4e0ab in sm501_2d_operation qemu/hw/display/sm501.c:729:21 #1 0x55c655d4b8a1 in sm501_2d_engine_write qemu/hw/display/sm501.c:1551:13 Reproducer: cat << EOF | qemu-system-x86_64 \ -display none -machine accel=qtest, -m 512M -machine q35 -nodefaults \ -device sm501 -qtest stdio outl 0xcf8 0x80000814 outl 0xcfc 0xe4000000 outl 0xcf8 0x80000804 outw 0xcfc 0x02 writel 0xe4000010 0xe000 writel 0xe4100010 0x10000 writel 0xe4100008 0x10001 writel 0xe410000c 0x80000000 EOF Signed-off-by: Zheyu Ma Message-Id: <20240703155633.17352-1-zheyuma97@gmail.com> --- hw/display/sm501.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 26dc8170d89b..a878c35dd9c7 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1020,11 +1020,21 @@ static void sm501_system_config_write(void *opaque, hwaddr addr, s->gpio_63_32_control = value & 0xFF80FFFF; break; case SM501_DRAM_CONTROL: - s->local_mem_size_index = (value >> 13) & 0x7; - /* TODO : check validity of size change */ + { + int local_mem_size_index = (value >> 13) & 0x7; + if (local_mem_size_index < ARRAY_SIZE(sm501_mem_local_size) && + sm501_mem_local_size[local_mem_size_index] <= + memory_region_size(&s->local_mem_region)) { + s->local_mem_size_index = local_mem_size_index; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "sm501: Invalid local_mem_size_index value: %d or memory size too large\n", + local_mem_size_index); + } s->dram_control &= 0x80000000; s->dram_control |= value & 0x7FFFFFC3; break; + } case SM501_ARBTRTN_CONTROL: s->arbitration_control = value & 0x37777777; break;