I am new to ebpf and trying to use ebpf to inspect tcp packets.
I hooked kprobe on tcp_v4_rcv() and my programs are below (just modified a helloworld program):
//hello_kern.c
#include <linux/tcp.h>
#include <uapi/linux/bpf.h>
#include <uapi/linux/tcp.h>
#include "bpf_helpers.h"
SEC("kprobe/tcp_v4_rcv")
int bpf_prog(void *ctx, struct sk_buff* skb)
{
struct tcphdr* th;
int dest;
char msg[] = "hello world! My dest is %d\n";
th = tcp_hdr(skb);
dest = th->dest;
bpf_trace_printk(msg, sizeof(msg), dest); //comment this line can make program run
return 0;
}
char _license[] SEC("license") = "GPL";
//hello_user.c
#include "bpf_load.h"
int main(void)
{
if (load_bpf_file("hello_kern.o"))
return -1;
read_trace_pipe();
return 0;
}
Compiling was just fine. But when I run this program the following error happened:
bpf_load_program() err=13
0: (b7) r1 = 680997
1: (63) *(u32 *)(r10 -8) = r1
2: (18) r1 = 0x2073692074736564
4: (7b) *(u64 *)(r10 -16) = r1
5: (18) r1 = 0x20794d2021646c72
7: (7b) *(u64 *)(r10 -24) = r1
8: (18) r1 = 0x6f77206f6c6c6568
10: (7b) *(u64 *)(r10 -32) = r1
11: (69) r1 = *(u16 *)(r2 +178)
R2 !read_ok
processed 9 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
I tried comment the line of "bpf_trace_printk" and program just run successfully (without anything printed out). Did I use bpf_trace_printk wrong?
btw is there any well-organized ebpf tutorial or documents I can refer to? I can only find some tutorial blogs. If anyone knows please tell me. thx :)
Anyway I tried many times and finally code below works.
Key points: 1. use bpf_probe_read to read address in kernel space; 2. do not use tcp_hdr().
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <uapi/linux/bpf.h>
#include <uapi/linux/tcp.h>
#include "bpf_helpers.h"
SEC("kprobe/tcp_v4_rcv")
int bpf_prog(struct pt_regs *ctx)
{
struct sk_buff *skb= (struct sk_buff *)PT_REGS_PARM1(ctx);
struct tcphdr *th;
unsigned short dest;
char msg[] = "hello world! My dest is %u\n";
bpf_probe_read(&th, sizeof(struct tcphdr *), &(skb->data));
// bpf_probe_read(th, sizeof(struct tcphdr *), (skb->data)); Wrong! idk why.
bpf_probe_read(&dest, sizeof(unsigned short), &(th->dest));
bpf_trace_printk(msg, sizeof(msg), ntohs(dest));
return 0;
}
char _license[] SEC("license") = "GPL";