diff options
| author | Namhyung Kim <namhyung@kernel.org> | 2025-06-04 20:48:35 +0300 |
|---|---|---|
| committer | Namhyung Kim <namhyung@kernel.org> | 2025-06-09 21:18:17 +0300 |
| commit | 189a977e4dc011b05aa1fee044d1a98cf904341b (patch) | |
| tree | c41aece187514f9f123a4d68b02181638952e9f4 | |
| parent | 19272b37aa4f83ca52bdf9c16d5d81bdd1354494 (diff) | |
| download | linux-189a977e4dc011b05aa1fee044d1a98cf904341b.tar.xz | |
perf bpf-filter: Improve error messages
The BPF filter needs libbpf/BPF-skeleton support and root privilege.
Add error messages to help users understand the problem easily.
When it's not build with BPF support (make BUILD_BPF_SKEL=0).
$ sudo perf record -e cycles --filter "pid != 0" true
Error: BPF filter is requested but perf is not built with BPF.
Please make sure to build with libbpf and BPF skeleton.
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
--filter <filter>
event filter
When it supports BPF but runs without root or CAP_BPF. Note that it
also checks pinned BPF filters.
$ perf record -e cycles --filter "pid != 0" -o /dev/null true
Error: BPF filter only works for users with the CAP_BPF capability!
Please run 'perf record --setup-filter pin' as root first.
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
--filter <filter>
event filter
Reviewed-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250604174835.1852481-1-namhyung@kernel.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
| -rw-r--r-- | tools/perf/util/bpf-filter.c | 28 | ||||
| -rw-r--r-- | tools/perf/util/bpf-filter.h | 3 | ||||
| -rw-r--r-- | tools/perf/util/cap.c | 1 | ||||
| -rw-r--r-- | tools/perf/util/cap.h | 5 |
4 files changed, 36 insertions, 1 deletions
diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c index a4fdf6911ec1..92e2f054b45e 100644 --- a/tools/perf/util/bpf-filter.c +++ b/tools/perf/util/bpf-filter.c @@ -52,6 +52,7 @@ #include <internal/xyarray.h> #include <perf/threadmap.h> +#include "util/cap.h" #include "util/debug.h" #include "util/evsel.h" #include "util/target.h" @@ -618,11 +619,38 @@ struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(enum perf_bpf_filter_term return expr; } +static bool check_bpf_filter_capable(void) +{ + bool used_root; + + if (perf_cap__capable(CAP_BPF, &used_root)) + return true; + + if (!used_root) { + /* Check if root already pinned the filter programs and maps */ + int fd = get_pinned_fd("filters"); + + if (fd >= 0) { + close(fd); + return true; + } + } + + pr_err("Error: BPF filter only works for %s!\n" + "\tPlease run 'perf record --setup-filter pin' as root first.\n", + used_root ? "root" : "users with the CAP_BPF capability"); + + return false; +} + int perf_bpf_filter__parse(struct list_head *expr_head, const char *str) { YY_BUFFER_STATE buffer; int ret; + if (!check_bpf_filter_capable()) + return -EPERM; + buffer = perf_bpf_filter__scan_string(str); ret = perf_bpf_filter_parse(expr_head); diff --git a/tools/perf/util/bpf-filter.h b/tools/perf/util/bpf-filter.h index 916ed7770b73..122477f2de44 100644 --- a/tools/perf/util/bpf-filter.h +++ b/tools/perf/util/bpf-filter.h @@ -5,6 +5,7 @@ #include <linux/list.h> #include "bpf_skel/sample-filter.h" +#include "util/debug.h" struct perf_bpf_filter_expr { struct list_head list; @@ -38,6 +39,8 @@ int perf_bpf_filter__unpin(void); static inline int perf_bpf_filter__parse(struct list_head *expr_head __maybe_unused, const char *str __maybe_unused) { + pr_err("Error: BPF filter is requested but perf is not built with BPF.\n" + "\tPlease make sure to build with libbpf and BPF skeleton.\n"); return -EOPNOTSUPP; } static inline int perf_bpf_filter__prepare(struct evsel *evsel __maybe_unused, diff --git a/tools/perf/util/cap.c b/tools/perf/util/cap.c index 69d9a2bcd40b..24a0ea7e6d97 100644 --- a/tools/perf/util/cap.c +++ b/tools/perf/util/cap.c @@ -7,7 +7,6 @@ #include "debug.h" #include <errno.h> #include <string.h> -#include <linux/capability.h> #include <sys/syscall.h> #include <unistd.h> diff --git a/tools/perf/util/cap.h b/tools/perf/util/cap.h index 0c6a1ff55f07..c1b8ac033ccc 100644 --- a/tools/perf/util/cap.h +++ b/tools/perf/util/cap.h @@ -3,6 +3,7 @@ #define __PERF_CAP_H #include <stdbool.h> +#include <linux/capability.h> /* For older systems */ #ifndef CAP_SYSLOG @@ -13,6 +14,10 @@ #define CAP_PERFMON 38 #endif +#ifndef CAP_BPF +#define CAP_BPF 39 +#endif + /* Query if a capability is supported, used_root is set if the fallback root check was used. */ bool perf_cap__capable(int cap, bool *used_root); |
