Skip to content

Commit 7c116db

Browse files
committed
efi/libstub/arm64: Retain 2MB kernel Image alignment if !KASLR
Since commit 8204670 ("efi/libstub/arm64: Replace 'preferred' offset with alignment check"), loading a relocatable arm64 kernel at a physical address which is not 2MB aligned and subsequently booting with EFI will leave the Image in-place, relying on the kernel to relocate itself early during boot. In conjunction with commit dd4bc60 ("arm64: warn on incorrect placement of the kernel by the bootloader"), which enables CONFIG_RELOCATABLE by default, this effectively means that entering an arm64 kernel loaded at an alignment smaller than 2MB with EFI (e.g. using QEMU) will result in silent relocation at runtime. Unfortunately, this has a subtle but confusing affect for developers trying to inspect the PC value during a crash and comparing it to the symbol addresses in vmlinux using tools such as 'nm' or 'addr2line'; all text addresses will be displaced by a sub-2MB offset, resulting in the wrong symbol being identified in many cases. Passing "nokaslr" on the command line or disabling "CONFIG_RANDOMIZE_BASE" does not help, since the EFI stub only copies the kernel Image to a 2MB boundary if it is not relocatable. Adjust the EFI stub for arm64 so that the minimum Image alignment is 2MB unless KASLR is in use. Cc: Mark Rutland <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: David Brazdil <[email protected]> Acked-by: Ard Biesheuvel <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 5679b28 commit 7c116db

File tree

2 files changed

+15
-12
lines changed

2 files changed

+15
-12
lines changed

drivers/firmware/efi/libstub/arm64-stub.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@ efi_status_t check_platform_features(void)
3535
}
3636

3737
/*
38-
* Relocatable kernels can fix up the misalignment with respect to
39-
* MIN_KIMG_ALIGN, so they only require a minimum alignment of EFI_KIMG_ALIGN
40-
* (which accounts for the alignment of statically allocated objects such as
41-
* the swapper stack.)
38+
* Although relocatable kernels can fix up the misalignment with respect to
39+
* MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
40+
* sync with those recorded in the vmlinux when kaslr is disabled but the
41+
* image required relocation anyway. Therefore retain 2M alignment unless
42+
* KASLR is in use.
4243
*/
43-
static const u64 min_kimg_align = IS_ENABLED(CONFIG_RELOCATABLE) ? EFI_KIMG_ALIGN
44-
: MIN_KIMG_ALIGN;
44+
static u64 min_kimg_align(void)
45+
{
46+
return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
47+
}
4548

4649
efi_status_t handle_kernel_image(unsigned long *image_addr,
4750
unsigned long *image_size,
@@ -74,21 +77,21 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
7477

7578
kernel_size = _edata - _text;
7679
kernel_memsize = kernel_size + (_end - _edata);
77-
*reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align;
80+
*reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align();
7881

7982
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
8083
/*
8184
* If KASLR is enabled, and we have some randomness available,
8285
* locate the kernel at a randomized offset in physical memory.
8386
*/
84-
status = efi_random_alloc(*reserve_size, min_kimg_align,
87+
status = efi_random_alloc(*reserve_size, min_kimg_align(),
8588
reserve_addr, phys_seed);
8689
} else {
8790
status = EFI_OUT_OF_RESOURCES;
8891
}
8992

9093
if (status != EFI_SUCCESS) {
91-
if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align)) {
94+
if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align())) {
9295
/*
9396
* Just execute from wherever we were loaded by the
9497
* UEFI PE/COFF loader if the alignment is suitable.
@@ -99,7 +102,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
99102
}
100103

101104
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
102-
ULONG_MAX, min_kimg_align);
105+
ULONG_MAX, min_kimg_align());
103106

104107
if (status != EFI_SUCCESS) {
105108
efi_err("Failed to relocate kernel\n");
@@ -108,7 +111,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
108111
}
109112
}
110113

111-
*image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align;
114+
*image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align();
112115
memcpy((void *)*image_addr, _text, kernel_size);
113116

114117
return EFI_SUCCESS;

drivers/firmware/efi/libstub/efi-stub-helper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "efistub.h"
2020

2121
bool efi_nochunk;
22-
bool efi_nokaslr;
22+
bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
2323
bool efi_noinitrd;
2424
int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
2525
bool efi_novamap;

0 commit comments

Comments
 (0)