XDP 程序 ip 链接错误:Prog 部分被拒绝:不允许操作

bin*_*Int 3 linux networking bpf xdp-bpf

我尝试进入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;
}
Run Code Online (Sandbox Code Playgroud)

但如果我尝试将其加载到虚拟接口中veth-basic02,则会收到此错误:

$ sudo ip -force link set dev veth-basic02 xdp 对象 xdpsock_kern.o 部分 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)
Run Code Online (Sandbox Code Playgroud)

封锁:

$ 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
Run Code Online (Sandbox Code Playgroud)

编辑: echo 1 > /proc/sys/kernel/sysrq++echo x > /proc/sysrq-trigger确实Alt+SysRq+x解决了问题 - 我终于可以加载 XDP 程序了!不过有趣的复活节彩蛋。谢谢@Qeole!

Qeo*_*ole 8

eBPF:不允许操作

\n\n

使用 eBPF 时,有多种可能的原因导致权限错误(-EPERM由 返回bpf(),您可以使用 观察)。strace -e bpf <command>但没有那么多。通常,它们属于以下项目之一:

\n\n
    \n
  • 用户不具备所需的能力CAP_SYS_ADMINCAP_NET_ADMIN、 ... 通常取决于所使用的程序的类型)。这通常可以通过运行 asroot来解决,它具有所有必要的功能。在你的情况下,你与 一起运行sudo,所以你被覆盖了。

  • \n
  • 创建 BPF 对象(新映射或加载程序)将超出用户可以在内核中锁定的内存量限制。这通常可以root通过ulimit -l <something_big>在终端或setrlimit()C 程序中使用来解决(对于 ) 。在你的情况下不太可能,你的程序非常小,并且你没有提到在你的系统上加载了很多 BPF 对象。

  • \n
  • 还有一些可能性,例如尝试在 \xe2\x80\x9cfrozen\xe2\x80\x9d 或只读等映射上写入,或者尝试对非用户使用函数调用root。这些通常用于更高级的用例,不应该使用像您的程序一样简单的程序。

  • \n
\n\n

锁定、安全启动、EFI 和(不幸的)bpf()限制向后移植

\n\n

但您似乎遇到的问题可能与其他问题有关。\xe2\x80\x9cLockdown\xe2\x80\x9d 是一个安全模块,已合并到 Linux 5.5 内核中。它的目的是防止用户修改正在运行的Linux镜像。事实证明,多个发行版决定将 Lockdown 向后移植到其内核,有时他们会选择早于合并到主线 Linux 的最终版本的补丁。

\n\n

例如,Ubuntu 和 Fedora 有一堆自定义补丁,可以将该功能向后移植到 Disco/19.04 和 Eoan/19.10 中使用的内核(后者的内核 5.3,我不记得 Disco 的内核)。它包含一个补丁,可以在激活 Lockdown 时完全禁用bpf()系统调用,这意味着无法创建地图或加载 BPF 程序。此外,他们在激活安全启动时默认启用锁定,我认为这是使用 EFI 启动的计算机的默认设置。

\n\n

另请参阅这篇博客文章:检查 Lockdown 是否影响 BPF 使用的一个好方法是尝试加载最小的程序,或者运行dmesg | grep Lockdown看看它是否显示如下内容:

\n\n
Lockdown: systemd: BPF is restricted; see man kernel_lockdown.7\n
Run Code Online (Sandbox Code Playgroud)\n\n

例如,对于Ubuntu 19.04 和 19.10,您必须禁用 Lockdown 才能与 eBPF 一起使用。这可以通过物理敲击SysRq+ 键x来完成(我没有测试过),但不能通过写入来完成/proc/sysrq-trigger(Ubuntu禁用了此操作)。或者,您可以禁用安全启动(在 BIOS 中或使用mokutil,在 Internet 上搜索相关选项,并且不要忘记检查安全含义)。

\n\n

请注意,Linux 内核 5.4 或最新版本对具有主线限制bpf(),不会停用系统调用,因此 Focal/20.04 和最新版本不会受到影响。因此,升级到新内核可能是另一种解决方法。几天前我提交了一张票,bpf()要求向后移植此更改(而不是停用),并且工作正在进行中,因此当新读者查看答案时,锁定对 eBPF 的影响可能会得到缓解(编辑:应该在内核 5.3.0-43 的 Ubuntu 19.10 上已修复)。不确定其他发行版如何处理这个问题。不过,它仍然对使用 eBPF 进行跟踪有很大的影响

\n