perf trace: Switch user option to use BPF filter
authorIan Rogers <irogers@google.com>
Wed, 4 Jun 2025 17:45:41 +0000 (10:45 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 9 Jun 2025 18:18:18 +0000 (11:18 -0700)
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>
tools/perf/builtin-trace.c

index 2ab1b8e05ad3174b41d171da35ee5d1fb6a518b6..4bb062b96f5138477c9c73170146ef4a1aa841ef 100644 (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 @@ init_augmented_syscall_tp:
                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))