mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-15 18:34:47 +08:00
efi: zboot: Use EFI protocol to remap code/data with the right attributes
Use the recently introduced EFI_MEMORY_ATTRIBUTES_PROTOCOL in the zboot implementation to set the right attributes for the code and data sections of the decompressed image, i.e., EFI_MEMORY_RO for code and EFI_MEMORY_XP for data. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
79729f26b0
commit
ace013a543
@ -651,3 +651,70 @@ efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
|
|||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_remap_image - Remap a loaded image with the appropriate permissions
|
||||||
|
* for code and data
|
||||||
|
*
|
||||||
|
* @image_base: the base of the image in memory
|
||||||
|
* @alloc_size: the size of the area in memory occupied by the image
|
||||||
|
* @code_size: the size of the leading part of the image containing code
|
||||||
|
* and read-only data
|
||||||
|
*
|
||||||
|
* efi_remap_image() uses the EFI memory attribute protocol to remap the code
|
||||||
|
* region of the loaded image read-only/executable, and the remainder
|
||||||
|
* read-write/non-executable. The code region is assumed to start at the base
|
||||||
|
* of the image, and will therefore cover the PE/COFF header as well.
|
||||||
|
*/
|
||||||
|
void efi_remap_image(unsigned long image_base, unsigned alloc_size,
|
||||||
|
unsigned long code_size)
|
||||||
|
{
|
||||||
|
efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
|
||||||
|
efi_memory_attribute_protocol_t *memattr;
|
||||||
|
efi_status_t status;
|
||||||
|
u64 attr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the firmware implements the EFI_MEMORY_ATTRIBUTE_PROTOCOL, let's
|
||||||
|
* invoke it to remap the text/rodata region of the decompressed image
|
||||||
|
* as read-only and the data/bss region as non-executable.
|
||||||
|
*/
|
||||||
|
status = efi_bs_call(locate_protocol, &guid, NULL, (void **)&memattr);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the current attributes for the entire region
|
||||||
|
status = memattr->get_memory_attributes(memattr, image_base,
|
||||||
|
alloc_size, &attr);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
efi_warn("Failed to retrieve memory attributes for image region: 0x%lx\n",
|
||||||
|
status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the code region as read-only
|
||||||
|
status = memattr->set_memory_attributes(memattr, image_base, code_size,
|
||||||
|
EFI_MEMORY_RO);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
efi_warn("Failed to remap code region read-only\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the entire region was already mapped as non-exec, clear the
|
||||||
|
// attribute from the code region. Otherwise, set it on the data
|
||||||
|
// region.
|
||||||
|
if (attr & EFI_MEMORY_XP) {
|
||||||
|
status = memattr->clear_memory_attributes(memattr, image_base,
|
||||||
|
code_size,
|
||||||
|
EFI_MEMORY_XP);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
efi_warn("Failed to remap code region executable\n");
|
||||||
|
} else {
|
||||||
|
status = memattr->set_memory_attributes(memattr,
|
||||||
|
image_base + code_size,
|
||||||
|
alloc_size - code_size,
|
||||||
|
EFI_MEMORY_XP);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
efi_warn("Failed to remap data region non-executable\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1096,4 +1096,7 @@ struct efi_smbios_type1_record {
|
|||||||
|
|
||||||
const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
|
const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
|
||||||
|
|
||||||
|
void efi_remap_image(unsigned long image_base, unsigned alloc_size,
|
||||||
|
unsigned long code_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -137,6 +137,8 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
|||||||
|
|
||||||
efi_cache_sync_image(image_base, alloc_size, code_size);
|
efi_cache_sync_image(image_base, alloc_size, code_size);
|
||||||
|
|
||||||
|
efi_remap_image(image_base, alloc_size, code_size);
|
||||||
|
|
||||||
status = efi_stub_common(handle, image, image_base, cmdline_ptr);
|
status = efi_stub_common(handle, image, image_base, cmdline_ptr);
|
||||||
|
|
||||||
free_image:
|
free_image:
|
||||||
|
Loading…
Reference in New Issue
Block a user