···251251extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);252252extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);253253extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);254254+static inline bool perfmon_capable(void)255255+{256256+ return capable(CAP_PERFMON) || capable(CAP_SYS_ADMIN);257257+}254258255259/* audit system wants to get cap info from files as well */256260extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
+7-1
include/uapi/linux/capability.h
···367367368368#define CAP_AUDIT_READ 37369369370370+/*371371+ * Allow system performance and observability privileged operations372372+ * using perf_events, i915_perf and other kernel subsystems373373+ */370374371371-#define CAP_LAST_CAP CAP_AUDIT_READ375375+#define CAP_PERFMON 38376376+377377+#define CAP_LAST_CAP CAP_PERFMON372378373379#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)374380
···686686 break;687687 }688688 }689689- if (child_pid != -1)689689+ if (child_pid != -1) {690690+ if (timeout)691691+ kill(child_pid, SIGTERM);690692 wait4(child_pid, &status, 0, &stat_config.ru_data);693693+ }691694692695 if (workload_exec_errno) {693696 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
+20
tools/perf/util/annotate.c
···18211821}18221822#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)1823182318241824+static int18251825+symbol__disassemble_bpf_image(struct symbol *sym,18261826+ struct annotate_args *args)18271827+{18281828+ struct annotation *notes = symbol__annotation(sym);18291829+ struct disasm_line *dl;18301830+18311831+ args->offset = -1;18321832+ args->line = strdup("to be implemented");18331833+ args->line_nr = 0;18341834+ dl = disasm_line__new(args);18351835+ if (dl)18361836+ annotation_line__add(&dl->al, ¬es->src->source);18371837+18381838+ free(args->line);18391839+ return 0;18401840+}18411841+18241842/*18251843 * Possibly create a new version of line with tabs expanded. Returns the18261844 * existing or new line, storage is updated if a new line is allocated. If···1938192019391921 if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {19401922 return symbol__disassemble_bpf(sym, args);19231923+ } else if (dso->binary_type == DSO_BINARY_TYPE__BPF_IMAGE) {19241924+ return symbol__disassemble_bpf_image(sym, args);19411925 } else if (dso__is_kcore(dso)) {19421926 kce.kcore_filename = symfs_filename;19431927 kce.addr = map__rip_2objdump(map, sym->start);
+93
tools/perf/util/bpf-event.c
···66#include <bpf/libbpf.h>77#include <linux/btf.h>88#include <linux/err.h>99+#include <linux/string.h>1010+#include <internal/lib.h>1111+#include <symbol/kallsyms.h>912#include "bpf-event.h"1013#include "debug.h"1114#include "dso.h"···293290 return err ? -1 : 0;294291}295292293293+struct kallsyms_parse {294294+ union perf_event *event;295295+ perf_event__handler_t process;296296+ struct machine *machine;297297+ struct perf_tool *tool;298298+};299299+300300+static int301301+process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data)302302+{303303+ struct machine *machine = data->machine;304304+ union perf_event *event = data->event;305305+ struct perf_record_ksymbol *ksymbol;306306+ int len;307307+308308+ ksymbol = &event->ksymbol;309309+310310+ *ksymbol = (struct perf_record_ksymbol) {311311+ .header = {312312+ .type = PERF_RECORD_KSYMBOL,313313+ .size = offsetof(struct perf_record_ksymbol, name),314314+ },315315+ .addr = addr,316316+ .len = page_size,317317+ .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF,318318+ .flags = 0,319319+ };320320+321321+ len = scnprintf(ksymbol->name, KSYM_NAME_LEN, "%s", name);322322+ ksymbol->header.size += PERF_ALIGN(len + 1, sizeof(u64));323323+ memset((void *) event + event->header.size, 0, machine->id_hdr_size);324324+ event->header.size += machine->id_hdr_size;325325+326326+ return perf_tool__process_synth_event(data->tool, event, machine,327327+ data->process);328328+}329329+330330+static int331331+kallsyms_process_symbol(void *data, const char *_name,332332+ char type __maybe_unused, u64 start)333333+{334334+ char disp[KSYM_NAME_LEN];335335+ char *module, *name;336336+ unsigned long id;337337+ int err = 0;338338+339339+ module = strchr(_name, '\t');340340+ if (!module)341341+ return 0;342342+343343+ /* We are going after [bpf] module ... */344344+ if (strcmp(module + 1, "[bpf]"))345345+ return 0;346346+347347+ name = memdup(_name, (module - _name) + 1);348348+ if (!name)349349+ return -ENOMEM;350350+351351+ name[module - _name] = 0;352352+353353+ /* .. and only for trampolines and dispatchers */354354+ if ((sscanf(name, "bpf_trampoline_%lu", &id) == 1) ||355355+ (sscanf(name, "bpf_dispatcher_%s", disp) == 1))356356+ err = process_bpf_image(name, start, data);357357+358358+ free(name);359359+ return err;360360+}361361+296362int perf_event__synthesize_bpf_events(struct perf_session *session,297363 perf_event__handler_t process,298364 struct machine *machine,299365 struct record_opts *opts)300366{367367+ const char *kallsyms_filename = "/proc/kallsyms";368368+ struct kallsyms_parse arg;301369 union perf_event *event;302370 __u32 id = 0;303371 int err;···377303 event = malloc(sizeof(event->bpf) + KSYM_NAME_LEN + machine->id_hdr_size);378304 if (!event)379305 return -1;306306+307307+ /* Synthesize all the bpf programs in system. */380308 while (true) {381309 err = bpf_prog_get_next_id(id, &id);382310 if (err) {···411335 break;412336 }413337 }338338+339339+ /* Synthesize all the bpf images - trampolines/dispatchers. */340340+ if (symbol_conf.kallsyms_name != NULL)341341+ kallsyms_filename = symbol_conf.kallsyms_name;342342+343343+ arg = (struct kallsyms_parse) {344344+ .event = event,345345+ .process = process,346346+ .machine = machine,347347+ .tool = session->tool,348348+ };349349+350350+ if (kallsyms__parse(kallsyms_filename, &arg, kallsyms_process_symbol)) {351351+ pr_err("%s: failed to synthesize bpf images: %s\n",352352+ __func__, strerror(errno));353353+ }354354+414355 free(event);415356 return err;416357}
+1
tools/perf/util/dso.c
···191191 case DSO_BINARY_TYPE__GUEST_KALLSYMS:192192 case DSO_BINARY_TYPE__JAVA_JIT:193193 case DSO_BINARY_TYPE__BPF_PROG_INFO:194194+ case DSO_BINARY_TYPE__BPF_IMAGE:194195 case DSO_BINARY_TYPE__NOT_FOUND:195196 ret = -1;196197 break;