perf target: Remove uid from target

Gathering threads with a uid by scanning /proc is inherently racy
leading to perf_event_open failures that quit perf. All users of the
functionality now use BPF filters, so remove uid and uid_str from
target.

Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250604174545.2853620-10-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Ian Rogers 2025-06-04 10:45:43 -07:00 committed by Namhyung Kim
parent 278538ddf1
commit b4c658d4d6
13 changed files with 6 additions and 73 deletions

View file

@ -1663,7 +1663,6 @@ int cmd_ftrace(int argc, const char **argv)
int (*cmd_func)(struct perf_ftrace *) = NULL; int (*cmd_func)(struct perf_ftrace *) = NULL;
struct perf_ftrace ftrace = { struct perf_ftrace ftrace = {
.tracer = DEFAULT_TRACER, .tracer = DEFAULT_TRACER,
.target = { .uid = UINT_MAX, },
}; };
const struct option common_options[] = { const struct option common_options[] = {
OPT_STRING('p', "pid", &ftrace.target.pid, "pid", OPT_STRING('p', "pid", &ftrace.target.pid, "pid",

View file

@ -1871,8 +1871,6 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
kvm->opts.user_interval = 1; kvm->opts.user_interval = 1;
kvm->opts.mmap_pages = 512; kvm->opts.mmap_pages = 512;
kvm->opts.target.uses_mmap = false; kvm->opts.target.uses_mmap = false;
kvm->opts.target.uid_str = NULL;
kvm->opts.target.uid = UINT_MAX;
symbol__init(NULL); symbol__init(NULL);
disable_buildid_cache(); disable_buildid_cache();

View file

@ -108,9 +108,7 @@ static struct parse_events_option_args parse_events_option_args = {
static bool all_counters_use_bpf = true; static bool all_counters_use_bpf = true;
static struct target target = { static struct target target;
.uid = UINT_MAX,
};
static volatile sig_atomic_t child_pid = -1; static volatile sig_atomic_t child_pid = -1;
static int detailed_run = 0; static int detailed_run = 0;

View file

@ -5399,7 +5399,6 @@ int cmd_trace(int argc, const char **argv)
struct trace trace = { struct trace trace = {
.opts = { .opts = {
.target = { .target = {
.uid = UINT_MAX,
.uses_mmap = true, .uses_mmap = true,
}, },
.user_freq = UINT_MAX, .user_freq = UINT_MAX,

View file

@ -91,7 +91,6 @@ static int test__backward_ring_buffer(struct test_suite *test __maybe_unused, in
struct parse_events_error parse_error; struct parse_events_error parse_error;
struct record_opts opts = { struct record_opts opts = {
.target = { .target = {
.uid = UINT_MAX,
.uses_mmap = true, .uses_mmap = true,
}, },
.freq = 0, .freq = 0,

View file

@ -17,9 +17,7 @@
static int attach__enable_on_exec(struct evlist *evlist) static int attach__enable_on_exec(struct evlist *evlist)
{ {
struct evsel *evsel = evlist__last(evlist); struct evsel *evsel = evlist__last(evlist);
struct target target = { struct target target = {};
.uid = UINT_MAX,
};
const char *argv[] = { "true", NULL, }; const char *argv[] = { "true", NULL, };
char sbuf[STRERR_BUFSIZE]; char sbuf[STRERR_BUFSIZE];
int err; int err;

View file

@ -28,7 +28,6 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
{ {
struct record_opts opts = { struct record_opts opts = {
.target = { .target = {
.uid = UINT_MAX,
.uses_mmap = true, .uses_mmap = true,
}, },
.no_buffering = true, .no_buffering = true,

View file

@ -45,7 +45,6 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
{ {
struct record_opts opts = { struct record_opts opts = {
.target = { .target = {
.uid = UINT_MAX,
.uses_mmap = true, .uses_mmap = true,
}, },
.no_buffering = true, .no_buffering = true,

View file

@ -46,7 +46,6 @@ static int test__task_exit(struct test_suite *test __maybe_unused, int subtest _
struct evsel *evsel; struct evsel *evsel;
struct evlist *evlist; struct evlist *evlist;
struct target target = { struct target target = {
.uid = UINT_MAX,
.uses_mmap = true, .uses_mmap = true,
}; };
const char *argv[] = { "true", NULL }; const char *argv[] = { "true", NULL };

View file

@ -450,7 +450,7 @@ int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target)
struct bpf_program *prog; struct bpf_program *prog;
struct bpf_link *link; struct bpf_link *link;
struct perf_bpf_filter_entry *entry; struct perf_bpf_filter_entry *entry;
bool needs_idx_hash = !target__has_cpu(target) && !target->uid_str; bool needs_idx_hash = !target__has_cpu(target);
entry = calloc(MAX_FILTERS, sizeof(*entry)); entry = calloc(MAX_FILTERS, sizeof(*entry));
if (entry == NULL) if (entry == NULL)

View file

@ -1006,8 +1006,7 @@ int evlist__create_maps(struct evlist *evlist, struct target *target)
* per-thread data. thread_map__new_str will call * per-thread data. thread_map__new_str will call
* thread_map__new_all_cpus to enumerate all threads. * thread_map__new_all_cpus to enumerate all threads.
*/ */
threads = thread_map__new_str(target->pid, target->tid, target->uid, threads = thread_map__new_str(target->pid, target->tid, UINT_MAX, all_threads);
all_threads);
if (!threads) if (!threads)
return -1; return -1;

View file

@ -28,20 +28,6 @@ enum target_errno target__validate(struct target *target)
ret = TARGET_ERRNO__PID_OVERRIDE_CPU; ret = TARGET_ERRNO__PID_OVERRIDE_CPU;
} }
/* UID and PID are mutually exclusive */
if (target->tid && target->uid_str) {
target->uid_str = NULL;
if (ret == TARGET_ERRNO__SUCCESS)
ret = TARGET_ERRNO__PID_OVERRIDE_UID;
}
/* UID and CPU are mutually exclusive */
if (target->uid_str && target->cpu_list) {
target->cpu_list = NULL;
if (ret == TARGET_ERRNO__SUCCESS)
ret = TARGET_ERRNO__UID_OVERRIDE_CPU;
}
/* PID and SYSTEM are mutually exclusive */ /* PID and SYSTEM are mutually exclusive */
if (target->tid && target->system_wide) { if (target->tid && target->system_wide) {
target->system_wide = false; target->system_wide = false;
@ -49,13 +35,6 @@ enum target_errno target__validate(struct target *target)
ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM; ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM;
} }
/* UID and SYSTEM are mutually exclusive */
if (target->uid_str && target->system_wide) {
target->system_wide = false;
if (ret == TARGET_ERRNO__SUCCESS)
ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
}
/* BPF and CPU are mutually exclusive */ /* BPF and CPU are mutually exclusive */
if (target->bpf_str && target->cpu_list) { if (target->bpf_str && target->cpu_list) {
target->cpu_list = NULL; target->cpu_list = NULL;
@ -70,13 +49,6 @@ enum target_errno target__validate(struct target *target)
ret = TARGET_ERRNO__BPF_OVERRIDE_PID; ret = TARGET_ERRNO__BPF_OVERRIDE_PID;
} }
/* BPF and UID are mutually exclusive */
if (target->bpf_str && target->uid_str) {
target->uid_str = NULL;
if (ret == TARGET_ERRNO__SUCCESS)
ret = TARGET_ERRNO__BPF_OVERRIDE_UID;
}
/* BPF and THREADS are mutually exclusive */ /* BPF and THREADS are mutually exclusive */
if (target->bpf_str && target->per_thread) { if (target->bpf_str && target->per_thread) {
target->per_thread = false; target->per_thread = false;
@ -124,31 +96,19 @@ uid_t parse_uid(const char *str)
return result->pw_uid; return result->pw_uid;
} }
enum target_errno target__parse_uid(struct target *target)
{
target->uid = parse_uid(target->uid_str);
return target->uid != UINT_MAX ? TARGET_ERRNO__SUCCESS : TARGET_ERRNO__INVALID_UID;
}
/* /*
* This must have a same ordering as the enum target_errno. * This must have a same ordering as the enum target_errno.
*/ */
static const char *target__error_str[] = { static const char *target__error_str[] = {
"PID/TID switch overriding CPU", "PID/TID switch overriding CPU",
"PID/TID switch overriding UID",
"UID switch overriding CPU",
"PID/TID switch overriding SYSTEM", "PID/TID switch overriding SYSTEM",
"UID switch overriding SYSTEM",
"SYSTEM/CPU switch overriding PER-THREAD", "SYSTEM/CPU switch overriding PER-THREAD",
"BPF switch overriding CPU", "BPF switch overriding CPU",
"BPF switch overriding PID/TID", "BPF switch overriding PID/TID",
"BPF switch overriding UID",
"BPF switch overriding THREAD", "BPF switch overriding THREAD",
"Invalid User: %s",
}; };
int target__strerror(struct target *target, int errnum, int target__strerror(struct target *target __maybe_unused, int errnum,
char *buf, size_t buflen) char *buf, size_t buflen)
{ {
int idx; int idx;
@ -173,10 +133,6 @@ int target__strerror(struct target *target, int errnum,
snprintf(buf, buflen, "%s", msg); snprintf(buf, buflen, "%s", msg);
break; break;
case TARGET_ERRNO__INVALID_UID:
snprintf(buf, buflen, msg, target->uid_str);
break;
default: default:
/* cannot reach here */ /* cannot reach here */
break; break;

View file

@ -9,9 +9,7 @@ struct target {
const char *pid; const char *pid;
const char *tid; const char *tid;
const char *cpu_list; const char *cpu_list;
const char *uid_str;
const char *bpf_str; const char *bpf_str;
uid_t uid;
bool system_wide; bool system_wide;
bool uses_mmap; bool uses_mmap;
bool default_per_cpu; bool default_per_cpu;
@ -36,32 +34,24 @@ enum target_errno {
/* for target__validate() */ /* for target__validate() */
TARGET_ERRNO__PID_OVERRIDE_CPU = __TARGET_ERRNO__START, TARGET_ERRNO__PID_OVERRIDE_CPU = __TARGET_ERRNO__START,
TARGET_ERRNO__PID_OVERRIDE_UID,
TARGET_ERRNO__UID_OVERRIDE_CPU,
TARGET_ERRNO__PID_OVERRIDE_SYSTEM, TARGET_ERRNO__PID_OVERRIDE_SYSTEM,
TARGET_ERRNO__UID_OVERRIDE_SYSTEM,
TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD, TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD,
TARGET_ERRNO__BPF_OVERRIDE_CPU, TARGET_ERRNO__BPF_OVERRIDE_CPU,
TARGET_ERRNO__BPF_OVERRIDE_PID, TARGET_ERRNO__BPF_OVERRIDE_PID,
TARGET_ERRNO__BPF_OVERRIDE_UID,
TARGET_ERRNO__BPF_OVERRIDE_THREAD, TARGET_ERRNO__BPF_OVERRIDE_THREAD,
/* for target__parse_uid() */
TARGET_ERRNO__INVALID_UID,
__TARGET_ERRNO__END, __TARGET_ERRNO__END,
}; };
enum target_errno target__validate(struct target *target); enum target_errno target__validate(struct target *target);
uid_t parse_uid(const char *str); uid_t parse_uid(const char *str);
enum target_errno target__parse_uid(struct target *target);
int target__strerror(struct target *target, int errnum, char *buf, size_t buflen); int target__strerror(struct target *target, int errnum, char *buf, size_t buflen);
static inline bool target__has_task(struct target *target) static inline bool target__has_task(struct target *target)
{ {
return target->tid || target->pid || target->uid_str; return target->tid || target->pid;
} }
static inline bool target__has_cpu(struct target *target) static inline bool target__has_cpu(struct target *target)