iovisor / iovisor/bcc

Reserve ring buffer in kprobe and submit it in kretprobe

Open
#5,158 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
22.7k
Forks
4.1k
Avg merge
10d 4h
Merged PRs (30d)
3

Description

Hello, I'm new to eBPF. Currently, I want to use eBPF to trace the successful syscalls with high performance.
Specifically, I allocate the data in the entry of syscall (hooked by kprobe) by ringbuf_reserve and store the pointer on a map. Then, in the return of the syscall (hooked by kretprobe), I get the pointer and do ringbuf_submit/ringbuf_discard according to the return value of this syscall.

However, I got this eBPF error:
```
Unreleased reference id=3 alloc_insn=9
processed 263 insns (limit 1000000) max_states_per_insn 0 total_states 22 peak_states 22 mark_read 20

Traceback (most recent call last):
File "./kernel_trace.py", line 44, in
b.attach_kprobe(event="vfs_unlink", fn_name="trace_vfs_unlink")
File "/usr/lib/python3/dist-packages/bcc-0.31.0+0b5be9bb-py3.8.egg/bcc/__init__.py", line 877, in attach_kprobe
File "/usr/lib/python3/dist-packages/bcc-0.31.0+0b5be9bb-py3.8.egg/bcc/__init__.py", line 552, in load_func
Exception: Failed to load BPF program b'trace_vfs_unlink': Invalid argument
```
I guess this error is caused by eBPF not being aware the reserved ring buffer will be handled in kretprobe. Any idea to solve/bypass this? Thanks in advance.

Here is my code snippets

```
BPF_RINGBUF_OUTPUT(ring_buffer, 1024);

int trace_vfs_rename(struct pt_regs *ctx, struct renamedata *rd) {
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 pid = pid_tgid >> 32;
u32 tid = (u32)pid_tgid;

/* Allocate the data structure in ring buffer */
data_t *data = (data_t *)ring_buffer.ringbuf_reserve(sizeof(data_t));

if (data == NULL) {
return 0;
}

/* Fill the data structure, ignored here */

/* Insert the data ptr to map*/
currdata.update(&tid, data);
return 0;
}

int trace_return(struct pt_regs *ctx)
{
data_t **data;
u32 tid = (u32)bpf_get_current_pid_tgid();
int ret = PT_REGS_RC(ctx);

/* Get the ring buffer pointer from map */
data = currdata.lookup(&tid);
if (data == 0)
return 0;

currdata.delete(&tid);

/* Skip the failed function call */
if (ret)
return 0;

/* Submit the successful syscalls */
ring_buffer.ringbuf_submit(*data, sizeof(**data), 0);
return 0;
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the trace_vfs_rename and trace_return handlers in the issue, focusing on the ringbuf_reserve, map storage, and ringbuf_submit/ringbuf_discard flow. Check how the verifier treats reserved references across kprobe and kretprobe programs; done means establishing a supported resolution or documenting the limitation and its workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux
Domain
observability, operating-systems
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.