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

非Root用户运行eBPF Hello World时.rodata map冻结失败求助

问题解决与非Root用户eBPF Hello World实现

问题根源分析

你遇到的hello.rodata map创建失败问题,本质是非特权用户默认缺少创建只读数据段map的权限,即便启用了非特权eBPF功能,内核仍会对部分map操作做权限限制。以下是具体解决步骤:


解决步骤

1. 配置内核参数(必须)

确保系统已启用非特权eBPF支持,并放开相关限制:

# 启用非特权eBPF
sudo sysctl -w kernel.unprivileged_bpf_disabled=0
# 允许非特权用户访问系统BTF信息(加载带CO-RE的程序需要)
sudo sysctl -w kernel.bpf_unprivileged_override_btf=1
# 可选:启用eBPF JIT编译提升性能
sudo sysctl -w net.core.bpf_jit_enable=1

2. 调整用户权限

将当前用户加入bpf和tracing组,获得BPF资源访问和trace文件系统权限:

sudo usermod -aG bpf $USER
sudo usermod -aG tracing $USER

执行后重新登录使组权限生效。

3. 修改用户态加载代码

在bpf_object__load前,遍历并调整hello.rodata map的标志位,去掉非特权用户不允许的只读限制:

// 在bpf_object__open_file之后添加
struct bpf_map *map;
bpf_object__for_each_map(map, obj) {
    if (strcmp(bpf_map__name(map), "hello.rodata") == 0) {
        // 移除特权级只读/只写标志
        map->def.map_flags &= ~(BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG);
        // 添加可mmap标志(非特权用户创建map的必要条件)
        map->def.map_flags |= BPF_F_MMAPABLE;
    }
}

完整非Root用户eBPF Hello World实现

1. 环境准备(内核5.10+)

安装编译依赖:

sudo apt install clang libbpf-dev linux-tools-common linux-headers-$(uname -r)

2. eBPF程序(hello.bpf.c)

#include "vmlinux.h"
#include <bpf_helpers.h>

SEC("tracepoint/syscalls/sys_enter_execve")
int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter *ctx)
{
    bpf_printk("Hello from unprivileged eBPF!\n");
    return 0;
}

char LICENSE[] SEC("license") = "GPL";

3. 用户态加载程序(hello.c)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <bpf/libbpf.h>
#include <bpf/bpf.h>

void read_trace_pipe(void)
{
    int trace_fd = open("/sys/kernel/debug/tracing/trace_pipe", O_RDONLY);
    if (trace_fd < 0) {
        fprintf(stderr, "Failed to open trace_pipe\n");
        return;
    }

    char buf[4096];
    while (1) {
        ssize_t sz = read(trace_fd, buf, sizeof(buf)-1);
        if (sz > 0) {
            buf[sz] = '\0';
            puts(buf);
        }
    }
}

int main(void)
{
    struct rlimit rlim = {
        .rlim_cur = 512UL << 20,
        .rlim_max = 512UL << 20,
    };
    if (setrlimit(RLIMIT_MEMLOCK, &rlim) != 0) {
        perror("setrlimit");
        return 1;
    }

    struct bpf_object *obj = bpf_object__open_file("hello.bpf.o", NULL);
    if (!obj) {
        fprintf(stderr, "Failed to open BPF object\n");
        return 1;
    }

    // 调整rodata map权限
    struct bpf_map *map;
    bpf_object__for_each_map(map, obj) {
        if (strcmp(bpf_map__name(map), "hello.rodata") == 0) {
            map->def.map_flags &= ~(BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG);
            map->def.map_flags |= BPF_F_MMAPABLE;
        }
    }

    if (bpf_object__load(obj) != 0) {
        perror("bpf_object__load");
        bpf_object__close(obj);
        return 1;
    }

    struct bpf_program *prog = bpf_object__find_program_by_name(obj, "tracepoint__syscalls__sys_enter_execve");
    if (!prog) {
        fprintf(stderr, "Failed to find program\n");
        bpf_object__close(obj);
        return 1;
    }

    if (bpf_program__attach(prog) != 0) {
        perror("bpf_program__attach");
        bpf_object__close(obj);
        return 1;
    }

    read_trace_pipe();

    bpf_object__close(obj);
    return 0;
}

4. 编译运行

# 编译eBPF程序
clang -target bpf -D__TARGET_ARCH_x86_64 -I/usr/include/x86_64-linux-gnu -I. -O2 -c hello.bpf.c -o hello.bpf.o
# 编译用户态程序
gcc hello.c -o hello -lbpf -lelf -lz
# 普通用户直接运行
./hello

打开新终端执行ls等命令,即可看到trace_pipe输出的eBPF日志。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:14:57