On Wed, Oct 21, 2026 at 04:28:31PM +0800, Jinjie Ruan wrote: > > > 在 2026/10/20 16:09, Mike Rapoport 写道: > > Hi Jinjie, > > > >> On 32-bit x86 systems with HIGHMEM, kmap_local_page() only maps a single > >> 4KB page. However, the elfcorehdr segment can span several pages (up to > >> hundreds of kilobytes). > >> > >> The original code blindly copies 'elfsz' bytes at once via > >> memcpy_flushcache(), overwriting adjacent fixmap entries or critical > >> virtual addresses. > >> > >> Fix this by copying the new elfcorehdr page by page. > > > > This is independed of other fixes and can be sent as a separate x86b fix. > > Yes > > > > >> Cc: Thomas Gleixner <[email protected]> > >> Cc: Ingo Molnar <[email protected]> > >> Cc: Borislav Petkov <[email protected]> > >> Cc: Dave Hansen <[email protected]> > >> Cc: "H. Peter Anvin" <[email protected]> > >> Cc: "Mike Rapoport (Microsoft)" <[email protected]> > >> Cc: Vishal Verma <[email protected]> > >> Cc: Baoquan He <[email protected]> > >> Cc: Chao Gao <[email protected]> > >> Cc: Sean Christopherson <[email protected]> > >> Cc: Eric DeVolder <[email protected]> > >> Cc: Hari Bathini <[email protected]> > >> Cc: Andrew Morton <[email protected]> > >> Cc: Sourabh Jain <[email protected]> > >> Cc: [email protected] > >> Fixes: ea53ad9cf73b ("x86/crash: add x86 crash hotplug support") > >> Link: > >> https://sashiko.dev/#/patchset/20260907125404.922123-1-ruanjinjie%40huawei.com > >> Signed-off-by: Jinjie Ruan <[email protected]> > >> --- > >> arch/x86/kernel/crash.c | 26 +++++++++++++------------- > >> 1 file changed, 13 insertions(+), 13 deletions(-) > >> > >> diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c > >> index e681ec9cf1dc8..3c9f4fbbe7ff0 100644 > >> --- a/arch/x86/kernel/crash.c > >> +++ b/arch/x86/kernel/crash.c > >> @@ -447,9 +447,10 @@ unsigned int arch_crash_get_elfcorehdr_size(void) > >> */ > >> void arch_crash_handle_hotplug_event(struct kimage *image, void *arg) > >> { > >> - void *elfbuf = NULL, *old_elfcorehdr; > >> unsigned long mem, memsz; > >> unsigned long elfsz = 0; > >> + void *elfbuf = NULL; > >> + unsigned long done; > >> > >> /* > >> * As crash_prepare_elf64_headers() has already described all > >> @@ -484,21 +485,20 @@ void arch_crash_handle_hotplug_event(struct kimage > >> *image, void *arg) > >> > >> /* > >> * Copy new elfcorehdr over the old elfcorehdr at destination. > >> - */ > >> - old_elfcorehdr = kmap_local_page(pfn_to_page(mem >> PAGE_SHIFT)); > >> - if (!old_elfcorehdr) { > >> - pr_err("mapping elfcorehdr segment failed\n"); > >> - goto out; > >> - } > >> - > >> - /* > >> - * Temporarily invalidate the crash image while the > >> - * elfcorehdr is updated. > >> + * The segment is physically contiguous but can span several pages. > >> + * On 32-bit Highmem architectures, kmap_local_page() maps only a > >> + * single page at a time, so copy page by page. > >> */ > >> xchg(&kexec_crash_image, NULL); > >> - memcpy_flushcache(old_elfcorehdr, elfbuf, elfsz); > >> + for (done = 0; done < elfsz; ) { > >> + size_t chunk = min_t(size_t, PAGE_SIZE, elfsz - done); > >> + void *dst = kmap_local_page(pfn_to_page((mem + done) >> > >> PAGE_SHIFT)); > >> + > >> + memcpy_flushcache(dst, elfbuf + done, chunk); > >> + kunmap_local(dst); > >> + done += chunk; > >> + } > > > > HIGMEM is only enabled on 32-bit and there elfsz cannot be "massive" > > because it is the size of the headers just built for the CPUs and RAM > > ranges actually present, not the large memsz reserved for hotplug. > > On x86_32 (NR_CPUS <= 64) that is a few KiB at most. > > > > Also, crashkernel is capped at CRASH_ADDR_HIGH_MAX = SZ_512M on X86_32, > > which is below the default lowmem limit. For lowmem pages, > > kmap_local_page() returns the contiguous direct-map address, so the old > > Hi Mike, > > x86 32-bit doesn't support memory hotplug, and NR_CPUS is capped at 8. > > config NR_CPUS_RANGE_END > int > depends on X86_32 > default 8 if SMP > default 1 if !SMP > > According to the elf header size calculation in > crash_prepare_elf64_headers(): > > - nr_phdr = num_possible_cpus() + nr_mem_ranges + 2 > - sizeof(Elf64_Ehdr) = 64 > - sizeof(Elf64_Phdr) = 56 > > so: > elf_sz = 64 + (num_possible_cpus() + nr_mem_ranges + 2) * 56 > > To exceed 4K: > > 64 + (num_possible_cpus() + nr_ranges + 2) * 56 > 4096 > > > So we'd need at least 60+ RAM ranges, which seems unlikely on real > hardware without memory hotplug. I think this problem can't actually be > triggered in practice, so we can safely drop this patch.
I think you are right and my LLM overestimated the amount of memory used :) > > code was already fine. > > > > So the overflow needs the crash region to be in highmem, either through > > crashkernel=size@offset above lowmem or through a large vmalloc= > > setting, and an elfcorehdr larger than one page. > > > > It is still worth fixing, but please drop "massive" from the subject. > > > > The changelog should also mention the conditions when this could happen. > > > > -- > Best regards, > Jinjie > -- Sincerely yours, Mike.
