[PATCHv7 09/13] kexec_file: Integrate bpf light skeleton to load image with bpf-prog

bot+bpf-ci at kernel.org bot+bpf-ci at kernel.org
Sat Mar 21 19:14:27 PDT 2026


> diff --git a/kernel/kexec_bpf_loader.c b/kernel/kexec_bpf_loader.c
> index 7f7884411e2c..430f6c3970b6 100644
> --- a/kernel/kexec_bpf_loader.c
> +++ b/kernel/kexec_bpf_loader.c

[ ... ]

> +static void *get_symbol_from_elf(const char *elf_data, size_t elf_size,
> +				 const char *symbol_name,
> +				 unsigned int *symbol_size)
> +{

[ ... ]

> +	/* Check section data bounds */
> +	if (dst_shdr->sh_offset > elf_size ||
> +	    dst_shdr->sh_offset + dst_shdr->sh_size > elf_size ||
> +	    sym->st_value > dst_shdr->sh_size) {
> +		pr_err("Symbol data out of bounds\n");
> +		return NULL;
> +	}
> +
> +	symbol_data = (void *)(elf_data + dst_shdr->sh_offset + sym->st_value);
> +
> +	if (symbol_size)
> +		*symbol_size = sym->st_size;
> +
> +	return symbol_data;
> +}

The bounds check validates that sym->st_value falls within the section,
but it does not validate that sym->st_value + sym->st_size also fits
within the section (or the ELF buffer).

The caller arm_bpf_prog() passes the returned sym->st_size through to
bpf_load_and_run() as opts.data_sz / opts.insns_sz, which controls how
many bytes are copied from the pointer:

    arm_bpf_prog()
      opts_data = get_symbol_from_elf(..., &opts_data_sz);
        -> *symbol_size = sym->st_size;
      ...
      kexec_pe_parser_bpf__open_and_load()
        kexec_pe_parser_bpf__load()
          opts.data_sz = opts_data_sz;
          bpf_load_and_run(&opts);
            skel_map_update_elem(map_fd, &key, opts->data, 0);

Since the ELF comes from userspace via the PE .bpf section, could a
crafted ELF with a valid st_value but an oversized st_size cause a
read beyond the buffer here? Something like:

    if (sym->st_value + sym->st_size > dst_shdr->sh_size) ...

might be needed alongside the existing st_value check.

> + /* Load a ELF */
>  static int arm_bpf_prog(char *bpf_elf, unsigned long sz)
>  {

[ ... ]

> +	pe_parser = kexec_pe_parser_bpf__open_and_load();
> +	if (!pe_parser) {
> +		pr_info("Can not open and load bpf parser\n");
> +		return -1;
> +	}
> +	kexec_pe_parser_bpf__attach(pe_parser);
> +
> +	return 0;
>  }

kexec_pe_parser_bpf__attach() returns an error code, but its return
value is not checked here. If attach fails (e.g.
skel_raw_tracepoint_open() returns an error), arm_bpf_prog() still
returns 0.

The caller process_bpf_parsers_container() then proceeds to call
kexec_image_parser_anchor(), which is a no-op without the fentry
hook. context->parsed stays false, and every section appears to fail
with "no BPF section succeeded" -- hiding the real cause.

Should the return value of kexec_pe_parser_bpf__attach() be checked,
with the parser destroyed and an error returned on failure?


---
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