mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									92ea0720ba
								
							
						
					
					
						commit
						14e4b9f428
					
				
					 3 changed files with 89 additions and 19 deletions
				
			
		| 
						 | 
				
			
			@ -1239,7 +1239,8 @@ includedir = $(abspath $(prefix)/$(includedir_relative))
 | 
			
		|||
mandir = share/man
 | 
			
		||||
infodir = share/info
 | 
			
		||||
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
 | 
			
		||||
sharedir = $(prefix)/share
 | 
			
		||||
template_dir = share/perf-core/templates
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,13 +14,21 @@
 | 
			
		|||
 * 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/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_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,
 | 
			
		||||
| 
						 | 
				
			
			@ -29,24 +37,39 @@ bpf_map(__augmented_syscalls__, PERF_EVENT_ARRAY, int, u32, __NR_CPUS__);
 | 
			
		|||
 */
 | 
			
		||||
struct syscall {
 | 
			
		||||
	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?
 | 
			
		||||
 *
 | 
			
		||||
 * 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?
 | 
			
		||||
 *
 | 
			
		||||
 * 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 {
 | 
			
		||||
	unsigned long long common_tp_fields;
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +89,38 @@ struct augmented_arg {
 | 
			
		|||
	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 syscall_enter_args args;
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +133,12 @@ struct augmented_args_payload {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
{
 | 
			
		||||
	/* 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
 | 
			
		||||
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);
 | 
			
		||||
	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;
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +205,7 @@ int sys_enter_connect(struct syscall_enter_args *args)
 | 
			
		|||
	if (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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +224,7 @@ int sys_enter_sendto(struct syscall_enter_args *args)
 | 
			
		|||
	if (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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -234,6 +293,16 @@ int sys_enter_renameat(struct syscall_enter_args *args)
 | 
			
		|||
	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")
 | 
			
		||||
int sys_enter(struct syscall_enter_args *args)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -257,7 +326,7 @@ int sys_enter(struct syscall_enter_args *args)
 | 
			
		|||
	if (augmented_args == NULL)
 | 
			
		||||
		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,
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +347,7 @@ int sys_exit(struct syscall_exit_args *args)
 | 
			
		|||
	if (pid_filter__has(&pids_filtered, getpid()))
 | 
			
		||||
		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,
 | 
			
		||||
	 * "!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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
license(GPL);
 | 
			
		||||
char _license[] SEC("license") = "GPL";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),
 | 
			
		||||
		 "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;
 | 
			
		||||
	force_set_env("NR_CPUS", nr_cpus_avail_str);
 | 
			
		||||
	force_set_env("LINUX_VERSION_CODE", linux_version_code_str);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue