[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