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/
Unified · Split
| @@ -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 | ||
| 85 | retry: | 89 | retry: |
| 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 = |