Linux EFI development
 help / color / mirror / Atom feed
* [PATCH v5 0/3] LoongArch: Move KASLR to EFI stub to avoid initrd overlap
@ 2026-05-11 10:45 WANG Rui
  2026-05-11 10:45 ` [PATCH v5 1/3] efi/loongarch: Randomize kernel preferred address for KASLR WANG Rui
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: WANG Rui @ 2026-05-11 10:45 UTC (permalink / raw)
  To: Huacai Chen, Ard Biesheuvel
  Cc: WANG Xuerui, Ilias Apalodimas, Haiyong Sun, Lisa Robinson,
	loongarch, linux-efi, linux-kernel, WANG Rui

Changes since [v4]:
  * Add a comment above kaslr_disabled() introducing the terms
    "strictly-defined KASLR" and "broadly-defined KASLR", and
    explaining what kaslr_disabled() returns. (Huacai Chen)
  * Set efi_nokaslr when "resume=<devname>" is present, since
    LoongArch hibernation does not support KASLR. (Huacai Chen)
  * Adjust local variable declarations, comment wording, and
    function placement. (Huacai Chen)

Changes since [v3]:
  * Minor cleanups based on review comments.

Changes since [v2]:
  * Add a new patch to prevent initrd overlap during relocation.
  * Revert changes to the CONFIG_RANDOMIZE_BASE_MAX_OFFSET range.

Changes since [v1]:
  * Drop the patch "LoongArch: Allow rdtime_h() and rdtime_l() in 64-bit builds".
  * Use random_get_entropy() instead of rdtime_l().

This series addresses a potential overlap issue between the kernel
image and the initrd when KASLR is enabled.

In the normal boot flow, the bootloader is responsible for loading
both vmlinux and the initrd, and it can guarantee that the two do
not overlap in memory. However, this assumption only holds as long
as neither image changes its location afterwards.

The in-kernel KASLR implementation breaks that assumption. When the
initrd is placed close to the kernel image, randomizing the kernel
location at runtime may move it into the initrd region, leading to
memory corruption early during boot.

To fix this, this series moves the KASLR logic out of the kernel
proper and into the EFI stub. With this change, the final placement
of both the kernel image and the initrd is determined by the EFI
memory allocator. This ensures that the two allocations are
coordinated and cannot overlap.

Functionally, the kernel still supports KASLR as before, but the
randomization now happens before the kernel is entered, rather than
during early kernel relocation.

[v4]: https://lore.kernel.org/loongarch/20260429120300.1786210-1-r@hev.cc
[v3]: https://lore.kernel.org/loongarch/20260429051318.1581350-1-r@hev.cc
[v2]: https://lore.kernel.org/loongarch/20260428040159.1065822-1-r@hev.cc
[v1]: https://lore.kernel.org/loongarch/20260427104721.47724-1-r@hev.cc

WANG Rui (3):
  efi/loongarch: Randomize kernel preferred address for KASLR
  LoongArch: Skip relocation-time KASLR if already applied
  LoongArch: Avoid initrd overlap during kernel relocation

 arch/loongarch/include/asm/efi.h              |  4 +-
 arch/loongarch/kernel/relocate.c              | 50 +++++++++++++++++++
 .../firmware/efi/libstub/efi-stub-helper.c    |  4 ++
 drivers/firmware/efi/libstub/loongarch.c      | 16 ++++++
 4 files changed, 73 insertions(+), 1 deletion(-)

-- 
2.54.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v5 1/3] efi/loongarch: Randomize kernel preferred address for KASLR
  2026-05-11 10:45 [PATCH v5 0/3] LoongArch: Move KASLR to EFI stub to avoid initrd overlap WANG Rui
@ 2026-05-11 10:45 ` WANG Rui
  2026-05-11 10:45 ` [PATCH v5 2/3] LoongArch: Skip relocation-time KASLR if already applied WANG Rui
  2026-05-11 10:45 ` [PATCH v5 3/3] LoongArch: Avoid initrd overlap during kernel relocation WANG Rui
  2 siblings, 0 replies; 4+ messages in thread
From: WANG Rui @ 2026-05-11 10:45 UTC (permalink / raw)
  To: Huacai Chen, Ard Biesheuvel
  Cc: WANG Xuerui, Ilias Apalodimas, Haiyong Sun, Lisa Robinson,
	loongarch, linux-efi, linux-kernel, WANG Rui, Huacai Chen

Introduce efi_get_kimg_kaslr_address() helper to compute the preferred
kernel image load address dynamically when CONFIG_RANDOMIZE_BASE is
enabled. The function derives a random offset by using the EFI-provided
randomness combined with the timer tick value, and constrains it within
CONFIG_RANDOMIZE_BASE_MAX_OFFSET.

Update EFI_KIMG_PREFERRED_ADDRESS to call this helper so that the EFI
stub can select a randomized load address when KASLR is active, while
preserving the original base address behavior when KASLR is disabled or
"nokaslr" is specified.

