Skip to content

Commit 189a977

Browse files
committed
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>
1 parent 19272b3 commit 189a977

File tree

4 files changed

+36
-1
lines changed

4 files changed

+36
-1
lines changed

tools/perf/util/bpf-filter.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include <internal/xyarray.h>
5353
#include <perf/threadmap.h>
5454

55+
#include "util/cap.h"
5556
#include "util/debug.h"
5657
#include "util/evsel.h"
5758
#include "util/target.h"
@@ -618,11 +619,38 @@ struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(enum perf_bpf_filter_term
618619
return expr;
619620
}
620621

622+
static bool check_bpf_filter_capable(void)
623+
{
624+
bool used_root;
625+
626+
if (perf_cap__capable(CAP_BPF, &used_root))
627+
return true;
628+
629+
if (!used_root) {
630+
/* Check if root already pinned the filter programs and maps */
631+
int fd = get_pinned_fd("filters");
632+
633+
if (fd >= 0) {
634+
close(fd);
635+
return true;
636+
}
637+
}
638+
639+
pr_err("Error: BPF filter only works for %s!\n"
640+
"\tPlease run 'perf record --setup-filter pin' as root first.\n",
641+
used_root ? "root" : "users with the CAP_BPF capability");
642+
643+
return false;
644+
}
645+
621646
int perf_bpf_filter__parse(struct list_head *expr_head, const char *str)
622647
{
623648
YY_BUFFER_STATE buffer;
624649
int ret;
625650

651+
if (!check_bpf_filter_capable())
652+
return -EPERM;
653+
626654
buffer = perf_bpf_filter__scan_string(str);
627655

628656
ret = perf_bpf_filter_parse(expr_head);

tools/perf/util/bpf-filter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/list.h>
66

77
#include "bpf_skel/sample-filter.h"
8+
#include "util/debug.h"
89

910
struct perf_bpf_filter_expr {
1011
struct list_head list;
@@ -38,6 +39,8 @@ int perf_bpf_filter__unpin(void);
3839
static inline int perf_bpf_filter__parse(struct list_head *expr_head __maybe_unused,
3940
const char *str __maybe_unused)
4041
{
42+
pr_err("Error: BPF filter is requested but perf is not built with BPF.\n"
43+
"\tPlease make sure to build with libbpf and BPF skeleton.\n");
4144
return -EOPNOTSUPP;
4245
}
4346
static inline int perf_bpf_filter__prepare(struct evsel *evsel __maybe_unused,

tools/perf/util/cap.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include "debug.h"
88
#include <errno.h>
99
#include <string.h>
10-
#include <linux/capability.h>
1110
#include <sys/syscall.h>
1211
#include <unistd.h>
1312

tools/perf/util/cap.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define __PERF_CAP_H
44

55
#include <stdbool.h>
6+
#include <linux/capability.h>
67

78
/* For older systems */
89
#ifndef CAP_SYSLOG
@@ -13,6 +14,10 @@
1314
#define CAP_PERFMON 38
1415
#endif
1516

17+
#ifndef CAP_BPF
18+
#define CAP_BPF 39
19+
#endif
20+
1621
/* Query if a capability is supported, used_root is set if the fallback root check was used. */
1722
bool perf_cap__capable(int cap, bool *used_root);
1823

0 commit comments

Comments
 (0)