// SPDX-License-Identifier: GPL-2.0 /* * Helper functions used by the EFI stub on multiple * architectures to deal with physical address space randomization.
*/ #include <linux/efi.h>
#include"efistub.h"
/** * efi_kaslr_get_phys_seed() - Get random seed for physical kernel KASLR * @image_handle: Handle to the image * * If KASLR is not disabled, obtain a random seed using EFI_RNG_PROTOCOL * that will be used to move the kernel physical mapping. * * Return: the random seed
*/
u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle)
{
efi_guid_t li_fixed_proto = LINUX_EFI_LOADED_IMAGE_FIXED_GUID; void *p;
if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE)) return 0;
if (efi_nokaslr) {
efi_info("KASLR disabled on kernel command line\n");
} elseif (efi_bs_call(handle_protocol, image_handle,
&li_fixed_proto, &p) == EFI_SUCCESS) {
efi_info("Image placement fixed by loader\n");
} else {
efi_status_t status;
u32 phys_seed;
status = efi_get_random_bytes(sizeof(phys_seed),
(u8 *)&phys_seed); if (status == EFI_SUCCESS) return phys_seed;
/* * Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail * to provide space, and fail to zero it). Check for this condition by double * checking that the first and the last byte of the image are covered by the * same EFI memory map entry.
*/ staticbool check_image_region(u64 base, u64 size)
{ struct efi_boot_memmap *map __free(efi_pool) = NULL;
efi_status_t status; bool ret = false; int map_offset;
status = efi_get_memory_map(&map, false); if (status != EFI_SUCCESS) returnfalse;
/* * Find the region that covers base, and return whether * it covers base+size bytes.
*/ if (base >= md->phys_addr && base < end) {
ret = (base + size) <= end; break;
}
}
return ret;
}
/** * efi_kaslr_relocate_kernel() - Relocate the kernel (random if KASLR enabled) * @image_addr: Pointer to the current kernel location * @reserve_addr: Pointer to the relocated kernel location * @reserve_size: Size of the relocated kernel * @kernel_size: Size of the text + data * @kernel_codesize: Size of the text * @kernel_memsize: Size of the text + data + bss * @phys_seed: Random seed used for the relocation * * If KASLR is not enabled, this function relocates the kernel to a fixed * address (or leave it as its current location). If KASLR is enabled, the * kernel physical location is randomized using the seed in parameter. * * Return: status code, EFI_SUCCESS if relocation is successful
*/
efi_status_t efi_kaslr_relocate_kernel(unsignedlong *image_addr, unsignedlong *reserve_addr, unsignedlong *reserve_size, unsignedlong kernel_size, unsignedlong kernel_codesize, unsignedlong kernel_memsize,
u32 phys_seed)
{
efi_status_t status;
u64 min_kimg_align = efi_get_kimg_min_align();
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) { /* * If KASLR is enabled, and we have some randomness available, * locate the kernel at a randomized offset in physical memory.
*/
status = efi_random_alloc(*reserve_size, min_kimg_align,
reserve_addr, phys_seed,
EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT); if (status != EFI_SUCCESS)
efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
} else {
status = EFI_OUT_OF_RESOURCES;
}
if (status != EFI_SUCCESS) { if (!check_image_region(*image_addr, kernel_memsize)) {
efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
} elseif (IS_ALIGNED(*image_addr, min_kimg_align) &&
(unsignedlong)_end < EFI_ALLOC_LIMIT) { /* * Just execute from wherever we were loaded by the * UEFI PE/COFF loader if the placement is suitable.
*/
*reserve_size = 0; return EFI_SUCCESS;
}
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
ULONG_MAX, min_kimg_align,
EFI_LOADER_CODE);
if (status != EFI_SUCCESS) {
efi_err("Failed to relocate kernel\n");
*reserve_size = 0; return status;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.