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


Reply via email to