Merge branch 'samples/bpf: enhance syscall tracing program'
"Daniel T. Lee" says: ==================== Syscall tracing using kprobe is quite unstable. Since it uses the exact name of the kernel function, the program might broke due to the rename of a function. The problem can also be caused by a changes in the arguments of the function to which the kprobe connects. This commit enhances syscall tracing program with the following instruments. In this patchset, ksyscall is used instead of kprobe. By using ksyscall, libbpf will detect the appropriate kernel function name. (e.g. sys_write -> __s390_sys_write). This eliminates the need to worry about which wrapper function to attach in order to parse arguments. Also ksyscall provides more fine method with attaching system call, the coarse SYSCALL helper at trace_common.h can be removed. Next, BPF_SYSCALL is used to reduce the inconvenience of parsing arguments. Since the nature of SYSCALL_WRAPPER function wraps the argument once, additional process of argument extraction is required to properly parse the argument. The BPF_SYSCALL macro will reduces the hassle of parsing arguments from pt_regs. Lastly, vmlinux.h is applied to syscall tracing program. This change allows the bpf program to refer to the internal structure as a single "vmlinux.h" instead of including each header referenced by the bpf program. Additionally, this patchset changes the suffix of _kern to .bpf to make use of the new compile rule (CLANG-BPF) which is more simple and neat. By just changing the _kern suffix to .bpf will inherit the benefit of the new CLANG-BPF compile target. Also, this commit adds dummy gnu/stub.h to the samples/bpf directory. This will fix the compiling problem with 'clang -target bpf'. To fix the build error with the s390x, this patchset also includes the fix of libbpf invalid return address register mapping in s390. --- Changes in V2: - add gnu/stub.h hack to fix compile error with 'clang -target bpf' Changes in V3: - fix libbpf invalid return address register mapping in s390 ==================== Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
This commit is contained in:
commit
ac807e6839
samples/bpf
Makefile
gnu
map_perf_test.bpf.cmap_perf_test_user.ctest_current_task_under_cgroup.bpf.ctest_current_task_under_cgroup_user.ctest_map_in_map_kern.ctest_probe_write_user.bpf.ctest_probe_write_user_user.ctrace_common.htrace_output.bpf.ctrace_output_user.ctracex2.bpf.ctracex2_user.ctools/lib/bpf
@ -125,21 +125,21 @@ always-y += sockex1_kern.o
|
||||
always-y += sockex2_kern.o
|
||||
always-y += sockex3_kern.o
|
||||
always-y += tracex1_kern.o
|
||||
always-y += tracex2_kern.o
|
||||
always-y += tracex2.bpf.o
|
||||
always-y += tracex3_kern.o
|
||||
always-y += tracex4_kern.o
|
||||
always-y += tracex5_kern.o
|
||||
always-y += tracex6_kern.o
|
||||
always-y += tracex7_kern.o
|
||||
always-y += sock_flags_kern.o
|
||||
always-y += test_probe_write_user_kern.o
|
||||
always-y += trace_output_kern.o
|
||||
always-y += test_probe_write_user.bpf.o
|
||||
always-y += trace_output.bpf.o
|
||||
always-y += tcbpf1_kern.o
|
||||
always-y += tc_l2_redirect_kern.o
|
||||
always-y += lathist_kern.o
|
||||
always-y += offwaketime_kern.o
|
||||
always-y += spintest_kern.o
|
||||
always-y += map_perf_test_kern.o
|
||||
always-y += map_perf_test.bpf.o
|
||||
always-y += test_overhead_tp_kern.o
|
||||
always-y += test_overhead_raw_tp_kern.o
|
||||
always-y += test_overhead_kprobe_kern.o
|
||||
@ -147,7 +147,7 @@ always-y += parse_varlen.o parse_simple.o parse_ldabs.o
|
||||
always-y += test_cgrp2_tc_kern.o
|
||||
always-y += xdp1_kern.o
|
||||
always-y += xdp2_kern.o
|
||||
always-y += test_current_task_under_cgroup_kern.o
|
||||
always-y += test_current_task_under_cgroup.bpf.o
|
||||
always-y += trace_event_kern.o
|
||||
always-y += sampleip_kern.o
|
||||
always-y += lwt_len_hist_kern.o
|
||||
|
1
samples/bpf/gnu/stubs.h
Normal file
1
samples/bpf/gnu/stubs.h
Normal file
@ -0,0 +1 @@
|
||||
/* dummy .h to trick /usr/include/features.h to work with 'clang -target bpf' */
|
@ -4,14 +4,12 @@
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "vmlinux.h"
|
||||
#include <errno.h>
|
||||
#include <linux/version.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "trace_common.h"
|
||||
|
||||
#define MAX_ENTRIES 1000
|
||||
#define MAX_NR_CPUS 1024
|
||||
@ -102,8 +100,8 @@ struct {
|
||||
__uint(max_entries, MAX_ENTRIES);
|
||||
} lru_hash_lookup_map SEC(".maps");
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_getuid))
|
||||
int stress_hmap(struct pt_regs *ctx)
|
||||
SEC("ksyscall/getuid")
|
||||
int BPF_KSYSCALL(stress_hmap)
|
||||
{
|
||||
u32 key = bpf_get_current_pid_tgid();
|
||||
long init_val = 1;
|
||||
@ -120,8 +118,8 @@ int stress_hmap(struct pt_regs *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_geteuid))
|
||||
int stress_percpu_hmap(struct pt_regs *ctx)
|
||||
SEC("ksyscall/geteuid")
|
||||
int BPF_KSYSCALL(stress_percpu_hmap)
|
||||
{
|
||||
u32 key = bpf_get_current_pid_tgid();
|
||||
long init_val = 1;
|
||||
@ -137,8 +135,8 @@ int stress_percpu_hmap(struct pt_regs *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_getgid))
|
||||
int stress_hmap_alloc(struct pt_regs *ctx)
|
||||
SEC("ksyscall/getgid")
|
||||
int BPF_KSYSCALL(stress_hmap_alloc)
|
||||
{
|
||||
u32 key = bpf_get_current_pid_tgid();
|
||||
long init_val = 1;
|
||||
@ -154,8 +152,8 @@ int stress_hmap_alloc(struct pt_regs *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_getegid))
|
||||
int stress_percpu_hmap_alloc(struct pt_regs *ctx)
|
||||
SEC("ksyscall/getegid")
|
||||
int BPF_KSYSCALL(stress_percpu_hmap_alloc)
|
||||
{
|
||||
u32 key = bpf_get_current_pid_tgid();
|
||||
long init_val = 1;
|
||||
@ -170,11 +168,10 @@ int stress_percpu_hmap_alloc(struct pt_regs *ctx)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_connect))
|
||||
int stress_lru_hmap_alloc(struct pt_regs *ctx)
|
||||
SEC("ksyscall/connect")
|
||||
int BPF_KSYSCALL(stress_lru_hmap_alloc, int fd, struct sockaddr_in *uservaddr,
|
||||
int addrlen)
|
||||
{
|
||||
struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1_CORE(ctx);
|
||||
char fmt[] = "Failed at stress_lru_hmap_alloc. ret:%dn";
|
||||
union {
|
||||
u16 dst6[8];
|
||||
@ -187,14 +184,11 @@ int stress_lru_hmap_alloc(struct pt_regs *ctx)
|
||||
u32 key;
|
||||
};
|
||||
} test_params;
|
||||
struct sockaddr_in6 *in6;
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)uservaddr;
|
||||
u16 test_case;
|
||||
int addrlen, ret;
|
||||
long val = 1;
|
||||
u32 key = 0;
|
||||
|
||||
in6 = (struct sockaddr_in6 *)PT_REGS_PARM2_CORE(real_regs);
|
||||
addrlen = (int)PT_REGS_PARM3_CORE(real_regs);
|
||||
int ret;
|
||||
|
||||
if (addrlen != sizeof(*in6))
|
||||
return 0;
|
||||
@ -251,8 +245,8 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_gettid))
|
||||
int stress_lpm_trie_map_alloc(struct pt_regs *ctx)
|
||||
SEC("ksyscall/gettid")
|
||||
int BPF_KSYSCALL(stress_lpm_trie_map_alloc)
|
||||
{
|
||||
union {
|
||||
u32 b32[2];
|
||||
@ -273,8 +267,8 @@ int stress_lpm_trie_map_alloc(struct pt_regs *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_getpgid))
|
||||
int stress_hash_map_lookup(struct pt_regs *ctx)
|
||||
SEC("ksyscall/getpgid")
|
||||
int BPF_KSYSCALL(stress_hash_map_lookup)
|
||||
{
|
||||
u32 key = 1, i;
|
||||
long *value;
|
||||
@ -286,8 +280,8 @@ int stress_hash_map_lookup(struct pt_regs *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_getppid))
|
||||
int stress_array_map_lookup(struct pt_regs *ctx)
|
||||
SEC("ksyscall/getppid")
|
||||
int BPF_KSYSCALL(stress_array_map_lookup)
|
||||
{
|
||||
u32 key = 1, i;
|
||||
long *value;
|
@ -443,7 +443,7 @@ int main(int argc, char **argv)
|
||||
if (argc > 4)
|
||||
max_cnt = atoi(argv[4]);
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
|
||||
obj = bpf_object__open_file(filename, NULL);
|
||||
if (libbpf_get_error(obj)) {
|
||||
fprintf(stderr, "ERROR: opening BPF object file failed\n");
|
||||
|
11
samples/bpf/test_current_task_under_cgroup_kern.c → samples/bpf/test_current_task_under_cgroup.bpf.c
11
samples/bpf/test_current_task_under_cgroup_kern.c → samples/bpf/test_current_task_under_cgroup.bpf.c
@ -5,12 +5,11 @@
|
||||
* License as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/ptrace.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include "vmlinux.h"
|
||||
#include <linux/version.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <uapi/linux/utsname.h>
|
||||
#include "trace_common.h"
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
|
||||
@ -27,8 +26,8 @@ struct {
|
||||
} perf_map SEC(".maps");
|
||||
|
||||
/* Writes the last PID that called sync to a map at index 0 */
|
||||
SEC("kprobe/" SYSCALL(sys_sync))
|
||||
int bpf_prog1(struct pt_regs *ctx)
|
||||
SEC("ksyscall/sync")
|
||||
int BPF_KSYSCALL(bpf_prog1)
|
||||
{
|
||||
u64 pid = bpf_get_current_pid_tgid();
|
||||
int idx = 0;
|
@ -21,7 +21,7 @@ int main(int argc, char **argv)
|
||||
char filename[256];
|
||||
int map_fd[2];
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
|
||||
obj = bpf_object__open_file(filename, NULL);
|
||||
if (libbpf_get_error(obj)) {
|
||||
fprintf(stderr, "ERROR: opening BPF object file failed\n");
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "trace_common.h"
|
||||
|
||||
#define MAX_NR_PORTS 65536
|
||||
|
||||
|
@ -4,14 +4,12 @@
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include "vmlinux.h"
|
||||
#include <string.h>
|
||||
#include <linux/version.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "trace_common.h"
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
@ -28,25 +26,23 @@ struct {
|
||||
* This example sits on a syscall, and the syscall ABI is relatively stable
|
||||
* of course, across platforms, and over time, the ABI may change.
|
||||
*/
|
||||
SEC("kprobe/" SYSCALL(sys_connect))
|
||||
int bpf_prog1(struct pt_regs *ctx)
|
||||
SEC("ksyscall/connect")
|
||||
int BPF_KSYSCALL(bpf_prog1, int fd, struct sockaddr_in *uservaddr,
|
||||
int addrlen)
|
||||
{
|
||||
struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1_CORE(ctx);
|
||||
void *sockaddr_arg = (void *)PT_REGS_PARM2_CORE(real_regs);
|
||||
int sockaddr_len = (int)PT_REGS_PARM3_CORE(real_regs);
|
||||
struct sockaddr_in new_addr, orig_addr = {};
|
||||
struct sockaddr_in *mapped_addr;
|
||||
|
||||
if (sockaddr_len > sizeof(orig_addr))
|
||||
if (addrlen > sizeof(orig_addr))
|
||||
return 0;
|
||||
|
||||
if (bpf_probe_read_user(&orig_addr, sizeof(orig_addr), sockaddr_arg) != 0)
|
||||
if (bpf_probe_read_user(&orig_addr, sizeof(orig_addr), uservaddr) != 0)
|
||||
return 0;
|
||||
|
||||
mapped_addr = bpf_map_lookup_elem(&dnat_map, &orig_addr);
|
||||
if (mapped_addr != NULL) {
|
||||
memcpy(&new_addr, mapped_addr, sizeof(new_addr));
|
||||
bpf_probe_write_user(sockaddr_arg, &new_addr,
|
||||
bpf_probe_write_user(uservaddr, &new_addr,
|
||||
sizeof(new_addr));
|
||||
}
|
||||
return 0;
|
@ -24,7 +24,7 @@ int main(int ac, char **argv)
|
||||
mapped_addr_in = (struct sockaddr_in *)&mapped_addr;
|
||||
tmp_addr_in = (struct sockaddr_in *)&tmp_addr;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
|
||||
obj = bpf_object__open_file(filename, NULL);
|
||||
if (libbpf_get_error(obj)) {
|
||||
fprintf(stderr, "ERROR: opening BPF object file failed\n");
|
||||
|
@ -1,13 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#ifndef __TRACE_COMMON_H
|
||||
#define __TRACE_COMMON_H
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define SYSCALL(SYS) "__x64_" __stringify(SYS)
|
||||
#elif defined(__s390x__)
|
||||
#define SYSCALL(SYS) "__s390x_" __stringify(SYS)
|
||||
#else
|
||||
#define SYSCALL(SYS) __stringify(SYS)
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,8 +1,6 @@
|
||||
#include <linux/ptrace.h>
|
||||
#include "vmlinux.h"
|
||||
#include <linux/version.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "trace_common.h"
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
@ -11,7 +9,7 @@ struct {
|
||||
__uint(max_entries, 2);
|
||||
} my_map SEC(".maps");
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_write))
|
||||
SEC("ksyscall/write")
|
||||
int bpf_prog1(struct pt_regs *ctx)
|
||||
{
|
||||
struct S {
|
@ -51,7 +51,7 @@ int main(int argc, char **argv)
|
||||
char filename[256];
|
||||
FILE *f;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
|
||||
obj = bpf_object__open_file(filename, NULL);
|
||||
if (libbpf_get_error(obj)) {
|
||||
fprintf(stderr, "ERROR: opening BPF object file failed\n");
|
||||
|
@ -4,13 +4,11 @@
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "vmlinux.h"
|
||||
#include <linux/version.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include "trace_common.h"
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
@ -78,15 +76,14 @@ struct {
|
||||
__uint(max_entries, 1024);
|
||||
} my_hist_map SEC(".maps");
|
||||
|
||||
SEC("kprobe/" SYSCALL(sys_write))
|
||||
int bpf_prog3(struct pt_regs *ctx)
|
||||
SEC("ksyscall/write")
|
||||
int BPF_KSYSCALL(bpf_prog3, unsigned int fd, const char *buf, size_t count)
|
||||
{
|
||||
long write_size = PT_REGS_PARM3(ctx);
|
||||
long init_val = 1;
|
||||
long *value;
|
||||
struct hist_key key;
|
||||
|
||||
key.index = log2l(write_size);
|
||||
key.index = log2l(count);
|
||||
key.pid_tgid = bpf_get_current_pid_tgid();
|
||||
key.uid_gid = bpf_get_current_uid_gid();
|
||||
bpf_get_current_comm(&key.comm, sizeof(key.comm));
|
@ -123,7 +123,7 @@ int main(int ac, char **argv)
|
||||
int i, j = 0;
|
||||
FILE *f;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
|
||||
obj = bpf_object__open_file(filename, NULL);
|
||||
if (libbpf_get_error(obj)) {
|
||||
fprintf(stderr, "ERROR: opening BPF object file failed\n");
|
||||
|
@ -137,7 +137,7 @@ struct pt_regs___s390 {
|
||||
#define __PT_PARM3_REG gprs[4]
|
||||
#define __PT_PARM4_REG gprs[5]
|
||||
#define __PT_PARM5_REG gprs[6]
|
||||
#define __PT_RET_REG grps[14]
|
||||
#define __PT_RET_REG gprs[14]
|
||||
#define __PT_FP_REG gprs[11] /* Works only with CONFIG_FRAME_POINTER */
|
||||
#define __PT_RC_REG gprs[2]
|
||||
#define __PT_SP_REG gprs[15]
|
||||
|
Loading…
x
Reference in New Issue
Block a user