summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrii Nakryiko <andrii@kernel.org>2026-09-08 16:29:27 -0700
committerAndrii Nakryiko <andrii@kernel.org>2026-09-08 16:30:00 -0700
commitaf0b84a9215d951d16f26b7ee34353b970cf5d4e (patch)
treec4e82433faf56a93383cccacee547e431dc7756a
parent1b7415bf70be95b9a1e7e87d544867881065613f (diff)
parent208637af0dc2ddad0e0d96dbd02b961a2cb6fd8a (diff)
downloadlinux-next-af0b84a9215d951d16f26b7ee34353b970cf5d4e.tar.gz
linux-next-af0b84a9215d951d16f26b7ee34353b970cf5d4e.zip
Merge branch 'libbpf-fix-array-comparison-in-btf-dedup'
Mingpei says: ==================== libbpf: Fix array comparison in BTF dedup The recursive array comparison in BTF dedup reads both descriptors from the first type. This can merge distinct structures and corrupt CO-RE relocation metadata. Fix the comparison and add three regression cases to the existing BTF dedup tests. Changes in v2: - Move the tests into prog_tests/btf.c using Alan Maguire's two cases. - Add a separate negative case with the same index type to isolate element-type comparison. - Keep patch 1 unchanged. v1: https://lore.kernel.org/bpf/20260907131021.34343-1-caomingpei@gmail.com/ Report: https://lore.kernel.org/bpf/CABzjXVz3iBuump-pXFkefZ5v+2uu4fG61zqRyWD4xmz3PuBycw@mail.gmail.com/ Validation with a focused runner using the existing selftest sources and assertions: - 52 existing BTF cases passed before and after the fix. - Both negative cases failed before the fix and passed afterwards. - The positive case passed before and after the fix. ==================== Link: https://patch.msgid.link/20260908164920.108074-1-caomingpei@gmail.com Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
-rw-r--r--tools/lib/bpf/btf.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/btf.c126
2 files changed, 127 insertions, 1 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index c783359977b4..908bd344229d 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -4831,7 +4831,7 @@ recur:
return false;
a1 = btf_array(t1);
- a2 = btf_array(t1);
+ a2 = btf_array(t2);
if (a1->index_type != a2->index_type &&
!btf_dedup_identical_types(d, a1->index_type, a2->index_type, depth - 1))
diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
index 67b9015cbd98..df6ad38d287d 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf.c
@@ -7063,6 +7063,132 @@ static struct btf_dedup_test dedup_tests[] = {
},
},
{
+ .descr = "dedup: array element comparison",
+ .input = {
+ .raw_types = {
+ /* signed int */
+ BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+ /* unsigned int */
+ BTF_TYPE_INT_ENC(NAME_NTH(2), 0, 0, 32, 4), /* [2] */
+ /* signed int[1] */
+ BTF_TYPE_ARRAY_ENC(1, 1, 1), /* [3] */
+ /* duplicate signed int[1] */
+ BTF_TYPE_ARRAY_ENC(1, 1, 1), /* [4] */
+ /* unsigned int[1] */
+ BTF_TYPE_ARRAY_ENC(2, 2, 1), /* [5] */
+ /* struct s { signed int a[1]; signed int b[1]; } */
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [6] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 3, 32),
+ /* struct s { signed int a[1]; unsigned int b[1]; } */
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [7] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 4, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 5, 32),
+ BTF_END_RAW,
+ },
+ BTF_STR_SEC("\0int\0unsigned int\0s\0a\0b"),
+ },
+ .expect = {
+ .raw_types = {
+ BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+ BTF_TYPE_INT_ENC(NAME_NTH(2), 0, 0, 32, 4), /* [2] */
+ BTF_TYPE_ARRAY_ENC(1, 1, 1), /* [3] */
+ BTF_TYPE_ARRAY_ENC(2, 2, 1), /* [4] */
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [5] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 3, 32),
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [6] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 4, 32),
+ BTF_END_RAW,
+ },
+ BTF_STR_SEC("\0int\0unsigned int\0s\0a\0b"),
+ },
+},
+{
+ .descr = "dedup: array element comparison with same index type",
+ .input = {
+ .raw_types = {
+ BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+ BTF_TYPE_INT_ENC(NAME_NTH(2), 0, 0, 32, 4), /* [2] */
+ BTF_TYPE_ARRAY_ENC(1, 1, 1), /* [3] */
+ BTF_TYPE_ARRAY_ENC(1, 1, 1), /* [4] */
+ BTF_TYPE_ARRAY_ENC(2, 1, 1), /* [5] */
+ /* struct s { int a[1]; int b[1]; } */
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [6] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 3, 32),
+ /* struct s { int a[1]; unsigned int b[1]; } */
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [7] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 4, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 5, 32),
+ BTF_END_RAW,
+ },
+ BTF_STR_SEC("\0int\0unsigned int\0s\0a\0b"),
+ },
+ .expect = {
+ .raw_types = {
+ BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+ BTF_TYPE_INT_ENC(NAME_NTH(2), 0, 0, 32, 4), /* [2] */
+ BTF_TYPE_ARRAY_ENC(1, 1, 1), /* [3] */
+ BTF_TYPE_ARRAY_ENC(2, 1, 1), /* [4] */
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [5] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 3, 32),
+ BTF_STRUCT_ENC(NAME_NTH(3), 2, 8), /* [6] */
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(5), 4, 32),
+ BTF_END_RAW,
+ },
+ BTF_STR_SEC("\0int\0unsigned int\0s\0a\0b"),
+ },
+},
+{
+ .descr = "dedup: identical array element comparison",
+ .input = {
+ .raw_types = {
+ /* int */
+ BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+ /* struct container { struct elem first[1]; struct elem second[1]; } */
+ BTF_STRUCT_ENC(NAME_NTH(2), 2, 8), /* [2] */
+ BTF_MEMBER_ENC(NAME_NTH(3), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 32),
+ /* struct elem[1] */
+ BTF_TYPE_ARRAY_ENC(4, 1, 1), /* [3] */
+ /* struct elem { int x; } */
+ BTF_STRUCT_ENC(NAME_NTH(5), 1, 4), /* [4] */
+ BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+ /* duplicate struct container */
+ BTF_STRUCT_ENC(NAME_NTH(2), 2, 8), /* [5] */
+ BTF_MEMBER_ENC(NAME_NTH(3), 6, 0),
+ BTF_MEMBER_ENC(NAME_NTH(4), 7, 32),
+ /* duplicate struct elem[1] */
+ BTF_TYPE_ARRAY_ENC(8, 1, 1), /* [6] */
+ BTF_TYPE_ARRAY_ENC(9, 1, 1), /* [7] */
+ /* duplicate struct elem */
+ BTF_STRUCT_ENC(NAME_NTH(5), 1, 4), /* [8] */
+ BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+ BTF_STRUCT_ENC(NAME_NTH(5), 1, 4), /* [9] */
+ BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+ BTF_END_RAW,
+ },
+ BTF_STR_SEC("\0int\0container\0first\0second\0elem\0x"),
+ },
+ .expect = {
+ .raw_types = {
+ BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+ BTF_STRUCT_ENC(NAME_NTH(2), 2, 8), /* [2] */
+ BTF_MEMBER_ENC(NAME_NTH(3), 3, 0),
+ BTF_MEMBER_ENC(NAME_NTH(4), 3, 32),
+ BTF_TYPE_ARRAY_ENC(4, 1, 1), /* [3] */
+ BTF_STRUCT_ENC(NAME_NTH(5), 1, 4), /* [4] */
+ BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+ BTF_END_RAW,
+ },
+ BTF_STR_SEC("\0int\0container\0first\0second\0elem\0x"),
+ },
+},
+{
.descr = "dedup: struct example #1",
/*
* struct s {