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.

Reply via email to