All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Aaron Tomlin" <atomlin@atomlin.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH perf-tools-next v5 3/4] perf trace: Enhance BTF type formatting to symbolise kernel function pointers
Date: Sat, 22 Aug 2026 21:51:23 +0000	[thread overview]
Message-ID: <20260822215124.353251F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260822213558.704018-4-atomlin@atomlin.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] Pointers to function pointers (and deeper pointer indirections) will be incorrectly symbolized as kernel functions due to greedy unwrapping in `btf_is_func_ptr()` and missing pointer checks in `trace__btf_scnprintf()`.

Pre-existing issues:
- [Medium] Incorrect error handling in `btf_struct_scnprintf` causes `arg->augmented.args` to be inappropriately advanced on failure, leading to an out-of-bounds read in fallback formatters.
--

--- Patch [3]: [PATCH perf-tools-next v5 3/4] perf trace: Enhance BTF type formatting to symbolise kernel function pointers ---
commit 544922c709767641e98cb8ac1eabf4bff305afea
Author: Aaron Tomlin <atomlin@atomlin.com>

perf trace: Enhance BTF type formatting to symbolise kernel function pointers

When BTF (BPF Type Format) metadata is loaded from vmlinux, 'perf trace'
can inspect the precise C types of tracepoint and system call parameters.
This patch introduces btf_is_func_ptr() to inspect BTF type hierarchies
to determine whether a parameter resolves to a function prototype.

> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 10fbea7ed4dbf..4f8b4f2cf677e 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c

[ ... ]

> @@ -979,21 +980,61 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
>  #define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
>  
>  #ifdef HAVE_LIBBPF_SUPPORT
> -static void syscall_arg_fmt__cache_btf_enum(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type)
> +static bool btf_is_func_ptr(const struct btf *btf, const struct btf_type *type)
>  {
> +	while (type) {
> +		if (btf_is_ptr(type) || btf_is_typedef(type) || btf_is_mod(type))
> +			type = btf__type_by_id(btf, type->type);
> +		else
> +			break;
> +	}
> +	return type && btf_is_func_proto(type);
> +}

[Severity: Medium]
Will this loop eagerly unwrap all pointer modifiers, failing to enforce a
strict single-pointer limit for function pointers?

If perf trace encounters a tracepoint or syscall argument whose type
string contains an asterisk but resolves to a function pointer typedef
(e.g. bpf_callback_t *), wouldn't this greedily unwrap all pointer
indirections, causing pointers to function pointers to be incorrectly
symbolized as kernel functions?

[ ... ]

