]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
efi/loongarch: Randomize kernel preferred address for KASLR
authorWANG Rui <wangrui@loongson.cn>
Thu, 21 May 2026 12:58:36 +0000 (20:58 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Thu, 21 May 2026 12:58:36 +0000 (20:58 +0800)
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>
Signed-off-by: WANG Rui <wangrui@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/include/asm/efi.h
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/libstub/loongarch.c

index eddc8e79b3fae7ba6688e702164f4c2c9d204811..1ad764b18c3e8afff09c15ca800a93102bc2d24c 100644 (file)
@@ -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 */
index 7aa2f9ad2935627b3eff4fd48f42942f6d93d75b..f27f2e1f00199704c30f9661e14b96111e934ade 100644 (file)
@@ -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"))
index f7938d5c196aad573f63493a23fee0ef0fdc5bf4..2b0c87dc99088179e3bf8561701ed7046576a767 100644 (file)
@@ -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;