perf trace: Raw augmented syscalls fix libbpf 1.0+ compatibility

Don't use deprecated and now broken map style. Avoid use of
tools/perf/include/bpf/bpf.h and use the more regular BPF headers.

Committer notes:

Add /usr/include to the include path so that bpf/bpf_helpers.h can be
found, remove sys/socket.h, adding the sockaddr_storage definition, also
remove stdbool.h, both were preventing building the
augmented_raw_syscalls.c file with clang, revisit later.

Testing it:

Asking for syscalls that have string arguments:

  # perf trace -e ~acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c,string --max-events 10
     0.000 thermald/1144 openat(dfd: CWD, filename: "/sys/class/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:2/energy_uj", flags: RDONLY) = 13
     0.158 thermald/1144 openat(dfd: CWD, filename: "/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj", flags: RDONLY) = 13
     0.215 thermald/1144 openat(dfd: CWD, filename: "/sys/class/thermal/thermal_zone3/temp", flags: RDONLY) = 13
    16.448 cgroupify/36478 openat(dfd: 4, filename: ".", flags: RDONLY|CLOEXEC|DIRECTORY|NONBLOCK) = 5
    16.468 cgroupify/36478 newfstatat(dfd: 5, filename: "", statbuf: 0x7fffca5b4130, flag: 4096) = 0
    16.473 systemd-oomd/972 openat(dfd: CWD, filename: "/proc/meminfo", flags: RDONLY|CLOEXEC) = 12
    16.499 systemd-oomd/972 newfstatat(dfd: 12, filename: "", statbuf: 0x7ffd2bc73cc0, flag: 4096) = 0
    16.516 abrt-dump-jour/1370 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 21
    16.538 abrt-dump-jour/1370 newfstatat(dfd: 21, filename: "", statbuf: 0x7ffc651b8980, flag: 4096) = 0
    16.540 abrt-dump-jour/1371 openat(dfd: CWD, filename: "/var/log/journal/d6a97235307247e09f13f326fb607e3c/system.journal", flags: RDONLY|CLOEXEC|NONBLOCK) = 21
  #

Networking syscalls:

  # perf trace -e ~acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c,sendto*,connect* --max-events 10
     0.000 isc-net-0005/1206 connect(fd: 512, uservaddr: { .family: INET, port: 53, addr: 23.211.132.65 }, addrlen: 16) = 0
     0.070 isc-net-0002/1203 connect(fd: 515, uservaddr: { .family: INET6, port: 53, addr: 2600:1401:2::43 }, addrlen: 28) = -1 ENETUNREACH (Network is unreachable)
     0.031 isc-net-0006/1207 connect(fd: 513, uservaddr: { .family: INET6, port: 53, addr: 2600:1401:2::43 }, addrlen: 28) = -1 ENETUNREACH (Network is unreachable)
     0.079 isc-net-0006/1207 sendto(fd: 3, buff: 0x7f73a40611b0, len: 106, flags: NOSIGNAL, addr: { .family: UNSPEC }, addr_len: NULL) = 106
     0.180 isc-net-0006/1207 connect(fd: 519, uservaddr: { .family: INET6, port: 53, addr: 2600:1401:1::43 }, addrlen: 28) = -1 ENETUNREACH (Network is unreachable)
     0.211 isc-net-0006/1207 sendto(fd: 3, buff: 0x7f73a4061230, len: 106, flags: NOSIGNAL, addr: { .family: UNSPEC }, addr_len: NULL) = 106
     0.298 isc-net-0006/1207 connect(fd: 515, uservaddr: { .family: INET, port: 53, addr: 96.7.49.67 }, addrlen: 16) = 0
     0.109 isc-net-0004/1205 connect(fd: 518, uservaddr: { .family: INET6, port: 53, addr: 2600:1401:2::43 }, addrlen: 28) = -1 ENETUNREACH (Network is unreachable)
     0.164 isc-net-0002/1203 sendto(fd: 3, buff: 0x7f73ac064300, len: 107, flags: NOSIGNAL, addr: { .family: UNSPEC }, addr_len: NULL) = 107
     0.247 isc-net-0002/1203 connect(fd: 522, uservaddr: { .family: INET6, port: 53, addr: 2600:1401:1::43 }, addrlen: 28) = -1 ENETUNREACH (Network is unreachable)
  #

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: https://lore.kernel.org/r/20221103045437.163510-2-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Ian Rogers 2022-11-02 21:54:31 -07:00 committed by Arnaldo Carvalho de Melo
parent 92ea0720ba
commit 14e4b9f428
3 changed files with 89 additions and 19 deletions

View File

