perf trace: Switch user option to use BPF filter

Finding user processes by scanning /proc is inherently racy and
results in perf_event_open failures. Use a BPF filter to drop samples
where the uid doesn't match. Ensure adding the BPF filter forces
system-wide.

Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250604174545.2853620-8-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Ian Rogers 2025-06-04 10:45:41 -07:00 committed by Namhyung Kim
parent 38f83cc9ab
commit bf1976dd28

View File

@ -236,6 +236,7 @@ struct trace {
struct ordered_events data;
u64 last;
} oe;
const char *uid_str;
};
static void trace__load_vmlinux_btf(struct trace *trace __maybe_unused)
@ -4412,8 +4413,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
evlist__add(evlist, pgfault_min);
}
/* Enable ignoring missing threads when -u/-p option is defined. */
trace->opts.ignore_missing_thread = trace->opts.target.uid != UINT_MAX || trace->opts.target.pid;
/* Enable ignoring missing threads when -p option is defined. */
trace->opts.ignore_missing_thread = trace->opts.target.pid;
if (trace->sched &&
evlist__add_newtp(evlist, "sched", "sched_stat_runtime", trace__sched_stat_runtime))
@ -5445,8 +5446,7 @@ int cmd_trace(int argc, const char **argv)
"child tasks do not inherit counters"),
OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
"number of mmap data pages", evlist__parse_mmap_pages),
OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
"user to profile"),
OPT_STRING('u', "uid", &trace.uid_str, "user", "user to profile"),
OPT_CALLBACK(0, "duration", &trace, "float",
"show only events with duration > N.M ms",
trace__set_duration),
@ -5804,11 +5804,19 @@ int cmd_trace(int argc, const char **argv)
goto out_close;
}
err = target__parse_uid(&trace.opts.target);
if (err) {
target__strerror(&trace.opts.target, err, bf, sizeof(bf));
fprintf(trace.output, "%s", bf);
goto out_close;
if (trace.uid_str) {
uid_t uid = parse_uid(trace.uid_str);
if (uid == UINT_MAX) {
ui__error("Invalid User: %s", trace.uid_str);
err = -EINVAL;
goto out_close;
}
err = parse_uid_filter(trace.evlist, uid);
if (err)
goto out_close;
trace.opts.target.system_wide = true;
}
if (!argc && target__none(&trace.opts.target))