History

tracing/probes: Fix anon_stack check for unnamed bitfields in btf_find_struct_member

btf_find_struct_member() traverses into nested anonymous structures and unions by pushing members with !member->name_off onto anon_stack. However, it does not consider the unnamed bitfields (e.g. `int : 5` or `unsigned int : 0`) which also have member->name_off == 0. If such an unnamed bitfield is pushed to anon_stack, the btf_find_struct_member() return an error even if there are other valid entries in anon_stack. To fix this, only push unnamed struct/union members to anon_stack. Also move the btf_type_is_struct() check to the entry of this function because now it is sure only struct/union are pushed to anon_stack. Link: https://lore.kernel.org/all/178827249775.123716.7813217688423513612.stgit@devnote2/

Masami Hiramatsu (Google) committed 2 months ago

Commit f36d94a1 parent 738ef4c1 file · +6 −6Browse files

Unified · Split

kernel/trace/trace_btf.c+6−6
@@ -74,24 +74,24 @@ const struct btf_member *btf_find_struct_member(struct btf *btf, · 73 unmodified lines
74{74{
75 struct btf_anon_stack *anon_stack;75 struct btf_anon_stack *anon_stack;
76 const struct btf_member *member;76 const struct btf_member *member;
77 const struct btf_type *mtype;
77 u32 tid, cur_offset = 0;78 u32 tid, cur_offset = 0;
78 const char *name;79 const char *name;
79 int i, top = 0;80 int i, top = 0;
80 81
82 if (!btf_type_is_struct(type))
83 return ERR_PTR(-EINVAL);
84
81 anon_stack = kzalloc_objs(*anon_stack, BTF_ANON_STACK_MAX);85 anon_stack = kzalloc_objs(*anon_stack, BTF_ANON_STACK_MAX);
82 if (!anon_stack)86 if (!anon_stack)
83 return ERR_PTR(-ENOMEM);87 return ERR_PTR(-ENOMEM);
84 88
85retry:89retry:
86 if (!btf_type_is_struct(type)) {
87 member = ERR_PTR(-EINVAL);
88 goto out;
89 }
90
91 for_each_member(i, type, member) {90 for_each_member(i, type, member) {
92 if (!member->name_off) {91 if (!member->name_off) {
93 /* Anonymous union/struct: push it for later use */92 /* Anonymous union/struct: push it for later use */
94 if (btf_type_skip_modifiers(btf, member->type, &tid) &&93 mtype = btf_type_skip_modifiers(btf, member->type, &tid);
94 if (mtype && btf_type_is_struct(mtype) &&
95 top < BTF_ANON_STACK_MAX) {95 top < BTF_ANON_STACK_MAX) {
96 anon_stack[top].tid = tid;96 anon_stack[top].tid = tid;
97 anon_stack[top++].offset =97 anon_stack[top++].offset =