Note: LoongArch can't KASLR for hibernation, so set efi_nokaslr to true
if "resume=<devname>" is explicitly specified in cmdline.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Co-authored-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: WANG Rui <r@hev.cc>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 arch/loongarch/include/asm/efi.h               |  4 +++-
 drivers/firmware/efi/libstub/efi-stub-helper.c |  4 ++++
 drivers/firmware/efi/libstub/loongarch.c       | 16 ++++++++++++++++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/arch/loongarch/include/asm/efi.h b/arch/loongarch/include/asm/efi.h
index eddc8e79b3fa..1ad764b18c3e 100644
--- a/arch/loongarch/include/asm/efi.h
+++ b/arch/loongarch/include/asm/efi.h
@@ -30,6 +30,8 @@ static inline unsigned long efi_get_kimg_min_align(void)
 	return SZ_2M;
 }
 
-#define EFI_KIMG_PREFERRED_ADDRESS	PHYSADDR(VMLINUX_LOAD_ADDRESS)
+unsigned long efi_get_kimg_kaslr_address(void);
+
+#define EFI_KIMG_PREFERRED_ADDRESS efi_get_kimg_kaslr_address()
 
 #endif /* _ASM_LOONGARCH_EFI_H */
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 7aa2f9ad2935..f27f2e1f0019 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -79,6 +79,10 @@ efi_status_t efi_parse_options(char const *cmdline)
 			efi_noinitrd = true;
 		} else if (IS_ENABLED(CONFIG_X86_64) && !strcmp(param, "no5lvl")) {
 			efi_no5lvl = true;
+		} else if (IS_ENABLED(CONFIG_LOONGARCH) &&
+			   IS_ENABLED(CONFIG_HIBERNATION) &&
+			   !strcmp(param, "resume") && val) {
+			efi_nokaslr = true; /* LoongArch can't KASLR for hibernation */
 		} else if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT) &&
 			   !strcmp(param, "mem_encrypt") && val) {
 			if (parse_option_str(val, "on"))
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c
index f7938d5c196a..2b0c87dc9908 100644
--- a/drivers/firmware/efi/libstub/loongarch.c
+++ b/drivers/firmware/efi/libstub/loongarch.c
@@ -23,6 +23,22 @@ void efi_cache_sync_image(unsigned long image_base, unsigned long alloc_size)
 	asm volatile ("ibar 0" ::: "memory");
 }
 
+unsigned long efi_get_kimg_kaslr_address(void)
+{
+	unsigned int random_offset = 0;
+
+#ifdef CONFIG_RANDOMIZE_BASE
+	if (!efi_nokaslr) {
+		efi_get_random_bytes(sizeof(random_offset), (u8 *)&random_offset);
+		random_offset ^= (random_get_entropy() << 16);
+		random_offset &= (CONFIG_RANDOMIZE_BASE_MAX_OFFSET - 1);
+		random_offset = ALIGN(random_offset + SZ_64K, SZ_64K);
+	}
+#endif
+
+	return PHYSADDR(VMLINUX_LOAD_ADDRESS) + random_offset;
+}
+
 struct exit_boot_struct {
 	efi_memory_desc_t	*runtime_map;
 	int			runtime_entry_count;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 2/3] LoongArch: Skip relocation-time KASLR if already applied
  2026-05-11 10:45 [PATCH v5 0/3] LoongArch: Move KASLR to EFI stub to avoid initrd overlap WANG Rui
  2026-05-11 10:45 ` [PATCH v5 1/3] efi/loongarch: Randomize kernel preferred address for KASLR WANG Rui
@ 2026-05-11 10:45 ` WANG Rui
  2026-05-11 10:45 ` [PATCH v5 3/3] LoongArch: Avoid initrd overlap during kernel relocation WANG Rui
  2 siblings, 0 replies; 4+ messages in thread
From: WANG Rui @ 2026-05-11 10:45 UTC (permalink / raw)
  To: Huacai Chen, Ard Biesheuvel
  Cc: WANG Xuerui, Ilias Apalodimas, Haiyong Sun, Lisa Robinson,
	loongarch, linux-efi, linux-kernel, WANG Rui, Huacai Chen

When the kernel is relocated during early boot (efistub or kexec_file),
a randomized load address may has already been selected and applied. In
this case, performing KASLR again in relocate.c is unnecessary.

Note: strictly-defined KASLR means the kernel's final runtime address
has a random offset from the kernel's load address, which is implemented
in relocate.c; broadly-defined KALSR means the kernel's final runtime
address has a random offset from the kernel's link address (a.k.a.
VMLINUX_LOAD_ADDRESS), which also include the efistlub implementation,
kexec_file implementation and QEMU direct kernel boot. kaslr_disabled()
return true only means strictly-defined KASLR is disabled.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Co-authored-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: WANG Rui <r@hev.cc>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 arch/loongarch/kernel/relocate.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c
index 16f6a9b39659..0a045964fad5 100644
--- a/arch/loongarch/kernel/relocate.c
+++ b/arch/loongarch/kernel/relocate.c
@@ -134,11 +134,23 @@ early_param("nokaslr", nokaslr);
 
 #define KASLR_DISABLED_MESSAGE "KASLR is disabled by %s in %s cmdline.\n"
 
+/*
+ * Note: strictly-defined KASLR means the kernel's final runtime address
+ * has a random offset from the kernel's load address, which is implemented
+ * in relocate.c; broadly-defined KALSR means the kernel's final runtime
+ * address has a random offset from the kernel's link address (a.k.a.
+ * VMLINUX_LOAD_ADDRESS), which also include the efistlub implementation,
+ * kexec_file implementation and QEMU direct kernel boot. kaslr_disabled()
+ * return true only means strictly-defined KASLR is disabled.
+ */
 static inline __init bool kaslr_disabled(void)
 {
 	char *str;
 	const char *builtin_cmdline = CONFIG_CMDLINE;
 
+	if (kaslr_offset())
+		return true; /* KASLR is performed during early boot. */
+
 	str = strstr(builtin_cmdline, "nokaslr");
 	if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) {
 		pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "built-in");
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 3/3] LoongArch: Avoid initrd overlap during kernel relocation
  2026-05-11 10:45 [PATCH v5 0/3] LoongArch: Move KASLR to EFI stub to avoid initrd overlap WANG Rui
  2026-05-11 10:45 ` [PATCH v5 1/3] efi/loongarch: Randomize kernel preferred address for KASLR WANG Rui
  2026-05-11 10:45 ` [PATCH v5 2/3] LoongArch: Skip relocation-time KASLR if already applied WANG Rui
@ 2026-05-11 10:45 ` WANG Rui
  2 siblings, 0 replies; 4+ messages in thread
