I'm trying to implement the killsnoop.py program in bcc in C. When executing the program, I'm getting a failed to load: -13
error. Can someone help me to debug this?
Note: For compilation, I've taken the libbpf-bootstrap example from Andrii Nakryiko
's blog post.
Below is the program that I've used.
killsnoop.bpf.c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "killsnoop.h"
struct val_t {
__u32 uid;
__u32 pid;
int sig;
int tpid;
char comm[TASK_COMM_LEN];
};
struct data_t {
__u32 uid;
__u32 pid;
int tpid;
int sig;
int ret;
char comm[TASK_COMM_LEN];
};
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32);
__type(value, struct val_t);
__uint(max_entries, 10240);
} info_map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32);
__type(value, struct data_t);
__uint(max_entries, 10240);
} event SEC(".maps");
SEC("kprobe/__x64_sys_kill")
int entry_probe(struct pt_regs *ctx, int tpid, int sig) {
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32) pid_tgid;
__u64 uid_gid = bpf_get_current_uid_gid();
__u32 uid = (__u32) uid_gid;
struct val_t val = {
.uid = uid,
.pid = pid
};
if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
val.tpid = tpid;
val.sig = sig;
bpf_map_update_elem(&info_map, &tid, &val, BPF_ANY);
}
return 0;
}
SEC("kretprobe/__x64_sys_kill")
int return_probe(struct pt_regs *ctx) {
struct data_t data = {};
struct val_t *valp;
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32) pid_tgid;
valp = bpf_map_lookup_elem(&info_map, &tid);
if (!valp) {
return 0; // missed entry
}
bpf_core_read(&data.comm, sizeof(data.comm), valp->comm);
data.pid = pid;
data.tpid = valp->tpid;
data.ret = PT_REGS_RC_CORE(ctx);
data.sig = valp->sig;
data.uid = valp->uid;
bpf_perf_event_output(ctx, &event, BPF_F_CURRENT_CPU, &data, sizeof(data));
bpf_map_delete_elem(&info_map, &tid);
return 0;
}
killsnoop.c
#include <signal.h>
#include "killsnoop.skel.h"
#include "killsnoop.h"
#define OUTPUT_FORMAT "%lld %d %d %s %d %d"
#define PERF_POLL_TIMEOUT_MS 10
#define PERF_BUFFER_PAGES 64
static volatile int shutdown = 0;
static void sig_int(int signal) {
shutdown = 1;
}
void handle_event(void *ctx, int cpu, void *data, u32 data_size) {
const struct event *e = data;
time_t curr_time;
time(&curr_time);
printf(OUTPUT_FORMAT, (long long) curr_time, e->pid, e->tpid, e->comm, e->sig, e->uid);
}
void handle_lost_event(void *ctx, int cpu, u64 lost_cnt) {
fprintf(stderr, "Lost %llu events on CPU #%d!\n", lost_cnt, cpu);
}
int main(int argc, char **argv) {
int err;
struct perf_buffer *perfBuffer;
struct killsnoop_bpf *obj;
obj = killsnoop_bpf__open_and_load();
if (!obj) {
fprintf(stderr, "failed to open/load BPF skeleton!");
goto cleanup;
}
err = killsnoop_bpf__attach(obj);
if (err) {
fprintf(stderr, "failed to attach BPF programs\n");
goto cleanup;
}
perfBuffer = perf_buffer__new(bpf_map__fd(obj->maps.info_map), PERF_BUFFER_PAGES, handle_event, handle_lost_event,
NULL, NULL);
if (!perfBuffer) {
err = -errno;
fprintf(stderr, "failed to open perf buffer: %d\n", err);
goto cleanup;
}
if (signal(SIGINT, sig_int) == SIG_ERR) {
fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
err = 1;
goto cleanup;
}
while (!shutdown) {
err = perf_buffer__poll(perfBuffer, PERF_POLL_TIMEOUT_MS);
if (err < 0 && err != -EINTR) {
fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err));
goto cleanup;
}
/* reset err to return 0 if exiting */
err = 0;
}
cleanup:
perf_buffer__free(perfBuffer);
killsnoop_bpf__destroy(obj);
return err != 0;
}
killsnoop.h
#define TASK_COMM_LEN 16
typedef unsigned int u32;
typedef unsigned long long u64;
struct event {
u32 uid;
u32 pid;
int tpid;
int sig;
int ret;
char comm[TASK_COMM_LEN];
};