You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

eBPF程序使用Ringbuffer时exec__open触发段错误求助

问题:使用ringbuffer时exec__open触发段错误

我在学习eBPF,参考一个libbpf示例项目,其中simple程序运行正常,但尝试使用ringbuffer时,调用exec__open会触发段错误。


exec.bpf.c

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include "exec.h"

struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 256 * 1024);
} rb SEC(".maps");

struct exec_params_t {
    u64 __unused;
     u64 __unused2;
 
    char *file;
};
 
SEC("tp/syscalls/sys_enter_execve")
int handle_execve(struct exec_params_t *params)
{
    struct task_struct *task = (struct task_struct*)bpf_get_current_task();
    struct exec_evt *evt = {0};
 
    evt = bpf_ringbuf_reserve(&rb, sizeof(*evt), 0);
    if (!evt) {
        bpf_printk("ringbuffer not reserved\n");
        return 0;
    }
 
    evt->tgid = BPF_CORE_READ(task, tgid);
    evt->pid = BPF_CORE_READ(task, pid);
    bpf_get_current_comm(&evt->comm, sizeof(evt->comm));
    bpf_probe_read_user_str(evt->file, sizeof(evt->file), params->file);
    bpf_ringbuf_submit(evt, 0);
    bpf_printk("Exec Called\n");
    return 0;
}
 
char LICENSE[] SEC("license") = "GPL";

exec.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>

#include "exec.skel.h"
#include "exec.h"


static int libbpf_log_fn(enum libbpf_print_level level, const char *format, va_list args){
    vprintf(format,args);
    fflush(stdout);
    return 0; 
}

static void bump_memlock_rlimit(void)
{
    struct rlimit rlim_new = {
        .rlim_cur   = RLIM_INFINITY,
        .rlim_max   = RLIM_INFINITY,
    };

    if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
        fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
        exit(1);
    }
}
   
static int handle_evt(void *ctx, void *data, size_t sz)
{
    const struct exec_evt *evt = data;

    fprintf(stdout, "tgid: %d <> pid: %d -- comm: %s <> file: %s\n", evt->tgid, evt->pid, evt->comm, evt->file);
  
    return 0;
}
    
int main(void)
{
    libbpf_set_print(libbpf_log_fn);

    printf("reached start\n");
    fflush(stdout);
    bump_memlock_rlimit();
    printf("bumped the memory limit\n");
    fflush(stdout);
    struct exec *skel = exec__open();
  
    printf("opened the ebpf program\n");
    fflush(stdout);
    exec__load(skel);
    printf("loaded the ebpf program\n");
    fflush(stdout);
    exec__attach(skel);
    printf("attached the ebpf program\n");
    fflush(stdout);

    struct ring_buffer *rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_evt, NULL, NULL);
 
    for(;;) {
        ring_buffer__poll(rb, 1000);
    }
    return 0;
}

exec.h

#ifndef __EXEC_H__
#define __EXEC_H__

struct exec_evt {
    pid_t pid;
    pid_t tgid;
    char comm[32];
    char file[32];
};

#endif // __EXEC_H__

程序输出日志(ring.log)

reached start
bumped the memory limit
libbpf: loading object 'exec' from buffer
libbpf: elf: section(3) tp/syscalls/sys_enter_execve, size 56, link 0, flags 6, type=1
libbpf: sec 'tp/syscalls/sys_enter_execve': found program 'handle_execve' at insn offset 0 (0 bytes), code size 7 insns (56 bytes)
libbpf: elf: section(4) .reltp/syscalls/sys_enter_execve, size 16, link 26, flags 40, type=9
libbpf: elf: section(5) .rodata, size 12, link 0, flags 2, type=1
libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
libbpf: license of exec is GPL
libbpf: elf: section(7) .maps, size 24, link 0, flags 3, type=1
libbpf: elf: section(16) .BTF, size 1098, link 0, flags 0, type=1
libbpf: elf: section(18) .BTF.ext, size 112, link 0, flags 0, type=1
libbpf: elf: section(26) .symtab, size 360, link 1, flags 0, type=2
libbpf: looking for externs among 15 symbols...
libbpf: collected 0 externs total
libbpf: map 'rb': at sec_idx 7, offset 0.
libbpf: map 'rb': found type = 27.
libbpf: map 'rb': found max_entries = 262144.
libbpf: map 'rb': found map_flags = 0x0.
libbpf: map 'exec.rodata' (global data): at sec_idx 5, offset 0, flags 80.
libbpf: map 1 is "exec.rodata"
libbpf: sec '.reltp/syscalls/sys_enter_execve': collecting relocation for section(3) 'tp/syscalls/sys_enter_execve'
libbpf: sec '.reltp/syscalls/sys_enter_execve': relo #0: insn #0 against '.rodata'
libbpf: prog 'handle_execve': found data map 1 (exec.rodata, sec 5, off 0) for insn 0

日志中未显示任何错误,但程序在调用exec__open时崩溃。移除所有ringbuffer相关代码后,程序可正常运行,说明问题出在BPF代码的ringbuffer使用部分。


更新:
更奇怪的是,触发段错误的环境是定制化Debian系统,内核版本6.x.x且启用了PREEMPT_DYNAMIC;但在我的个人机器(Linux Mint,内核6.8)上程序运行完全正常。

内容的提问来源于stack exchange,提问作者Huchsle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:05:54