Re: [PATCH 1/4] perf libbfd: Validate BPF prog info arrays before pointer cast

[email protected] Sun, 02 Aug 2026 14:54:39 +0000
Newsgroups org.kernel.vger.linux-perf-users
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] Missing bitmask validation for several PERF_BPIL_* flags before calling bpf_prog_linfo__new(), leading to raw file offset dereferences.
- [High] Missing bitmask validation for PERF_BPIL_PROG_TAGS and PERF_BPIL_FUNC_INFO in bpf-event.c call sites.
--

--- Patch [1]: [PATCH 1/4] perf libbfd: Validate BPF prog info arrays before pointer cast ---
commit 91de4e21d8f65551a65e6afd999ee44cac7b52f7
Author: Arnaldo Carvalho de Melo <[email protected]>

perf libbfd: Validate BPF prog info arrays before pointer cast

This commit adds bitmask checks for PERF_BPIL_JITED_INSNS and
PERF_BPIL_JITED_KSYMS in libbfd.c before casting them to pointers. This
prevents raw file offsets from being dereferenced when processing a crafted
perf.data file.

> perf libbfd: Validate BPF prog info arrays before pointer cast
>
> symbol__disassemble_bpf_libbfd() casts info_linear->info.jited_prog_insns
> and info_linear->info.jited_ksyms to pointers without checking whether
> bpil_offs_to_addr() actually converted the file offsets.  A crafted
> perf.data with PERF_BPIL_* bits unset but non-zero counts causes raw
> file offsets to be dereferenced as pointers.
>
> Add bitmask checks for PERF_BPIL_JITED_INSNS and PERF_BPIL_JITED_KSYMS
> before the casts, matching the validation added to bpf-event.c call
> sites.

[Severity: High]
This is a pre-existing issue, but is the validation in the bpf-event.c call
sites complete?

In tools/perf/util/bpf-event.c:__bpf_event__print_bpf_prog_info(), the
required_arrays bitmask fails to include PERF_BPIL_PROG_TAGS and
PERF_BPIL_FUNC_INFO.

It then proceeds to call synthesize_bpf_prog_name(), which dereferences
info->prog_tags without checking if they were converted:

tools/perf/util/bpf-event.c:synthesize_bpf_prog_name() {
    ...
    name_len += snprintf_hex(buf + name_len, size - name_len,
                             prog_tags[sub_id], BPF_TAG_SIZE);
    ...
}

Could a crafted perf.data file provide non-zero counts but omit the
corresponding bits in the array mask, leaving them as unconverted raw
file offsets?

> diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c
> index c1c12308cc12f..d6c2d9807fc9c 100644
> --- a/tools/perf/util/libbfd.c
> +++ b/tools/perf/util/libbfd.c

[ ... ]

> @@ -581,6 +586,12 @@ int symbol__disassemble_bpf_libbfd(struct symbol *sym __maybe_unused,
>  	if (disassemble == NULL)
>  		abort();
>  
> +	/* jited_ksyms is only valid if bpil_offs_to_addr() converted it */
> +	if (!(info_linear->arrays & (1UL << PERF_BPIL_JITED_KSYMS))) {
> +		ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
> +		goto out;
> +	}
> +

[Severity: High]
This is a pre-existing issue, but does calling bpf_prog_linfo__new() earlier
in this function before validating the PERF_BPIL_JITED_KSYMS bitmask risk
dereferencing raw file offsets?

Because bpf_prog_linfo__new() relies on jited_ksyms internally, putting the
validation for PERF_BPIL_JITED_KSYMS here means the validation happens after
the structure has already been accessed:

tools/lib/bpf/bpf_prog_linfo.c:dissect_jited_func() {
    ...
    if (ksym_func[0] != *jited_linfo)
    ...
}

It also seems that bpf_prog_linfo__new() uses info->line_info, which doesn't
have a PERF_BPIL_LINE_INFO check before the call.

Should the validation for PERF_BPIL_JITED_KSYMS (and other arrays like
line_info) be moved earlier, before info_linear->info is passed to
bpf_prog_linfo__new()?

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1