[PATCH v6 09/14] x86/crash: Fix massive out-of-bounds write on 32-bit Highmem

Mike Rapoport rppt at kernel.org
Tue Oct 20 01:09:39 PDT 2026


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.

> Cc: Thomas Gleixner <tglx at kernel.org>
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: Borislav Petkov <bp at alien8.de>
> Cc: Dave Hansen <dave.hansen at linux.intel.com>
> Cc: "H. Peter Anvin" <hpa at zytor.com>
> Cc: "Mike Rapoport (Microsoft)" <rppt at kernel.org>
> Cc: Vishal Verma <vishal.l.verma at intel.com>
> Cc: Baoquan He <baoquan.he at linux.dev>
> Cc: Chao Gao <chao.gao at intel.com>
> Cc: Sean Christopherson <seanjc at google.com>
> Cc: Eric DeVolder <eric.devolder at oracle.com>
> Cc: Hari Bathini <hbathini at linux.ibm.com>
> Cc: Andrew Morton <akpm at linux-foundation.org>
> Cc: Sourabh Jain <sourabhjain at linux.ibm.com>
> Cc: stable at vger.kernel.org
> 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 <ruanjinjie at huawei.com>
> ---
>  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
code was already fine.

So the overflow needs the crash region to be in highmem, either through
crashkernel=size at 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.

-- 
Sincerely yours,
Mike.




More information about the kexec mailing list