mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
Merge tag 'perf-for-bpf-2020-05-06' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into bpf-next
CAP_PERFMON for BPF
This commit is contained in:
@@ -251,6 +251,10 @@ extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct
|
|||||||
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
|
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
|
||||||
extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
|
extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
|
||||||
extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
|
extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
|
||||||
|
static inline bool perfmon_capable(void)
|
||||||
|
{
|
||||||
|
return capable(CAP_PERFMON) || capable(CAP_SYS_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
/* audit system wants to get cap info from files as well */
|
/* audit system wants to get cap info from files as well */
|
||||||
extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
|
extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
|
||||||
|
@@ -367,8 +367,14 @@ struct vfs_ns_cap_data {
|
|||||||
|
|
||||||
#define CAP_AUDIT_READ 37
|
#define CAP_AUDIT_READ 37
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow system performance and observability privileged operations
|
||||||
|
* using perf_events, i915_perf and other kernel subsystems
|
||||||
|
*/
|
||||||
|
|
||||||
#define CAP_LAST_CAP CAP_AUDIT_READ
|
#define CAP_PERFMON 38
|
||||||
|
|
||||||
|
#define CAP_LAST_CAP CAP_PERFMON
|
||||||
|
|
||||||
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
|
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
|
||||||
|
|
||||||
|
@@ -27,9 +27,9 @@
|
|||||||
"audit_control", "setfcap"
|
"audit_control", "setfcap"
|
||||||
|
|
||||||
#define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \
|
#define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \
|
||||||
"wake_alarm", "block_suspend", "audit_read"
|
"wake_alarm", "block_suspend", "audit_read", "perfmon"
|
||||||
|
|
||||||
#if CAP_LAST_CAP > CAP_AUDIT_READ
|
#if CAP_LAST_CAP > CAP_PERFMON
|
||||||
#error New capability defined, please update COMMON_CAP2_PERMS.
|
#error New capability defined, please update COMMON_CAP2_PERMS.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -686,8 +686,11 @@ try_again_reset:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (child_pid != -1)
|
if (child_pid != -1) {
|
||||||
|
if (timeout)
|
||||||
|
kill(child_pid, SIGTERM);
|
||||||
wait4(child_pid, &status, 0, &stat_config.ru_data);
|
wait4(child_pid, &status, 0, &stat_config.ru_data);
|
||||||
|
}
|
||||||
|
|
||||||
if (workload_exec_errno) {
|
if (workload_exec_errno) {
|
||||||
const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
|
const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
|
||||||
|
@@ -1821,6 +1821,24 @@ static int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
|
|||||||
}
|
}
|
||||||
#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
|
||||||
|
|
||||||
|
static int
|
||||||
|
symbol__disassemble_bpf_image(struct symbol *sym,
|
||||||
|
struct annotate_args *args)
|
||||||
|
{
|
||||||
|
struct annotation *notes = symbol__annotation(sym);
|
||||||
|
struct disasm_line *dl;
|
||||||
|
|
||||||
|
args->offset = -1;
|
||||||
|
args->line = strdup("to be implemented");
|
||||||
|
args->line_nr = 0;
|
||||||
|
dl = disasm_line__new(args);
|
||||||
|
if (dl)
|
||||||
|
annotation_line__add(&dl->al, ¬es->src->source);
|
||||||
|
|
||||||
|
free(args->line);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Possibly create a new version of line with tabs expanded. Returns the
|
* Possibly create a new version of line with tabs expanded. Returns the
|
||||||
* existing or new line, storage is updated if a new line is allocated. If
|
* existing or new line, storage is updated if a new line is allocated. If
|
||||||
@@ -1920,6 +1938,8 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
|
|||||||
|
|
||||||
if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
|
if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
|
||||||
return symbol__disassemble_bpf(sym, args);
|
return symbol__disassemble_bpf(sym, args);
|
||||||
|
} else if (dso->binary_type == DSO_BINARY_TYPE__BPF_IMAGE) {
|
||||||
|
return symbol__disassemble_bpf_image(sym, args);
|
||||||
} else if (dso__is_kcore(dso)) {
|
} else if (dso__is_kcore(dso)) {
|
||||||
kce.kcore_filename = symfs_filename;
|
kce.kcore_filename = symfs_filename;
|
||||||
kce.addr = map__rip_2objdump(map, sym->start);
|
kce.addr = map__rip_2objdump(map, sym->start);
|
||||||
|
@@ -6,6 +6,9 @@
|
|||||||
#include <bpf/libbpf.h>
|
#include <bpf/libbpf.h>
|
||||||
#include <linux/btf.h>
|
#include <linux/btf.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <internal/lib.h>
|
||||||
|
#include <symbol/kallsyms.h>
|
||||||
#include "bpf-event.h"
|
#include "bpf-event.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "dso.h"
|
#include "dso.h"
|
||||||
@@ -290,11 +293,82 @@ out:
|
|||||||
return err ? -1 : 0;
|
return err ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct kallsyms_parse {
|
||||||
|
union perf_event *event;
|
||||||
|
perf_event__handler_t process;
|
||||||
|
struct machine *machine;
|
||||||
|
struct perf_tool *tool;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data)
|
||||||
|
{
|
||||||
|
struct machine *machine = data->machine;
|
||||||
|
union perf_event *event = data->event;
|
||||||
|
struct perf_record_ksymbol *ksymbol;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
ksymbol = &event->ksymbol;
|
||||||
|
|
||||||
|
*ksymbol = (struct perf_record_ksymbol) {
|
||||||
|
.header = {
|
||||||
|
.type = PERF_RECORD_KSYMBOL,
|
||||||
|
.size = offsetof(struct perf_record_ksymbol, name),
|
||||||
|
},
|
||||||
|
.addr = addr,
|
||||||
|
.len = page_size,
|
||||||
|
.ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF,
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
len = scnprintf(ksymbol->name, KSYM_NAME_LEN, "%s", name);
|
||||||
|
ksymbol->header.size += PERF_ALIGN(len + 1, sizeof(u64));
|
||||||
|
memset((void *) event + event->header.size, 0, machine->id_hdr_size);
|
||||||
|
event->header.size += machine->id_hdr_size;
|
||||||
|
|
||||||
|
return perf_tool__process_synth_event(data->tool, event, machine,
|
||||||
|
data->process);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kallsyms_process_symbol(void *data, const char *_name,
|
||||||
|
char type __maybe_unused, u64 start)
|
||||||
|
{
|
||||||
|
char disp[KSYM_NAME_LEN];
|
||||||
|
char *module, *name;
|
||||||
|
unsigned long id;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
module = strchr(_name, '\t');
|
||||||
|
if (!module)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* We are going after [bpf] module ... */
|
||||||
|
if (strcmp(module + 1, "[bpf]"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
name = memdup(_name, (module - _name) + 1);
|
||||||
|
if (!name)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
name[module - _name] = 0;
|
||||||
|
|
||||||
|
/* .. and only for trampolines and dispatchers */
|
||||||
|
if ((sscanf(name, "bpf_trampoline_%lu", &id) == 1) ||
|
||||||
|
(sscanf(name, "bpf_dispatcher_%s", disp) == 1))
|
||||||
|
err = process_bpf_image(name, start, data);
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
int perf_event__synthesize_bpf_events(struct perf_session *session,
|
int perf_event__synthesize_bpf_events(struct perf_session *session,
|
||||||
perf_event__handler_t process,
|
perf_event__handler_t process,
|
||||||
struct machine *machine,
|
struct machine *machine,
|
||||||
struct record_opts *opts)
|
struct record_opts *opts)
|
||||||
{
|
{
|
||||||
|
const char *kallsyms_filename = "/proc/kallsyms";
|
||||||
|
struct kallsyms_parse arg;
|
||||||
union perf_event *event;
|
union perf_event *event;
|
||||||
__u32 id = 0;
|
__u32 id = 0;
|
||||||
int err;
|
int err;
|
||||||
@@ -303,6 +377,8 @@ int perf_event__synthesize_bpf_events(struct perf_session *session,
|
|||||||
event = malloc(sizeof(event->bpf) + KSYM_NAME_LEN + machine->id_hdr_size);
|
event = malloc(sizeof(event->bpf) + KSYM_NAME_LEN + machine->id_hdr_size);
|
||||||
if (!event)
|
if (!event)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* Synthesize all the bpf programs in system. */
|
||||||
while (true) {
|
while (true) {
|
||||||
err = bpf_prog_get_next_id(id, &id);
|
err = bpf_prog_get_next_id(id, &id);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -335,6 +411,23 @@ int perf_event__synthesize_bpf_events(struct perf_session *session,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Synthesize all the bpf images - trampolines/dispatchers. */
|
||||||
|
if (symbol_conf.kallsyms_name != NULL)
|
||||||
|
kallsyms_filename = symbol_conf.kallsyms_name;
|
||||||
|
|
||||||
|
arg = (struct kallsyms_parse) {
|
||||||
|
.event = event,
|
||||||
|
.process = process,
|
||||||
|
.machine = machine,
|
||||||
|
.tool = session->tool,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (kallsyms__parse(kallsyms_filename, &arg, kallsyms_process_symbol)) {
|
||||||
|
pr_err("%s: failed to synthesize bpf images: %s\n",
|
||||||
|
__func__, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
free(event);
|
free(event);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@@ -191,6 +191,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
|
|||||||
case DSO_BINARY_TYPE__GUEST_KALLSYMS:
|
case DSO_BINARY_TYPE__GUEST_KALLSYMS:
|
||||||
case DSO_BINARY_TYPE__JAVA_JIT:
|
case DSO_BINARY_TYPE__JAVA_JIT:
|
||||||
case DSO_BINARY_TYPE__BPF_PROG_INFO:
|
case DSO_BINARY_TYPE__BPF_PROG_INFO:
|
||||||
|
case DSO_BINARY_TYPE__BPF_IMAGE:
|
||||||
case DSO_BINARY_TYPE__NOT_FOUND:
|
case DSO_BINARY_TYPE__NOT_FOUND:
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
|
@@ -40,6 +40,7 @@ enum dso_binary_type {
|
|||||||
DSO_BINARY_TYPE__GUEST_KCORE,
|
DSO_BINARY_TYPE__GUEST_KCORE,
|
||||||
DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
|
DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
|
||||||
DSO_BINARY_TYPE__BPF_PROG_INFO,
|
DSO_BINARY_TYPE__BPF_PROG_INFO,
|
||||||
|
DSO_BINARY_TYPE__BPF_IMAGE,
|
||||||
DSO_BINARY_TYPE__NOT_FOUND,
|
DSO_BINARY_TYPE__NOT_FOUND,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -736,6 +736,12 @@ int machine__process_switch_event(struct machine *machine __maybe_unused,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_bpf_image(const char *name)
|
||||||
|
{
|
||||||
|
return strncmp(name, "bpf_trampoline_", sizeof("bpf_trampoline_") - 1) ||
|
||||||
|
strncmp(name, "bpf_dispatcher_", sizeof("bpf_dispatcher_") - 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int machine__process_ksymbol_register(struct machine *machine,
|
static int machine__process_ksymbol_register(struct machine *machine,
|
||||||
union perf_event *event,
|
union perf_event *event,
|
||||||
struct perf_sample *sample __maybe_unused)
|
struct perf_sample *sample __maybe_unused)
|
||||||
@@ -759,6 +765,12 @@ static int machine__process_ksymbol_register(struct machine *machine,
|
|||||||
map->start = event->ksymbol.addr;
|
map->start = event->ksymbol.addr;
|
||||||
map->end = map->start + event->ksymbol.len;
|
map->end = map->start + event->ksymbol.len;
|
||||||
maps__insert(&machine->kmaps, map);
|
maps__insert(&machine->kmaps, map);
|
||||||
|
dso__set_loaded(dso);
|
||||||
|
|
||||||
|
if (is_bpf_image(event->ksymbol.name)) {
|
||||||
|
dso->binary_type = DSO_BINARY_TYPE__BPF_IMAGE;
|
||||||
|
dso__set_long_name(dso, "", false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sym = symbol__new(map->map_ip(map, map->start),
|
sym = symbol__new(map->map_ip(map, map->start),
|
||||||
|
@@ -1544,6 +1544,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case DSO_BINARY_TYPE__BPF_PROG_INFO:
|
case DSO_BINARY_TYPE__BPF_PROG_INFO:
|
||||||
|
case DSO_BINARY_TYPE__BPF_IMAGE:
|
||||||
case DSO_BINARY_TYPE__NOT_FOUND:
|
case DSO_BINARY_TYPE__NOT_FOUND:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
Reference in New Issue
Block a user