2014-12-02 02:06:37 +03:00
|
|
|
#ifndef __BPF_HELPERS_H
|
|
|
|
#define __BPF_HELPERS_H
|
|
|
|
|
|
|
|
/* helper macro to place programs, maps, license in
|
|
|
|
* different sections in elf_bpf file. Section names
|
|
|
|
* are interpreted by elf_bpf loader
|
|
|
|
*/
|
|
|
|
#define SEC(NAME) __attribute__((section(NAME), used))
|
|
|
|
|
|
|
|
/* helper functions called from eBPF programs written in C */
|
|
|
|
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
|
|
|
|
(void *) BPF_FUNC_map_lookup_elem;
|
|
|
|
static int (*bpf_map_update_elem)(void *map, void *key, void *value,
|
|
|
|
unsigned long long flags) =
|
|
|
|
(void *) BPF_FUNC_map_update_elem;
|
|
|
|
static int (*bpf_map_delete_elem)(void *map, void *key) =
|
|
|
|
(void *) BPF_FUNC_map_delete_elem;
|
2015-03-25 22:49:23 +03:00
|
|
|
static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr) =
|
|
|
|
(void *) BPF_FUNC_probe_read;
|
|
|
|
static unsigned long long (*bpf_ktime_get_ns)(void) =
|
|
|
|
(void *) BPF_FUNC_ktime_get_ns;
|
|
|
|
static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
|
|
|
|
(void *) BPF_FUNC_trace_printk;
|
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>
2015-05-20 02:59:05 +03:00
|
|
|
static void (*bpf_tail_call)(void *ctx, void *map, int index) =
|
|
|
|
(void *) BPF_FUNC_tail_call;
|
2015-05-20 02:59:06 +03:00
|
|
|
static unsigned long long (*bpf_get_smp_processor_id)(void) =
|
|
|
|
(void *) BPF_FUNC_get_smp_processor_id;
|
2015-06-13 05:39:12 +03:00
|
|
|
static unsigned long long (*bpf_get_current_pid_tgid)(void) =
|
|
|
|
(void *) BPF_FUNC_get_current_pid_tgid;
|
|
|
|
static unsigned long long (*bpf_get_current_uid_gid)(void) =
|
|
|
|
(void *) BPF_FUNC_get_current_uid_gid;
|
|
|
|
static int (*bpf_get_current_comm)(void *buf, int buf_size) =
|
|
|
|
(void *) BPF_FUNC_get_current_comm;
|
2015-08-06 10:02:36 +03:00
|
|
|
static int (*bpf_perf_event_read)(void *map, int index) =
|
|
|
|
(void *) BPF_FUNC_perf_event_read;
|
2015-09-16 09:05:43 +03:00
|
|
|
static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
|
|
|
|
(void *) BPF_FUNC_clone_redirect;
|
|
|
|
static int (*bpf_redirect)(int ifindex, int flags) =
|
|
|
|
(void *) BPF_FUNC_redirect;
|
2015-10-21 06:02:35 +03:00
|
|
|
static int (*bpf_perf_event_output)(void *ctx, void *map, int index, void *data, int size) =
|
|
|
|
(void *) BPF_FUNC_perf_event_output;
|
2016-02-18 06:58:59 +03:00
|
|
|
static int (*bpf_get_stackid)(void *ctx, void *map, int flags) =
|
|
|
|
(void *) BPF_FUNC_get_stackid;
|
2014-12-02 02:06:37 +03:00
|
|
|
|
|
|
|
/* llvm builtin functions that eBPF C program may use to
|
|
|
|
* emit BPF_LD_ABS and BPF_LD_IND instructions
|
|
|
|
*/
|
|
|
|
struct sk_buff;
|
|
|
|
unsigned long long load_byte(void *skb,
|
|
|
|
unsigned long long off) asm("llvm.bpf.load.byte");
|
|
|
|
unsigned long long load_half(void *skb,
|
|
|
|
unsigned long long off) asm("llvm.bpf.load.half");
|
|
|
|
unsigned long long load_word(void *skb,
|
|
|
|
unsigned long long off) asm("llvm.bpf.load.word");
|
|
|
|
|
|
|
|
/* a helper structure used by eBPF C program
|
|
|
|
* to describe map attributes to elf_bpf loader
|
|
|
|
*/
|
|
|
|
struct bpf_map_def {
|
|
|
|
unsigned int type;
|
|
|
|
unsigned int key_size;
|
|
|
|
unsigned int value_size;
|
|
|
|
unsigned int max_entries;
|
2016-03-08 08:57:20 +03:00
|
|
|
unsigned int map_flags;
|
2014-12-02 02:06:37 +03:00
|
|
|
};
|
|
|
|
|
2015-04-02 03:12:13 +03:00
|
|
|
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
|
|
|
|
(void *) BPF_FUNC_skb_store_bytes;
|
|
|
|
static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flags) =
|
|
|
|
(void *) BPF_FUNC_l3_csum_replace;
|
|
|
|
static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flags) =
|
|
|
|
(void *) BPF_FUNC_l4_csum_replace;
|
|
|
|
|
2015-07-06 17:20:07 +03:00
|
|
|
#if defined(__x86_64__)
|
|
|
|
|
|
|
|
#define PT_REGS_PARM1(x) ((x)->di)
|
|
|
|
#define PT_REGS_PARM2(x) ((x)->si)
|
|
|
|
#define PT_REGS_PARM3(x) ((x)->dx)
|
|
|
|
#define PT_REGS_PARM4(x) ((x)->cx)
|
|
|
|
#define PT_REGS_PARM5(x) ((x)->r8)
|
|
|
|
#define PT_REGS_RET(x) ((x)->sp)
|
|
|
|
#define PT_REGS_FP(x) ((x)->bp)
|
|
|
|
#define PT_REGS_RC(x) ((x)->ax)
|
|
|
|
#define PT_REGS_SP(x) ((x)->sp)
|
2016-04-04 20:01:34 +03:00
|
|
|
#define PT_REGS_IP(x) ((x)->ip)
|
2015-07-06 17:20:07 +03:00
|
|
|
|
|
|
|
#elif defined(__s390x__)
|
|
|
|
|
|
|
|
#define PT_REGS_PARM1(x) ((x)->gprs[2])
|
|
|
|
#define PT_REGS_PARM2(x) ((x)->gprs[3])
|
|
|
|
#define PT_REGS_PARM3(x) ((x)->gprs[4])
|
|
|
|
#define PT_REGS_PARM4(x) ((x)->gprs[5])
|
|
|
|
#define PT_REGS_PARM5(x) ((x)->gprs[6])
|
|
|
|
#define PT_REGS_RET(x) ((x)->gprs[14])
|
|
|
|
#define PT_REGS_FP(x) ((x)->gprs[11]) /* Works only with CONFIG_FRAME_POINTER */
|
|
|
|
#define PT_REGS_RC(x) ((x)->gprs[2])
|
|
|
|
#define PT_REGS_SP(x) ((x)->gprs[15])
|
2016-04-04 20:01:34 +03:00
|
|
|
#define PT_REGS_IP(x) ((x)->ip)
|
2015-07-06 17:20:07 +03:00
|
|
|
|
2015-10-27 03:02:19 +03:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
|
|
|
|
#define PT_REGS_PARM1(x) ((x)->regs[0])
|
|
|
|
#define PT_REGS_PARM2(x) ((x)->regs[1])
|
|
|
|
#define PT_REGS_PARM3(x) ((x)->regs[2])
|
|
|
|
#define PT_REGS_PARM4(x) ((x)->regs[3])
|
|
|
|
#define PT_REGS_PARM5(x) ((x)->regs[4])
|
|
|
|
#define PT_REGS_RET(x) ((x)->regs[30])
|
|
|
|
#define PT_REGS_FP(x) ((x)->regs[29]) /* Works only with CONFIG_FRAME_POINTER */
|
|
|
|
#define PT_REGS_RC(x) ((x)->regs[0])
|
|
|
|
#define PT_REGS_SP(x) ((x)->sp)
|
2016-04-04 20:01:34 +03:00
|
|
|
#define PT_REGS_IP(x) ((x)->pc)
|
|
|
|
|
|
|
|
#elif defined(__powerpc__)
|
|
|
|
|
|
|
|
#define PT_REGS_PARM1(x) ((x)->gpr[3])
|
|
|
|
#define PT_REGS_PARM2(x) ((x)->gpr[4])
|
|
|
|
#define PT_REGS_PARM3(x) ((x)->gpr[5])
|
|
|
|
#define PT_REGS_PARM4(x) ((x)->gpr[6])
|
|
|
|
#define PT_REGS_PARM5(x) ((x)->gpr[7])
|
|
|
|
#define PT_REGS_RC(x) ((x)->gpr[3])
|
|
|
|
#define PT_REGS_SP(x) ((x)->sp)
|
|
|
|
#define PT_REGS_IP(x) ((x)->nip)
|
2015-10-27 03:02:19 +03:00
|
|
|
|
2015-07-06 17:20:07 +03:00
|
|
|
#endif
|
2016-04-04 20:01:34 +03:00
|
|
|
|
|
|
|
#ifdef __powerpc__
|
|
|
|
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
|
|
|
|
#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
|
|
|
|
#else
|
|
|
|
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ \
|
|
|
|
bpf_probe_read(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); })
|
|
|
|
#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ \
|
|
|
|
bpf_probe_read(&(ip), sizeof(ip), \
|
|
|
|
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
|
|
|
|
#endif
|
|
|
|
|
2014-12-02 02:06:37 +03:00
|
|
|
#endif
|