Skip to contentSkip to conversation

FAILED: patch "[PATCH] powerpc/kexec_file: Prevent kexec range truncation" failed to apply to 5.15-stable tree

PATCH New [email protected] 2 participants 3 messages Sep 9 – Sep 11

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x fa40f9dbdd4af53e7445d9135b5b207eb8adf372
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090925-sliceable-cold-552f@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From fa40f9dbdd4af53e7445d9135b5b207eb8adf372 Mon Sep 17 00:00:00 2001
From: Jinjie Ruan <[email protected]>
Date: Wed, 29 Jul 2026 09:29:48 +0800
Subject: [PATCH] powerpc/kexec_file: Prevent kexec range truncation

Sashiko AI review pointed out the following issue.

The __merge_memory_ranges() function incorrectly handles overlapping memory ranges when merging them. Although sort_memory_ranges() sorts all ranges by their start address in ascending order beforehand, the merge logic remains defective in two ways:

1. It compares the current range's start against the previous element (i-1) instead of the running target index (idx)

2. It unconditionally overwrites 'ranges[idx].end' with 'ranges[i].end'.

This logic flaw leads to critical memory truncation when a larger memory range completely subsumes subsequent smaller ranges.

For example, consider a sorted input array with three ranges:
Range A (idx=0): [0x1000 - 0x9000]
Range B (i=1): [0x2000 - 0x5000] (completely inside Range A)
Range C (i=2): [0x6000 - 0x8000] (completely inside Range A)

1. When i=1 (Range B):
ranges[1].start (0x2000) <= ranges[0].end + 1 (0x9001) is TRUE. The code executes: ranges[0].end = ranges[1].end, which erroneously shrinks Range A's end from 0x9000 down to 0x5000.

2. When i=2 (Range C):
ranges[2].start (0x6000) <= ranges[1].end + 1 (0x5001) is FALSE. The code falls into the else block, creating a broken new range.

As a result, valid memory fragments [0x5001 - 0x5fff] and [0x8001 - 0x9000] are completely lost from the kexec exclude lists, potentially allowing the crash kernel to overwrite active memory, causing data corruption or crashes.

Fix this by ensuring the start of the current range is compared against the end of the active merged range (idx), and use max() to safely prevent the outer boundary from being truncated.

Fixes 180adfc532a8 ("powerpc/kexec_file: Add helper functions for getting memory ranges")
arch/powerpc/kexec/ranges.c +5 -7
index 867135560e5c..eb45e89502ca 100644
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/memblock.h>
+#include <linux/minmax.h>
 #include <linux/crash_core.h>
 #include <asm/sections.h>
 #include <asm/kexec_ranges.h>
@@ -105,19 +106,16 @@ static void __merge_memory_ranges(struct crash_mem *mem_rngs)
 	struct range *ranges;
 	int i, idx;
 
-	if (!mem_rngs)
+	if (!mem_rngs || mem_rngs->nr_ranges <= 1)
 		return;
 
 	idx = 0;
-	ranges = &(mem_rngs->ranges[0]);
+	ranges = mem_rngs->ranges;
 	for (i = 1; i < mem_rngs->nr_ranges; i++) {
-		if (ranges[i].start <= (ranges[i-1].end + 1))
-			ranges[idx].end = ranges[i].end;
+		if (ranges[i].start <= (ranges[idx].end + 1))
+			ranges[idx].end = max(ranges[idx].end, ranges[i].end);
 		else {
 			idx++;
-			if (i == idx)
-				continue;
-
 			ranges[idx] = ranges[i];
 		}
 	}
maintainer
#1 lore raw

PATCH 1/2 powerpc/kexec: move *_memory_ranges functions to ranges.c

From: Sourabh Jain <[email protected]>

[ Upstream commit f5f0da5a7b18fab383bac92044fd8f4f288c9d38 ]

Move the following functions form kexec/{file_load_64.c => ranges.c} and make them public so that components other than KEXEC_FILE can also use these functions.
1. get_exclude_memory_ranges
2. get_reserved_memory_ranges
3. get_crash_memory_ranges
4. get_usable_memory_ranges

Later in the series get_crash_memory_ranges function is utilized for in-kernel updates to kdump image during CPU/Memory hotplug or online/offline events for both kexec_load and kexec_file_load syscalls.

Since the above functions are moved to ranges.c, some of the helper functions in ranges.c are no longer required to be public. Mark them as static and removed them from kexec_ranges.h header file.

Finally, remove the CONFIG_KEXEC_FILE build dependency for range.c because it is required for other config, such as CONFIG_CRASH_DUMP.

No functional changes are intended.

