无法 运行 bpf 程序作为非 root
Unable to run bpf program as non root
我正在尝试 运行 我编写的一个简单的 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, -4),
BPF_LD_MAP_FD(BPF_REG_1,map_fd),
BPF_RAW_INSN(BPF_CALL | BPF_JMP, 0, 0, 0, BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
BPF_EXIT_INSN(),
TL;DR. Qeole 是正确的,您首先需要确保您使用的是允许非特权用户使用的 BPF 程序类型之一。您还需要检查您的 sysctl 设置。最后,你当前的程序有一个指针泄漏,应该在它被非特权用户加载之前修复。
使用正确的程序类型
内核只允许非特权用户加载两种类型的BPF程序,BPF_PROG_TYPE_SOCKET_FILTER
和BPF_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?)。
我正在尝试 运行 我编写的一个简单的 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, -4),
BPF_LD_MAP_FD(BPF_REG_1,map_fd),
BPF_RAW_INSN(BPF_CALL | BPF_JMP, 0, 0, 0, BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_EXIT_INSN(),
BPF_EXIT_INSN(),
TL;DR. Qeole 是正确的,您首先需要确保您使用的是允许非特权用户使用的 BPF 程序类型之一。您还需要检查您的 sysctl 设置。最后,你当前的程序有一个指针泄漏,应该在它被非特权用户加载之前修复。
使用正确的程序类型
内核只允许非特权用户加载两种类型的BPF程序,BPF_PROG_TYPE_SOCKET_FILTER
和BPF_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?)。