[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