* [PATCH] riscv: kexec_file: Keep segments out of the new kernel's PMD padding
@ 2026-11-14 3:49 ` Cong Wang
0 siblings, 0 replies; 3+ messages in thread
From: Cong Wang @ 2026-11-14 3:49 UTC (permalink / raw)
To: linux-kernel, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, linux-riscv
Cc: Song Shuai, Björn Töpel, Han Gao, Jinjie Ruan,
Mike Rapoport, Baoquan He, Guo Ren, kexec, Cong Wang
From: Cong Wang <cwang@multikernel.io>
A 64-bit kernel with STRICT_KERNEL_RWX reserves itself up to the next
PMD boundary past _end in setup_bootmem(). load_extra_segments() only
keeps the other segments above kernel_start + kernel_len, which is the
unaligned _end of the new kernel, so they may be placed in that padding.
The segments are placed top-down, which normally keeps them far from
the kernel. A kdump kernel's segments are confined to the crashkernel
region though, and when it has little room to spare, the lowest of
them, the initrd and the device tree, end up in the padding. The kdump
kernel then finds its initrd in memory it reserved for itself, drops
it, and panics without a root file system:
crashkernel reserved: 0x000000017be00000 - 0x000000017fe00000 (64 MB)
Loaded kernel at 0x17be00000 bufsz=0x1c40600 memsz=0x1cb1000
Loaded initrd at 0x17db58000
...
Starting crashdump kernel...
INITRD: 0x17db58000+0x022a4000 overlaps in-use memory region
...
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
The load itself succeeds, so this only shows once the system crashes.
The kernel being loaded may be any version or configuration that
reserves the padding, so the loader has to keep clear of it. Start the
other segments at the next PMD boundary. A crashkernel region too small
for them now fails the load with -EADDRNOTAVAIL, and one with enough
room boots the kdump kernel with its initrd.
This was found while testing multikernel, which loads a kernel with
kexec_file and hits the same overlap.
Fixes: 809a11eea8e8 ("riscv: kexec_file: Support loading Image binary file")
Signed-off-by: Cong Wang <cwang@multikernel.io>
---
arch/riscv/kernel/machine_kexec_file.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/machine_kexec_file.c b/arch/riscv/kernel/machine_kexec_file.c
index 26cd2a8bd0cd..0d2d43a7dbfa 100644
--- a/arch/riscv/kernel/machine_kexec_file.c
+++ b/arch/riscv/kernel/machine_kexec_file.c
@@ -251,7 +251,8 @@ int load_extra_segments(struct kimage *image, unsigned long kernel_start,
char *modified_cmdline = NULL;
kbuf.image = image;
- kbuf.buf_min = kernel_start + kernel_len;
+ /* The new kernel reserves itself up to the next PMD boundary */
+ kbuf.buf_min = ALIGN(kernel_start + kernel_len, PMD_SIZE);
kbuf.buf_max = PFN_PHYS(max_low_pfn);
#ifdef CONFIG_CRASH_DUMP
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH] riscv: kexec_file: Keep segments out of the new kernel's PMD padding
@ 2026-11-14 3:49 ` Cong Wang
0 siblings, 0 replies; 3+ messages in thread
From: Cong Wang @ 2026-11-14 3:49 UTC (permalink / raw)
To: linux-kernel, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, linux-riscv
Cc: Song Shuai, Björn Töpel, Han Gao, Jinjie Ruan,
Mike Rapoport, Baoquan He, Guo Ren, kexec, Cong Wang
From: Cong Wang <cwang@multikernel.io>
A 64-bit kernel with STRICT_KERNEL_RWX reserves itself up to the next
PMD boundary past _end in setup_bootmem(). load_extra_segments() only
keeps the other segments above kernel_start + kernel_len, which is the
unaligned _end of the new kernel, so they may be placed in that padding.
The segments are placed top-down, which normally keeps them far from
the kernel. A kdump kernel's segments are confined to the crashkernel
region though, and when it has little room to spare, the lowest of
them, the initrd and the device tree, end up in the padding. The kdump
kernel then finds its initrd in memory it reserved for itself, drops
it, and panics without a root file system:
crashkernel reserved: 0x000000017be00000 - 0x000000017fe00000 (64 MB)
Loaded kernel at 0x17be00000 bufsz=0x1c40600 memsz=0x1cb1000
Loaded initrd at 0x17db58000
...
Starting crashdump kernel...
INITRD: 0x17db58000+0x022a4000 overlaps in-use memory region
...
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
The load itself succeeds, so this only shows once the system crashes.
The kernel being loaded may be any version or configuration that
reserves the padding, so the loader has to keep clear of it. Start the
other segments at the next PMD boundary. A crashkernel region too small
for them now fails the load with -EADDRNOTAVAIL, and one with enough
room boots the kdump kernel with its initrd.
This was found while testing multikernel, which loads a kernel with
kexec_file and hits the same overlap.
Fixes: 809a11eea8e8 ("riscv: kexec_file: Support loading Image binary file")
Signed-off-by: Cong Wang <cwang@multikernel.io>
---
arch/riscv/kernel/machine_kexec_file.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/machine_kexec_file.c b/arch/riscv/kernel/machine_kexec_file.c
index 26cd2a8bd0cd..0d2d43a7dbfa 100644
--- a/arch/riscv/kernel/machine_kexec_file.c
+++ b/arch/riscv/kernel/machine_kexec_file.c
@@ -251,7 +251,8 @@ int load_extra_segments(struct kimage *image, unsigned long kernel_start,
char *modified_cmdline = NULL;
kbuf.image = image;
- kbuf.buf_min = kernel_start + kernel_len;
+ /* The new kernel reserves itself up to the next PMD boundary */
+ kbuf.buf_min = ALIGN(kernel_start + kernel_len, PMD_SIZE);
kbuf.buf_max = PFN_PHYS(max_low_pfn);
#ifdef CONFIG_CRASH_DUMP
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] riscv: kexec_file: Keep segments out of the new kernel's PMD padding
2026-11-14 3:49 ` Cong Wang
(?)
@ 2026-11-14 3:58 ` sashiko-bot
-1 siblings, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-11-14 3:58 UTC (permalink / raw)
To: Cong Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti
Cc: Song Shuai, Björn Töpel, Han Gao, Jinjie Ruan,
Mike Rapoport, Baoquan He, Guo Ren, kexec, Cong Wang
Thank you for your contribution! Sashiko AI review found no new issues
in this patch, but noticed 1 related pre-existing issue it does not
introduce:
- [High] kexec_file: missing placement bounds checks in
kexec_alloc_contig() [1]
--
commit e91ae0bea9270620f64704189d1d94046334bdb0
Author: Cong Wang <cwang@multikernel.io>
riscv: kexec_file: Keep segments out of the new kernel's PMD padding
This commit aligns kbuf.buf_min in load_extra_segments() to PMD_SIZE so
extra kexec segments are not placed inside the new kernel's PMD padding.
> diff --git a/arch/riscv/kernel/machine_kexec_file.c b/arch/riscv/kernel/machine_kexec_file.c
> index 26cd2a8bd0cd3..0d2d43a7dbfaa 100644
> --- a/arch/riscv/kernel/machine_kexec_file.c
> +++ b/arch/riscv/kernel/machine_kexec_file.c
> @@ -251,7 +251,8 @@ int load_extra_segments(struct kimage *image, unsigned long kernel_start,
> char *modified_cmdline = NULL;
>
> kbuf.image = image;
> - kbuf.buf_min = kernel_start + kernel_len;
> + /* The new kernel reserves itself up to the next PMD boundary */
> + kbuf.buf_min = ALIGN(kernel_start + kernel_len, PMD_SIZE);
> kbuf.buf_max = PFN_PHYS(max_low_pfn);
>
> #ifdef CONFIG_CRASH_DUMP
[Severity: High]
This problem wasn't introduced by this patch, but can kexec_alloc_contig()
bypass kbuf.buf_min and kbuf.buf_max when allocating a CMA segment for a
non-crash kexec_file_load() [1]?
Unlike locate_mem_hole_top_down() and locate_mem_hole_bottom_up(), which
check kbuf->buf_min, kbuf->buf_max, and arch_check_excluded_range(),
kexec_alloc_contig() only checks kimage_is_destination_range() (and passes
the exclusive end mem + kbuf->memsz rather than mem + kbuf->memsz - 1):
kernel/kexec_file.c:kexec_alloc_contig() {
...
p = dma_alloc_from_contiguous(NULL, nr_pages, get_order(kbuf->buf_align), true);
if (!p)
return -ENOMEM;
...
mem = page_to_boot_pfn(p) << PAGE_SHIFT;
if (kimage_is_destination_range(kbuf->image, mem, mem + kbuf->memsz)) {
...
dma_release_from_contiguous(NULL, p, nr_pages);
return -EBUSY;
}
kbuf->mem = page_to_boot_pfn(p) << PAGE_SHIFT;
kbuf->cma = p;
...
}
When CMA is enabled, kexec_add_buffer() -> kexec_locate_mem_hole() ->
kexec_alloc_contig() can place the initrd, DTB, or purgatory below
kbuf.buf_min, Above kbuf.buf_max, or inside an architecture-excluded range,
causing the new kernel to fail to boot or crash on kexec.
[1] https://sashiko.dev/#/bug/linux-83c15bd9-0ce0-4413-9330-a4e797594079
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261114034901.107028-1-xiyou.wangcong@gmail.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-14 3:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-14 3:49 [PATCH] riscv: kexec_file: Keep segments out of the new kernel's PMD padding Cong Wang
2026-11-14 3:49 ` Cong Wang
2026-11-14 3:58 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.