From: Ard Biesheuvel <ardb@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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 --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; } -- 2.43.0.429.g432eaa2c6b-goog