summaryrefslogtreecommitdiff
path: root/tools/lib
diff options
context:
space:
mode:
authorDarren Carreras <carrerasdarren@gmail.com>2026-08-13 20:43:18 -0400
committerAndrii Nakryiko <andrii@kernel.org>2026-08-21 12:00:30 -0700
commite40f61a31688898e7cf81e91074a42f805883e4d (patch)
tree294749ab7bbe00fdf2ae5d6e7d9d64ff98d68a94 /tools/lib
parent4954de7dbd1cfafecafcf7e4e801c50c11be49d9 (diff)
libbpf: Avoid overflow in BTF.ext bounds check
A malformed BTF.ext subsection length in an ELF input can wrap the pointer addition used by btf_ext_parse_sec_info() on 32-bit builds. The wrapped pointer passes the bounds check and parsing then reads beyond the copied BTF.ext data. Ensure the header fits in the copied data, then validate the subsection offset and length with subtraction before forming its pointer. Fixes: ae4ab4b4117d ("btf: expose API to work with raw btf_ext data") Closes: https://issues.oss-fuzz.com/issues/477315119 Signed-off-by: Darren Carreras <carrerasdarren@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20260813-b4-libbpf-v6-send-20260813-v6-1-56be61c52758@gmail.com
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/btf.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 8417de92d028..c783359977b4 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -3364,7 +3364,7 @@ static int btf_ext_parse_sec_info(struct btf_ext *btf_ext,
{
const struct btf_ext_info_sec *sinfo;
struct btf_ext_info *ext_info;
- __u32 info_left, record_size;
+ __u32 data_left, info_left, record_size;
size_t sec_cnt = 0;
void *info;
@@ -3377,16 +3377,20 @@ static int btf_ext_parse_sec_info(struct btf_ext *btf_ext,
return -EINVAL;
}
- /* The start of the info sec (including the __u32 record_size). */
- info = btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off;
- info_left = ext_sec->len;
+ if (btf_ext->hdr->hdr_len > btf_ext->data_size)
+ return -EINVAL;
- if (btf_ext->data + btf_ext->data_size < info + ext_sec->len) {
+ data_left = btf_ext->data_size - btf_ext->hdr->hdr_len;
+ if (ext_sec->off > data_left || ext_sec->len > data_left - ext_sec->off) {
pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
ext_sec->desc, ext_sec->off, ext_sec->len);
return -EINVAL;
}
+ /* The start of the info sec (including the __u32 record_size). */
+ info = btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off;
+ info_left = ext_sec->len;
+
/* At least a record size */
if (info_left < sizeof(__u32)) {
pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc);