Re: [PATCH v13 04/15] arm64: kexec_file: Fix potential buffer overflow in prepare_elf_headers()
From: Jinjie Ruan <hidden>
Date: 2026-05-11 11:30:52
Also in:
kexec, linux-devicetree, linux-doc, linux-riscv, lkml, loongarch
On 5/11/2026 5:46 PM, Breno Leitao wrote:
On Mon, May 11, 2026 at 11:04:43AM +0800, Jinjie Ruan wrote:quoted
There is a race condition between the kexec_load() system call (crash kernel loading path) and memory hotplug operations that can lead to buffer overflow and potential kernel crash. During prepare_elf_headers(), the following steps occur: 1. The first for_each_mem_range() queries current System RAM memory ranges 2. Allocates buffer based on queried count 3. The 2st for_each_mem_range() populates ranges from memblock If memory hotplug occurs between step 1 and step 3, the number of ranges can increase, causing out-of-bounds write when populating cmem->ranges[]. This happens because kexec_load() uses kexec_trylock (atomic_t) while memory hotplug uses device_hotplug_lock (mutex), so they don't serialize with each other. Add the explicit bounds checking to prevent out-of-bounds access.It seems you have a TOCTOU type of issue, and this seems to be shrinking the window, but not fully solving it?
Hi Breno, Thanks for your comments regarding the TOCTOU issue. You are correct that the current bounds checking only "shrinks the window" and prevents a kernel crash, but doesn't fully guarantee header consistency if a race occurs. In my local environment, this race is extremely difficult to reproduce, but it is theoretically possible. To address this properly for arm64, I am considering two steps: - For this patch: I will change the return value to -EAGAIN and keep the bounds check. This ensures that even if a race happens, the kernel remains safe (no OOB access), and user-space is notified to retry. - Long-term solution: A better way to solve this is to implement ARM64 CRASH_HOTPLUG support (similar to x86). With crash hotplug, the kernel will automatically re-generate the crash headers whenever a memory hotplug event occurs. This makes the TOCTOU during the initial kexec_load less critical, as any transient inconsistency will be immediately corrected by the subsequent hotplug handler. Does it make sense to you to use this patch as a safety guard first, and then I (or someone else) follow up with the full CRASH_HOTPLUG support for arm64 as [1]? [1]: https://lore.kernel.org/all/20260402081459.635022-1-ruanjinjie@huawei.com/ (local) Best regards, Jinjie
quoted
Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <redacted> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Baoquan He <redacted> Cc: Breno Leitao <leitao@debian.org> Cc: stable@vger.kernel.org Fixes: 3751e728cef2 ("arm64: kexec_file: add crash dump support") Closes: https://sashiko.dev/#/patchset/20260323072745.2481719-1-ruanjinjie%40huawei.com Signed-off-by: Jinjie Ruan <redacted> --- arch/arm64/kernel/machine_kexec_file.c | 5 +++++ 1 file changed, 5 insertions(+)diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c index e31fabed378a..a67e7b1abbab 100644 --- a/arch/arm64/kernel/machine_kexec_file.c +++ b/arch/arm64/kernel/machine_kexec_file.c@@ -59,6 +59,11 @@ static 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 (cmem->nr_ranges >= cmem->max_nr_ranges) { + ret = -ENOMEM;-ENOMEM seems to be the the wrong errno. This isn't an allocation failure; it's a transient race. -EBUSY or -EAGAIN would be more honest