[PATCH v10 8/8] crash: Fix race condition between crash kernel loading and memory hotplug

Jinjie Ruan ruanjinjie at huawei.com
Wed Mar 25 13:59:04 AEDT 2026


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 crash_prepare_headers(), the following steps occur:
1. arch_get_system_nr_ranges() queries current memory ranges from memblock
2. alloc_cmem() allocates buffer based on queried count
3. arch_crash_populate_cmem() 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.

Fix by adding lock_device_hotplug()/unlock_device_hotplug() around the
critical section in crash_prepare_headers(). The lock is only acquired
when CONFIG_MEMORY_HOTPLUG is enabled to avoid overhead on systems without
hotplug support.

Fixes: dd5f726076cc ("kexec: support for kexec on panic using new system call")
Fixes: 3751e728cef2 ("arm64: kexec_file: add crash dump support")
Fixes: 8acea455fafa ("RISC-V: Support for kexec_file on panic")
Fixes: 1bcca8620a91 ("LoongArch: Add crash dump support for kexec_file")
Signed-off-by: Jinjie Ruan <ruanjinjie at huawei.com>
---
 kernel/crash_core.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index 300d44ad5471..f01d03d42c67 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -326,15 +326,25 @@ int crash_prepare_headers(int need_kernel_map, void **addr, unsigned long *sz,
 	struct crash_mem *cmem;
 	int ret;
 
+	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+		lock_device_hotplug();
+
 	max_nr_ranges = arch_get_system_nr_ranges();
-	if (!max_nr_ranges)
-		return -ENOMEM;
+	if (!max_nr_ranges) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
 
 	cmem = alloc_cmem(max_nr_ranges);
-	if (!cmem)
-		return -ENOMEM;
+	if (!cmem) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
 
 	ret = arch_crash_populate_cmem(cmem);
+	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+		unlock_device_hotplug();
+
 	if (ret)
 		goto out;
 
@@ -355,6 +365,12 @@ int crash_prepare_headers(int need_kernel_map, void **addr, unsigned long *sz,
 out:
 	kvfree(cmem);
 	return ret;
+
+unlock:
+	if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+		unlock_device_hotplug();
+
+	return ret;
 }
 
 /**
-- 
2.34.1



More information about the Linuxppc-dev mailing list