*** The history ***
Nowadays, UEFI PE bootable images are becoming increasingly popular among distributions. Currently, we have several kinds of image format parsers in user space (kexec-tools). However, this approach breaks the integrity protection of the images. To address this integrity protection concern, several approaches have been proposed to resolve this issue, but none of them have been accepted upstream yet. The summary of those approaches: -1. UEFI service emulator for UEFI stub -2. PE format parser in kernel -3. Signing the arm64/boot/Image For the first approach, I tried a purgatory-style emulator [1], but it encounters hardware scaling issues. For the second approach, both zboot-format [2] and UKI-format [3] parsers were rejected due to concerns that variant format parsers would bloat the kernel code. Additionally, for example in arm64, both UKI and zboot format parsers would need to be introduced and chained together to handle image loading. For the third approach, I attempted [4], but since zboot or UKI images already have signatures, upstream maintainers dislike the additional signature on the Image. Moreover, for secure boot UKI, this method cannot use signatures to protect the initramfs. *** The approach in this series *** This series introduces an approach that allows image formats to be parsed by BPF programs. As a result, the kexec kernel code can remain relatively stable without introducing new parsers for different architectures. This approach introduces a dedicated '.bpf' section in the PE file, which stores BPF bytecode. The integrity of all components -- kernel, initramfs, cmdline, and even the BPF bytecode itself is protected by the PE file's signature. After signature verification, the BPF bytecode is loaded and executed from within the kernel using BPF lskel. Therefore, the bytecode itself is protected from malicious attacks on the BPF loader in user space. When a .bpf section is extracted from the current image file, its bytecode is attached to the kexec kernel function kexec_image_parser_anchor(). After the bytecode parses the image, the next-stage image is prepared, and the bytecode in the new .bpf section can be attached to kexec_image_parser_anchor(). In this way, nested image format issues (e.g., zboot image within UKI on arm64) can be resolved. (Theoretically not yet tested.) *** Thanks *** I would like to thank Philipp Rudo, whose insights inspired this approach and who dedicated significant time to evaluating its practicality. I am also grateful to Viktor Malik for his guidance on using BPF light skeleton to prevent malicious attacks from user space. *** Test approach *** -1. compile kernel -2. get the zboot image with bpf-prog by 'make -C tools/kexec zboot' -3. compile kexec-tools from https://github.com/pfliu/kexec-tools/tree/pe_bpf The rest test process is the common convention to use kexec. [1]: https://lore.kernel.org/lkml/[email protected]/T/ [2]: https://lore.kernel.org/kexec/[email protected]/ [3]: https://lore.kernel.org/lkml/[email protected]/ [4]: https://lore.kernel.org/linux-efi/[email protected]/ *** Changes *** v5 -> v6 - Re-organize the layers in kexec_file_load into two layers: format-parsing and kernel boot protocol handling. - Simplify the bpf kfunc interface. - rebased onto Linux 6.19-rc2 v4 -> v5 - rebased onto Linux 6.17-rc2 - [1/12], use a separate CONFIG_KEEP_COMPRESSOR to decide the section of decompressor method - [10/12], add Catalin's acked-by (Thanks Catalin!) v3 -> v4 - Use dynamic allocator in decompression ([4/12]) - Fix issue caused by Identical Code Folding ([5/12]) - Integrate the image generator tool in the kernel tree ([11,12/12]) - Address the issue according to Philipp's comments in v3 reviewing. Thanks Philipp! RFCv2 -> v3 - move the introduced bpf kfuncs to kernel/bpf/* and mark them sleepable - use listener and publisher model to implement bpf_copy_to_kernel() - keep each introduced kfunc under the control of memcg RFCv1 -> RFCv2 - Use bpf kfunc instead of helper - Use C source code to generate the light skeleton file --- Pingfan Liu (13): bpf: Introduce kfuncs to parser buffer content kexec_file: Move signature validation ahead kexec_file: Introduce routines to parse PE file kexec_file: Use bpf-prog to decompose image lib/decompress: Keep decompressor when CONFIG_KEEP_DECOMPRESSOR kexec_file: Implement decompress method for parser kexec_file: Implement copy method for parser kexec_file: Introduce a bpf-prog lskel to parse PE file kexec_file: Factor out routine to find a symbol in ELF kexec_file: Integrate bpf light skeleton to load image with bpf-prog arm64/kexec: Select KEXEC_BPF to support UEFI-style kernel image tools/kexec: Introduce a bpf-prog to parse zboot image format tools/kexec: Add a zboot image building tool arch/arm64/Kconfig | 1 + include/linux/bpf.h | 19 + include/linux/decompress/mm.h | 8 + kernel/Kconfig.kexec | 8 + kernel/Makefile | 2 + kernel/bpf/Makefile | 3 + kernel/bpf/bpf_buffer_parser.c | 170 +++++++ kernel/kexec_bpf/Makefile | 70 +++ kernel/kexec_bpf/kexec_pe_parser_bpf.c | 12 + kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h | 130 ++++++ kernel/kexec_bpf/template.c | 68 +++ kernel/kexec_bpf_loader.c | 439 +++++++++++++++++++ kernel/kexec_file.c | 106 +++-- kernel/kexec_internal.h | 5 + kernel/kexec_uefi_app.c | 81 ++++ lib/Kconfig | 6 + lib/decompress.c | 6 +- tools/kexec/Makefile | 91 ++++ tools/kexec/pe.h | 177 ++++++++ tools/kexec/template.c | 68 +++ tools/kexec/zboot_image_builder.c | 278 ++++++++++++ tools/kexec/zboot_parser_bpf.c | 114 +++++ 22 files changed, 1813 insertions(+), 49 deletions(-) create mode 100644 kernel/bpf/bpf_buffer_parser.c create mode 100644 kernel/kexec_bpf/Makefile create mode 100644 kernel/kexec_bpf/kexec_pe_parser_bpf.c create mode 100644 kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h create mode 100644 kernel/kexec_bpf/template.c create mode 100644 kernel/kexec_bpf_loader.c create mode 100644 kernel/kexec_uefi_app.c create mode 100644 tools/kexec/Makefile create mode 100644 tools/kexec/pe.h create mode 100644 tools/kexec/template.c create mode 100644 tools/kexec/zboot_image_builder.c create mode 100644 tools/kexec/zboot_parser_bpf.c -- 2.49.0
