[PATCH 5/8] arm64: kexec_file: Fix CMA page leaks in segment placement retry loops

Jinjie Ruan <[email protected]>
Newsgroups org.ozlabs.lists.linuxppc-dev,org.infradead.lists.kexec,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Sashiko AI code review pointed out, during kexec image placement retry
loops in image_load(), the loader attempts to find a suitable memory
hole for the kernel and its associated segments (initrd, dtb, etc.).
When a placement attempt fails midway, it restores `image->nr_segments` to
its initial state to purge failed segments.

However, this truncation causes a memory leak. Any CMA pages allocated
via kexec_add_buffer() during the failed attempt are tracked  in
the `image->segment_cma` array. Because the subsequent cleanup
kimage_free_cma() cleanup only iterates up to the truncated `nr_segments`
boundary, these allocated CMA pages outside the new boundary permanently
leaked.

Fix this by using kexec_free_segment_cma() to explicitly release the
associated CMA buffers in the failure paths before `image->nr_segments`
is reduced.

Cc: Catalin Marinas <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Breno Leitao <[email protected]>
Cc: Pratyush Yadav <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Yeoreum Yun <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: "Rob Herring (Arm)" <[email protected]>
Cc: Baoquan He <[email protected]>
Cc: Coiby Xu <[email protected]>
Cc: Alexander Graf <[email protected]>
Cc: Pasha Tatashin <[email protected]>
Cc: [email protected]
Fixes: 07d24902977e4 ("kexec: enable CMA based contiguous allocation")
Signed-off-by: Jinjie Ruan <[email protected]>
---
 arch/arm64/kernel/kexec_image.c        | 1 +
 arch/arm64/kernel/machine_kexec_file.c | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index b70f4df15a1a..ffcb7f9075e6 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -107,6 +107,7 @@ static void *image_load(struct kimage *image,
 		 * We couldn't find space for the other segments; erase the
 		 * kernel segment and try the next available hole.
 		 */
+		kexec_free_segment_cma(image, kernel_segment_number);
 		image->nr_segments -= 1;
 		kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
 		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 854d872dfd0f..e48f29167b38 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -179,7 +179,10 @@ int load_other_segments(struct kimage *image,
 	return 0;
 
 out_err:
-	image->nr_segments = orig_segments;
+	while (image->nr_segments > orig_segments) {
+		kexec_free_segment_cma(image, image->nr_segments - 1);
+		image->nr_segments--;
+	}
 	kvfree(dtb);
 	return ret;
 }
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.