Commit 1151208e authored by Ian Rogers's avatar Ian Rogers Committed by Namhyung Kim
Browse files

perf record: 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: default avatarIan Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250604174545.2853620-5-irogers@google.com


Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent 466db427
Loading
Loading
Loading
Loading
+16 −11
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ struct record {
	bool			timestamp_boundary;
	bool			off_cpu;
	const char		*filter_action;
	const char		*uid_str;
	struct switch_output	switch_output;
	unsigned long long	samples;
	unsigned long		output_max_size;	/* = 0: unlimited */
@@ -3513,8 +3514,7 @@ static struct option __record_options[] = {
		     "or ranges of time to enable events e.g. '-D 10-20,30-40'",
		     record__parse_event_enable_time),
	OPT_BOOLEAN(0, "kcore", &record.opts.kcore, "copy /proc/kcore"),
	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
		   "user to profile"),
	OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),

	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
		     "branch any", "sample any taken branches",
@@ -4256,19 +4256,24 @@ int cmd_record(int argc, const char **argv)
		ui__warning("%s\n", errbuf);
	}

	err = target__parse_uid(&rec->opts.target);
	if (err) {
		int saved_errno = errno;

		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
		ui__error("%s", errbuf);
	if (rec->uid_str) {
		uid_t uid = parse_uid(rec->uid_str);

		err = -saved_errno;
		if (uid == UINT_MAX) {
			ui__error("Invalid User: %s", rec->uid_str);
			err = -EINVAL;
			goto out;
		}
		err = parse_uid_filter(rec->evlist, uid);
		if (err)
			goto out;

		/* User ID filtering implies system wide. */
		rec->opts.target.system_wide = true;
	}

	/* Enable ignoring missing threads when -u/-p option is defined. */
	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
	/* Enable ignoring missing threads when -p option is defined. */
	rec->opts.ignore_missing_thread = rec->opts.target.pid;

	evlist__warn_user_requested_cpus(rec->evlist, rec->opts.target.cpu_list);