@ -1239,7 +1239,8 @@ includedir = $(abspath $(prefix)/$(includedir_relative))
mandir = share/man mandir = share/man
infodir = share/info infodir = share/info
perfexecdir = libexec/perf-core perfexecdir = libexec/perf-core
perf_include_dir = lib/perf/include # FIXME: system's libbpf header directory, where we expect to find bpf/bpf_helpers.h, for instance
perf_include_dir = /usr/include
perf_examples_dir = lib/perf/examples perf_examples_dir = lib/perf/examples
sharedir = $(prefix)/share sharedir = $(prefix)/share
template_dir = share/perf-core/templates template_dir = share/perf-core/templates

View File

@ -14,13 +14,21 @@
* code that will combine entry/exit in a strace like way. * code that will combine entry/exit in a strace like way.
*/ */
#include <unistd.h> #include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/socket.h>
#include <pid_filter.h> // FIXME: These should come from system headers
typedef char bool;
typedef int pid_t;
/* bpf-output associated map */ /* bpf-output associated map */
bpf_map(__augmented_syscalls__, PERF_EVENT_ARRAY, int, u32, __NR_CPUS__); struct __augmented_syscalls__ {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__type(key, int);
__type(value, __u32);
__uint(max_entries, __NR_CPUS__);
} __augmented_syscalls__ SEC(".maps");
/* /*
* string_args_len: one per syscall arg, 0 means not a string or don't copy it, * string_args_len: one per syscall arg, 0 means not a string or don't copy it,
@ -29,24 +37,39 @@ bpf_map(__augmented_syscalls__, PERF_EVENT_ARRAY, int, u32, __NR_CPUS__);
*/ */
struct syscall { struct syscall {
bool enabled; bool enabled;
u16 string_args_len[6]; __u16 string_args_len[6];
}; };
bpf_map(syscalls, ARRAY, int, struct syscall, 512); struct syscalls {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, int);
__type(value, struct syscall);
__uint(max_entries, 512);
} syscalls SEC(".maps");
/* /*
* What to augment at entry? * What to augment at entry?
* *
* Pointer arg payloads (filenames, etc) passed from userspace to the kernel * Pointer arg payloads (filenames, etc) passed from userspace to the kernel
*/ */
bpf_map(syscalls_sys_enter, PROG_ARRAY, u32, u32, 512); struct syscalls_sys_enter {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__type(key, __u32);
__type(value, __u32);
__uint(max_entries, 512);
} syscalls_sys_enter SEC(".maps");
/* /*
* What to augment at exit? * What to augment at exit?
* *
* Pointer arg payloads returned from the kernel (struct stat, etc) to userspace. * Pointer arg payloads returned from the kernel (struct stat, etc) to userspace.
*/ */
bpf_map(syscalls_sys_exit, PROG_ARRAY, u32, u32, 512); struct syscalls_sys_exit {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__type(key, __u32);
__type(value, __u32);
__uint(max_entries, 512);
} syscalls_sys_exit SEC(".maps");
struct syscall_enter_args { struct syscall_enter_args {
unsigned long long common_tp_fields; unsigned long long common_tp_fields;
@ -66,7 +89,38 @@ struct augmented_arg {
char value[PATH_MAX]; char value[PATH_MAX];
}; };
pid_filter(pids_filtered); struct pids_filtered {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, pid_t);
__type(value, bool);
__uint(max_entries, 64);
} pids_filtered SEC(".maps");
/*
* Desired design of maximum size and alignment (see RFC2553)
*/
#define SS_MAXSIZE 128 /* Implementation specific max size */
typedef unsigned short sa_family_t;
/*
* FIXME: Should come from system headers
*
* The definition uses anonymous union and struct in order to control the
* default alignment.
*/
struct sockaddr_storage {
union {
struct {
sa_family_t ss_family; /* address family */
/* Following field(s) are implementation specific */
char __data[SS_MAXSIZE - sizeof(unsigned short)];
/* space to achieve desired size, */
/* _SS_MAXSIZE value minus size of ss_family */
};
void *__align; /* implementation specific desired alignment */
};
};
struct augmented_args_payload { struct augmented_args_payload {
struct syscall_enter_args args; struct syscall_enter_args args;
@ -79,7 +133,12 @@ struct augmented_args_payload {
}; };
// We need more tmp space than the BPF stack can give us // We need more tmp space than the BPF stack can give us
bpf_map(augmented_args_tmp, PERCPU_ARRAY, int, struct augmented_args_payload, 1); struct augmented_args_tmp {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, int);
__type(value, struct augmented_args_payload);
__uint(max_entries, 1);
} augmented_args_tmp SEC(".maps");
static inline struct augmented_args_payload *augmented_args_payload(void) static inline struct augmented_args_payload *augmented_args_payload(void)
{ {
@ -90,14 +149,14 @@ static inline struct augmented_args_payload *augmented_args_payload(void)
static inline int augmented__output(void *ctx, struct augmented_args_payload *args, int len) static inline int augmented__output(void *ctx, struct augmented_args_payload *args, int len)
{ {
/* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */
return perf_event_output(ctx, &__augmented_syscalls__, BPF_F_CURRENT_CPU, args, len); return bpf_perf_event_output(ctx, &__augmented_syscalls__, BPF_F_CURRENT_CPU, args, len);
} }
static inline static inline
unsigned int augmented_arg__read_str(struct augmented_arg *augmented_arg, const void *arg, unsigned int arg_len) unsigned int augmented_arg__read_str(struct augmented_arg *augmented_arg, const void *arg, unsigned int arg_len)
{ {
unsigned int augmented_len = sizeof(*augmented_arg); unsigned int augmented_len = sizeof(*augmented_arg);
int string_len = probe_read_str(&augmented_arg->value, arg_len, arg); int string_len = bpf_probe_read_str(&augmented_arg->value, arg_len, arg);
augmented_arg->size = augmented_arg->err = 0; augmented_arg->size = augmented_arg->err = 0;
/* /*
@ -146,7 +205,7 @@ int sys_enter_connect(struct syscall_enter_args *args)
if (socklen > sizeof(augmented_args->saddr)) if (socklen > sizeof(augmented_args->saddr))
socklen = sizeof(augmented_args->saddr); socklen = sizeof(augmented_args->saddr);
probe_read(&augmented_args->saddr, socklen, sockaddr_arg); bpf_probe_read(&augmented_args->saddr, socklen, sockaddr_arg);
return augmented__output(args, augmented_args, len + socklen); return augmented__output(args, augmented_args, len + socklen);
} }
@ -165,7 +224,7 @@ int sys_enter_sendto(struct syscall_enter_args *args)
if (socklen > sizeof(augmented_args->saddr)) if (socklen > sizeof(augmented_args->saddr))
socklen = sizeof(augmented_args->saddr); socklen = sizeof(augmented_args->saddr);
probe_read(&augmented_args->saddr, socklen, sockaddr_arg); bpf_probe_read(&augmented_args->saddr, socklen, sockaddr_arg);
return augmented__output(args, augmented_args, len + socklen); return augmented__output(args, augmented_args, len + socklen);
} }
@ -234,6 +293,16 @@ int sys_enter_renameat(struct syscall_enter_args *args)
return augmented__output(args, augmented_args, len); return augmented__output(args, augmented_args, len);
} }
static pid_t getpid(void)
{
return bpf_get_current_pid_tgid();
}
static bool pid_filter__has(struct pids_filtered *pids, pid_t pid)
{
return bpf_map_lookup_elem(pids, &pid) != NULL;
}
SEC("raw_syscalls:sys_enter") SEC("raw_syscalls:sys_enter")
int sys_enter(struct syscall_enter_args *args) int sys_enter(struct syscall_enter_args *args)
{ {
@ -257,7 +326,7 @@ int sys_enter(struct syscall_enter_args *args)
if (augmented_args == NULL) if (augmented_args == NULL)
return 1; return 1;
probe_read(&augmented_args->args, sizeof(augmented_args->args), args); bpf_probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
/* /*
* Jump to syscall specific augmenter, even if the default one, * Jump to syscall specific augmenter, even if the default one,
@ -278,7 +347,7 @@ int sys_exit(struct syscall_exit_args *args)
if (pid_filter__has(&pids_filtered, getpid())) if (pid_filter__has(&pids_filtered, getpid()))
return 0; return 0;
probe_read(&exit_args, sizeof(exit_args), args); bpf_probe_read(&exit_args, sizeof(exit_args), args);
/* /*
* Jump to syscall specific return augmenter, even if the default one, * Jump to syscall specific return augmenter, even if the default one,
* "!raw_syscalls:unaugmented" that will just return 1 to return the * "!raw_syscalls:unaugmented" that will just return 1 to return the
@ -291,4 +360,4 @@ int sys_exit(struct syscall_exit_args *args)
return 0; return 0;
} }
license(GPL); char _license[] SEC("license") = "GPL";

View File

@ -495,7 +495,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
snprintf(linux_version_code_str, sizeof(linux_version_code_str), snprintf(linux_version_code_str, sizeof(linux_version_code_str),
"0x%x", kernel_version); "0x%x", kernel_version);
if (asprintf(&perf_bpf_include_opts, "-I%s/bpf", perf_include_dir) < 0) if (asprintf(&perf_bpf_include_opts, "-I%s/", perf_include_dir) < 0)
goto errout; goto errout;
force_set_env("NR_CPUS", nr_cpus_avail_str); force_set_env("NR_CPUS", nr_cpus_avail_str);
force_set_env("LINUX_VERSION_CODE", linux_version_code_str); force_set_env("LINUX_VERSION_CODE", linux_version_code_str);