On 2023-03-08 23:22, Ard Biesheuvel wrote:
Modern PE loader implementations used by EFI will honour the PE section
permission attributes, and so we can use them to avoid mappings that
are
writable and executable at the same time.
Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx>
---
arch/x86/boot/header.S | 17 ++++++++++++++++
arch/x86/boot/tools/build.c | 21 +++++++++++++++-----
2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 4f1e1791cda4d316..a8ff8bbb17bca7d7 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -253,6 +253,23 @@ section_table:
IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_EXECUTE # Characteristics
+ .ascii ".data"
+ .byte 0
+ .byte 0
+ .byte 0
+ .long 0
+ .long 0x0 # startup_{32,64}
+ .long 0 # Size of initialized data
+ # on disk
+ .long 0x0 # startup_{32,64}
+ .long 0 # PointerToRelocations
+ .long 0 # PointerToLineNumbers
+ .word 0 # NumberOfRelocations
+ .word 0 # NumberOfLineNumbers
+ .long IMAGE_SCN_CNT_INITIALIZED_DATA | \
+ IMAGE_SCN_MEM_READ | \
+ IMAGE_SCN_MEM_WRITE # Characteristics
+
.set section_count, (. - section_table) / 40
#endif /* CONFIG_EFI_STUB */
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 883e6359221cd588..b449c82feaadf2b8 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -119,6 +119,7 @@ static unsigned long efi_boot_params;
static unsigned long kernel_info;
static unsigned long startup_64;
static unsigned long _ehead;
+static unsigned long _data;
static unsigned long _end;
/*----------------------------------------------------------------------*/
@@ -347,10 +348,15 @@ static unsigned int
update_pecoff_sections(unsigned int text_start, unsigned int
init_sz += CONFIG_PHYSICAL_ALIGN;
/*
- * Size of code: Subtract the size of the first sector (512 bytes)
- * which includes the header.
+ * Size of code: the size of the combined .text/.rodata section,
which
+ * ends at the _data marker symbol.
*/
- put_unaligned_le32(text_sz + bss_sz, &hdr->text_size);
+ put_unaligned_le32(_data, &hdr->text_size);
+
+ /*
+ * Size of data: the size of the combined .data/.bss section.
+ */
+ put_unaligned_le32(text_sz - _data + bss_sz, &hdr->data_size);
/* Size of image */
put_unaligned_le32(init_sz, &hdr->image_size);
@@ -360,9 +366,13 @@ static unsigned int
update_pecoff_sections(unsigned int text_start, unsigned int
*/
put_unaligned_le32(text_start + efi_pe_entry, &hdr->entry_point);
- update_pecoff_section_header_fields(".text", text_start, text_sz +
bss_sz,
- text_sz, text_start);
+ update_pecoff_section_header_fields(".text", text_start, _data,
+ _data, text_start);
+ update_pecoff_section_header_fields(".data", text_start + _data,
+ text_sz - _data + bss_sz,
+ text_sz - _data,
+ text_start + _data);
return text_start + file_sz;
}
@@ -455,6 +465,7 @@ static void parse_zoffset(char *fname)
PARSE_ZOFS(p, kernel_info);
PARSE_ZOFS(p, startup_64);
PARSE_ZOFS(p, _ehead);
+ PARSE_ZOFS(p, _data);
This also requires _data to be fetched to zoffset.h:
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 8203f1a23f7a..0e5a18c3c165 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -91,7 +91,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z]
\(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|efi32_pe_entry\|efi_boot_params\|input_data\|kernel_info\|_end\|_ehead\|_text\|z_.*\)$$/\#define
ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z]
\(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|efi32_pe_entry\|efi_boot_params\|input_data\|kernel_info\|_end\|_ehead\|_text\|_data\|z_.*\)$$/\#define
ZO_\2 0x\1/p'
quiet_cmd_zoffset = ZOFFSET $@
cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
PARSE_ZOFS(p, _end);
p = strchr(p, '\n');