Re: [PATCH v15 bpf-next 6/9] libbpf: Support sanitization of BTF layout for older kernels

[email protected] Tue, 24 Mar 2026 18:55:29 +0000 (UTC)
Newsgroups org.kernel.vger.dwarves,org.kernel.vger.bpf
Message-ID <ef3fe9d80d24f7498410bffe938da1882448e5b6012fcc3ca97fff5645018ba8@mail.kernel.org>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 1eaa7527d4dab..e32b42ef9be84 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c

[ ... ]

> +	/* btf_header() gives us endian-safe header info */
> +	hdr = btf_header(orig_btf);
> +
> +	if (!has_layout && hdr->hdr_len >= sizeof(struct btf_header) &&
> +	    (hdr->layout_len != 0 || hdr->layout_off != 0)) {
> +		const struct btf_header *old_hdr = raw_data;
> +		struct btf_header *new_hdr;
> +		void *new_raw_data;
> +		__u32 new_str_off;
> +
> +		/*
> +		 * Need to rewrite BTF to exclude layout information and
> +		 * move string section to immediately after types.
> +		 */
> +		new_raw_data = malloc(sz);
> +		if (!new_raw_data)
> +			return ERR_PTR(-ENOMEM);
> +
> +		memcpy(new_raw_data, raw_data, sz);
> +		new_hdr = new_raw_data;
> +		new_hdr->layout_off = 0;
> +		new_hdr->layout_len = 0;
> +		new_str_off = hdr->type_off + hdr->type_len;
> +		/* Handle swapped endian case */
> +		if (old_hdr->str_off != hdr->str_off)
> +			new_hdr->str_off = bswap_32(new_str_off);
> +		else
> +			new_hdr->str_off = new_str_off;
> +
> +		memmove(new_raw_data + hdr->hdr_len + new_hdr->str_off,
> +			new_raw_data + hdr->hdr_len + hdr->str_off,
> +			hdr->str_len);

In the swapped-endian case, new_hdr->str_off holds the byte-swapped
(file-endian) value after the bswap_32() above.  When that value is
used here as a host memory offset for the memmove destination, it
produces a nonsensical address.

For example, if new_str_off is 24 (0x00000018), then bswap_32 gives
0x18000000, which is ~400 MB past the buffer.  This would overflow
the malloc'd new_raw_data buffer.

Should the memmove destination use new_str_off (the host-endian
offset) instead of new_hdr->str_off?  Something like:

    memmove(new_raw_data + hdr->hdr_len + new_str_off,
            new_raw_data + hdr->hdr_len + hdr->str_off,
            hdr->str_len);

> +		sz = hdr->hdr_len + hdr->type_off + hdr->type_len + hdr->str_len;
> +		btf = btf__new(new_raw_data, sz);
> +		free(new_raw_data);

[ ... ]


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