[PATCH v5 13/17] crash: Assert device_hotplug_lock in crash_get_memory_ranges_nolock()
From: Jinjie Ruan
Date: Fri Sep 18 2026 - 06:44:20 EST
crash_get_memory_ranges_nolock() walks memblock, which memory hotplug
modifies under device_hotplug_lock. A caller that does not hold the lock
can race with memblock_double_array() and iterate a freed regions array.
Add device_hotplug_lock_assert_held() and call it at the top of the
function so that such callers are caught by lockdep.
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
drivers/base/core.c | 5 +++++
include/linux/device.h | 1 +
kernel/crash_core.c | 7 +++++++
3 files changed, 13 insertions(+)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 4c0c373998a1..c04adc457a96 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2420,6 +2420,11 @@ void unlock_device_hotplug(void)
mutex_unlock(&device_hotplug_lock);
}
+void device_hotplug_lock_assert_held(void)
+{
+ lockdep_assert_held(&device_hotplug_lock);
+}
+
int lock_device_hotplug_sysfs(void)
{
if (mutex_trylock(&device_hotplug_lock))
diff --git a/include/linux/device.h b/include/linux/device.h
index aee79fd6b32b..9cca8c8bd372 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1261,6 +1261,7 @@ do { \
void lock_device_hotplug(void);
void unlock_device_hotplug(void);
int lock_device_hotplug_sysfs(void);
+void device_hotplug_lock_assert_held(void);
int device_offline(struct device *dev);
int device_online(struct device *dev);
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index 760ca9822a13..852a5f51d472 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -338,6 +338,13 @@ int crash_get_memory_ranges_nolock(struct crash_mem **mem_ranges)
struct crash_mem *cmem;
int ret;
+ /*
+ * Callers must serialize against memory hotplug by holding
+ * device_hotplug_lock, otherwise the memblock iteration below can
+ * race with memblock_double_array() and read freed memory.
+ */
+ device_hotplug_lock_assert_held();
+
max_nr_ranges = arch_get_system_nr_ranges();
if (!max_nr_ranges)
return -ENOMEM;
--
2.34.1