samples/bpf: bpf_tail_call example for tracing
kprobe example that demonstrates how future seccomp programs may look like.
It attaches to seccomp_phase1() function and tail-calls other BPF programs
depending on syscall number.
Existing optimized classic BPF seccomp programs generated by Chrome look like:
if (sd.nr < 121) {
if (sd.nr < 57) {
if (sd.nr < 22) {
if (sd.nr < 7) {
if (sd.nr < 4) {
if (sd.nr < 1) {
check sys_read
} else {
if (sd.nr < 3) {
check sys_write and sys_open
} else {
check sys_close
}
}
} else {
} else {
} else {
} else {
} else {
}
the future seccomp using native eBPF may look like:
bpf_tail_call(&sd, &syscall_jmp_table, sd.nr);
which is simpler, faster and leaves more room for per-syscall checks.
Usage:
$ sudo ./tracex5
<...>-366 [001] d... 4.870033: : read(fd=1, buf=00007f6d5bebf000, size=771)
<...>-369 [003] d... 4.870066: : mmap
<...>-369 [003] d... 4.870077: : syscall=110 (one of get/set uid/pid/gid)
<...>-369 [003] d... 4.870089: : syscall=107 (one of get/set uid/pid/gid)
sh-369 [000] d... 4.891740: : read(fd=0, buf=00000000023d1000, size=512)
sh-369 [000] d... 4.891747: : write(fd=1, buf=00000000023d3000, size=512)
sh-369 [000] d... 4.891747: : read(fd=1, buf=00000000023d3000, size=512)
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
b52f00e6a7
commit
5bacd7805a
@@ -16,6 +16,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <poll.h>
|
||||
#include <ctype.h>
|
||||
#include "libbpf.h"
|
||||
#include "bpf_helpers.h"
|
||||
#include "bpf_load.h"
|
||||
@@ -29,6 +30,19 @@ int map_fd[MAX_MAPS];
|
||||
int prog_fd[MAX_PROGS];
|
||||
int event_fd[MAX_PROGS];
|
||||
int prog_cnt;
|
||||
int prog_array_fd = -1;
|
||||
|
||||
static int populate_prog_array(const char *event, int prog_fd)
|
||||
{
|
||||
int ind = atoi(event), err;
|
||||
|
||||
err = bpf_update_elem(prog_array_fd, &ind, &prog_fd, BPF_ANY);
|
||||
if (err < 0) {
|
||||
printf("failed to store prog_fd in prog_array\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
|
||||
{
|
||||
@@ -54,12 +68,40 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = bpf_prog_load(prog_type, prog, size, license, kern_version);
|
||||
if (fd < 0) {
|
||||
printf("bpf_prog_load() err=%d\n%s", errno, bpf_log_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
prog_fd[prog_cnt++] = fd;
|
||||
|
||||
if (is_socket) {
|
||||
event += 6;
|
||||
if (*event != '/')
|
||||
return 0;
|
||||
event++;
|
||||
if (!isdigit(*event)) {
|
||||
printf("invalid prog number\n");
|
||||
return -1;
|
||||
}
|
||||
return populate_prog_array(event, fd);
|
||||
}
|
||||
|
||||
if (is_kprobe || is_kretprobe) {
|
||||
if (is_kprobe)
|
||||
event += 7;
|
||||
else
|
||||
event += 10;
|
||||
|
||||
if (*event == 0) {
|
||||
printf("event name cannot be empty\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (isdigit(*event))
|
||||
return populate_prog_array(event, fd);
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"echo '%c:%s %s' >> /sys/kernel/debug/tracing/kprobe_events",
|
||||
is_kprobe ? 'p' : 'r', event, event);
|
||||
@@ -71,18 +113,6 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
|
||||
}
|
||||
}
|
||||
|
||||
fd = bpf_prog_load(prog_type, prog, size, license, kern_version);
|
||||
|
||||
if (fd < 0) {
|
||||
printf("bpf_prog_load() err=%d\n%s", errno, bpf_log_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
prog_fd[prog_cnt++] = fd;
|
||||
|
||||
if (is_socket)
|
||||
return 0;
|
||||
|
||||
strcpy(buf, DEBUGFS);
|
||||
strcat(buf, "events/kprobes/");
|
||||
strcat(buf, event);
|
||||
@@ -130,6 +160,9 @@ static int load_maps(struct bpf_map_def *maps, int len)
|
||||
maps[i].max_entries);
|
||||
if (map_fd[i] < 0)
|
||||
return 1;
|
||||
|
||||
if (maps[i].type == BPF_MAP_TYPE_PROG_ARRAY)
|
||||
prog_array_fd = map_fd[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user