aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf/btf.c
diff options
context:
space:
mode:
authorAndrii Nakryiko <andriin@fb.com>2019-02-28 18:31:24 -0500
committerDaniel Borkmann <daniel@iogearbox.net>2019-02-28 19:31:48 -0500
commit91097fbee4c025ac72f91ae41feba3a822cc1316 (patch)
tree3e1fb0359be566403120bd51df1e921c3b217d83 /tools/lib/bpf/btf.c
parent51edf5f6e015c48b62e24ab2fbcad8885ca1c74e (diff)
btf: fix bug with resolving STRUCT/UNION into corresponding FWD
When checking available canonical candidates for struct/union algorithm utilizes btf_dedup_is_equiv to determine if candidate is suitable. This check is not enough when candidate is corresponding FWD for that struct/union, because according to equivalence logic they are equivalent. When it so happens that FWD and STRUCT/UNION end in hashing to the same bucket, it's possible to create remapping loop from FWD to STRUCT and STRUCT to same FWD, which will cause btf_dedup() to loop forever. This patch fixes the issue by additionally checking that type and canonical candidate are strictly equal (utilizing btf_equal_struct). Fixes: d5caef5b5655 ("btf: add BTF types deduplication algorithm") Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Andrii Nakryiko <andriin@fb.com> Acked-by: Song Liu <songliubraving@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/lib/bpf/btf.c')
-rw-r--r--tools/lib/bpf/btf.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 820f7fc8ebcc..1b8d8cdd3575 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -1663,7 +1663,7 @@ static __u32 btf_hash_struct(struct btf_type *t)
1663 * IDs. This check is performed during type graph equivalence check and 1663 * IDs. This check is performed during type graph equivalence check and
1664 * referenced types equivalence is checked separately. 1664 * referenced types equivalence is checked separately.
1665 */ 1665 */
1666static bool btf_equal_struct(struct btf_type *t1, struct btf_type *t2) 1666static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2)
1667{ 1667{
1668 struct btf_member *m1, *m2; 1668 struct btf_member *m1, *m2;
1669 __u16 vlen; 1669 __u16 vlen;
@@ -2124,7 +2124,7 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
2124 struct btf_member *cand_m, *canon_m; 2124 struct btf_member *cand_m, *canon_m;
2125 __u16 vlen; 2125 __u16 vlen;
2126 2126
2127 if (!btf_equal_struct(cand_type, canon_type)) 2127 if (!btf_shallow_equal_struct(cand_type, canon_type))
2128 return 0; 2128 return 0;
2129 vlen = BTF_INFO_VLEN(cand_type->info); 2129 vlen = BTF_INFO_VLEN(cand_type->info);
2130 cand_m = (struct btf_member *)(cand_type + 1); 2130 cand_m = (struct btf_member *)(cand_type + 1);
@@ -2265,7 +2265,7 @@ static void btf_dedup_merge_hypot_map(struct btf_dedup *d)
2265static int btf_dedup_struct_type(struct btf_dedup *d, __u32 type_id) 2265static int btf_dedup_struct_type(struct btf_dedup *d, __u32 type_id)
2266{ 2266{
2267 struct btf_dedup_node *cand_node; 2267 struct btf_dedup_node *cand_node;
2268 struct btf_type *t; 2268 struct btf_type *cand_type, *t;
2269 /* if we don't find equivalent type, then we are canonical */ 2269 /* if we don't find equivalent type, then we are canonical */
2270 __u32 new_id = type_id; 2270 __u32 new_id = type_id;
2271 __u16 kind; 2271 __u16 kind;
@@ -2285,6 +2285,20 @@ static int btf_dedup_struct_type(struct btf_dedup *d, __u32 type_id)
2285 for_each_dedup_cand(d, h, cand_node) { 2285 for_each_dedup_cand(d, h, cand_node) {
2286 int eq; 2286 int eq;
2287 2287
2288 /*
2289 * Even though btf_dedup_is_equiv() checks for
2290 * btf_shallow_equal_struct() internally when checking two
2291 * structs (unions) for equivalence, we need to guard here
2292 * from picking matching FWD type as a dedup candidate.
2293 * This can happen due to hash collision. In such case just
2294 * relying on btf_dedup_is_equiv() would lead to potentially
2295 * creating a loop (FWD -> STRUCT and STRUCT -> FWD), because
2296 * FWD and compatible STRUCT/UNION are considered equivalent.
2297 */
2298 cand_type = d->btf->types[cand_node->type_id];
2299 if (!btf_shallow_equal_struct(t, cand_type))
2300 continue;
2301
2288 btf_dedup_clear_hypot_map(d); 2302 btf_dedup_clear_hypot_map(d);
2289 eq = btf_dedup_is_equiv(d, type_id, cand_node->type_id); 2303 eq = btf_dedup_is_equiv(d, type_id, cand_node->type_id);
2290 if (eq < 0) 2304 if (eq < 0)