Skip to content

Commit 3a26242

Browse files
committed
efi/libstub: arm64: Relax 2M alignment again for relocatable kernels
Commit 8204670 ("efi/libstub/arm64: Replace 'preferred' offset with alignment check") simplified the way the stub moves the kernel image around in memory before booting it, given that a relocatable image does not need to be copied to a 2M aligned offset if it was loaded on a 64k boundary by EFI. Commit d32de91 ("efi/arm64: libstub: Deal gracefully with EFI_RNG_PROTOCOL failure") inadvertently defeated this logic by overriding the value of efi_nokaslr if EFI_RNG_PROTOCOL is not available, which was mistaken by the loader logic as an explicit request on the part of the user to disable KASLR and any associated relocation of an Image not loaded on a 2M boundary. So let's reinstate this functionality, by capturing the value of efi_nokaslr at function entry to choose the minimum alignment. Fixes: d32de91 ("efi/arm64: libstub: Deal gracefully with EFI_RNG_PROTOCOL failure") Signed-off-by: Ard Biesheuvel <[email protected]> Tested-by: Benjamin Herrenschmidt <[email protected]>
1 parent 5b94046 commit 3a26242

File tree

1 file changed

+13
-15
lines changed

1 file changed

+13
-15
lines changed

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

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,6 @@ static bool check_image_region(u64 base, u64 size)
7979
return ret;
8080
}
8181

82-
/*
83-
* Although relocatable kernels can fix up the misalignment with respect to
84-
* MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
85-
* sync with those recorded in the vmlinux when kaslr is disabled but the
86-
* image required relocation anyway. Therefore retain 2M alignment unless
87-
* KASLR is in use.
88-
*/
89-
static u64 min_kimg_align(void)
90-
{
91-
return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
92-
}
93-
9482
efi_status_t handle_kernel_image(unsigned long *image_addr,
9583
unsigned long *image_size,
9684
unsigned long *reserve_addr,
@@ -101,6 +89,16 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
10189
unsigned long kernel_size, kernel_memsize = 0;
10290
u32 phys_seed = 0;
10391

92+
/*
93+
* Although relocatable kernels can fix up the misalignment with
94+
* respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
95+
* subtly out of sync with those recorded in the vmlinux when kaslr is
96+
* disabled but the image required relocation anyway. Therefore retain
97+
* 2M alignment if KASLR was explicitly disabled, even if it was not
98+
* going to be activated to begin with.
99+
*/
100+
u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
101+
104102
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
105103
if (!efi_nokaslr) {
106104
status = efi_get_random_bytes(sizeof(phys_seed),
@@ -130,7 +128,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
130128
* If KASLR is enabled, and we have some randomness available,
131129
* locate the kernel at a randomized offset in physical memory.
132130
*/
133-
status = efi_random_alloc(*reserve_size, min_kimg_align(),
131+
status = efi_random_alloc(*reserve_size, min_kimg_align,
134132
reserve_addr, phys_seed);
135133
} else {
136134
status = EFI_OUT_OF_RESOURCES;
@@ -139,7 +137,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
139137
if (status != EFI_SUCCESS) {
140138
if (!check_image_region((u64)_text, kernel_memsize)) {
141139
efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
142-
} else if (IS_ALIGNED((u64)_text, min_kimg_align())) {
140+
} else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
143141
/*
144142
* Just execute from wherever we were loaded by the
145143
* UEFI PE/COFF loader if the alignment is suitable.
@@ -150,7 +148,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
150148
}
151149

152150
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
153-
ULONG_MAX, min_kimg_align());
151+
ULONG_MAX, min_kimg_align);
154152

155153
if (status != EFI_SUCCESS) {
156154
efi_err("Failed to relocate kernel\n");

0 commit comments

Comments
 (0)