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
7474 {
7575 struct btf_anon_stack *anon_stack;
7676 const struct btf_member *member;
77+ const struct btf_type *mtype;
7778 u32 tid, cur_offset = 0;
7879 const char *name;
7980 int i, top = 0;
8081
82+ if (!btf_type_is_struct(type))
83+ return ERR_PTR(-EINVAL);
84+
8185 anon_stack = kzalloc_objs(*anon_stack, BTF_ANON_STACK_MAX);
8286 if (!anon_stack)
8387 return ERR_PTR(-ENOMEM);
8488
8589 retry:
86− if (!btf_type_is_struct(type)) {
87− member = ERR_PTR(-EINVAL);
88− goto out;
89− }
90−
9190 for_each_member(i, type, member) {
9291 if (!member->name_off) {
9392 /* 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) &&
9595 top < BTF_ANON_STACK_MAX) {
9696 anon_stack[top].tid = tid;
9797 anon_stack[top++].offset =