Re: [PATCHv6 00/13] kexec: Use BPF lskel to enable kexec to load PE format boot image

From: Pingfan Liu

Date: Fri Feb 27 2026 - 01:04:12 EST


Hi Philipp,

Thank you for taking the time to look into this.

On Thu, Feb 26, 2026 at 9:36 PM Philipp Rudo <prudo@xxxxxxxxxx> wrote:
>
> Hi Pingfan,
>
> please excuse my late reply. I've looked through the series and all in
> all it looks fine to me. I've got two comments/questions in addition to
> what the bpf-bot found. In general the findings from the bpf-bot look
> valid to me. But fixing them should be rather straight forward. Only
> for the first finding, where it "complains" that ctx->buf is NULL, I
> don't understand what it is wants to tell us.
>

A race condition exists: when bpf_buffer_parser() is called multiple
times on ctx, later calls overwrite the previous ctx->buf without
releasing it. While re-entrancy is uncommon in this design, it still
needs to be addressed.

> In my opinion the next step we should take is to implement an example
> bpf-prog for UKIs. I expect it to be much more complex compared to the
> zboot one. So having a example bpf-prog will show us if we run into any
> limitations with bpf or need to adjust the interfaces.
>

Yeah, it's a little challenge. The traditional kexec_file_load syscall
interface was tailored for the kernel boot protocol. However, with the
emergence of Zboot and UKI images, it fails to automatically
accommodate these new formats.

Now, with the introduction of decompose_kexec_kimage() to
kexec_file_load, the design takes a different approach. It decomposes
these complex modern images and then reassembles them into the kernel
boot protocol. Consequently, the fds parameter in kexec_file_load()
can have more flexible meanings, no longer limited to kernel or initrd
file descriptors.

I'm considering two alternative approaches. The first is to introduce
an fd array to pass the file descriptors for UKI and cmdline add-ons.
The second option is to reuse the current interface but reinterpret
the meaning of fds. The first approach requires not just an fd array
but also metadata describing the purpose of each file descriptor. In
contrast, the second option avoids this complexity.
In the second option, the first fd in kexec_file_load can be used to
ship the bpf parsers. the second fd can be used to ship a temporary
file, which holds UKI and all addons. Inside the kernel, the bpf
parser can extract the PE files embeded inside the temporary file,
verify their signature, decide their role and reassemble them. So all
details are kept inside the bpf parser without changing the kernel
API.

To implement this, the design in this series requires some
adjustments. Rather than embedding BPF parsers in PE-based formats
like Zboot or UKI, this approach improves the design by keeping the
kernel image unmodified.


What is your opinion?


Thanks,

Pingfan




> Thanks
> Philipp
>
> On Mon, 19 Jan 2026 11:24:11 +0800
> Pingfan Liu <piliu@xxxxxxxxxx> wrote:
>
> > *** 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/20240819145417.23367-1-piliu@xxxxxxxxxx/T/
> > [2]: https://lore.kernel.org/kexec/20230306030305.15595-1-kernelfans@xxxxxxxxx/
> > [3]: https://lore.kernel.org/lkml/20230911052535.335770-1-kernel@xxxxxxxx/
> > [4]: https://lore.kernel.org/linux-efi/20230921133703.39042-1-kernelfans@xxxxxxxxx/
> >
> >
> > *** 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
> >
>