[PATCHv7 02/13] kexec_file: Use bpf-prog to decompose image
bot+bpf-ci at kernel.org
bot+bpf-ci at kernel.org
Sat Mar 21 19:14:29 PDT 2026
> diff --git a/kernel/kexec_bpf_loader.c b/kernel/kexec_bpf_loader.c
> new file mode 100644
> index 000000000000..bd1800a76782
> --- /dev/null
> +++ b/kernel/kexec_bpf_loader.c
[ ... ]
> +#include <linux/bpf.h>
> +#include <linux/filter.h>
> +#include <asm/byteorder.h>
> +#include <asm/image.h>
> +#include <asm/memory.h>
> +#include "kexec_internal.h"
Are asm/image.h and asm/memory.h needed here? I could not find any
symbols from either header used in this file. asm/image.h only exists
for arm64, loongarch, and riscv, and asm/memory.h only for arm, arm64,
and csky.
Since CONFIG_KEXEC_BPF has no architecture dependency, enabling it on
x86 would cause a build failure from these missing headers.
[ ... ]
> +static int process_bpf_parsers_container(const char *elf_buf, size_t elf_sz,
> + struct kexec_context *context, int depth)
> +{
[ ... ]
> + /*
> + * Give the BPF prog a clean slate so context->parsed reliably
> + * reflects whether *this* invocation succeeded.
> + */
> + context->parsed = false;
> + /* This is the hook point for bpf-prog */
> + kexec_image_parser_anchor(context, (unsigned long)bpf);
> + disarm_bpf_prog();
> +
> + /* Free the old parsing context, and reload the new */
> + for (int i = 0; i < MAX_PARSING_BUF_NUM; i++) {
> + if (!!context->parsing_buf[i])
> + break;
> + vfree(context->parsing_buf[i]);
> + context->parsing_buf[i] = NULL;
> + context->parsing_buf_sz[i] = 0;
> + }
The comment says "free the old parsing context" but the condition
appears inverted. !!context->parsing_buf[i] is true when the pointer
is non-NULL, so the loop breaks at the first populated entry and only
calls vfree() on NULL pointers (which is a no-op).
Should this be if (!context->parsing_buf[i]) instead?
[ ... ]
> +int decompose_kexec_image(struct kimage *image, int extended_fd)
> +{
> + struct kexec_context ctx = { 0 };
> + unsigned long parser_sz;
> + char *parser_start;
> + int ret = -EINVAL;
[ ... ]
> + if (!validate_elf_bpf_sections(parser_start, parser_sz)) {
> +
> + ret = kernel_read_file_from_fd(extended_fd,
> + 0,
> + (void **)&ctx.parsing_buf[0],
> + KEXEC_FILE_SIZE_MAX,
> + NULL,
> + 0);
> + if (ret < 0) {
> + pr_err("Fail to read image container\n");
> + return -EINVAL;
> + }
> + ctx.parsing_buf_sz[0] = ret;
> + ret = process_bpf_parsers_container(parser_start, parser_sz, &ctx, 0);
> + if (!ret) {
> + char *p;
> +
> + /* Envelop should hold valid kernel, initrd, cmdline sections */
> + if (!ctx.kernel || !ctx.initrd || !ctx.cmdline) {
> + vfree(ctx.kernel);
> + vfree(ctx.initrd);
> + vfree(ctx.cmdline);
> + return -EINVAL;
> + }
[ ... ]
> + }
> + return ret;
> + }
> +
> + return -EINVAL;
> +}
When process_bpf_parsers_container() fails, or when the
!ctx.kernel || !ctx.initrd || !ctx.cmdline check triggers,
ctx.parsing_buf[0] was allocated by kernel_read_file_from_fd() but
is never freed before returning. Does this leak the buffer?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23393379437
More information about the kexec
mailing list