On Thu, 25 Jan 2024 at 14:41, Ard Biesheuvel <ardb+git@xxxxxxxxxx> wrote: > > 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 > Forgot to mention: tested with Mu's OVMF build, which implements the EFI memory attribute protocol (and happily permits RWX mappings btw) https://github.com/microsoft/mu_tiano_platforms/releases > 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 >