diff mbox series

x86/efi: Remap kernel code read-only before dropping NX attribute

Message ID 20240125134058.2076660-2-ardb+git@google.com
State New
Headers show
Series x86/efi: Remap kernel code read-only before dropping NX attribute | expand

Commit Message

Ard Biesheuvel Jan. 25, 2024, 1:40 p.m. UTC
From: Ard Biesheuvel <ardb@kernel.org>

Currently, the EFI stub strips the NX restriction from the entire loaded
kernel. It would be better to only apply this change to the part of the
kernel that will actually execute from the firmware's 1:1 mapping of
memory, and make this region read-only first, rather than relying on
memory with RWX mappings before calling ExitBootServices().

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
Note that this patch relies on some non-trivial rework of the early 1:1
init code, which was necessary for unrelated reasons.

https://lkml.kernel.org/r/20240125112818.2016733-19-ardb%2Bgit%40google.com

 arch/x86/boot/compressed/Makefile       | 2 +-
 arch/x86/boot/compressed/misc.c         | 1 +
 arch/x86/include/asm/boot.h             | 1 +
 drivers/firmware/efi/libstub/x86-stub.c | 4 +++-
 4 files changed, 6 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index bccee07eae60..75c0b0be9685 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -84,7 +84,7 @@  LDFLAGS_vmlinux += -T
 hostprogs	:= mkpiggy
 HOST_EXTRACFLAGS += -I$(srctree)/tools/include
 
-sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABbCDGRSTtVW] \(_text\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p'
+sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABbCDGRrSTtVW] \(_text\|__end_rodata_aligned\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p'
 
 quiet_cmd_voffset = VOFFSET $@
       cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index b99e08e6815b..71c8415ee62e 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -330,6 +330,7 @@  static size_t parse_elf(void *output)
 	return ehdr.e_entry - LOAD_PHYSICAL_ADDR;
 }
 
+const unsigned long kernel_ro_size = VO___end_rodata_aligned - VO__text;
 const unsigned long kernel_total_size = VO__end - VO__text;
 
 static u8 boot_heap[BOOT_HEAP_SIZE] __aligned(4);
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
index a38cc0afc90a..852adf628067 100644
--- a/arch/x86/include/asm/boot.h
+++ b/arch/x86/include/asm/boot.h
@@ -81,6 +81,7 @@ 
 
 #ifndef __ASSEMBLY__
 extern unsigned int output_len;
+extern const unsigned long kernel_ro_size;
 extern const unsigned long kernel_total_size;
 
 unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 0d510c9a06a4..cd05081301c7 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -236,6 +236,8 @@  void efi_adjust_memory_range_protection(unsigned long start,
 	rounded_end = roundup(start + size, EFI_PAGE_SIZE);
 
 	if (memattr != NULL) {
+		efi_call_proto(memattr, set_memory_attributes, rounded_start,
+			       rounded_end - rounded_start, EFI_MEMORY_RO);
 		efi_call_proto(memattr, clear_memory_attributes, rounded_start,
 			       rounded_end - rounded_start, EFI_MEMORY_XP);
 		return;
@@ -805,7 +807,7 @@  static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
 
 	*kernel_entry = addr + entry;
 
-	efi_adjust_memory_range_protection(addr, kernel_total_size);
+	efi_adjust_memory_range_protection(addr, kernel_ro_size);
 
 	return EFI_SUCCESS;
 }