[PATCH v9 3/8] crash_core: serialize crash header preparation against hotplug
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Thu Oct 22 01:33:07 PDT 2026
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] crash_core: cmem->ranges overflow via unlocked iomem_resource hotplug
--
commit 24cd8bf08b74ae3e07f992972d3cd97b77d9fcf6
Author: Wandun Chen <chenwandun at lixiang.com>
crash_core: serialize crash header preparation against hotplug
This commit serializes crash_prepare_headers() with device_hotplug_lock
to prevent concurrent memory hotplug from changing the number of memory
ranges between counting and populating cmem->ranges. It also introduces
__crash_prepare_headers() for hotplug paths that already hold the lock.
Link: https://sashiko.dev/#/message/20260806101002.1F84E1F000E9@smtp.kernel.org
> diff --git a/kernel/crash_core.c b/kernel/crash_core.c
> index faa0f22dbb41d..8a861a946e261 100644
> --- a/kernel/crash_core.c
> +++ b/kernel/crash_core.c
[ ... ]
> @@ -344,8 +345,8 @@ int crash_exclude_core_ranges(struct crash_mem **cmem)
> return 0;
> }
>
> -int crash_prepare_headers(int need_kernel_map, void **addr, unsigned long *sz,
> - unsigned long *nr_mem_ranges)
> +int __crash_prepare_headers(int need_kernel_map, void **addr, unsigned long *sz,
> + unsigned long *nr_mem_ranges)
> {
> unsigned int max_nr_ranges;
> struct crash_mem *cmem;
> @@ -382,6 +383,18 @@ int crash_prepare_headers(int need_kernel_map, void **addr, unsigned long *sz,
> return ret;
> }
>
> +int crash_prepare_headers(int need_kernel_map, void **addr, unsigned long *sz,
> + unsigned long *nr_mem_ranges)
> +{
> + int ret;
> +
> + lock_device_hotplug();
> + ret = __crash_prepare_headers(need_kernel_map, addr, sz, nr_mem_ranges);
> + unlock_device_hotplug();
> +
> + return ret;
> +}
[Severity: Medium]
Can cmem->ranges[] still overflow during __crash_prepare_headers() even when
device_hotplug_lock is held?
In __crash_prepare_headers(), arch_get_system_nr_ranges() counts the current
system ram ranges (plus a fixed number of split slots for exclusions),
allocates cmem via alloc_cmem(max_nr_ranges), and then populates
cmem->ranges[] in arch_crash_populate_cmem().
Neither the x86 callback in arch/x86/kernel/crash.c:
static int prepare_elf64_ram_headers_callback(struct resource *res, void *arg)
{
struct crash_mem *cmem = arg;
cmem->ranges[cmem->nr_ranges].start = res->start;
cmem->ranges[cmem->nr_ranges].end = res->end;
cmem->nr_ranges++;
return 0;
}
nor the weak implementation in kernel/crash_core.c:
int __weak arch_crash_populate_cmem(struct crash_mem *cmem)
{
phys_addr_t start, end;
u64 i;
for_each_mem_range(i, &start, &end) {
cmem->ranges[cmem->nr_ranges].start = start;
cmem->ranges[cmem->nr_ranges].end = end - 1;
cmem->nr_ranges++;
}
return 0;
}
checks whether cmem->nr_ranges has reached cmem->max_nr_ranges before writing
to cmem->ranges[cmem->nr_ranges++].
However, Xen balloon memory hotplug inserts new system ram resources into
iomem_resource before acquiring device_hotplug_lock via the call chain:
balloon_thread() / xen_alloc_ballooned_pages()
-> add_ballooned_pages()
-> reserve_additional_memory()
-> additional_memory_resource()
Specifically, in drivers/xen/balloon.c:
static struct resource *additional_memory_resource(phys_addr_t size)
{
...
res->name = "System RAM";
res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
ret = allocate_resource(&iomem_resource, res,
size, 0, -1,
PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
...
}
static enum bp_state reserve_additional_memory(void)
{
...
resource = additional_memory_resource(balloon_hotplug * PAGE_SIZE);
if (!resource)
goto err;
...
mutex_unlock(&balloon_mutex);
/* add_memory_resource() requires the device_hotplug lock */
lock_device_hotplug();
rc = add_memory_resource(nid, resource, MHP_MERGE_RESOURCE);
unlock_device_hotplug();
mutex_lock(&balloon_mutex);
...
balloon_stats.total_pages += balloon_hotplug;
...
}
Because reserve_additional_memory() inserts the resource into iomem_resource
and drops balloon_mutex before waiting on lock_device_hotplug(), and only
updates balloon_stats.total_pages after add_memory_resource() completes,
concurrent callers (such as balloon_thread() and xen_alloc_ballooned_pages())
can insert new system ram entries into iomem_resource while
crash_prepare_headers() or arch_crash_handle_hotplug_event() holds
device_hotplug_lock.
If those entries are inserted between arch_get_system_nr_ranges() and
arch_crash_populate_cmem(), wouldn't the extra ranges consume the reserved
split slots (causing crash_exclude_mem_range() to fail) or overflow
cmem->ranges[]? Should arch_crash_populate_cmem() and
prepare_elf64_ram_headers_callback() also bounds-check cmem->nr_ranges
against cmem->max_nr_ranges?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261021083011.2170525-1-chenwandun1@gmail.com?part=3
More information about the kexec
mailing list