Skip to content

Commit 2f77465

Browse files
committed
x86/efistub: Avoid placing the kernel below LOAD_PHYSICAL_ADDR
The EFI stub's kernel placement logic randomizes the physical placement of the kernel by taking all available memory into account, and picking a region at random, based on a random seed. When KASLR is disabled, this seed is set to 0x0, and this results in the lowest available region of memory to be selected for loading the kernel, even if this is below LOAD_PHYSICAL_ADDR. Some of this memory is typically reserved for the GFP_DMA region, to accommodate masters that can only access the first 16 MiB of system memory. Even if such devices are rare these days, we may still end up with a warning in the kernel log, as reported by Tom: swapper/0: page allocation failure: order:10, mode:0xcc1(GFP_KERNEL|GFP_DMA), nodemask=(null),cpuset=/,mems_allowed=0 Fix this by tweaking the random allocation logic to accept a low bound on the placement, and set it to LOAD_PHYSICAL_ADDR. Fixes: a1b87d5 ("x86/efistub: Avoid legacy decompressor when doing EFI boot") Reported-by: Tom Englund <[email protected]> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218404 Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent a7a6a01 commit 2f77465

File tree

5 files changed

+12
-8
lines changed

5 files changed

+12
-8
lines changed

drivers/firmware/efi/libstub/efistub.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
956956

957957
efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
958958
unsigned long *addr, unsigned long random_seed,
959-
int memory_type, unsigned long alloc_limit);
959+
int memory_type, unsigned long alloc_min,
960+
unsigned long alloc_max);
960961

961962
efi_status_t efi_random_get_seed(void);
962963

drivers/firmware/efi/libstub/kaslr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ efi_status_t efi_kaslr_relocate_kernel(unsigned long *image_addr,
119119
*/
120120
status = efi_random_alloc(*reserve_size, min_kimg_align,
121121
reserve_addr, phys_seed,
122-
EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
122+
EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
123123
if (status != EFI_SUCCESS)
124124
efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
125125
} else {

drivers/firmware/efi/libstub/randomalloc.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
1818
unsigned long size,
1919
unsigned long align_shift,
20-
u64 alloc_limit)
20+
u64 alloc_min, u64 alloc_max)
2121
{
2222
unsigned long align = 1UL << align_shift;
2323
u64 first_slot, last_slot, region_end;
@@ -30,11 +30,11 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
3030
return 0;
3131

3232
region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
33-
alloc_limit);
33+
alloc_max);
3434
if (region_end < size)
3535
return 0;
3636

37-
first_slot = round_up(md->phys_addr, align);
37+
first_slot = round_up(max(md->phys_addr, alloc_min), align);
3838
last_slot = round_down(region_end - size + 1, align);
3939

4040
if (first_slot > last_slot)
@@ -56,7 +56,8 @@ efi_status_t efi_random_alloc(unsigned long size,
5656
unsigned long *addr,
5757
unsigned long random_seed,
5858
int memory_type,
59-
unsigned long alloc_limit)
59+
unsigned long alloc_min,
60+
unsigned long alloc_max)
6061
{
6162
unsigned long total_slots = 0, target_slot;
6263
unsigned long total_mirrored_slots = 0;
@@ -78,7 +79,8 @@ efi_status_t efi_random_alloc(unsigned long size,
7879
efi_memory_desc_t *md = (void *)map->map + map_offset;
7980
unsigned long slots;
8081

81-
slots = get_entry_num_slots(md, size, ilog2(align), alloc_limit);
82+
slots = get_entry_num_slots(md, size, ilog2(align), alloc_min,
83+
alloc_max);
8284
MD_NUM_SLOTS(md) = slots;
8385
total_slots += slots;
8486
if (md->attribute & EFI_MEMORY_MORE_RELIABLE)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
799799

800800
status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
801801
seed[0], EFI_LOADER_CODE,
802+
LOAD_PHYSICAL_ADDR,
802803
EFI_X86_KERNEL_ALLOC_LIMIT);
803804
if (status != EFI_SUCCESS)
804805
return status;

drivers/firmware/efi/libstub/zboot.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
119119
}
120120

121121
status = efi_random_alloc(alloc_size, min_kimg_align, &image_base,
122-
seed, EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
122+
seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
123123
if (status != EFI_SUCCESS) {
124124
efi_err("Failed to allocate memory\n");
125125
goto free_cmdline;

0 commit comments

Comments
 (0)