[Stable dependency adaptation for fa40f9dbdd4af53e7445d9135b5b207eb8adf372:
Keep only the linux/memblock.h and linux/crash_core.h include additions in ranges.c. The target inserts linux/minmax.h between these headers; without them its header hunk conflicts, while its range-merging fix already merges cleanly with the stable implementation.

Drop the helper moves, visibility changes, and build-rule changes. This stable tree predates the KEXEC_FILE/CRASH_DUMP split and keeps crash_mem under CONFIG_KEXEC_FILE, so importing the broader refactor is unnecessary for this fix. Retain the existing functions and configuration dependencies. No functions or runtime behavior are added by this dependency.]

[ sashal: Reduced backport -- upstream f5f0da5a7b18f touches 4 file(s), this
backport carries 1. Not backported here:
arch/powerpc/include/asm/kexec_ranges.h arch/powerpc/kexec/file_load_64.c
arch/powerpc/kexec/Makefile
This note is generated from the file lists only; see the resolution record for the reasoning. ]

Stable-dep-of: fa40f9dbdd4a ("powerpc/kexec_file: Prevent kexec range truncation")

---
 arch/powerpc/kexec/ranges.c | 2 ++
 1 file changed, 2 insertions(+)
arch/powerpc/kexec/ranges.c +2 -0
index 6b81c852feaba..4a3ac17263c8c 100644
@@ -20,6 +20,8 @@
 #include <linux/kexec.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
+#include <linux/memblock.h>
+#include <linux/crash_core.h>
 #include <asm/sections.h>
 #include <asm/kexec_ranges.h>
 
Signature · 1 line
2.53.0
maintainer
#2 lore raw

PATCH 2/2 powerpc/kexec_file: Prevent kexec range truncation

From: Jinjie Ruan <[email protected]>

[ Upstream commit fa40f9dbdd4af53e7445d9135b5b207eb8adf372 ]

Sashiko AI review pointed out the following issue.

The __merge_memory_ranges() function incorrectly handles overlapping memory ranges when merging them. Although sort_memory_ranges() sorts all ranges by their start address in ascending order beforehand, the merge logic remains defective in two ways:

1. It compares the current range's start against the previous element (i-1) instead of the running target index (idx)

2. It unconditionally overwrites 'ranges[idx].end' with 'ranges[i].end'.

This logic flaw leads to critical memory truncation when a larger memory range completely subsumes subsequent smaller ranges.

For example, consider a sorted input array with three ranges:
Range A (idx=0): [0x1000 - 0x9000]
Range B (i=1): [0x2000 - 0x5000] (completely inside Range A)
Range C (i=2): [0x6000 - 0x8000] (completely inside Range A)

1. When i=1 (Range B):
ranges[1].start (0x2000) <= ranges[0].end + 1 (0x9001) is TRUE. The code executes: ranges[0].end = ranges[1].end, which erroneously shrinks Range A's end from 0x9000 down to 0x5000.

2. When i=2 (Range C):
ranges[2].start (0x6000) <= ranges[1].end + 1 (0x5001) is FALSE. The code falls into the else block, creating a broken new range.

As a result, valid memory fragments [0x5001 - 0x5fff] and [0x8001 - 0x9000] are completely lost from the kexec exclude lists, potentially allowing the crash kernel to overwrite active memory, causing data corruption or crashes.

Fix this by ensuring the start of the current range is compared against the end of the active merged range (idx), and use max() to safely prevent the outer boundary from being truncated.

Fixes 180adfc532a8 ("powerpc/kexec_file: Add helper functions for getting memory ranges")
---
 arch/powerpc/kexec/ranges.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)
arch/powerpc/kexec/ranges.c +5 -7
index 4a3ac17263c8c..975b522f0d6aa 100644
@@ -21,6 +21,7 @@
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/memblock.h>
+#include <linux/minmax.h>
 #include <linux/crash_core.h>
 #include <asm/sections.h>
 #include <asm/kexec_ranges.h>
@@ -103,19 +104,16 @@ static void __merge_memory_ranges(struct crash_mem *mem_rngs)
 	struct crash_mem_range *ranges;
 	int i, idx;
 
-	if (!mem_rngs)
+	if (!mem_rngs || mem_rngs->nr_ranges <= 1)
 		return;
 
 	idx = 0;
-	ranges = &(mem_rngs->ranges[0]);
+	ranges = mem_rngs->ranges;
 	for (i = 1; i < mem_rngs->nr_ranges; i++) {
-		if (ranges[i].start <= (ranges[i-1].end + 1))
-			ranges[idx].end = ranges[i].end;
+		if (ranges[i].start <= (ranges[idx].end + 1))
+			ranges[idx].end = max(ranges[idx].end, ranges[i].end);
 		else {
 			idx++;
-			if (i == idx)
-				continue;
-
 			ranges[idx] = ranges[i];
 		}
 	}
Signature · 1 line
2.53.0