[PATCH v5 13/17] crash: Assert device_hotplug_lock in crash_get_memory_ranges_nolock()

Jinjie Ruan <[email protected]>
Newsgroups org.kernel.vger.linux-fsdevel,dev.linux.lists.driver-core,dev.linux.lists.loongarch,org.kernel.vger.linux-kernel,org.kvack.linux-mm,org.ozlabs.lists.linuxppc-dev
Message-ID <[email protected]>
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 <[email protected]>
---
 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
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.