Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reserve ring buffer in kprobe and submit it in kretprobe #5158

Open
KendrickChou opened this issue Nov 26, 2024 · 1 comment
Open

Reserve ring buffer in kprobe and submit it in kretprobe #5158

KendrickChou opened this issue Nov 26, 2024 · 1 comment

Comments

@KendrickChou
Copy link

KendrickChou commented Nov 26, 2024

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 <module>
    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;
}
@KendrickChou KendrickChou changed the title Store ring_buffer_reserve ptr in a map and use them in later hook Store ringbuf_reserve ptr in a map and use them in later hook Nov 26, 2024
@KendrickChou KendrickChou changed the title Store ringbuf_reserve ptr in a map and use them in later hook Reserve ring buffer in kprobe and commit it in kretprobe Nov 26, 2024
@KendrickChou KendrickChou changed the title Reserve ring buffer in kprobe and commit it in kretprobe Reserve ring buffer in kprobe and submit it in kretprobe Nov 26, 2024
@yonghong-song
Copy link
Collaborator

data_t **data; in trace_return() is incorrect. You should just do data_t *data;.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants