* [PATCH bpf v2 0/2] libbpf: Fix array comparison in BTF dedup
@ 2026-09-08 16:49 Mingpei CAO
2026-09-08 16:49 ` [PATCH bpf v2 1/2] " Mingpei CAO
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Mingpei CAO @ 2026-09-08 16:49 UTC (permalink / raw)
To: bpf; +Cc: Mingpei CAO, alexei.starovoitov, andrii, eddyz87, alan.maguire
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.
Mingpei CAO (2):
libbpf: Fix array comparison in BTF dedup
selftests/bpf: Test array element comparison in BTF dedup
tools/lib/bpf/btf.c | 2 +-
tools/testing/selftests/bpf/prog_tests/btf.c | 126 +++++++++++++++++++
2 files changed, 127 insertions(+), 1 deletion(-)
base-commit: df2908090cda368b01ff43709f51890076c56157
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH bpf v2 1/2] libbpf: Fix array comparison in BTF dedup 2026-09-08 16:49 [PATCH bpf v2 0/2] libbpf: Fix array comparison in BTF dedup Mingpei CAO @ 2026-09-08 16:49 ` Mingpei CAO 2026-09-08 17:01 ` sashiko-bot 2026-09-08 16:49 ` [PATCH bpf v2 2/2] selftests/bpf: Test array element " Mingpei CAO 2026-09-08 23:40 ` [PATCH bpf v2 0/2] libbpf: Fix array " patchwork-bot+netdevbpf 2 siblings, 1 reply; 5+ messages in thread From: Mingpei CAO @ 2026-09-08 16:49 UTC (permalink / raw) To: bpf; +Cc: Mingpei CAO, alexei.starovoitov, andrii, eddyz87, alan.maguire btf_dedup_identical_types() reads both array descriptors from t1, skipping comparisons of their referenced types. This can incorrectly merge distinct structs and corrupt CO-RE relocation metadata. Read the second descriptor from t2. Fixes: 62e23f183839 ("libbpf: Improve BTF dedup handling of "identical" BTF types") Closes: https://lore.kernel.org/bpf/CABzjXVz3iBuump-pXFkefZ5v+2uu4fG61zqRyWD4xmz3PuBycw@mail.gmail.com/ Assisted-by: LLM Signed-off-by: Mingpei CAO <caomingpei@gmail.com> --- tools/lib/bpf/btf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 8417de92d028..41cc3140925f 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -4827,7 +4827,7 @@ static bool btf_dedup_identical_types(struct btf_dedup *d, __u32 id1, __u32 id2, 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)) -- 2.43.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH bpf v2 1/2] libbpf: Fix array comparison in BTF dedup 2026-09-08 16:49 ` [PATCH bpf v2 1/2] " Mingpei CAO @ 2026-09-08 17:01 ` sashiko-bot 0 siblings, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-09-08 17:01 UTC (permalink / raw) To: Mingpei CAO; +Cc: bpf Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] btf_dedup_identical_types() can enter an infinite loop when resolving cyclic modifiers due to a missing depth decrement. -- commit 724de86c8298443100e097d1d516c73679a67fcc Author: Mingpei CAO <caomingpei@gmail.com> libbpf: Fix array comparison in BTF dedup btf_dedup_identical_types() reads both array descriptors from t1, skipping comparisons of their referenced types. This can incorrectly merge distinct structs and corrupt CO-RE relocation metadata. Closes: https://lore.kernel.org/bpf/CABzjXVz3iBuump-pXFkefZ5v+2uu4fG61zqRyWD4xmz3PuBycw@mail.gmail.com/ > diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c > index 8417de92d0282..41cc3140925fb 100644 > --- a/tools/lib/bpf/btf.c > +++ b/tools/lib/bpf/btf.c > @@ -4827,7 +4827,7 @@ static bool btf_dedup_identical_types(struct btf_dedup *d, __u32 id1, __u32 id2, > return false; > [Severity: High] This is a pre-existing issue, but looking slightly above this hunk in btf_dedup_identical_types(), can this code enter an infinite loop when resolving cyclic modifiers? case BTF_KIND_TYPE_TAG: if (t1->info != t2->info || t1->name_off != t2->name_off) return false; id1 = t1->type; id2 = t2->type; goto recur; The depth parameter is tracked to prevent infinite recursion on cyclic types. However, this path uses goto recur to iteratively traverse the modifiers without decrementing depth. If a malformed BTF contains a cycle of modifier types (such as a TYPEDEF that references itself), it appears depth would never decrease. Could this lead to an infinite loop and exhaust the CPU during BTF deduplication? > 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)) -- Sashiko AI review · https://sashiko.dev/#/patchset/20260908164920.108074-1-caomingpei@gmail.com?part=1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH bpf v2 2/2] selftests/bpf: Test array element comparison in BTF dedup 2026-09-08 16:49 [PATCH bpf v2 0/2] libbpf: Fix array comparison in BTF dedup Mingpei CAO 2026-09-08 16:49 ` [PATCH bpf v2 1/2] " Mingpei CAO @ 2026-09-08 16:49 ` Mingpei CAO 2026-09-08 23:40 ` [PATCH bpf v2 0/2] libbpf: Fix array " patchwork-bot+netdevbpf 2 siblings, 0 replies; 5+ messages in thread From: Mingpei CAO @ 2026-09-08 16:49 UTC (permalink / raw) To: bpf; +Cc: Mingpei CAO, alexei.starovoitov, andrii, eddyz87, alan.maguire Exercise recursive array comparison with different and identical element definitions using the existing BTF dedup tests. Add a separate case with the same index type to isolate the element-type comparison. Check that distinct containers remain separate and identical types are deduplicated. Both negative cases fail before the fix and pass afterwards; the positive case passes both before and after the fix. Suggested-by: Alan Maguire <alan.maguire@oracle.com> Assisted-by: LLM Signed-off-by: Mingpei CAO <caomingpei@gmail.com> --- tools/testing/selftests/bpf/prog_tests/btf.c | 126 +++++++++++++++++++ 1 file changed, 126 insertions(+) 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 @@ -7062,6 +7062,132 @@ static struct btf_dedup_test dedup_tests[] = { BTF_STR_SEC("\0int\0long int"), }, }, +{ + .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", /* -- 2.43.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH bpf v2 0/2] libbpf: Fix array comparison in BTF dedup 2026-09-08 16:49 [PATCH bpf v2 0/2] libbpf: Fix array comparison in BTF dedup Mingpei CAO 2026-09-08 16:49 ` [PATCH bpf v2 1/2] " Mingpei CAO 2026-09-08 16:49 ` [PATCH bpf v2 2/2] selftests/bpf: Test array element " Mingpei CAO @ 2026-09-08 23:40 ` patchwork-bot+netdevbpf 2 siblings, 0 replies; 5+ messages in thread From: patchwork-bot+netdevbpf @ 2026-09-08 23:40 UTC (permalink / raw) To: Mingpei CAO; +Cc: bpf, alexei.starovoitov, andrii, eddyz87, alan.maguire Hello: This series was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <andrii@kernel.org>: On Tue, 8 Sep 2026 16:49:18 +0000 you wrote: > 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. > > [...] Here is the summary with links: - [bpf,v2,1/2] libbpf: Fix array comparison in BTF dedup https://git.kernel.org/bpf/bpf-next/c/e62c5b97d6c4 - [bpf,v2,2/2] selftests/bpf: Test array element comparison in BTF dedup https://git.kernel.org/bpf/bpf-next/c/208637af0dc2 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-08 23:41 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-08 16:49 [PATCH bpf v2 0/2] libbpf: Fix array comparison in BTF dedup Mingpei CAO 2026-09-08 16:49 ` [PATCH bpf v2 1/2] " Mingpei CAO 2026-09-08 17:01 ` sashiko-bot 2026-09-08 16:49 ` [PATCH bpf v2 2/2] selftests/bpf: Test array element " Mingpei CAO 2026-09-08 23:40 ` [PATCH bpf v2 0/2] libbpf: Fix array " patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox