Skip to contentSkip to conversation

tracing/probes: Fix BTF structure member finder

PATCH In review Masami Hiramatsu (Google) 3 participants 10 messages Sep 1

Subsystems (2)
lore
Share & tools
lore

Masami Hiramatsu (Google)

author maintainer
#0 lore raw

v3 cover tracing/probes: Fix BTF structure member finder

Hi,

This is the 3rd version of fixes for the BTF structure member finder in trace_btf.c. Sashiko found 2 problems in it during reviewing the wprobe series.[1][2]
[1] https://lore.kernel.org/all/[email protected]/
[2] https://lore.kernel.org/all/[email protected]/

Here is the previous thread:
https://lore.kernel.org/all/178822361441.115597.11442662641658772793.stgit@devnote2/

This version decouple the indentation cleanup part from [2/3], and add a new cleanup patch[3/3].

Thanks,

---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935

Masami Hiramatsu (Google) (3):
tracing/probes: Fix anon_stack check for unnamed bitfields in btf_find_struct_member tracing/probes: Fix BTF kflag check for anonymous struct member access tracing/probes: Fix code indent in get_bitoffset_of_field()

 kernel/trace/trace_btf.c   |   31 +++++++++++++++++--------------
 kernel/trace/trace_btf.h   |    3 ++-
 kernel/trace/trace_probe.c |   15 ++++++++-------
 3 files changed, 27 insertions(+), 22 deletions(-)

--
Masami Hiramatsu (Google) <[email protected]>

author maintainer
#1 lore raw

PATCH v3 1/3 tracing/probes: Fix anon_stack check for unnamed bitfields in btf_find_struct_member

From: Masami Hiramatsu (Google) <[email protected]>

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.

Fixes 302db0f5b3d8 ("tracing/probes: Add a function to search a member of a struct/union")

---
Changes in v2:
- added tags.

---
 kernel/trace/trace_btf.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/trace/trace_btf.c +6 -6
