From: Sebastián Alba Vives Date: Wed, 1 Apr 2026 05:38:53 +0000 (-0600) Subject: hw/intc: fix heap OOB in ACLINT MTIMER multi-socket X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=d5b33fc180f557ee3574cef9c64650174d0ef5dd;p=thirdparty%2Fqemu.git hw/intc: fix heap OOB in ACLINT MTIMER multi-socket The MMIO read/write handlers index timecmp[] with the absolute hartid (hartid_base + offset) but the array is allocated with num_harts elements. In multi-socket configurations with hartid_base > 0 this causes heap OOB access in the QEMU process. Fix by using the relative offset for array indexing. Cc: qemu-security@nongnu.org Signed-off-by: Sebastián Alba Vives Reviewed-by: Alistair Francis Message-ID: <20260401053853.10473-2-sebasjosue84@gmail.com> Signed-off-by: Alistair Francis --- diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index 9c1491bd043..e27e5fb3941 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -131,6 +131,7 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr, addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) { size_t hartid = mtimer->hartid_base + ((addr - mtimer->timecmp_base) >> 3); + size_t hartid_offset = hartid - mtimer->hartid_base; CPUState *cpu = cpu_by_arch_id(hartid); CPURISCVState *env = cpu ? cpu_env(cpu) : NULL; if (!env) { @@ -138,11 +139,11 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr, "aclint-mtimer: invalid hartid: %zu", hartid); } else if ((addr & 0x7) == 0) { /* timecmp_lo for RV32/RV64 or timecmp for RV64 */ - uint64_t timecmp = mtimer->timecmp[hartid]; + uint64_t timecmp = mtimer->timecmp[hartid_offset]; return (size == 4) ? (timecmp & 0xFFFFFFFF) : timecmp; } else if ((addr & 0x7) == 4) { /* timecmp_hi */ - uint64_t timecmp = mtimer->timecmp[hartid]; + uint64_t timecmp = mtimer->timecmp[hartid_offset]; return (timecmp >> 32) & 0xFFFFFFFF; } else { qemu_log_mask(LOG_UNIMP, @@ -174,6 +175,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) { size_t hartid = mtimer->hartid_base + ((addr - mtimer->timecmp_base) >> 3); + size_t hartid_offset = hartid - mtimer->hartid_base; CPUState *cpu = cpu_by_arch_id(hartid); CPURISCVState *env = cpu ? cpu_env(cpu) : NULL; if (!env) { @@ -182,7 +184,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } else if ((addr & 0x7) == 0) { if (size == 4) { /* timecmp_lo for RV32/RV64 */ - uint64_t timecmp_hi = mtimer->timecmp[hartid] >> 32; + uint64_t timecmp_hi = mtimer->timecmp[hartid_offset] >> 32; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid, timecmp_hi << 32 | (value & 0xFFFFFFFF)); } else { @@ -193,7 +195,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } else if ((addr & 0x7) == 4) { if (size == 4) { /* timecmp_hi for RV32/RV64 */ - uint64_t timecmp_lo = mtimer->timecmp[hartid]; + uint64_t timecmp_lo = mtimer->timecmp[hartid_offset]; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid, value << 32 | (timecmp_lo & 0xFFFFFFFF)); } else {