eBPF CO:RE: vmlinux.h incomplete?



我正在尝试使用libbpf进入eBPF CO:RE。我的程序使用了一个跟踪点SEC("tracepoint/syscalls/sys_enter_kill"(,我想知道如何获得这些参数,以及为什么它们没有包含在vmlinux.h中。此外,似乎缺少定义BPF_F_CURRENT_CPU。或者可以将vmlinux.h和uapi/linux/bpf.h结合起来吗?

我的设置:

  • Ubuntu 20.04
  • 内核5.4.0-90-generic
  • bpftool--版本:/bpftool v5.16.0-rc2-功能:libbfd,骨架(来自Kernel github,应该是最新的(
  • 使用bpftool btf转储文件/sys/kernel/btf/vmlinux格式c生成的vmlinux.h>vmlinux.h

我知道关于如何获取参数,已经存在这个问题(阅读eBPF跟踪点参数(。然而,这并不能回答我的问题(为什么它不在vmlinux.h中?vmlinux.h还有什么意义?(,我还有一个问题,内核显示的布局似乎不正确(见下文(。此外,似乎缺少定义BPF_F_CURRENT_CPU。

我的代码:

common.h:只有一个小结构可以将数据传输到用户空间

struct dataStruct {
int pid;
};

main.bpf.c

// Compiling with: clang -target bpf -S -D __BPF_TRACING__ -Wall -Werror -O2 -emit-llvm -c -g main.bpf.c
// and then: llc -march=bpf -filetype=obj -o main.bpf.o main.bpf.ll
#include "vmlinux.h"
#include "../90_lib/libbpf/build/root/usr/include/bpf/bpf_helpers.h"
#include "../90_lib/libbpf/build/root/usr/include/bpf/bpf_tracing.h"
#include "../90_lib/libbpf/build/root/usr/include/bpf/bpf_core_read.h"
#include "common.h"

struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
} pb SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, 1);
__type(key, int);;
__type(value, struct dataStruct);
} heap SEC(".maps");

// sudo cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format
// name: sys_enter_kill
// ID: 184
// format:
//  field:unsigned short common_type;   offset:0;   size:2; signed:0;
//  field:unsigned char common_flags;   offset:2;   size:1; signed:0;
//  field:unsigned char common_preempt_count;   offset:3;   size:1;signed:0;
//  field:int common_pid;   offset:4;   size:4; signed:1;
//  field:int __syscall_nr; offset:8;   size:4; signed:1;
//  field:pid_t pid;    offset:16;  size:8; signed:0;
//  field:int sig;  offset:24;  size:8; signed:0;
// print fmt: "pid: 0x%08lx, sig: 0x%08lx", ((unsigned long)(REC->pid)), ((unsigned long)(REC->sig))

// >> How to obtain this structurecorrectly?
struct syscalls_enter_kill_args
{
unsigned short common_type;
unsigned char common_flags;
unsigned char common_preempt_count;
int common_pid;
// int syscall_nr;      // From sudo cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format
// pid_t pid;
// int sig;
long syscall_nr;    // From https://hed.am/papers/2021-EBPF.pdf
long pid;
long sig;
};

enum {      // from #include "../90_lib/libbpf/include/uapi/linux/bpf.h"
BPF_F_INDEX_MASK        = 0xffffffffULL,
BPF_F_CURRENT_CPU       = BPF_F_INDEX_MASK,
/* BPF_FUNC_perf_event_output for sk_buff input context. */
BPF_F_CTXLEN_MASK       = (0xfffffULL << 32),
};

SEC("tracepoint/syscalls/sys_enter_kill")
int kill_example(struct syscalls_enter_kill_args *ctx)
{
if(ctx->sig != 9)
return 0;
// int s = BPF_CORE_READ(ctx, sig); // Does not work
// if(s != 9)
//  return 0;
char fmt[] = "BPF handlen";
bpf_trace_printk(fmt, sizeof(fmt));

struct dataStruct *e;
int zero = 0;

e = bpf_map_lookup_elem(&heap, &zero);
if (!e) /* can't happen */
return 0;
e->pid = bpf_get_current_pid_tgid() >> 32;
bpf_perf_event_output(ctx, &pb, BPF_F_CURRENT_CPU, e, sizeof(*e));
return 0;
}
char _license[] SEC("license") = "GPL";

main.cc:

// Compile loader
// >> g++ -I../90_lib/libbpf/src/root/usr/include/ -L../90_lib/libbpf/src/ -o ebpf main.cc -lbpf -lelf -Wl,-R../90_lib/libbpf/src/

# include <stdio.h>
#include <iostream>
# include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <poll.h>
#include <sys/select.h>
#include </usr/include/asm-generic/errno-base.h>

// Should be defined in up-to-date linux/bpf.h, but is not (and other linux/bpf.h conflicts with a lot of definitions)
/* type for BPF_ENABLE_STATS */
enum bpf_stats_type {
/* enabled run_time_ns and run_cnt */
BPF_STATS_RUN_TIME = 0,
};
#include "../90_lib/libbpf/build/root/usr/include/bpf/bpf.h"
#include "../90_lib/libbpf/build/root/usr/include/bpf/libbpf.h"
#include "common.h"

void bump_memlock_rlimit(void)
{
struct rlimit rlim_new = {
.rlim_cur   = RLIM_INFINITY,
.rlim_max   = RLIM_INFINITY,
};
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!n");
exit(1);
}
}

using namespace std;
void handle_event(void *ctx, int cpu, void *data, unsigned int data_sz)
{
cout << "perfBuffer - Event!; got " << data_sz << " Bytes? data." << endl;
struct dataStruct* d = static_cast<struct dataStruct*>(data);
cout << "    PID: " << d->pid << endl;
}

int main (int argc , char ** argv )
{
int prog_fd ;
struct bpf_object *obj;
bump_memlock_rlimit();
if(bpf_prog_load("main.bpf.o", BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd) != 0)
{
printf (" eBPF program not loaded n");
return -1;
}
// Check that we got a file descriptor for the loaded object file.
if(prog_fd < 1)
{
printf (" Error creating prog_fd n");
return -2;
}
// Attach the eBPF program by it 's function name
struct bpf_program * prog = bpf_object__find_program_by_name(obj, "kill_example");
bpf_program__attach(prog);
int numMaps = 0;
struct bpf_map * map;
struct bpf_map* map_pb;
struct bpf_map* maps[10];
for (map = bpf_map__next(NULL, (obj));  
map != NULL;               
map = bpf_map__next(map, (obj)))
{
++numMaps;
cout << "Found map, name: '" << bpf_map__name(map) << "'" << endl;
if(strcmp(bpf_map__name(map), "pb") == 0)
{
cout << "  Found map 'pb'; fileDescriptor: " << bpf_map__fd(map) << endl;
map_pb = map;
}
}
cout << "Found " << numMaps << " Maps." << endl;
int map_pb_fd = bpf_map__fd(map_pb);
cout << "Got Map File Descriptor: " << map_pb_fd << endl;
uint32_t map_key_cnt = 0;
uint64_t val = 0;
uint64_t val_last = val;
struct perf_buffer *pb = NULL;
struct perf_buffer_opts pb_opts = {};
pb_opts.sample_cb = handle_event;
pb = perf_buffer__new(map_pb_fd, 8 /* 32KB per CPU */, &pb_opts);
if (libbpf_get_error(pb)) {
fprintf(stderr, "Failed to create perf buffern");
}
int res = 0;
cout << "Entering main loop." << endl;
while(1)
{
res = perf_buffer__poll(pb, -1);
if(res == -EINTR)
{
cout << "-EINTR" << endl;
return 0;
}
}
return 0;
}

这适用于结构

struct syscalls_enter_kill_args
{
unsigned short common_type;
unsigned char common_flags;
unsigned char common_preempt_count;
int common_pid;
long syscall_nr;    // From https://hed.am/papers/2021-EBPF.pdf
long pid;
long sig;
};

但当我将结构更改为时不会

struct syscalls_enter_kill_args
{
unsigned short common_type;
unsigned char common_flags;
unsigned char common_preempt_count;
int common_pid;
int syscall_nr;     // From sudo cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format
pid_t pid;
int sig;
};

这似乎很奇怪。有人知道出了什么问题吗?提前感谢!:(

唯一的原因是它不起作用,因为在这种情况下,变量和大小的格式不匹配。检查该文件的syskill_enter格式/sys/kernel/debug/tracing/events/syscalls/sys_enter_kill/format

尽管pid的字段是pid_t,而sig的字段是int.

但如果你检查一下pid和sig的大小,它们都是8。

所以CCD_ 1在CCD_。

相关内容

  • 没有找到相关文章

最新更新