Re: [PATCH v9 bpf-next 02/10] libbpf: Support layout section handling in BTF

[email protected]
Newsgroups org.kernel.vger.dwarves,org.kernel.vger.bpf
Message-ID <1e030700935a6f99789250a8841c908cfda89f4e5cd215ada2485b02c07994c7@mail.kernel.org>
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index 83fe79ffcb8f..3438cc15bb7a 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c

[ ... ]

> @@ -224,66 +242,95 @@ static void btf_bswap_hdr(struct btf_header *h)

[ ... ]

>  static int btf_parse_hdr(struct btf *btf)
>  {
> -	struct btf_header *hdr = btf->hdr;
> +	struct btf_header *hdr = btf->raw_data;
> +	__u32 hdr_len = hdr->hdr_len;

[ ... ]

> +	memcpy(&btf->hdr, hdr, min((size_t)hdr_len, sizeof(struct btf_header)));

The memcpy here correctly caps the copy at sizeof(struct btf_header),
but btf->hdr.hdr_len retains the original value from the raw data.
If the input BTF has a future-extended header where hdr_len exceeds
sizeof(struct btf_header), only sizeof(struct btf_header) bytes are
stored, yet hdr_len remembers the larger original value. This
matters in btf_get_raw_data() below.

[ ... ]

> @@ -1601,7 +1664,7 @@ static const void *btf_strs_data(const struct btf *btf)
>
>  static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endian)
>  {
> -	struct btf_header *hdr = btf->hdr;
> +	const struct btf_header *hdr = &btf->hdr;
>  	struct btf_type *t;
>  	void *data, *p;
>  	__u32 data_sz;

[ ... ]

>  	memcpy(p, hdr, hdr->hdr_len);

When hdr_len > sizeof(struct btf_header), does this read past the
end of the embedded btf->hdr struct? hdr points to &btf->hdr which
is sizeof(struct btf_header) bytes, but hdr->hdr_len can be larger
if the parsed BTF had a future-extended header. The extra bytes
would come from adjacent struct btf fields (types_data, etc.),
leaking internal state into the serialized output.

Previously, btf->hdr pointed directly into raw_data where the full
header (including any extension bytes) was available. The switch to
an embedded struct loses those extra bytes, but the serialization
still tries to write hdr_len bytes.

One possible fix:

    memcpy(p, hdr, min((__u32)sizeof(struct btf_header), hdr->hdr_len));
    if (hdr->hdr_len > sizeof(struct btf_header))
        memset(p + sizeof(struct btf_header), 0,
               hdr->hdr_len - sizeof(struct btf_header));

>  	if (swap_endian)
> -		btf_bswap_hdr(p);
> +		btf_bswap_hdr(p, hdr->hdr_len);
>  	p += hdr->hdr_len;

[ ... ]


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

AI-authorship-score: low
AI-authorship-explanation: The patch went through nine review iterations on lore with detailed human reviewer interactions, follows established libbpf patterns, and the subtle header over-read is characteristic of human-authored refactoring.
issues-found: 1
issue-severity-score: medium
issue-severity-explanation: btf_get_raw_data() reads past the embedded btf->hdr struct into adjacent fields when hdr_len exceeds sizeof(struct btf_header), silently leaking internal state into serialized BTF output.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.