Linux Perf Users
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v4 2/7] perf bpf-filter: Support BPF sample filters on tracepoint events
Date: Mon, 19 Oct 2026 22:26:29 +0000	[thread overview]
Message-ID: <sashiko-outbox-178318@kernel.org> (raw)
In-Reply-To: <20261019220915.3943592-3-irogers@google.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] perf bpf-filter: double close of tracepoint fd via perf_bpf_filter__prepare()
- [Medium] perf bpf-filter: missing tracepoint BPF terms in is_possible_tp_filter()
--

commit d87f98375f9a6f9592030472ebfbf88f3edd6fdd
Author: Ian Rogers <irogers@google.com>

perf bpf-filter: Support BPF sample filters on tracepoint events

This commit adds a tracepoint BPF program (perf_tp_sample_filter) to
evaluate context-independent filter terms (uid, gid, tid, cpu, time,
cgroup) on PERF_TYPE_TRACEPOINT events, and attaches it once to the
shared trace_event_call in perf_bpf_filter__prepare().

> diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c
> index 72e83ac1d6a4b..4e99af4764f1d 100644
> --- a/tools/perf/util/bpf-filter.c
> +++ b/tools/perf/util/bpf-filter.c
> @@ -123,15 +123,26 @@ static int check_sample_flags(struct evsel *evsel, struct perf_bpf_filter_expr *
>  {
>  	const struct perf_sample_info *info;
>  
> -	if (expr->term >= PBF_TERM_SAMPLE_START && expr->term <= PBF_TERM_SAMPLE_END &&
> -	    (evsel->core.attr.sample_type & (1 << (expr->term - PBF_TERM_SAMPLE_START))))
> -		return 0;
> -
>  	if (expr->term == PBF_TERM_UID || expr->term == PBF_TERM_GID) {
>  		/* Not dependent on the sample_type as computed from a BPF helper. */
>  		return 0;
>  	}
>  
> +	if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
> +		if (expr->term == PBF_TERM_TID || expr->term == PBF_TERM_CPU ||
> +		    expr->term == PBF_TERM_TIME || expr->term == PBF_TERM_CGROUP)
> +			return 0;

[Severity: Medium]
Can standalone tracepoint BPF filters using gid, tid, pid, cpu, time, or
cgroup actually reach perf_bpf_filter__parse() from --filter?

In tools/perf/util/parse-events.c, set_filter() checks
is_possible_tp_filter(str) before deciding whether to route a
PERF_TYPE_TRACEPOINT filter to evsel__append_tp_filter() or
perf_bpf_filter__parse():

tools/perf/util/parse-events.c:is_possible_tp_filter() {
	return strstr(str, "uid") == NULL;
}

tools/perf/util/parse-events.c:set_filter() {
	...
	if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT && is_possible_tp_filter(str)) {
		if (evsel__append_tp_filter(evsel, str) < 0) {
	...
}

Because is_possible_tp_filter() only checks for "uid" in this commit,
passing --filter 'gid == 0' or --filter 'cpu == 0' on a tracepoint event
routes the expression to the ftrace tracepoint predicate filter via
evsel__append_tp_filter(), which fails with -EINVAL in
PERF_EVENT_IOC_SET_FILTER when the tracepoint lacks matching format fields.

Although a later commit in the series ("perf bpf-filter: Add lock_held()
sample filter") adds "gid" and "lock_held" to is_possible_tp_filter(), the
tid, pid, cpu, time, and cgroup terms supported here in check_sample_flags()
and perf_get_common_sample() still remain unrouted to perf_bpf_filter__parse()
unless combined with uid, gid, or lock_held in the same filter string.

Should is_possible_tp_filter() also check for gid, tid, pid, cpu, time, and
cgroup?

> +		if (expr->op != PBF_OP_GROUP_BEGIN) {
> +			pr_err("Error: %s tracepoint event does not support BPF sample term %d\n",
> +			       evsel__name(evsel), expr->term);
> +			return -1;
> +		}
> +	}

[ ... ]

> @@ -501,15 +528,35 @@ int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target)
>  		goto err;
>  	}
>  
> -	prog = skel->progs.perf_sample_filter;
> -	for (x = 0; x < xyarray__max_x(evsel->core.fd); x++) {
> -		for (y = 0; y < xyarray__max_y(evsel->core.fd); y++) {
> -			link = bpf_program__attach_perf_event_opts(prog, FD(evsel, x, y),
> -								   &pe_opts);
> -			if (IS_ERR(link)) {
> -				pr_err("Failed to attach perf sample-filter program\n");
> -				ret = PTR_ERR(link);
> -				goto err;
> +	if (is_tracepoint) {
> +		/*
> +		 * For PERF_TYPE_TRACEPOINT, PERF_EVENT_IOC_SET_BPF attaches the
> +		 * BPF program to event->tp_event->prog_array on the shared
> +		 * trace_event_call, which perf_trace_run_bpf_submit() executes
> +		 * for all CPUs and tasks before iterating the per-CPU perf
> +		 * events. Attach once on the first FD so tp_event->prog_array
> +		 * does not get duplicate copies for each per-CPU FD.
> +		 */
> +		prog = skel->progs.perf_tp_sample_filter;
> +		link = bpf_program__attach_perf_event_opts(prog, FD(evsel, 0, 0),
> +							   &pe_opts);
> +		ret = libbpf_get_error(link);
> +		if (ret) {
> +			pr_err("Failed to attach perf tracepoint sample-filter program\n");
> +			goto err;
> +		}
> +		skel->links.perf_tp_sample_filter = link;

[Severity: Medium]
Does storing link in skel->links.perf_tp_sample_filter cause FD(evsel, 0, 0)
to be closed twice during teardown?

In tools/lib/bpf/libbpf.c, bpf_program__attach_perf_event_opts() takes
ownership of the passed perf_event_fd without duplicating it, and its
detach callback closes that descriptor when the bpf_link is destroyed:

tools/lib/bpf/libbpf.c:bpf_link_perf_detach() {
	struct bpf_link_perf *perf_link = container_of(link, struct bpf_link_perf, link);
	int err = 0;

	if (ioctl(perf_link->perf_event_fd, PERF_EVENT_IOC_DISABLE, 0) < 0)
		err = -errno;

	if (perf_link->perf_event_fd != link->fd)
		close(perf_link->perf_event_fd);
	close(link->fd);
	...
}

During teardown (for example in evlist__put()), evlist__close() closes all
descriptors in evsel->core.fd, including FD(evsel, 0, 0), before
evlist__purge() destroys the evsels:

evlist__put()
  -> evlist__close()
       -> perf_evsel__close_cpu()
            -> perf_evsel__close_fd_cpu()  /* closes FD(evsel, 0, 0) */
  -> evlist__purge()
       -> evsel__put()
            -> evsel__exit()
                 -> perf_bpf_filter__destroy()
                      -> sample_filter_bpf__destroy()
                           -> bpf_link__destroy(skel->links.perf_tp_sample_filter)
                                -> bpf_link_perf_detach()  /* ioctls and closes FD(evsel, 0, 0) again */

In the non-tracepoint branch below, the returned link is not stored in
skel->links, or if skel->links.perf_tp_sample_filter is kept, should
FD(evsel, 0, 0) be duplicated before passing it to
bpf_program__attach_perf_event_opts()?

[ ... ]

>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019220915.3943592-1-irogers@google.com?part=2

  reply	other threads:[~2026-10-19 22:26 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-17  5:45 [PATCH v1 0/5] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-17  5:45 ` [PATCH v1 1/5] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-17  5:52   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 2/5] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-17  6:09   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 3/5] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-17  5:49   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 4/5] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-17  5:56   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 5/5] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-17  6:08   ` sashiko-bot
2026-10-17 17:14 ` [PATCH v2 0/6] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-17 17:14   ` [PATCH v2 1/6] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-17 17:31     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 2/6] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-17 17:35     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 3/6] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-17 17:17     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 4/6] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-17 17:25     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 5/6] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-17 17:30     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 6/6] perf lock contention: Filter events before creating lock_stat Ian Rogers
2026-10-17 17:17     ` sashiko-bot
2026-10-18  5:37   ` [PATCH v3 0/6] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-18  5:37     ` [PATCH v3 1/6] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-18  5:50       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 2/6] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-18  6:12       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 3/6] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-18  5:41       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 4/6] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-18  5:51       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 5/6] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-18  5:48       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 6/6] perf lock contention: Filter events before creating lock_stat Ian Rogers
2026-10-18  5:40       ` sashiko-bot
2026-10-19  7:00     ` [PATCH v3 0/6] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Namhyung Kim
2026-10-19 19:08       ` Ian Rogers
2026-10-19 22:09     ` [PATCH v4 0/7] " Ian Rogers
2026-10-19 22:09       ` [PATCH v4 1/7] perf lock contention: Filter events before creating lock_stat Ian Rogers
2026-10-19 22:14         ` sashiko-bot
2026-10-20  4:34         ` Namhyung Kim
2026-10-19 22:09       ` [PATCH v4 2/7] perf bpf-filter: Support BPF sample filters on tracepoint events Ian Rogers
2026-10-19 22:26         ` sashiko-bot [this message]
2026-10-20  5:41         ` Namhyung Kim
2026-10-20 15:30           ` Ian Rogers
2026-10-19 22:09       ` [PATCH v4 3/7] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-19 22:17         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 4/7] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-19 22:28         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 5/7] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-19 22:12         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 6/7] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-19 22:19         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 7/7] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-19 22:19         ` sashiko-bot

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=sashiko-outbox-178318@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=irogers@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox