* [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation
@ 2023-04-04 15:19 Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 1/6] efi/pe: Import new BTI/IBT header flags from the spec Ard Biesheuvel
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2023-04-04 15:19 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, will, catalin.marinas, mark.rutland, broonie,
Ard Biesheuvel
Some tweaks for the arm64 EFI header and the zboot version, to add the
annotation that informs the loader that the code regions may be mapped
with BTI enforcement enabled.
As a related cleanup, add the combined codesize (text+rodata+inittext)
to the arm64 Image header, so the EFI zboot loader can grab it from the
image after decompressing it.
Ard Biesheuvel (6):
efi/pe: Import new BTI/IBT header flags from the spec
arm64: efi: Enable BTI codegen and add PE/COFF annotation
arm64: image: Add code size to the image header
efi/zboot: Add BSS padding before compression
efi/zboot: Set forward edge CFI compat header flag if supported
efi/zboot: arm64: Grab code size from image header
Documentation/arm64/booting.rst | 3 +-
arch/arm64/boot/Makefile | 1 +
arch/arm64/include/asm/image.h | 3 +-
arch/arm64/kernel/efi-header.S | 71 ++++++++++++--------
arch/arm64/kernel/head.S | 3 +-
arch/arm64/kernel/image.h | 10 ++-
drivers/firmware/efi/libstub/Makefile | 3 +-
drivers/firmware/efi/libstub/Makefile.zboot | 41 +++++++----
drivers/firmware/efi/libstub/arm64.c | 18 +++--
drivers/firmware/efi/libstub/efistub.h | 3 +-
drivers/firmware/efi/libstub/zboot-header.S | 51 +++++++++-----
drivers/firmware/efi/libstub/zboot.c | 13 +---
include/linux/pe.h | 4 ++
13 files changed, 139 insertions(+), 85 deletions(-)
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/6] efi/pe: Import new BTI/IBT header flags from the spec
2023-04-04 15:19 [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation Ard Biesheuvel
@ 2023-04-04 15:19 ` Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 2/6] arm64: efi: Enable BTI codegen and add PE/COFF annotation Ard Biesheuvel
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2023-04-04 15:19 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, will, catalin.marinas, mark.rutland, broonie,
Ard Biesheuvel
The latest version of your favorite fork of the PE/COFF spec includes a
new type of header flag that is intended to be used in the context of
EFI firmware to indicate to the image loader that the executable regions
of an image can be mapped with BTI/IBT enforcement enabled.
So let's import these definitions so we can use them in subsequent
patches.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
include/linux/pe.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/linux/pe.h b/include/linux/pe.h
index 6ffabf1e6d039e67..5e1e115408702c77 100644
--- a/include/linux/pe.h
+++ b/include/linux/pe.h
@@ -118,6 +118,9 @@
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
+#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001
+#define IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040
+
/* they actually defined 0x00000000 as well, but I think we'll skip that one. */
#define IMAGE_SCN_RESERVED_0 0x00000001
#define IMAGE_SCN_RESERVED_1 0x00000002
@@ -165,6 +168,7 @@
#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */
#define IMAGE_DEBUG_TYPE_CODEVIEW 2
+#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20
#ifndef __ASSEMBLY__
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/6] arm64: efi: Enable BTI codegen and add PE/COFF annotation
2023-04-04 15:19 [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 1/6] efi/pe: Import new BTI/IBT header flags from the spec Ard Biesheuvel
@ 2023-04-04 15:19 ` Ard Biesheuvel
2023-04-05 16:33 ` Mark Brown
2023-04-04 15:19 ` [PATCH 3/6] arm64: image: Add code size to the image header Ard Biesheuvel
` (3 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Ard Biesheuvel @ 2023-04-04 15:19 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, will, catalin.marinas, mark.rutland, broonie,
Ard Biesheuvel
UEFI heavily relies on so-called protocols, which are essentially
tables populated with pointers to executable code, and these are invoked
indirectly using BR or BLR instructions.
This makes the EFI execution context vulnerable to attacks on forward
edge control flow, and so it would help if we could enable hardware
enforcement (BTI) on CPUs that implement it.
So let's no longer disable BTI codegen for the EFI stub, and set the
newly introduced PE/COFF header flag when the kernel is built with BTI
landing pads.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
| 71 ++++++++++++--------
drivers/firmware/efi/libstub/Makefile | 3 +-
2 files changed, 44 insertions(+), 30 deletions(-)
--git a/arch/arm64/kernel/efi-header.S b/arch/arm64/kernel/efi-header.S
index d731b4655df8eb27..11d7f7de202d0ed2 100644
--- a/arch/arm64/kernel/efi-header.S
+++ b/arch/arm64/kernel/efi-header.S
@@ -81,9 +81,47 @@
.quad 0 // CertificationTable
.quad 0 // BaseRelocationTable
-#ifdef CONFIG_DEBUG_EFI
+#if defined(CONFIG_DEBUG_EFI) || defined(CONFIG_ARM64_BTI_KERNEL)
.long .Lefi_debug_table - .L_head // DebugTable
.long .Lefi_debug_table_size
+
+ /*
+ * The debug table is referenced via its Relative Virtual Address (RVA),
+ * which is only defined for those parts of the image that are covered
+ * by a section declaration. Since this header is not covered by any
+ * section, the debug table must be emitted elsewhere. So stick it in
+ * the .init.rodata section instead.
+ *
+ * Note that the payloads themselves are permitted to have zero RVAs,
+ * which means we can simply put those right after the section headers.
+ */
+ __INITRODATA
+
+ .align 2
+.Lefi_debug_table:
+#ifdef CONFIG_DEBUG_EFI
+ // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
+ .long 0 // Characteristics
+ .long 0 // TimeDateStamp
+ .short 0 // MajorVersion
+ .short 0 // MinorVersion
+ .long IMAGE_DEBUG_TYPE_CODEVIEW // Type
+ .long .Lefi_debug_entry_size // SizeOfData
+ .long 0 // RVA
+ .long .Lefi_debug_entry - .L_head // FileOffset
+#endif
+#ifdef CONFIG_ARM64_BTI_KERNEL
+ .long 0 // Characteristics
+ .long 0 // TimeDateStamp
+ .short 0 // MajorVersion
+ .short 0 // MinorVersion
+ .long IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS // Type
+ .long 4 // SizeOfData
+ .long 0 // RVA
+ .long .Lefi_dll_characteristics_ex - .L_head // FileOffset
+#endif
+ .set .Lefi_debug_table_size, . - .Lefi_debug_table
+ .previous
#endif
// Section table
@@ -119,33 +157,6 @@
.set .Lsection_count, (. - .Lsection_table) / 40
#ifdef CONFIG_DEBUG_EFI
- /*
- * The debug table is referenced via its Relative Virtual Address (RVA),
- * which is only defined for those parts of the image that are covered
- * by a section declaration. Since this header is not covered by any
- * section, the debug table must be emitted elsewhere. So stick it in
- * the .init.rodata section instead.
- *
- * Note that the EFI debug entry itself may legally have a zero RVA,
- * which means we can simply put it right after the section headers.
- */
- __INITRODATA
-
- .align 2
-.Lefi_debug_table:
- // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
- .long 0 // Characteristics
- .long 0 // TimeDateStamp
- .short 0 // MajorVersion
- .short 0 // MinorVersion
- .long IMAGE_DEBUG_TYPE_CODEVIEW // Type
- .long .Lefi_debug_entry_size // SizeOfData
- .long 0 // RVA
- .long .Lefi_debug_entry - .L_head // FileOffset
-
- .set .Lefi_debug_table_size, . - .Lefi_debug_table
- .previous
-
.Lefi_debug_entry:
// EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
.ascii "NB10" // Signature
@@ -157,6 +168,10 @@
.set .Lefi_debug_entry_size, . - .Lefi_debug_entry
#endif
+#ifdef CONFIG_ARM64_BTI_KERNEL
+.Lefi_dll_characteristics_ex:
+ .long IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT
+#endif
.balign SEGMENT_ALIGN
.Lefi_header_end:
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 80d85a5169fb2c72..3abb2b357482a416 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -23,8 +23,7 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
# arm64 uses the full KBUILD_CFLAGS so it's necessary to explicitly
# disable the stackleak plugin
cflags-$(CONFIG_ARM64) += -fpie $(DISABLE_STACKLEAK_PLUGIN) \
- -fno-unwind-tables -fno-asynchronous-unwind-tables \
- $(call cc-option,-mbranch-protection=none)
+ -fno-unwind-tables -fno-asynchronous-unwind-tables
cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
-DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \
-DEFI_HAVE_STRCMP -fno-builtin -fpic \
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/6] arm64: image: Add code size to the image header
2023-04-04 15:19 [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 1/6] efi/pe: Import new BTI/IBT header flags from the spec Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 2/6] arm64: efi: Enable BTI codegen and add PE/COFF annotation Ard Biesheuvel
@ 2023-04-04 15:19 ` Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 4/6] efi/zboot: Add BSS padding before compression Ard Biesheuvel
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2023-04-04 15:19 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, will, catalin.marinas, mark.rutland, broonie,
Ard Biesheuvel
In order for loaders to be able to create a preliminary mapping of the
image without having to rely on mappings that have both write and
execute permissions, it is necessary to expose the size of the leading
part of the image consisting of .text, .rodata and .inittext.
So add this information to the arm64 bare metal boot header.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
Documentation/arm64/booting.rst | 3 ++-
arch/arm64/include/asm/image.h | 3 ++-
arch/arm64/kernel/head.S | 3 ++-
arch/arm64/kernel/image.h | 10 +++++++---
4 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/Documentation/arm64/booting.rst b/Documentation/arm64/booting.rst
index ffeccdd6bdac9442..4d6966833c8c7472 100644
--- a/Documentation/arm64/booting.rst
+++ b/Documentation/arm64/booting.rst
@@ -79,7 +79,8 @@ The decompressed kernel image contains a 64-byte header as follows::
u64 text_offset; /* Image load offset, little endian */
u64 image_size; /* Effective Image size, little endian */
u64 flags; /* kernel flags, little endian */
- u64 res2 = 0; /* reserved */
+ u32 code_size; /* Image code size, little endian */
+ u32 res2 = 0; /* reserved */
u64 res3 = 0; /* reserved */
u64 res4 = 0; /* reserved */
u32 magic = 0x644d5241; /* Magic number, little endian, "ARM\x64" */
diff --git a/arch/arm64/include/asm/image.h b/arch/arm64/include/asm/image.h
index c2b13213c7207c02..5361694c5a7b4956 100644
--- a/arch/arm64/include/asm/image.h
+++ b/arch/arm64/include/asm/image.h
@@ -47,7 +47,8 @@ struct arm64_image_header {
__le64 text_offset;
__le64 image_size;
__le64 flags;
- __le64 res2;
+ __le32 code_size;
+ __le32 res2;
__le64 res3;
__le64 res4;
__le32 magic;
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index b98970907226b36c..8f684a2e8f05ac7e 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -62,7 +62,8 @@
.quad 0 // Image load offset from start of RAM, little-endian
le64sym _kernel_size_le // Effective size of kernel image, little-endian
le64sym _kernel_flags_le // Informative flags, little-endian
- .quad 0 // reserved
+ .long _kernel_codesize_le // Size of leading text/rodata/inittext region, LE
+ .long 0 // reserved
.quad 0 // reserved
.quad 0 // reserved
.ascii ARM64_IMAGE_MAGIC // Magic number
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index 7bc3ba8979019182..4c08409b2129d510 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -34,6 +34,9 @@
#define DATA_LE32(data) ((data) & 0xffffffff)
#endif
+#define DEFINE_IMAGE_LE32(sym, data) \
+ sym = DATA_LE32((data) & 0xffffffff)
+
#define DEFINE_IMAGE_LE64(sym, data) \
sym##_lo32 = DATA_LE32((data) & 0xffffffff); \
sym##_hi32 = DATA_LE32((data) >> 32)
@@ -60,8 +63,9 @@
* regardless of the endianness of the kernel. While constant values could be
* endian swapped in head.S, all are done here for consistency.
*/
-#define HEAD_SYMBOLS \
- DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \
- DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS);
+#define HEAD_SYMBOLS \
+ DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \
+ DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS); \
+ DEFINE_IMAGE_LE32(_kernel_codesize_le, __initdata_begin - _text);
#endif /* __ARM64_KERNEL_IMAGE_H */
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/6] efi/zboot: Add BSS padding before compression
2023-04-04 15:19 [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation Ard Biesheuvel
` (2 preceding siblings ...)
2023-04-04 15:19 ` [PATCH 3/6] arm64: image: Add code size to the image header Ard Biesheuvel
@ 2023-04-04 15:19 ` Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 5/6] efi/zboot: Set forward edge CFI compat header flag if supported Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 6/6] efi/zboot: arm64: Grab code size from image header Ard Biesheuvel
5 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2023-04-04 15:19 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, will, catalin.marinas, mark.rutland, broonie,
Ard Biesheuvel
We don't really care about the size of the decompressed image - what
matters is how much space needs to be allocated for the image to
execute, and this includes space for BSS that is not part of the
loadable image and so it is not accounted for in the decompressed size.
So let's add some zero padding to the end of the image: this compresses
well, and it ensures that BSS is accounted for, and as a bonus, it will
be zeroed before launching the image.
Since all architectures that implement support for EFI zboot carry this
value in the header in the same location, we can just grab it from the
binary that is being compressed.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
drivers/firmware/efi/libstub/Makefile.zboot | 36 +++++++++++++++-----
| 2 +-
drivers/firmware/efi/libstub/zboot.c | 6 ++--
3 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot
index ccdd6a130d98618e..2d78770236049b21 100644
--- a/drivers/firmware/efi/libstub/Makefile.zboot
+++ b/drivers/firmware/efi/libstub/Makefile.zboot
@@ -3,6 +3,14 @@
# to be include'd by arch/$(ARCH)/boot/Makefile after setting
# EFI_ZBOOT_PAYLOAD, EFI_ZBOOT_BFD_TARGET and EFI_ZBOOT_MACH_TYPE
+quiet_cmd_copy_and_pad = PAD $@
+ cmd_copy_and_pad = cp $< $@ && \
+ truncate -s $(shell hexdump -s16 -n4 -e '"%u"' $<) $@
+
+# Pad the file to the size of the uncompressed image in memory, including BSS
+$(obj)/vmlinux.bin: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
+ $(call if_changed,copy_and_pad)
+
comp-type-$(CONFIG_KERNEL_GZIP) := gzip
comp-type-$(CONFIG_KERNEL_LZ4) := lz4
comp-type-$(CONFIG_KERNEL_LZMA) := lzma
@@ -10,16 +18,25 @@ comp-type-$(CONFIG_KERNEL_LZO) := lzo
comp-type-$(CONFIG_KERNEL_XZ) := xzkern
comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
-# Copy the SizeOfHeaders, SizeOfCode and SizeOfImage fields from the payload to
-# the end of the compressed image. Note that this presupposes a PE header
-# offset of 64 bytes, which is what arm64, RISC-V and LoongArch use.
-quiet_cmd_compwithsize = $(quiet_cmd_$(comp-type-y))
- cmd_compwithsize = $(cmd_$(comp-type-y)) && ( \
+# in GZIP, the appended le32 carrying the uncompressed size is part of the
+# format, but in other cases, we just append it at the end for convenience,
+# causing the original tools to complain when checking image integrity.
+# So disregard it when calculating the payload size in the zimage header.
+zboot-method-y := $(comp-type-y)_with_size
+zboot-size-len-y := 12
+
+zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
+zboot-size-len-$(CONFIG_KERNEL_GZIP) := 8
+
+# Copy the SizeOfHeaders and SizeOfCode fields from the payload to the end of
+# the compressed image. Note that this presupposes a PE header offset of 64
+# bytes, which is what arm64, RISC-V and LoongArch use.
+quiet_cmd_compwithsize = $(quiet_cmd_$(zboot-method-y))
+ cmd_compwithsize = $(cmd_$(zboot-method-y)) && ( \
dd status=none if=$< bs=4 count=1 skip=37 ; \
- dd status=none if=$< bs=4 count=1 skip=23 ; \
- dd status=none if=$< bs=4 count=1 skip=36 ) >> $@
+ dd status=none if=$< bs=4 count=1 skip=23 ) >> $@
-$(obj)/vmlinuz: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
+$(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
$(call if_changed,compwithsize)
OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) \
@@ -29,6 +46,7 @@ $(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE
AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \
-DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \
+ -DZBOOT_SIZE_LEN=$(zboot-size-len-y) \
-DCOMP_TYPE="\"$(comp-type-y)\""
$(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
@@ -44,4 +62,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
$(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.elf FORCE
$(call if_changed,objcopy)
-targets += zboot-header.o vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
+targets += zboot-header.o vmlinux.bin vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
--git a/drivers/firmware/efi/libstub/zboot-header.S b/drivers/firmware/efi/libstub/zboot-header.S
index 445cb646eaaaf1c6..053aba073594936b 100644
--- a/drivers/firmware/efi/libstub/zboot-header.S
+++ b/drivers/firmware/efi/libstub/zboot-header.S
@@ -17,7 +17,7 @@ __efistub_efi_zboot_header:
.long MZ_MAGIC
.ascii "zimg" // image type
.long __efistub__gzdata_start - .Ldoshdr // payload offset
- .long __efistub__gzdata_size - 12 // payload size
+ .long __efistub__gzdata_size - ZBOOT_SIZE_LEN // payload size
.long 0, 0 // reserved
.asciz COMP_TYPE // compression type
.org .Ldoshdr + 0x38
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index 6105e5e2eda4612b..63ece480090032c1 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -91,12 +91,12 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
efi_info("Decompressing Linux Kernel...\n");
// SizeOfImage from the compressee's PE/COFF header
- alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
+ alloc_size = round_up(get_unaligned_le32(_gzdata_end - 12),
EFI_ALLOC_ALIGN);
// SizeOfHeaders and SizeOfCode from the compressee's PE/COFF header
- code_size = get_unaligned_le32(_gzdata_end - 8) +
- get_unaligned_le32(_gzdata_end - 12);
+ code_size = get_unaligned_le32(_gzdata_end - 4) +
+ get_unaligned_le32(_gzdata_end - 8);
// If the architecture has a preferred address for the image,
// try that first.
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/6] efi/zboot: Set forward edge CFI compat header flag if supported
2023-04-04 15:19 [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation Ard Biesheuvel
` (3 preceding siblings ...)
2023-04-04 15:19 ` [PATCH 4/6] efi/zboot: Add BSS padding before compression Ard Biesheuvel
@ 2023-04-04 15:19 ` Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 6/6] efi/zboot: arm64: Grab code size from image header Ard Biesheuvel
5 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2023-04-04 15:19 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, will, catalin.marinas, mark.rutland, broonie,
Ard Biesheuvel
Add some plumbing to the zboot EFI header generation to set the newly
introduced DllCharacteristicsEx flag associated with forward edge CFI
enforcement instructions (BTI on arm64, IBT on x86)
x86 does not currently uses the zboot infrastructure, so let's wire it
up only for arm64.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/arm64/boot/Makefile | 1 +
drivers/firmware/efi/libstub/Makefile.zboot | 9 +++-
| 49 +++++++++++++-------
3 files changed, 40 insertions(+), 19 deletions(-)
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index c65aee0884103c6f..ae645fda90bca574 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -42,5 +42,6 @@ $(obj)/Image.zst: $(obj)/Image FORCE
EFI_ZBOOT_PAYLOAD := Image
EFI_ZBOOT_BFD_TARGET := elf64-littleaarch64
EFI_ZBOOT_MACH_TYPE := ARM64
+EFI_ZBOOT_FORWARD_CFI := $(CONFIG_ARM64_BTI_KERNEL)
include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot
diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot
index 2d78770236049b21..0a9dcc2b13736519 100644
--- a/drivers/firmware/efi/libstub/Makefile.zboot
+++ b/drivers/firmware/efi/libstub/Makefile.zboot
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# to be include'd by arch/$(ARCH)/boot/Makefile after setting
-# EFI_ZBOOT_PAYLOAD, EFI_ZBOOT_BFD_TARGET and EFI_ZBOOT_MACH_TYPE
+# EFI_ZBOOT_PAYLOAD, EFI_ZBOOT_BFD_TARGET, EFI_ZBOOT_MACH_TYPE and
+# EFI_ZBOOT_FORWARD_CFI
quiet_cmd_copy_and_pad = PAD $@
cmd_copy_and_pad = cp $< $@ && \
@@ -44,10 +45,14 @@ OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) \
$(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE
$(call if_changed,objcopy)
+aflags-zboot-header-$(EFI_ZBOOT_FORWARD_CFI) := \
+ -DPE_DLL_CHAR_EX=IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT
+
AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \
-DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \
-DZBOOT_SIZE_LEN=$(zboot-size-len-y) \
- -DCOMP_TYPE="\"$(comp-type-y)\""
+ -DCOMP_TYPE="\"$(comp-type-y)\"" \
+ $(aflags-zboot-header-y)
$(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
$(call if_changed_rule,as_o_S)
--git a/drivers/firmware/efi/libstub/zboot-header.S b/drivers/firmware/efi/libstub/zboot-header.S
index 053aba073594936b..fb676ded47fa4341 100644
--- a/drivers/firmware/efi/libstub/zboot-header.S
+++ b/drivers/firmware/efi/libstub/zboot-header.S
@@ -78,9 +78,36 @@ __efistub_efi_zboot_header:
.quad 0 // ExceptionTable
.quad 0 // CertificationTable
.quad 0 // BaseRelocationTable
-#ifdef CONFIG_DEBUG_EFI
+#if defined(PE_DLL_CHAR_EX) || defined(CONFIG_DEBUG_EFI)
.long .Lefi_debug_table - .Ldoshdr // DebugTable
.long .Lefi_debug_table_size
+
+ .section ".rodata", "a"
+ .p2align 2
+.Lefi_debug_table:
+ // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY[]
+#ifdef PE_DLL_CHAR_EX
+ .long 0 // Characteristics
+ .long 0 // TimeDateStamp
+ .short 0 // MajorVersion
+ .short 0 // MinorVersion
+ .long IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS // Type
+ .long 4 // SizeOfData
+ .long 0 // RVA
+ .long .Lefi_dll_characteristics_ex - .Ldoshdr // FileOffset
+#endif
+#ifdef CONFIG_DEBUG_EFI
+ .long 0 // Characteristics
+ .long 0 // TimeDateStamp
+ .short 0 // MajorVersion
+ .short 0 // MinorVersion
+ .long IMAGE_DEBUG_TYPE_CODEVIEW // Type
+ .long .Lefi_debug_entry_size // SizeOfData
+ .long 0 // RVA
+ .long .Lefi_debug_entry - .Ldoshdr // FileOffset
+#endif
+ .set .Lefi_debug_table_size, . - .Lefi_debug_table
+ .previous
#endif
.Lsection_table:
@@ -110,23 +137,11 @@ __efistub_efi_zboot_header:
.set .Lsection_count, (. - .Lsection_table) / 40
+#ifdef PE_DLL_CHAR_EX
+.Lefi_dll_characteristics_ex:
+ .long PE_DLL_CHAR_EX
+#endif
#ifdef CONFIG_DEBUG_EFI
- .section ".rodata", "a"
- .align 2
-.Lefi_debug_table:
- // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
- .long 0 // Characteristics
- .long 0 // TimeDateStamp
- .short 0 // MajorVersion
- .short 0 // MinorVersion
- .long IMAGE_DEBUG_TYPE_CODEVIEW // Type
- .long .Lefi_debug_entry_size // SizeOfData
- .long 0 // RVA
- .long .Lefi_debug_entry - .Ldoshdr // FileOffset
-
- .set .Lefi_debug_table_size, . - .Lefi_debug_table
- .previous
-
.Lefi_debug_entry:
// EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
.ascii "NB10" // Signature
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/6] efi/zboot: arm64: Grab code size from image header
2023-04-04 15:19 [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation Ard Biesheuvel
` (4 preceding siblings ...)
2023-04-04 15:19 ` [PATCH 5/6] efi/zboot: Set forward edge CFI compat header flag if supported Ard Biesheuvel
@ 2023-04-04 15:19 ` Ard Biesheuvel
5 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2023-04-04 15:19 UTC (permalink / raw)
To: linux-efi
Cc: linux-arm-kernel, will, catalin.marinas, mark.rutland, broonie,
Ard Biesheuvel
Instead of relying on a dodgy dd hack to copy the image code size from
the uncompressed image's PE header to the end of the compressed image,
let's grab the code size from the arm64 image header after
decompression, which we can do now that we have added this information
to this header.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
drivers/firmware/efi/libstub/Makefile.zboot | 14 +++-----------
drivers/firmware/efi/libstub/arm64.c | 18 ++++++++++++------
drivers/firmware/efi/libstub/efistub.h | 3 +--
drivers/firmware/efi/libstub/zboot.c | 15 ++++-----------
4 files changed, 20 insertions(+), 30 deletions(-)
diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot
index 0a9dcc2b13736519..d34d4f0ed33349d5 100644
--- a/drivers/firmware/efi/libstub/Makefile.zboot
+++ b/drivers/firmware/efi/libstub/Makefile.zboot
@@ -24,21 +24,13 @@ comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
# causing the original tools to complain when checking image integrity.
# So disregard it when calculating the payload size in the zimage header.
zboot-method-y := $(comp-type-y)_with_size
-zboot-size-len-y := 12
+zboot-size-len-y := 4
zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
-zboot-size-len-$(CONFIG_KERNEL_GZIP) := 8
-
-# Copy the SizeOfHeaders and SizeOfCode fields from the payload to the end of
-# the compressed image. Note that this presupposes a PE header offset of 64
-# bytes, which is what arm64, RISC-V and LoongArch use.
-quiet_cmd_compwithsize = $(quiet_cmd_$(zboot-method-y))
- cmd_compwithsize = $(cmd_$(zboot-method-y)) && ( \
- dd status=none if=$< bs=4 count=1 skip=37 ; \
- dd status=none if=$< bs=4 count=1 skip=23 ) >> $@
+zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0
$(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
- $(call if_changed,compwithsize)
+ $(call if_changed,$(zboot-method-y))
OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) \
--rename-section .data=.gzdata,load,alloc,readonly,contents
diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
index 8aad8c49d43f18e0..b65bf5371d3d4700 100644
--- a/drivers/firmware/efi/libstub/arm64.c
+++ b/drivers/firmware/efi/libstub/arm64.c
@@ -9,6 +9,7 @@
#include <linux/efi.h>
#include <asm/efi.h>
+#include <asm/image.h>
#include <asm/memory.h>
#include <asm/sysreg.h>
@@ -89,25 +90,30 @@ efi_status_t check_platform_features(void)
#endif
void efi_cache_sync_image(unsigned long image_base,
- unsigned long alloc_size,
- unsigned long code_size)
+ unsigned long alloc_size)
{
+ const struct arm64_image_header *header = (void *)image_base;
u32 ctr = read_cpuid_effective_cachetype();
u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
CTR_EL0_DminLine_SHIFT);
/* only perform the cache maintenance if needed for I/D coherency */
if (!(ctr & BIT(CTR_EL0_IDC_SHIFT))) {
+ unsigned long base = image_base;
+ unsigned long size = le32_to_cpu(header->code_size);
+
do {
- asm("dc " DCTYPE ", %0" :: "r"(image_base));
- image_base += lsize;
- code_size -= lsize;
- } while (code_size >= lsize);
+ asm("dc " DCTYPE ", %0" :: "r"(base));
+ base += lsize;
+ size -= lsize;
+ } while (size >= lsize);
}
asm("ic ialluis");
dsb(ish);
isb();
+
+ efi_remap_image(image_base, alloc_size, le32_to_cpu(header->code_size));
}
unsigned long __weak primary_entry_offset(void)
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 148013bcb5f89fdd..67d5a20802e0b7c6 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1066,8 +1066,7 @@ struct screen_info *__alloc_screen_info(void);
void free_screen_info(struct screen_info *si);
void efi_cache_sync_image(unsigned long image_base,
- unsigned long alloc_size,
- unsigned long code_size);
+ unsigned long alloc_size);
struct efi_smbios_record {
u8 type;
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index 63ece480090032c1..e5d7fa1f1d8fd160 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -50,8 +50,7 @@ static unsigned long alloc_preferred_address(unsigned long alloc_size)
}
void __weak efi_cache_sync_image(unsigned long image_base,
- unsigned long alloc_size,
- unsigned long code_size)
+ unsigned long alloc_size)
{
// Provided by the arch to perform the cache maintenance necessary for
// executable code loaded into memory to be safe for execution.
@@ -66,7 +65,7 @@ asmlinkage efi_status_t __efiapi
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
{
unsigned long compressed_size = _gzdata_end - _gzdata_start;
- unsigned long image_base, alloc_size, code_size;
+ unsigned long image_base, alloc_size;
efi_loaded_image_t *image;
efi_status_t status;
char *cmdline_ptr;
@@ -91,13 +90,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
efi_info("Decompressing Linux Kernel...\n");
// SizeOfImage from the compressee's PE/COFF header
- alloc_size = round_up(get_unaligned_le32(_gzdata_end - 12),
+ alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
EFI_ALLOC_ALIGN);
- // SizeOfHeaders and SizeOfCode from the compressee's PE/COFF header
- code_size = get_unaligned_le32(_gzdata_end - 4) +
- get_unaligned_le32(_gzdata_end - 8);
-
// If the architecture has a preferred address for the image,
// try that first.
image_base = alloc_preferred_address(alloc_size);
@@ -140,9 +135,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
goto free_image;
}
- efi_cache_sync_image(image_base, alloc_size, code_size);
-
- efi_remap_image(image_base, alloc_size, code_size);
+ efi_cache_sync_image(image_base, alloc_size);
status = efi_stub_common(handle, image, image_base, cmdline_ptr);
--
2.39.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/6] arm64: efi: Enable BTI codegen and add PE/COFF annotation
2023-04-04 15:19 ` [PATCH 2/6] arm64: efi: Enable BTI codegen and add PE/COFF annotation Ard Biesheuvel
@ 2023-04-05 16:33 ` Mark Brown
0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2023-04-05 16:33 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-efi, linux-arm-kernel, will, catalin.marinas, mark.rutland
[-- Attachment #1.1: Type: text/plain, Size: 271 bytes --]
On Tue, Apr 04, 2023 at 05:19:55PM +0200, Ard Biesheuvel wrote:
> So let's no longer disable BTI codegen for the EFI stub, and set the
> newly introduced PE/COFF header flag when the kernel is built with BTI
> landing pads.
Reviewed-by: Mark Brown <broonie@kernel.org>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2023-04-05 16:34 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-04 15:19 [PATCH 0/6] arm64/efi/zboot: Clean up and enable BTI annotation Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 1/6] efi/pe: Import new BTI/IBT header flags from the spec Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 2/6] arm64: efi: Enable BTI codegen and add PE/COFF annotation Ard Biesheuvel
2023-04-05 16:33 ` Mark Brown
2023-04-04 15:19 ` [PATCH 3/6] arm64: image: Add code size to the image header Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 4/6] efi/zboot: Add BSS padding before compression Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 5/6] efi/zboot: Set forward edge CFI compat header flag if supported Ard Biesheuvel
2023-04-04 15:19 ` [PATCH 6/6] efi/zboot: arm64: Grab code size from image header Ard Biesheuvel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).