From: WANG Rui @ 2026-05-11 10:45 UTC (permalink / raw)
  To: Huacai Chen, Ard Biesheuvel
  Cc: WANG Xuerui, Ilias Apalodimas, Haiyong Sun, Lisa Robinson,
	loongarch, linux-efi, linux-kernel, WANG Rui, Huacai Chen

Validate the relocation address against the initrd region specified via
"initrd=" or "initrdmem=" on the command line. Reject relocation targets
that overlap the initrd to prevent memory corruption during early boot.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Co-authored-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: WANG Rui <r@hev.cc>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 arch/loongarch/kernel/relocate.c | 38 ++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c
index 0a045964fad5..4b61a9632a98 100644
--- a/arch/loongarch/kernel/relocate.c
+++ b/arch/loongarch/kernel/relocate.c
@@ -222,14 +222,52 @@ static inline void __init *determine_relocation_address(void)
 	return RELOCATED_KASLR(destination);
 }
 
+static unsigned long __init determine_initrd_address(unsigned long *size)
+{
+	unsigned long start = 0;
+	unsigned long key_length;
+	char *p, *endp, *key = "initrd=";
+
+	key_length = strlen(key);
+	p = strstr(boot_command_line, key);
+
+	if (!p) {
+		key = "initrdmem=";
+		key_length = strlen(key);
+		p = strstr(boot_command_line, key);
+	}
+
+	if (p == boot_command_line || (p > boot_command_line && *(p - 1) == ' ')) {
+		p += key_length;
+		start = memparse(p, &endp);
+		if (*endp == ',')
+			*size = memparse(endp + 1, NULL);
+	}
+
+	return start;
+}
+
 static inline int __init relocation_addr_valid(void *location_new)
 {
+	unsigned long kernel_start, kernel_size;
+	unsigned long initrd_start, initrd_size = 0;
+
 	if ((unsigned long)location_new & 0x00000ffff)
 		return 0; /* Inappropriately aligned new location */
 
 	if ((unsigned long)location_new < (unsigned long)_end)
 		return 0; /* New location overlaps original kernel */
 
+	initrd_start = determine_initrd_address(&initrd_size);
+	if (initrd_start && initrd_size) {
+		kernel_start = PHYSADDR(location_new);
+		kernel_size = (unsigned long)_end - (unsigned long)_text;
+
+		if (kernel_start < (initrd_start + initrd_size) &&
+			initrd_start < (kernel_start + kernel_size))
+			return 0; /* initrd/initramfs overlaps kernel */
+	}
+
 	return 1;
 }
 #endif
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-05-11 10:46 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-11 10:45 [PATCH v5 0/3] LoongArch: Move KASLR to EFI stub to avoid initrd overlap WANG Rui
2026-05-11 10:45 ` [PATCH v5 1/3] efi/loongarch: Randomize kernel preferred address for KASLR WANG Rui
2026-05-11 10:45 ` [PATCH v5 2/3] LoongArch: Skip relocation-time KASLR if already applied WANG Rui
2026-05-11 10:45 ` [PATCH v5 3/3] LoongArch: Avoid initrd overlap during kernel relocation WANG Rui

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox