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 to return -EAGAIN on unexpected overrun,
fully eradicating the overflow window and ensuring system stability.

Cc: Catalin Marinas <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Baoquan He <[email protected]>
Cc: Breno Leitao <[email protected]>
Cc: [email protected]
Fixes: 3751e728cef2 ("arm64: kexec_file: add crash dump support")
Signed-off-by: Jinjie Ruan <[email protected]>
---
 arch/arm64/kernel/machine_kexec_file.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/machine_kexec_file.c 
b/arch/arm64/kernel/machine_kexec_file.c
index 4cbb71e1f8ed..8a96fb68b88d 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -48,7 +48,8 @@ int prepare_elf_headers(void **addr, unsigned long *sz)
        u64 i;
        phys_addr_t start, end;
 
-       nr_ranges = 2; /* for exclusion of crashkernel region */
+       /* for exclusion of crashkernel region */
+       nr_ranges = 2 + CRASH_HOTPLUG_SAFETY_PADDING;
        for_each_mem_range(i, &start, &end)
                nr_ranges++;
 
@@ -59,6 +60,11 @@ int prepare_elf_headers(void **addr, unsigned long *sz)
        cmem->max_nr_ranges = nr_ranges;
        cmem->nr_ranges = 0;
        for_each_mem_range(i, &start, &end) {
+               if (unlikely(cmem->nr_ranges >= cmem->max_nr_ranges)) {
+                       ret = -EAGAIN;
+                       goto out;
+               }
+
                cmem->ranges[cmem->nr_ranges].start = start;
                cmem->ranges[cmem->nr_ranges].end = end - 1;
                cmem->nr_ranges++;
-- 
2.34.1


Reply via email to