*** Review the history *** Nowadays UEFI PE bootable image is more and more popular on the distribution. But it is still an open issue to load that kind of image by kexec with IMA enabled
There are several approaches to reslove this issue, but none of them are accepted in upstream till now. The summary of those approaches: -1. UEFI service emulator for UEFI stub -2. PE format parser in kernel For the first one, I have tried a purgatory-style emulator [1]. But it confronts the hardware scaling trouble. For the second one, there are two choices, one is to implement it inside the kernel, the other is inside the user space. Both zboot-format [2] and UKI-format [3] parsers are rejected due to the concern that the variant format parsers will inflate the kernel code. And finally, we have these kinds of parsers in the user space 'kexec-tools'. *** The approach in this series *** This approach allows the various PE boot image to be parsed in the bpf-prog, as a result, the kexec kernel code to remain relatively stable. To protect against malicious attacks on the BPF loader in user space, it employs BPF lskel to load and execute BPF programs from within the kernel. Each type of PE image contains a dedicated section '.bpf', which stores the bpf-prog designed to parse the format. This ensures that the PE's signature also protects the integrity of the '.bpf' section. The parsing process operates as a pipeline. The current BPF program parser attaches to bpf_handle_pefile() and detaches at the end of the current stage via disarm_bpf_prog(). The results parsed by the current BPF program are buffered in the kernel through prepare_nested_pe() and then delivered to the next stage. For each stage of the pipeline, the BPF bytecode is stored in the '.bpf' section of the PE file. That means a vmlinuz.efi embeded in UKI format can be handled. Special thanks to Philipp Rudo, who spent significant time evaluating the practicality of my solution, and to Viktor Malik, who guided me toward using BPF light skeleton to prevent malicious attacks from user space. *** To do *** For Poc, this series uses BPF fentry to call the parsing function. Later, it should implement a dedicated BPF_PROG_TYPE and confine the use of the newly introduced three kfuncs to the kexec_file_load context [1]: https://lore.kernel.org/lkml/20240819145417.23367-1-pi...@redhat.com/T/ [2]: https://lore.kernel.org/kexec/20230306030305.15595-1-kernelf...@gmail.com/ [3]: https://lore.kernel.org/lkml/20230911052535.335770-1-ker...@jfarr.cc/ [4]: https://lore.kernel.org/linux-arm-kernel/20230921133703.39042-2-kernelf...@gmail.com/T/ RFCv1 -> RFCv2 - Use bpf kfunc instead of helper - Use C source code to generate the light skeleton file --- Pingfan Liu (7): kexec_file: Make kexec_image_load_default global visible kexec: Introduce kexec_pe_image to parse and load PE file lib/decompress: Keep decompressor when CONFIG_KEXEC_PE_IMAGE bpf/kexec: Introduce two bpf kfunc for kexec kexec: Introduce a bpf-prog lskel kexec: Integrate bpf light skeleton to load zboot image arm64/kexec: Add PE image format support arch/arm64/Kconfig | 1 + arch/arm64/include/asm/kexec.h | 1 + arch/arm64/kernel/machine_kexec_file.c | 3 + include/linux/decompress/mm.h | 7 + include/linux/kexec.h | 2 + kernel/Kconfig.kexec | 8 + kernel/Makefile | 2 + kernel/kexec_bpf/Makefile | 65 ++ kernel/kexec_bpf/kexec_pe_parser_bpf.c | 66 ++ kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h | 147 +++++ kernel/kexec_file.c | 2 +- kernel/kexec_pe_image.c | 611 +++++++++++++++++++ lib/decompress.c | 6 +- 13 files changed, 917 insertions(+), 4 deletions(-) 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_pe_image.c -- 2.49.0