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

Alan Maguire <[email protected]> Wed, 25 Mar 2026 17:39:34 +0000
Newsgroups org.kernel.vger.dwarves,org.kernel.vger.bpf
Message-ID <[email protected]>
On 24/03/2026 18:55, [email protected] wrote:
>> 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);
>

yep, this is a legit issue and the fix makes sense. sashiko.dev [1] also
pointed out it would be better to use hdr->magic for endian comparison. 
It also suggested doing endian swaps for layout info despite the only 
endian-impacted field being the unused flags, and given that this will avoid 
future issues if/when flags starts being used I think that makes sense too.

I'll wait a few days for additional feedback if any and roll v16..

[1] https://sashiko.dev/#/patchset/20260324174450.1570809-1-alan.maguire%40oracle.com
 
>> +		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