Skip to content

Commit ace013a

Browse files
committed
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 <[email protected]>
1 parent 79729f2 commit ace013a

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,3 +651,70 @@ efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
651651

652652
return status;
653653
}
654+
655+
/**
656+
* efi_remap_image - Remap a loaded image with the appropriate permissions
657+
* for code and data
658+
*
659+
* @image_base: the base of the image in memory
660+
* @alloc_size: the size of the area in memory occupied by the image
661+
* @code_size: the size of the leading part of the image containing code
662+
* and read-only data
663+
*
664+
* efi_remap_image() uses the EFI memory attribute protocol to remap the code
665+
* region of the loaded image read-only/executable, and the remainder
666+
* read-write/non-executable. The code region is assumed to start at the base
667+
* of the image, and will therefore cover the PE/COFF header as well.
668+
*/
669+
void efi_remap_image(unsigned long image_base, unsigned alloc_size,
670+
unsigned long code_size)
671+
{
672+
efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
673+
efi_memory_attribute_protocol_t *memattr;
674+
efi_status_t status;
675+
u64 attr;
676+
677+
/*
678+
* If the firmware implements the EFI_MEMORY_ATTRIBUTE_PROTOCOL, let's
679+
* invoke it to remap the text/rodata region of the decompressed image
680+
* as read-only and the data/bss region as non-executable.
681+
*/
682+
status = efi_bs_call(locate_protocol, &guid, NULL, (void **)&memattr);
683+
if (status != EFI_SUCCESS)
684+
return;
685+
686+
// Get the current attributes for the entire region
687+
status = memattr->get_memory_attributes(memattr, image_base,
688+
alloc_size, &attr);
689+
if (status != EFI_SUCCESS) {
690+
efi_warn("Failed to retrieve memory attributes for image region: 0x%lx\n",
691+
status);
692+
return;
693+
}
694+
695+
// Mark the code region as read-only
696+
status = memattr->set_memory_attributes(memattr, image_base, code_size,
697+
EFI_MEMORY_RO);
698+
if (status != EFI_SUCCESS) {
699+
efi_warn("Failed to remap code region read-only\n");
700+
return;
701+
}
702+
703+
// If the entire region was already mapped as non-exec, clear the
704+
// attribute from the code region. Otherwise, set it on the data
705+
// region.
706+
if (attr & EFI_MEMORY_XP) {
707+
status = memattr->clear_memory_attributes(memattr, image_base,
708+
code_size,
709+
EFI_MEMORY_XP);
710+
if (status != EFI_SUCCESS)
711+
efi_warn("Failed to remap code region executable\n");
712+
} else {
713+
status = memattr->set_memory_attributes(memattr,
714+
image_base + code_size,
715+
alloc_size - code_size,
716+
EFI_MEMORY_XP);
717+
if (status != EFI_SUCCESS)
718+
efi_warn("Failed to remap data region non-executable\n");
719+
}
720+
}

drivers/firmware/efi/libstub/efistub.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,4 +1096,7 @@ struct efi_smbios_type1_record {
10961096

10971097
const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
10981098

1099+
void efi_remap_image(unsigned long image_base, unsigned alloc_size,
1100+
unsigned long code_size);
1101+
10991102
#endif

drivers/firmware/efi/libstub/zboot.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
137137

138138
efi_cache_sync_image(image_base, alloc_size, code_size);
139139

140+
efi_remap_image(image_base, alloc_size, code_size);
141+
140142
status = efi_stub_common(handle, image, image_base, cmdline_ptr);
141143

142144
free_image:

0 commit comments

Comments
 (0)