linux - XDP 程序 ip 链接错误:Prog 部分被拒绝:不允许操作
问题描述
我尝试进入XDP
,为此我有一个非常小的程序:
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include "bpf/bpf_helpers.h"
#include "xdpsock.h"
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, MAX_SOCKS);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
} xsks_map SEC(".maps");
SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx) {
return XDP_DROP;
}
但是,如果我尝试将其加载到虚拟接口veth-basic02
中,则会出现此错误:
$ sudo ip -force link set dev veth-basic02 xdp object xdpsock_kern.o section xdp_sock
Prog 部分“xdp_sock”被拒绝:不允许操作 (1)!- 类型:6 - 说明:2(0 超限) - 许可证:
验证者分析:
获取程序/地图时出错!
内核版本:5.3.0-28-generic
这是我正在使用的 Makefile:
OBJS = xdpsock_kern.o
LLC ?= llc
CLANG ?= clang
INC_FLAGS = -nostdinc -isystem `$(CLANG) -print-file-name=include`
EXTRA_CFLAGS ?= -O2 -emit-llvm
# In case up-to-date headers are not installed locally in /usr/include,
# use source build.
linuxhdrs ?= /usr/src/linux-headers-5.1.0-050100
LINUXINCLUDE = -I$(linuxhdrs)/arch/x86/include/uapi \
-I$(linuxhdrs)/arch/x86/include/generated/uapi \
-I$(linuxhdrs)/include/generated/uapi \
-I$(linuxhdrs)/include/uapi \
-I$(linuxhdrs)/include \
-I/bpf
prefix ?= /usr/local
INSTALLPATH = $(prefix)/lib/bpf
install_PROGRAM = install
install_DIR = install -dv
all: $(OBJS)
.PHONY: clean
clean:
rm -f $(OBJS)
INC_FLAGS = -nostdinc -isystem `$(CLANG) -print-file-name=include`
$(OBJS): %.o:%.c
$(CLANG) $(INC_FLAGS) \
-D__KERNEL__ -D__ASM_SYSREG_H \
-Wno-unused-value -Wno-pointer-sign \
-Wno-compare-distinct-pointer-types \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-address-of-packed-member -Wno-tautological-compare \
-Wno-unknown-warning-option \
-I../include $(LINUXINCLUDE) \
$(EXTRA_CFLAGS) -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
install: $(OBJS)
$(install_DIR) -d $(INSTALLPATH) ; \
$(install_PROGRAM) $^ -t $(INSTALLPATH)
uninstall: $(OBJS)
rm -rf $(INSTALLPATH)
封锁:
$ dmesg | grep Lockdown
[ 1.283355] Lockdown: swapper/0: Hibernation is restricted; see man kernel_lockdown.7
[ 11.313219] Lockdown: systemd: /dev/mem,kmem,port is restricted; see man kernel_lockdown.7
[ 11.337794] Lockdown: systemd: BPF is restricted; see man kernel_lockdown.7
[ 17.147844] Lockdown: Xorg: ioperm is restricted; see man kernel_lockdown.7
编辑:
++echo 1 > /proc/sys/kernel/sysrq
确实解决了问题——我终于可以加载 XDP 程序了!不过有趣的复活节彩蛋。谢谢@Qeole!echo x > /proc/sysrq-trigger
Alt+SysRq+x
解决方案
eBPF:不允许操作
使用 eBPF 时,权限错误(-EPERM
由 返回bpf()
,您可以观察到)有几个可能的原因。strace -e bpf <command>
但没有那么多。通常,它们属于以下项目之一:
用户没有所需的能力(
CAP_SYS_ADMIN
,CAP_NET_ADMIN
, ... 通常取决于所使用的程序的类型)。这通常通过运行 asroot
来解决,因为它具有所有必要的能力。在你的情况下,你运行sudo
,所以你被覆盖了。创建 BPF 对象(新映射或加载程序)将超过用户可以锁定在内核中的内存量的限制。这通常通过在终端或C 程序中
root
使用来解决(对于)。在您的情况下不太可能,您的程序非常小,并且您没有提到在您的系统上加载了很多 BPF 对象。ulimit -l <something_big>
setrlimit()
还有更多的可能性,比如尝试在“冻结”或只读的地图上写入等,或者尝试对非
root
用户使用函数调用。这些通常用于更高级的用例,不应使用像您这样简单的程序。
锁定、安全启动、EFI 和(不幸的)反向移植bpf()
限制
但是您似乎遇到的问题可能与其他问题有关。“Lockdown”是一个安全模块,已合并到 Linux 5.5 内核中。它旨在防止用户修改正在运行的 Linux 映像。事实证明,有几个发行版决定将 Lockdown 向后移植到他们的内核中,有时他们会选择在最终版本之前的补丁,该最终版本合并到主线 Linux。
例如,Ubuntu 和 Fedora 有一堆自定义补丁可以将该功能反向移植到 Disco/19.04 和 Eoan/19.10 中使用的内核(后者的内核是 5.3,我不记得 Disco 的内核)。它包括一个补丁,当 Lockdown 被激活时完全禁用bpf()
系统调用,这意味着创建地图或加载 BPF 程序是不可能的。此外,当 Secure Boot 被激活时,他们默认启用 Lockdown,我认为这是使用 EFI 引导的机器的默认设置。
另请参阅此博客文章:检查 Lockdown 是否影响您的 BPF 使用的一个好方法是尝试加载最少的程序,或者运行dmesg | grep Lockdown
以查看它是否显示如下内容:
Lockdown: systemd: BPF is restricted; see man kernel_lockdown.7
因此,例如,对于 Ubuntu 19.04 和 19.10,您必须禁用 Lockdown 才能使用 eBPF。这可以通过SysRq
+ 键x
的物理敲击来完成(我没有测试过),但不能通过写入来完成/proc/sysrq-trigger
(Ubuntu为此操作禁用了它)。或者,您可以禁用安全启动(在 BIOS 中或使用mokutil
,在 Internet 上搜索相关选项,不要忘记检查安全隐患)。
请注意,Linux 内核 5.4 或最新版本对 有主线限制,bpf()
不会停用系统调用,因此 Focal/20.04 和最新版本不会受到影响。因此,升级到新内核可能是另一种解决方法。几天前我提交了一张票bpf()
,要求将此更改向后移植(而不是停用)并且工作正在进行中,因此当新读者查看答案时,锁定对 eBPF 的影响可能会得到缓解(编辑:应该在内核 5.3.0-43 的 Ubuntu 19.10 上修复)。不确定其他发行版如何处理这个问题。不过,它仍然会对使用 eBPF 进行跟踪产生重大影响。
推荐阅读
- c# - 从自引用表中获取层次结构需要花费大量时间才能生成 Linq
- javascript - 在 Javascript 中访问目标按钮
- google-chrome - 适用于 Kiosk 模式的 Chromebook 渐进式网络应用
- css - 无法将素材图标垂直居中
- path - 在 Fish Shell 中修改单个用户 $PATH
- user-interface - 删除 Qt 中的填充
- python - 在 Python 中添加当前时间 2 小时并以时间戳打印时间
- ms-access - MS Access:对多个表的交叉表查询(多对多关系)
- javascript - javascript - 根据属性重新排序对象数组
- javascript - 将所有类移动到其他类(jQuery)