From 990b5825196d7bafc0b8a595574dfe3ae3bfe105 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Fri, 20 Sep 2024 16:58:54 -0700 Subject: [PATCH 1/2] Move read_perf_event_paranoid() to util so it can be used elsewhere. --- src/ContextSwitchEvent.cc | 13 ------------- src/util.cc | 19 +++++++++++++++++++ src/util.h | 3 +++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/ContextSwitchEvent.cc b/src/ContextSwitchEvent.cc index 4eb45e69a12..94aecab83af 100644 --- a/src/ContextSwitchEvent.cc +++ b/src/ContextSwitchEvent.cc @@ -20,19 +20,6 @@ using namespace std; namespace rr { -static optional read_perf_event_paranoid() { - ScopedFd fd("/proc/sys/kernel/perf_event_paranoid", O_RDONLY); - if (fd.is_open()) { - char buf[100]; - ssize_t size = read(fd, buf, sizeof(buf) - 1); - if (size >= 0) { - buf[size] = 0; - return atoi(buf); - } - } - return nullopt; -} - static volatile int sigio_count; static void sigio_handler(int, siginfo_t*, void*) { diff --git a/src/util.cc b/src/util.cc index ec5294214c4..f55765d9494 100644 --- a/src/util.cc +++ b/src/util.cc @@ -2600,4 +2600,23 @@ void base_name(string& s) { } } +static optional init_read_perf_event_paranoid() { + ScopedFd fd("/proc/sys/kernel/perf_event_paranoid", O_RDONLY); + if (fd.is_open()) { + char buf[100]; + ssize_t size = read(fd, buf, sizeof(buf) - 1); + if (size >= 0) { + buf[size] = 0; + return atoi(buf); + } + } + + return nullopt; +} + +optional read_perf_event_paranoid() { + static optional value = init_read_perf_event_paranoid(); + return value; +} + } // namespace rr diff --git a/src/util.h b/src/util.h index e45c5a8b68a..9a8459dd549 100644 --- a/src/util.h +++ b/src/util.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -666,6 +667,8 @@ void replace_in_buffer(MemoryRange src, const uint8_t* src_data, // Strip any directory part from the filename `s` void base_name(std::string& s); +std::optional read_perf_event_paranoid(); + } // namespace rr #endif /* RR_UTIL_H_ */ From c38a080dfd9ce72ccfefee4a4c1e8ed4fb20e67c Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Fri, 20 Sep 2024 17:43:17 -0700 Subject: [PATCH 2/2] Print a useful message for Debian/Ubuntu/Android systems with perf_event_paranoid == 4. --- src/PerfCounters.cc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/PerfCounters.cc b/src/PerfCounters.cc index d16c2db66bf..6e1558a1abe 100644 --- a/src/PerfCounters.cc +++ b/src/PerfCounters.cc @@ -336,7 +336,26 @@ static ScopedFd start_counter(pid_t tid, int group_fd, } if (fd < 0) { switch (errno) { - case EACCES: + case EACCES: { + // Debian/Ubuntu/Android? are known to carry a patch that creates + // additional perf_event_paranoid levels, and at level 4 no + // perf_event_open() is allowed at all. + // https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/noble/commit/kernel/events/core.c?id=e88769f04a4f050e02980f776942c28431e56faf + // XXXkhuey ideally we could suggest adding CAP_PERFMON to rr here + // but the patch only accepts CAP_SYS_ADMIN. + auto perf_event_paranoid = read_perf_event_paranoid(); + if (perf_event_paranoid.has_value() && *perf_event_paranoid > 3) { + string paranoid_value = std::to_string(*perf_event_paranoid); + CLEAN_FATAL() << + "rr needs /proc/sys/kernel/perf_event_paranoid <= 3, but it is " + << paranoid_value << ".\n" + << "Change it to <= 3.\n" + << "Consider putting 'kernel.perf_event_paranoid = 3' in /etc/sysctl.d/10-rr.conf.\n" + << "See 'man 8 sysctl', 'man 5 sysctl.d' (systemd systems)\n" + << "and 'man 5 sysctl.conf' (non-systemd systems) for more details."; + } + RR_FALLTHROUGH; + } case EPERM: CLEAN_FATAL() << "Permission denied to use 'perf_event_open'; are hardware perf events " "available? See https://github.com/rr-debugger/rr/wiki/Will-rr-work-on-my-system";