Linux Kernel Selftest development
 help / color / mirror / Atom feed
From: Mark Amirkan <markdamirkan@gmail.com>
To: bpf@vger.kernel.org
Cc: andrii@kernel.org, eddyz87@gmail.com, ihor.solodrai@linux.dev,
	ast@kernel.org, daniel@iogearbox.net, memxor@gmail.com,
	martin.lau@linux.dev, song@kernel.org, yonghong.song@linux.dev,
	jolsa@kernel.org, emil@etsalapatis.com, shuah@kernel.org,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	Mark Amirkan <markdamirkan@gmail.com>
Subject: [PATCH bpf-next] libbpf: Reject oversized unknown BTF type records
Date: Wed,  2 Sep 2026 02:11:26 -0700	[thread overview]
Message-ID: <20260902091126.59281-1-markdamirkan@gmail.com> (raw)

btf_type_size_unknown() returns an int, but calculates the type record
size using unsigned operands.  With a 24-bit vlen, an unknown kind whose
vlen is 0xffffff and whose info and element sizes are both 252 has a
record size of 0xfc00000c.  Converting this value to int produces
-67108852.

btf_parse_type_sec() returns the negative value, and btf_new() encodes it
with ERR_PTR().  Since the value is outside the error-pointer range,
libbpf_ptr() does not recognize it as an error.  On a 64-bit system, a
129-byte raw BTF input makes btf__new() return 0xfffffffffc00000c while
libbpf_get_error() returns zero and errno remains zero.  Calling
btf__type_cnt() or btf__free() on the result crashes.  The same input
makes bpftool's "btf dump file" command terminate with SIGSEGV.

Calculate the record size as size_t and reject values above INT_MAX
before converting it to int.  Add a regression test for the maximum-vlen
unknown kind.

Fixes: cacd6729c092 ("libbpf: Adjust btf_vlen() to return a __u32")
Assisted-by: Symbolic
Signed-off-by: Mark Amirkan <markdamirkan@gmail.com>
---
Testing:
- normal builds of libbpf and bpftool, plus an ASan/UBSan libbpf build;
- the reproducer through btf__new() and bpftool;
- the added btf_kind test and the existing encoding/decoding subtests;
- identical bpftool output before and after the fix for all 60 BTF blobs
  under /sys/kernel/btf on the test system.

The complete BPF selftest suite was not run locally because clang was not
available.

This fixes code present in Linux v7.2; please consider it for stable.

 tools/lib/bpf/btf.c                           | 11 +++++-
 .../selftests/bpf/prog_tests/btf_kind.c       | 39 +++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index c783359977b46e521965c1af223515cfd8701b12..83a7f199f37dfdc2384107a45a8be5b98c4cd8f1 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -421,6 +421,7 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
 {
 	__u32 l_cnt = btf->hdr.layout_len / sizeof(struct btf_layout);
 	struct btf_layout *l = btf->layout;
+	size_t type_size;
 	__u32 vlen = btf_vlen(t);
 	__u32 kind = btf_kind(t);
 
@@ -448,7 +449,15 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
 		return -EINVAL;
 	}
 
-	return sizeof(struct btf_type) + l[kind].info_sz + vlen * l[kind].elem_sz;
+	type_size = sizeof(struct btf_type) + l[kind].info_sz +
+		    (size_t)vlen * l[kind].elem_sz;
+	if (type_size > INT_MAX) {
+		pr_debug("BTF type size %zu for kind %u is too large\n",
+			 type_size, kind);
+		return -E2BIG;
+	}
+
+	return type_size;
 }
 
 static int btf_type_size(const struct btf *btf, const struct btf_type *t)
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_kind.c b/tools/testing/selftests/bpf/prog_tests/btf_kind.c
index f61afe6a79a51f86f22f62bd86c685b7db8b39d1..fc6a4db9993764536885a5c5f13980a4c3a6bd26 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf_kind.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf_kind.c
@@ -217,10 +217,49 @@ void test_btf_kind_decoding(void)
 	btf__free(btf);
 }
 
+static void test_btf_kind_size_overflow(void)
+{
+	/* Max vlen and aligned u8 layout sizes produce type size 0xfc00000c. */
+	struct {
+		struct btf_header hdr;
+		struct btf_type type;
+		struct btf_layout layouts[NR_BTF_KINDS + 1];
+		char strs[1];
+	} __packed raw_btf = {
+		.hdr = {
+			.magic = BTF_MAGIC,
+			.version = BTF_VERSION,
+			.hdr_len = sizeof(struct btf_header),
+			.type_len = sizeof(struct btf_type),
+			.layout_off = sizeof(struct btf_type),
+			.layout_len = sizeof(struct btf_layout) * (NR_BTF_KINDS + 1),
+			.str_off = sizeof(struct btf_type) +
+				   sizeof(struct btf_layout) * (NR_BTF_KINDS + 1),
+			.str_len = 1,
+		},
+		.type.info = (NR_BTF_KINDS << 24) | BTF_MAX_VLEN,
+		.layouts[NR_BTF_KINDS] = {
+			.info_sz = 252,
+			.elem_sz = 252,
+		},
+	};
+	struct btf *btf;
+	int err;
+
+	errno = 0;
+	btf = btf__new(&raw_btf, sizeof(raw_btf));
+	err = libbpf_get_error(btf);
+	if (!ASSERT_EQ(err, -E2BIG, "size_overflow_err"))
+		return;
+	ASSERT_NULL(btf, "size_overflow_btf");
+}
+
 void test_btf_kind(void)
 {
 	if (test__start_subtest("btf_kind_encoding"))
 		test_btf_kind_encoding();
 	if (test__start_subtest("btf_kind_decoding"))
 		test_btf_kind_decoding();
+	if (test__start_subtest("btf_kind_size_overflow"))
+		test_btf_kind_size_overflow();
 }

base-commit: d761934c9483ecde93fe99d8705282f716dfee50
-- 
2.39.3 (Apple Git-146)

             reply	other threads:[~2026-09-02  9:11 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02  9:11 Mark Amirkan [this message]
2026-09-03  0:40 ` [PATCH bpf-next] libbpf: Reject oversized unknown BTF type records Andrii Nakryiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260902091126.59281-1-markdamirkan@gmail.com \
    --to=markdamirkan@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=shuah@kernel.org \
    --cc=song@kernel.org \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox