无法以非 root 用户身份运行 bpf 程序 使用正确的程序类型设置正确的 sysctl修复指针泄漏

问题描述

我正在尝试运行我编写的一个简单的 bpf 程序。但我无法以非 root 用户身份运行它。下面是我正在尝试加载的程序,它基本上获取指向我的地图的指针,其 fd 是 map_fd(我没有显示创建地图的代码)。它以 root 用户身份运行,但由于某种原因,非 root 用户失败。

uname -a 的输出

Linux 5.8.0-38-generic #43~20.04.1-Ubuntu SMP Tue Jan 12 16:39:47 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

BPF 程序

BPF_MOV64_IMM(BPF_REG_0,0),BPF_STX_MEM(BPF_W,BPF_REG_10,BPF_REG_0,-4),BPF_MOV64_REG(BPF_REG_2,BPF_REG_10),BPF_ALU64_IMM(BPF_ADD,BPF_REG_2,BPF_LD_MAP_FD(BPF_REG_1,map_fd),BPF_RAW_INSN(BPF_CALL | BPF_JMP,BPF_FUNC_map_lookup_elem),BPF_JMP_IMM(BPF_JNE,1),BPF_EXIT_INSN(),

解决方法

TL;DR. Qeole 是正确的,您首先需要确保您使用的是允许非特权用户使用的 BPF 程序类型之一。您还需要检查您的 sysctl 设置。最后,您当前的程序有一个指针泄漏,应该在它被非特权用户加载之前修复。


使用正确的程序类型

内核只允许非特权用户加载两种类型的 BPF 程序,BPF_PROG_TYPE_SOCKET_FILTERBPF_PROG_TYPE_CGROUP_SKB。您可以在 kernel/bpf/syscall.c 中查看内核中对该条件的检查。


设置正确的 sysctl

kernel.unprivileged_bpf_disabled sysctl 控制非特权用户是否可以加载 eBPF 程序。不幸的是,它在主要发行版上设置为 0(允许加载)。

sysctl -w kernel.unprivileged_bpf_disabled=0

注意:如果您不使用非特权程序类型,我强烈建议将此 sysctl 设置为 1。


修复指针泄漏

无论上述设置如何,非特权用户加载的 BPF 程序都不允许泄漏指向用户空间的指针。例如,if the program is returning a pointer to a map value,it is considered a leak。这就是你的情况。

调用 BPF_FUNC_map_lookup_elem 后,如果 R0 非零,则应在返回之前覆盖其值(设置为 1?)。