> @@ -1095,8 +1142,10 @@ static size_t btf_struct_scnprintf(const struct btf_type *type, struct btf *btf,
>  		return 0;
>  
>  	/* pretty print the struct data here */
> -	if (btf_dump__dump_type_data(btf_dump, type_id, arg->augmented.args->value, type->size, &dump_data_opts) == 0)
> +	if (btf_dump__dump_type_data(btf_dump, type_id, augmented_arg->value, type->size, &dump_data_opts) == 0) {
> +		btf_dump__free(btf_dump);
>  		return 0;
> +	}
>  
>  	consumed = sizeof(*augmented_arg) + augmented_arg->size;
>  	arg->augmented.args = ((void *)arg->augmented.args) + consumed;

[Severity: Medium]
This is a pre-existing issue, but does this error handling correctly check
for negative error codes from btf_dump__dump_type_data()?

If btf_dump__dump_type_data() returns a negative error code (e.g., -EINVAL),
the equality check against 0 evaluates to false. The function incorrectly
proceeds to advance the arg->augmented.args pointer by the consumed struct
size and returns 0.

Then, in syscall__scnprintf_args():

tools/perf/builtin-trace.c:syscall__scnprintf_args() {
    ...
			if (trace->force_btf || default_scnprintf == NULL ||
			    default_scnprintf == SCA_PTR || default_scnprintf == SCA_KSYM) {
				btf_printed = trace__btf_scnprintf(trace, &arg, bf + printed,
								   size - printed, val, field->type);
				if (btf_printed) {
					printed += btf_printed;
					continue;
				}
			}

			printed += syscall_arg_fmt__scnprintf_val(&sc->arg_fmt[arg.idx],
								  bf + printed, size - printed, &arg, val);
    ...
}

Because btf_printed is 0, it falls back to the default formatter
(syscall_arg_fmt__scnprintf_val). Does this fallback formatter then read from
the erroneously advanced arg->augmented.args pointer (now pointing to the
next argument or past the buffer end), leading to an out-of-bounds memory
access?

[ ... ]

> @@ -1108,33 +1157,37 @@ static size_t btf_struct_scnprintf(const struct btf_type *type, struct btf *btf,
>  }
>  
>  static size_t trace__btf_scnprintf(struct trace *trace, struct syscall_arg *arg, char *bf,
> -				   size_t size, int val, char *type)
> +				   size_t size, unsigned long val, char *type)
>  {
>  	struct syscall_arg_fmt *arg_fmt = arg->fmt;
>  
>  	if (trace->btf == NULL)
>  		return 0;
>  
> -	if (arg_fmt->type == NULL) {
> -		// Check if this is an enum and if we have the BTF type for it.
> -		syscall_arg_fmt__cache_btf_enum(arg_fmt, trace->btf, type);
> -	}
> +	if (!arg_fmt->btf_type_cached)
> +		syscall_arg_fmt__cache_btf_type(arg_fmt, trace->btf, type);
>  
>  	// Did we manage to find a BTF type for the syscall/tracepoint argument?
>  	if (arg_fmt->type == NULL)
>  		return 0;
>  
> -	if (btf_is_enum(arg_fmt->type))
> +	if (btf_is_enum(arg_fmt->type)) {
> +		if (type && strchr(type, '*'))
> +			return 0;
>  		return btf_enum_scnprintf(arg_fmt->type, trace->btf, bf, size, val);
> -	else if (btf_is_struct(arg_fmt->type) || btf_is_union(arg_fmt->type))
> +	} else if (btf_is_struct(arg_fmt->type) || btf_is_union(arg_fmt->type))
>  		return btf_struct_scnprintf(arg_fmt->type, trace->btf, bf, size, arg);
> +	else if (btf_is_func_ptr(trace->btf, arg_fmt->type)) {
> +		arg->val = val;
> +		return syscall_arg__scnprintf_ksym(bf, size, arg);
> +	}
>  
>  	return 0;
>  }

[Severity: Medium]
Does this branch lack a safeguard for function pointers similar to the enum
check above?

Unlike the strchr(type, '*') check for enums, there is no verification that
the original C type string lacks an extra pointer asterisk. Since
btf_is_func_ptr() greedily unwraps pointer indirections, could a pointer to a
function pointer be mistakenly routed to syscall_arg__scnprintf_ksym(),
resulting in mis-symbolization of the memory address instead of the kernel
symbol?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260822213558.704018-1-atomlin@atomlin.com?part=3

  reply	other threads:[~2026-08-22 21:51 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-22 21:35 [PATCH perf-tools-next v5 0/4] perf trace: Symbolise kernel virtual addresses and function pointers Aaron Tomlin
2026-08-22 21:35 ` [PATCH perf-tools-next v5 1/4] perf trace: Introduce kernel symbol beautifier for virtual addresses Aaron Tomlin
2026-08-22 21:45   ` sashiko-bot
2026-08-22 21:35 ` [PATCH perf-tools-next v5 2/4] perf trace: Auto-assign kernel symbol beautifier to function pointer fields Aaron Tomlin
2026-08-22 21:48   ` sashiko-bot
2026-08-23 22:28     ` Aaron Tomlin
2026-08-22 21:35 ` [PATCH perf-tools-next v5 3/4] perf trace: Enhance BTF type formatting to symbolise kernel function pointers Aaron Tomlin
2026-08-22 21:51   ` sashiko-bot [this message]
2026-08-24 10:02     ` Aaron Tomlin
2026-08-22 21:35 ` [PATCH perf-tools-next v5 4/4] perf tests: Add shell test for kernel symbol beautifier Aaron Tomlin
2026-08-22 21:48   ` sashiko-bot
2026-08-24 11:28     ` Aaron Tomlin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260822215124.353251F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=atomlin@atomlin.com \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.