mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 04:50:53 +07:00
CAP_PERFMON for BPF
-----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAl6zMIUTHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYoTEOEACWUbZlswquZqSAr6pESTjAbjSPZ58s QfmiY218aXvyvwJeINfJduYIjtVjPL9F0qbqmm5Sh4CFflgF9QRUZLxsyuu6K7uY Bsy7hjHWUCO79anxgjie1rqhCxT/orW39E0nlDW72AlrebVwPRc4PmERsV9bl/9z Z7M7aJzza60938K8qN24A63Q4wb3uCfygUYDGkeaN46jmwlHLj8Qwu/L2pVv2/3O 7FHEHYFK0UuvVw6byRpbPoHDbBEGApYszRlEUMRtkk/7zsvdIQJGHQpPMD5PkGY1 kS6x1a7sdnA7++A7Oin7Uq+0y7sgVNeJyPO9o+u9wZgePZL4t87YZlwIL5NlyXIL JHDrz0DAckSYEAYuPnFrXtYW2AQ9TZxVuIHGsJdKW8KOdkHkYUqtXwLuj+0xf8v/ szeJR+l6mOJzDHML7W7KzZdl+AJB/+GE55cLaRPs0bBFyLpUs/vL8BjkoDiDm3/i okGIWQkh8PwpujiS/mHDHqoXuVpVHYAcHD0X+zuLIUVCzKf71Kq7y2fIiHyTR4Wo +x5aeOFWHYOC2DwFdUQ1EiOUCtLbORqq1CDsnIE4KCtsfx1K6IHmqI8X77D8CTEp oSPz0kd8kgBfHwPhCepQ7DnBA1cJTiRbs6/++frU0S5R2HhIOGeLN6hrhrMjNhYD 07jorSqL6hjjog== =+J1X -----END PGP SIGNATURE----- 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:
commit
f87b87a1c9
@ -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 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);
|
||||
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 */
|
||||
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
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
|
@ -27,9 +27,9 @@
|
||||
"audit_control", "setfcap"
|
||||
|
||||
#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.
|
||||
#endif
|
||||
|
||||
|
@ -686,8 +686,11 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (child_pid != -1)
|
||||
if (child_pid != -1) {
|
||||
if (timeout)
|
||||
kill(child_pid, SIGTERM);
|
||||
wait4(child_pid, &status, 0, &stat_config.ru_data);
|
||||
}
|
||||
|
||||
if (workload_exec_errno) {
|
||||
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)
|
||||
|
||||
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
|
||||
* 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) {
|
||||
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)) {
|
||||
kce.kcore_filename = symfs_filename;
|
||||
kce.addr = map__rip_2objdump(map, sym->start);
|
||||
|
@ -6,6 +6,9 @@
|
||||
#include <bpf/libbpf.h>
|
||||
#include <linux/btf.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/string.h>
|
||||
#include <internal/lib.h>
|
||||
#include <symbol/kallsyms.h>
|
||||
#include "bpf-event.h"
|
||||
#include "debug.h"
|
||||
#include "dso.h"
|
||||
@ -290,11 +293,82 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
|
||||
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,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine,
|
||||
struct record_opts *opts)
|
||||
{
|
||||
const char *kallsyms_filename = "/proc/kallsyms";
|
||||
struct kallsyms_parse arg;
|
||||
union perf_event *event;
|
||||
__u32 id = 0;
|
||||
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);
|
||||
if (!event)
|
||||
return -1;
|
||||
|
||||
/* Synthesize all the bpf programs in system. */
|
||||
while (true) {
|
||||
err = bpf_prog_get_next_id(id, &id);
|
||||
if (err) {
|
||||
@ -335,6 +411,23 @@ int perf_event__synthesize_bpf_events(struct perf_session *session,
|
||||
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);
|
||||
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__JAVA_JIT:
|
||||
case DSO_BINARY_TYPE__BPF_PROG_INFO:
|
||||
case DSO_BINARY_TYPE__BPF_IMAGE:
|
||||
case DSO_BINARY_TYPE__NOT_FOUND:
|
||||
ret = -1;
|
||||
break;
|
||||
|
@ -40,6 +40,7 @@ enum dso_binary_type {
|
||||
DSO_BINARY_TYPE__GUEST_KCORE,
|
||||
DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
|
||||
DSO_BINARY_TYPE__BPF_PROG_INFO,
|
||||
DSO_BINARY_TYPE__BPF_IMAGE,
|
||||
DSO_BINARY_TYPE__NOT_FOUND,
|
||||
};
|
||||
|
||||
|
@ -736,6 +736,12 @@ int machine__process_switch_event(struct machine *machine __maybe_unused,
|
||||
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,
|
||||
union perf_event *event,
|
||||
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->end = map->start + event->ksymbol.len;
|
||||
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),
|
||||
|
@ -1544,6 +1544,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
|
||||
return true;
|
||||
|
||||
case DSO_BINARY_TYPE__BPF_PROG_INFO:
|
||||
case DSO_BINARY_TYPE__BPF_IMAGE:
|
||||
case DSO_BINARY_TYPE__NOT_FOUND:
|
||||
default:
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user