Sashiko AI code review pointed out there is a TOCTOU (Time-of-Check to Time-of-Use) race condition in prepare_elf_headers() between the initial pass that counts System RAM ranges and the second pass that populates them. If a memory hotplug event occurs between these two steps, the number of memory regions may increase, causing an out-of-bounds write to the cmem->ranges[] array.
Fix this fundamentally by using `CRASH_HOTPLUG_SAFETY_PADDING` (128 slots) to expand the flexible array allocation ceiling upfront. This safely absorbs any concurrent memory region expansion. Concurrently, add a defensive boundary check inside the callback to return -EAGAIN on unexpected overrun, fully eradicating the overflow window and ensuring system stability. Cc: Paul Walmsley <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Albert Ou <[email protected]> Cc: Alexandre Ghiti <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Fixes: 8acea455fafa ("RISC-V: Support for kexec_file on panic") Reviewed-by: Guo Ren <[email protected]> Signed-off-by: Jinjie Ruan <[email protected]> --- arch/riscv/kernel/machine_kexec_file.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/riscv/kernel/machine_kexec_file.c b/arch/riscv/kernel/machine_kexec_file.c index 3f7766057cac..f3576dc0513f 100644 --- a/arch/riscv/kernel/machine_kexec_file.c +++ b/arch/riscv/kernel/machine_kexec_file.c @@ -48,6 +48,9 @@ static int prepare_elf64_ram_headers_callback(struct resource *res, void *arg) { struct crash_mem *cmem = arg; + if (unlikely(cmem->nr_ranges >= cmem->max_nr_ranges)) + return -EAGAIN; + cmem->ranges[cmem->nr_ranges].start = res->start; cmem->ranges[cmem->nr_ranges].end = res->end; cmem->nr_ranges++; @@ -61,7 +64,8 @@ static int prepare_elf_headers(void **addr, unsigned long *sz) unsigned int nr_ranges; int ret; - nr_ranges = 2; /* For exclusion of crashkernel region */ + /* For exclusion of crashkernel region */ + nr_ranges = 2 + CRASH_HOTPLUG_SAFETY_PADDING; walk_system_ram_res(0, -1, &nr_ranges, get_nr_ram_ranges_callback); cmem = kmalloc_flex(*cmem, ranges, nr_ranges); -- 2.34.1
