[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