summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinjie Ruan <ruanjinjie@huawei.com>2026-11-09 12:13:24 +0800
committerCatalin Marinas <catalin.marinas@arm.com>2026-11-12 19:38:26 +0000
commit18f2d01bfce99a885511c451cba95234eea190bc (patch)
tree1f4896db7ee7d2b6658857db2e7eebdf3b401615
parentbe777145858218f591b4d9d19f3d40d3ecea9de3 (diff)
downloadlinux-18f2d01bfce99a885511c451cba95234eea190bc.tar.gz
linux-18f2d01bfce99a885511c451cba95234eea190bc.zip
arm64: kexec_file: Do not use CMA for images with a non-zero text_offset
image_load() adds text_offset to kernel_segment->mem and subtracts it from kernel_segment->memsz. For CMA backed segments this breaks the load path: the payload is copied to page_address(cma), which is the CMA base, while image->start is set to the adjusted address, so kexec jumps into the middle of the kernel. kimage_map_segment() has the same mismatch when a segment has been moved. The adjusted memsz also breaks the release path: the CMA pages are freed using segment->memsz >> PAGE_SHIFT, which is fewer than were allocated, leaking the tail of the allocation. Both problems are specific to CMA segments, which are accessed through page_address(cma) and ignore segment->mem. The normal load path uses segment->mem, so the text_offset adjustment stays consistent there. Keep honoring text_offset, but load such images from regular memory by setting image->no_cma: they lose the CMA contiguous allocation, but keep working. Fixes: 07d24902977e ("kexec: enable CMA based contiguous allocation") Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> Cc: Will Deacon <will@kernel.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/all/20260921090450.807575-2-ruanjinjie@huawei.com/ Link: https://lore.kernel.org/all/20260921090450.807575-3-ruanjinjie@huawei.com/ Link: https://lore.kernel.org/all/au4JOjnQlx2aSpiE@arm.com/ Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/kernel/kexec_image.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index 78b1f956d8d7..f4ad22447259 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -81,6 +81,13 @@ static void *image_load(struct kimage *image,
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
kbuf.memsz = le64_to_cpu(h->image_size);
text_offset = le64_to_cpu(h->text_offset);
+ /*
+ * A CMA segment is loaded and mapped through page_address(cma), which
+ * is the CMA base and cannot represent the text_offset adjustment
+ * below. Load images with a non-zero text_offset from normal memory.
+ */
+ if (text_offset)
+ image->no_cma = true;
kbuf.buf_align = MIN_KIMG_ALIGN;
/* Adjust kernel segment with TEXT_OFFSET */