Instead of remapping all DXE runtime drivers with read-write-execute
permissions entirely when ExitBootServices() is called, remap only the
parts of those images that require writable access for applying
relocation fixups at SetVirtualAddressMap() time.
As illustrated below, this greatly reduces the footprint of those
regions, which is important for safe execution. And given that the most
important ISAs and toolchains split executable code from relocatable
quantities, the remapped pages in question are generally not the ones
that contain code as well.
On a ArmVirtQemu build, the footprint of those RWX pages is shown below.
As future work, we might investigate whether we can find a way to
guarantee in general that images are built in a way where executable
code and relocatable data never share a 4 KiB page, in which case we
could apply EFI_MEMORY_XP permissions here instead of allowing RWX.
Before:
SetUefiImageMemoryAttributes - 0x0000000047600000 - 0x0000000000050000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000044290000 - 0x0000000000050000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000044230000 - 0x0000000000050000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x00000000441D0000 - 0x0000000000050000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x00000000440D0000 - 0x0000000000050000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000043F90000 - 0x0000000000040000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000043F40000 - 0x0000000000040000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000043EF0000 - 0x0000000000040000 (0x0000000000000008)
After:
SetUefiImageMemoryAttributes - 0x0000000047630000 - 0x0000000000001000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x00000000442C0000 - 0x0000000000001000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000044260000 - 0x0000000000001000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000044200000 - 0x0000000000001000 (0x0000000000000008)
SetUefiImageMemoryAttributes - 0x0000000044100000 - 0x0000000000001000 (0x0000000000000008)
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index 5a82eee80781..3e6f2b4e74cc 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -1060,6 +1060,8 @@ MemoryProtectionExitBootServicesCallback (
{
EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage;
LIST_ENTRY *Link;
+ PHYSICAL_ADDRESS RelocationRangeStart;
+ PHYSICAL_ADDRESS RelocationRangeEnd;
//
// We need remove the RT protection, because RT relocation need write code segment
@@ -1073,7 +1075,22 @@ MemoryProtectionExitBootServicesCallback (
if (mImageProtectionPolicy != 0) {
for (Link = gRuntime->ImageHead.ForwardLink; Link != &gRuntime->ImageHead; Link = Link->ForwardLink) {
RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link);
- SetUefiImageMemoryAttributes ((UINT64)(UINTN)RuntimeImage->ImageBase, ALIGN_VALUE (RuntimeImage->ImageSize, EFI_PAGE_SIZE), 0);
+
+ PeCoffLoaderGetRelocationRange (
+ (PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase,
+ (UINTN)ALIGN_VALUE (RuntimeImage->ImageSize, EFI_PAGE_SIZE),
+ RuntimeImage->RelocationData,
+ &RelocationRangeStart,
+ &RelocationRangeEnd
+ );
+
+ if (RelocationRangeEnd > RelocationRangeStart) {
+ SetUefiImageMemoryAttributes (
+ RelocationRangeStart,
+ (UINTN)(RelocationRangeEnd - RelocationRangeStart),
+ 0
+ );
+ }
}
}
}
--
2.39.2
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#101123): https://edk2.groups.io/g/devel/message/101123
Mute This Topic: https://groups.io/mt/97586021/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-