[Kprobe] Get Argument Values

Get argument values of an event using Cilium's eBPF

0. Background

When a Kprobe had a event happening, it will call a function with argument named struct pt_regs *ctx with this, we can know what the register values were using some eBPF functions.

Let's assume that we were watching kprobe/tcp_v4_rcv to monitor TCP packet receive events.

1. Headers

For us to use PT_REGS_PARM1, PT_REGS_RC macros, we need to have following code:

#include <bpf/bpf_tracing.h>

Since retrieving register values are different by architectures, we need to explictly define target architecture by:

#define __TARGET_ARCH_x86

We are assuming that we have x86 system.

If you are using lots of #includes, including vmlinux.h , the target architecture definition must before any #include statements. For example, it shall be like below:

#define __TARGET_ARCH_x86
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>

If you would like to see the list of available architectures, check https://elixir.bootlin.com/linux/latest/source/tools/lib/bpf/bpf_tracing.h for more information on available architectures and their names.

2. Accessing ctx

We can retrieve the first parameter value using following statement:

struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx);

Since tcp_v4_rcv requires struct sk_buff's pointer as first argument, this will retrieve the data.

3. Accessing ctx

Since we have struct sk_buff *skb which is a pointer that points to a struct, we might fall into a temptation to use

u32 length = skb->len; // To retrieve packet length

But, this will return error something looks similar to the following message:

load program: permission denied: 19: (61) r1 = *(u32 *)(r9 +112): R9 invalid mem access 'inv' 

We need to use bpf_probe_read in order to read the values.

u32 len = 0;
bpf_probe_read(&len, sizeof(len), &skb->len);

Last updated