index 00172f301f25..d3ba356d5503 100644
@@ -74,24 +74,24 @@ const struct btf_member *btf_find_struct_member(struct btf *btf,
 {
 	struct btf_anon_stack *anon_stack;
 	const struct btf_member *member;
+	const struct btf_type *mtype;
 	u32 tid, cur_offset = 0;
 	const char *name;
 	int i, top = 0;
 
+	if (!btf_type_is_struct(type))
+		return ERR_PTR(-EINVAL);
+
 	anon_stack = kzalloc_objs(*anon_stack, BTF_ANON_STACK_MAX);
 	if (!anon_stack)
 		return ERR_PTR(-ENOMEM);
 
 retry:
-	if (!btf_type_is_struct(type)) {
-		member = ERR_PTR(-EINVAL);
-		goto out;
-	}
-
 	for_each_member(i, type, member) {
 		if (!member->name_off) {
 			/* Anonymous union/struct: push it for later use */
-			if (btf_type_skip_modifiers(btf, member->type, &tid) &&
+			mtype = btf_type_skip_modifiers(btf, member->type, &tid);
+			if (mtype && btf_type_is_struct(mtype) &&
 			    top < BTF_ANON_STACK_MAX) {
 				anon_stack[top].tid = tid;
 				anon_stack[top++].offset =
#2 lore raw

Re: [PATCH v3 1/3] tracing/probes: Fix anon_stack check for unnamed bitfields in btf_find_struct_member

Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 15 lines

From: Masami Hiramatsu (Google) <[email protected]>

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.

Quoted 5 lines
Fixes 302db0f5b3d8 ("tracing/probes: Add a function to search a member of a struct/union")

Sashiko has reviewed this patch and found no issues. It looks great!

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/178827248631.123716.2627172171811720261.stgit@devnote2?part=1
author maintainer
#3 lore raw

PATCH v3 2/3 tracing/probes: Fix BTF kflag check for anonymous struct member access

In reply to Masami Hiramatsu (Google)

From: Masami Hiramatsu (Google) <[email protected]>

btf_find_struct_member() traverses into nested anonymous structures and unions to find a struct member. However, get_bitoffset_of_field() in trace_probe.c checked btf_type_kflag(type) using the outer parent type instead of the actual anonymous structure/union that directly contains the found member.

If the parent structure and anonymous structure have mismatched kflags (e.g., the parent has kflag=0 while the anonymous structure has kflag=1 because it contains bitfields), the bitfield size encoded in the upper 8 bits of member->offset is erroneously treated as part of the byte/bit offset, corrupting the resolved offset and failing to set last_bitsize. Similarly, btf_find_struct_member() pushed anonymous member offsets onto anon_stack without masking BTF_MEMBER_BIT_OFFSET() when kflag is set.

To fix this problem, update btf_find_struct_member() to return actual containing structure/union type via member_type, use appropriate __btf_member_bit_offset() to get bit offset, and use member_type for btf_type_kflag() in get_bitoffset_of_field().

Fixes c440adfbe302 ("tracing/probes: Support BTF based data structure field access")
Assisted-by Antigravity:gemini-3.7-flash

---
Changes in v3:
- Remove indent cleanup part since that is a cleanup and no need
to be backported.
Changes in v2:
- remove unneeded NULL initializer for mtype, it should be set if btf_find_struct_member() succeeds.
- Add reported-by from Sashiko.
This is separated from wprobe patch series v14.
- https://lore.kernel.org/all/178810003326.64882.5820404025124695636.stgit@devnote2/

---
 kernel/trace/trace_btf.c   |   19 +++++++++++--------
 kernel/trace/trace_btf.h   |    3 ++-
 kernel/trace/trace_probe.c |    5 +++--
 3 files changed, 16 insertions(+), 11 deletions(-)
kernel/trace/trace_btf.c +11 -8
index d3ba356d5503..ee7a04886bf6 100644
@@ -61,16 +61,17 @@ struct btf_anon_stack {
 
 /*
  * Find a member of data structure/union by name and return it.
- * Return NULL if not found, or -EINVAL if parameter is invalid.
- * If the member is an member of anonymous union/structure, the offset
- * of that anonymous union/structure is stored into @anon_offset. Caller
- * can calculate the correct offset from the root data structure by
- * adding anon_offset to the member's offset.
+ * Return NULL if not found, or ERR_PTR(-EINVAL) if parameter is invalid.
+ * If the member is a member of an anonymous union/structure, the bit offset
+ * of that anonymous union/structure is stored into @anon_offset.
+ * If @member_type is non-NULL, the actual containing structure/union type
+ * of the found member is stored into @member_type.
  */
 const struct btf_member *btf_find_struct_member(struct btf *btf,
 						const struct btf_type *type,
 						const char *member_name,
-						u32 *anon_offset)
+						u32 *anon_offset,
+						const struct btf_type **member_type)
 {
 	struct btf_anon_stack *anon_stack;
 	const struct btf_member *member;
@@ -94,14 +95,16 @@ const struct btf_member *btf_find_struct_member(struct btf *btf,
 			if (mtype && btf_type_is_struct(mtype) &&
 			    top < BTF_ANON_STACK_MAX) {
 				anon_stack[top].tid = tid;
-				anon_stack[top++].offset =
-					cur_offset + member->offset;
+				anon_stack[top++].offset = cur_offset +
+					__btf_member_bit_offset(type, member);
 			}
 		} else {
 			name = btf_name_by_offset(btf, member->name_off);
 			if (name && !strcmp(member_name, name)) {
 				if (anon_offset)
 					*anon_offset = cur_offset;
+				if (member_type)
+					*member_type = type;
 				goto out;
 			}
 		}
kernel/trace/trace_btf.h +2 -1
index 4bc44bc261e6..4bd26bceae23 100644
@@ -8,4 +8,5 @@ const struct btf_param *btf_get_func_param(const struct btf_type *func_proto,
 const struct btf_member *btf_find_struct_member(struct btf *btf,
 						const struct btf_type *type,
 						const char *member_name,
-						u32 *anon_offset);
+						u32 *anon_offset,
+						const struct btf_type **member_type);
kernel/trace/trace_probe.c +3 -2
index c4163904ba74..144e790077c6 100644
@@ -625,6 +625,7 @@ static int get_bitoffset_of_field(char **pfieldname, const struct btf_type **pty
 {
 	const struct btf_type *type = *ptype;
 	const struct btf_member *field;
+	const struct btf_type *mtype;
 	struct btf *btf = ctx_btf(ctx);
 	char *fieldname = *pfieldname;
 	int bitoffs = 0;
@@ -640,7 +641,7 @@ static int get_bitoffset_of_field(char **pfieldname, const struct btf_type **pty
 
 		anon_offs = 0;
 		field = btf_find_struct_member(btf, type, fieldname,
-						&anon_offs);
+						&anon_offs, &mtype);
 		if (IS_ERR(field)) {
 			trace_probe_log_err(ctx->offset, BAD_BTF_TID);
 			return PTR_ERR(field);
@@ -653,7 +654,7 @@ static int get_bitoffset_of_field(char **pfieldname, const struct btf_type **pty
 		bitoffs += anon_offs;
 
 		/* Accumulate the bit-offsets of the dot-connected fields */
-		if (btf_type_kflag(type)) {
+		if (btf_type_kflag(mtype)) {
 			bitoffs += BTF_MEMBER_BIT_OFFSET(field->offset);
 			ctx->last_bitsize = BTF_MEMBER_BITFIELD_SIZE(field->offset);
 		} else {
#4 lore raw

Re: [PATCH v3 2/3] tracing/probes: Fix BTF kflag check for anonymous struct member access

Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 21 lines

From: Masami Hiramatsu (Google) <[email protected]>

btf_find_struct_member() traverses into nested anonymous structures and unions to find a struct member. However, get_bitoffset_of_field() in trace_probe.c checked btf_type_kflag(type) using the outer parent type instead of the actual anonymous structure/union that directly contains the found member.

If the parent structure and anonymous structure have mismatched kflags (e.g., the parent has kflag=0 while the anonymous structure has kflag=1 because it contains bitfields), the bitfield size encoded in the upper 8 bits of member->offset is erroneously treated as part of the byte/bit offset, corrupting the resolved offset and failing to set last_bitsize. Similarly, btf_find_struct_member() pushed anonymous member offsets onto anon_stack without masking BTF_MEMBER_BIT_OFFSET() when kflag is set.

To fix this problem, update btf_find_struct_member() to return actual containing structure/union type via member_type, use appropriate __btf_member_bit_offset() to get bit offset, and use member_type for btf_type_kflag() in get_bitoffset_of_field().

Quoted 6 lines
Fixes c440adfbe302 ("tracing/probes: Support BTF based data structure field access")
Assisted-by Antigravity:gemini-3.7-flash

Sashiko has reviewed this patch and found no issues. It looks great!

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/178827248631.123716.2627172171811720261.stgit@devnote2?part=2
maintainer Reviewed-by on v3 2/3
#5 lore raw

Re: [PATCH v3 2/3] tracing/probes: Fix BTF kflag check for anonymous struct member access

In reply to Masami Hiramatsu (Google)
Quoted 21 lines · On Tue, 1 Sep 2026 23:21:49 +0900 "Masami Hiramatsu (Google)"…

From: Masami Hiramatsu (Google) <[email protected]>

btf_find_struct_member() traverses into nested anonymous structures and unions to find a struct member. However, get_bitoffset_of_field() in trace_probe.c checked btf_type_kflag(type) using the outer parent type instead of the actual anonymous structure/union that directly contains the found member.

If the parent structure and anonymous structure have mismatched kflags (e.g., the parent has kflag=0 while the anonymous structure has kflag=1 because it contains bitfields), the bitfield size encoded in the upper 8 bits of member->offset is erroneously treated as part of the byte/bit offset, corrupting the resolved offset and failing to set last_bitsize. Similarly, btf_find_struct_member() pushed anonymous member offsets onto anon_stack without masking BTF_MEMBER_BIT_OFFSET() when kflag is set.

To fix this problem, update btf_find_struct_member() to return actual containing structure/union type via member_type, use appropriate __btf_member_bit_offset() to get bit offset, and use member_type for btf_type_kflag() in get_bitoffset_of_field().

Quoted 6 lines
Fixes c440adfbe302 ("tracing/probes: Support BTF based data structure field access")
Assisted-by Antigravity:gemini-3.7-flash

-- Steve

author maintainer
#6 lore raw

Re: [PATCH v3 2/3] tracing/probes: Fix BTF kflag check for anonymous struct member access

Quoted 24 lines · On Tue, 1 Sep 2026 10:37:25 -0400 Steven Rostedt <[email protected]> wrote:
Quoted 21 lines · On Tue, 1 Sep 2026 23:21:49 +0900 "Masami Hiramatsu (Google)"…

From: Masami Hiramatsu (Google) <[email protected]>

btf_find_struct_member() traverses into nested anonymous structures and unions to find a struct member. However, get_bitoffset_of_field() in trace_probe.c checked btf_type_kflag(type) using the outer parent type instead of the actual anonymous structure/union that directly contains the found member.

If the parent structure and anonymous structure have mismatched kflags (e.g., the parent has kflag=0 while the anonymous structure has kflag=1 because it contains bitfields), the bitfield size encoded in the upper 8 bits of member->offset is erroneously treated as part of the byte/bit offset, corrupting the resolved offset and failing to set last_bitsize. Similarly, btf_find_struct_member() pushed anonymous member offsets onto anon_stack without masking BTF_MEMBER_BIT_OFFSET() when kflag is set.

To fix this problem, update btf_find_struct_member() to return actual containing structure/union type via member_type, use appropriate __btf_member_bit_offset() to get bit offset, and use member_type for btf_type_kflag() in get_bitoffset_of_field().

Quoted 8 lines
Quoted 6 lines
Fixes c440adfbe302 ("tracing/probes: Support BTF based data structure field access")
Assisted-by Antigravity:gemini-3.7-flash

Thanks! Let me pick those to probes/fixes.

Quoted 2 lines

-- Steve

Signature · 1 line
Masami Hiramatsu (Google) <[email protected]>
author maintainer
#7 lore raw

PATCH v3 3/3 tracing/probes: Fix code indent in get_bitoffset_of_field()

In reply to Masami Hiramatsu (Google)

From: Masami Hiramatsu (Google) <[email protected]>

Fix code block indentation introduced by commit f21834524025 ("tracing/probes: Support field specifier option for typecast").

---
 kernel/trace/trace_probe.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
kernel/trace/trace_probe.c +5 -5
index 144e790077c6..908b4b6bc2df 100644
@@ -662,11 +662,11 @@ static int get_bitoffset_of_field(char **pfieldname, const struct btf_type **pty
 			ctx->last_bitsize = 0;
 		}
 
-			type = btf_type_skip_modifiers(btf, field->type, NULL);
-			if (!type) {
-				trace_probe_log_err(ctx->offset, BAD_BTF_TID);
-				return -EINVAL;
-			}
+		type = btf_type_skip_modifiers(btf, field->type, NULL);
+		if (!type) {
+			trace_probe_log_err(ctx->offset, BAD_BTF_TID);
+			return -EINVAL;
+		}
 
 		if (next)
 			ctx->offset += next - fieldname;
#8 lore raw

Re: [PATCH v3 3/3] tracing/probes: Fix code indent in get_bitoffset_of_field()

Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 6 lines

From: Masami Hiramatsu (Google) <[email protected]>

Fix code block indentation introduced by commit f21834524025 ("tracing/probes: Support field specifier option for typecast").

Sashiko has reviewed this patch and found no issues. It looks great!

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/178827248631.123716.2627172171811720261.stgit@devnote2?part=3
maintainer Reviewed-by on v3 3/3
#9 lore raw

Re: [PATCH v3 3/3] tracing/probes: Fix code indent in get_bitoffset_of_field()

In reply to Masami Hiramatsu (Google)
Quoted 6 lines · On Tue, 1 Sep 2026 23:22:00 +0900 "Masami Hiramatsu (Google)"…

From: Masami Hiramatsu (Google) <[email protected]>

Fix code block indentation introduced by commit f21834524025 ("tracing/probes: Support field specifier option for typecast").

-- Steve