XDP程序ip链接错误:Prog部分被拒绝:不允许操作 [英] XDP program ip link error: Prog section rejected: Operation not permitted
问题描述
我尝试进入XDP
,为此,我有一个非常小的程序:
I try to get into XDP
, for this I have this very small program:
// 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
中,则会出现此错误:
But if I try to load it into a virtual interface veth-basic02
, I get this error:
$ sudo ip -force链接集dev veth-basic02 xdp对象xdpsock_kern.o xdp_sock部分
$ sudo ip -force link set dev veth-basic02 xdp object xdpsock_kern.o section xdp_sock
编程节'xdp_sock'被拒绝:不允许操作(1)! -类型:6 -说明:2(超出限制0) -许可证:
Prog section 'xdp_sock' rejected: Operation not permitted (1)! - Type: 6 - Instructions: 2 (0 over limit) - License:
验证者分析:
获取程序/地图时出错!
Error fetching program/map!
内核版本:5.3.0-28-generic
这是我正在使用的Makefile:
This is the Makefile I am using:
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
+ echo x > /proc/sysrq-trigger
+ Alt+SysRq+x
确实解决了问题-我终于可以加载XDP-Program了!虽然有趣的复活节彩蛋.谢谢@Qeole!
echo 1 > /proc/sys/kernel/sysrq
+ echo x > /proc/sysrq-trigger
+ Alt+SysRq+x
indeed solves the problem - I can finally load the XDP-Program! Funny easter egg though. Thank you @Qeole!
推荐答案
eBPF:不允许操作
使用eBPF时,有几种可能的原因导致权限错误(bpf()
返回的-EPERM
,您可以通过strace -e bpf <command>
观察到).但是没有那么多.通常,它们属于以下项目之一:
eBPF: Operation not permitted
There are several possible causes for a permission error (-EPERM
returned by bpf()
, which you can observe with strace -e bpf <command>
) when working with eBPF. But no so many. Usually, they fall under one of the following items:
-
用户没有所需的功能(
CAP_SYS_ADMIN
,CAP_NET_ADMIN
等通常取决于所使用程序的类型).通常可以通过以root
运行来解决此问题,该功能具有所有必需的功能.在您的情况下,您可以使用sudo
运行,因此可以满足要求.
User does not have the required capabilities (
CAP_SYS_ADMIN
,CAP_NET_ADMIN
, ... typically depending on the types of the programs being used). This is usually solved by running asroot
, who has all necessary capabilities. In your case you run withsudo
, so you are covered.
创建BPF对象(新映射或加载程序)将超出用户可以锁定在内核中的内存量限制.通常(对于root
)可以通过在终端中使用 ulimit -l <something_big>
或在C程序中使用 setrlimit()
来解决.在您的情况下,您的程序非常小,并且您没有提到在系统上加载了很多BPF对象.
Creating the BPF object (new map, or loading a program) would exceed the limit for the amount of memory that can be locked in the kernel by the user. This is usually solved (for root
) by using ulimit -l <something_big>
in the terminal, or setrlimit()
in a C program. Very unlikely in your case, your program is very small and you did not mention having a lot of BPF objects loaded on your system.
还有更多的可能性,例如尝试在冻结"或只读的地图上书写等,或者尝试在非地图上使用函数调用root
用户.这些通常用于更高级的用例,不应被像您这样简单的程序所破坏.
There are a few more possibilies, like trying to write on maps that are "frozen" or read-only etc., or trying to use function calls for non-root
users. These are usually for more advanced use cases and should not be hit with a program as simple as yours.
但是您似乎遇到的问题可能与其他原因有关. 锁定"是已合并到Linux 5.5内核中的安全模块.它旨在防止用户修改正在运行的Linux映像.事实证明,有几个发行版决定将Lockdown移植到其内核中,有时他们选择的补丁要早于最终版本,该最终版本已合并到主线Linux中.
But the problem that you seem to be hitting could be related to something else. "Lockdown" is a security module that was merged into Linux 5.5 kernel. It aims at preventing users to modify the running Linux image. It turns out that several distributions decided to backport Lockdown to their kernels, and sometimes they picked patches that predated the final version that was merged to mainline Linux.
Ubuntu和Fedora具有完全禁用bpf()
系统调用,这意味着无法创建地图或加载BPF程序.此外,它们已启用激活安全启动后默认情况下会锁定,我认为这是使用EFI引导计算机的默认设置.
Ubuntu and Fedora, for example, have a bunch of custom patches to backport that feature to the kernels used in Disco/19.04 and Eoan/19.10 (kernel 5.3 for the latter, I don't remember for Disco). It includes a patch that completely disables the bpf()
system call when Lockdown is activated, meaning that creating maps or loading BPF programs is not possible. Also, they enabled Lockdown by default when Secure Boot is activated, which, I think, is the default for machines booting with EFI.
另请参见这篇博客文章:检查锁定是否影响您的BPF使用的一个好方法是尝试加载最少的程序,或者运行dmesg | grep Lockdown
看看它是否显示类似内容:
See also this blog post: a good way to check if Lockdown is affecting your BPF usage is to try and load minimal programs, or to run dmesg | grep Lockdown
to see if it says something like:
Lockdown: systemd: BPF is restricted; see man kernel_lockdown.7
例如,对于 Ubuntu 19.04和19.10 ,您必须禁用锁定才能使用eBPF .这可以通过 SysRq
键+ x
的物理笔触来完成(我尚未测试),但不是通过写/proc/sysrq-trigger
来完成(Ubuntu
So for Ubuntu 19.04 and 19.10, for example, you have to disable Lockdown to work with eBPF. This may be done with a physical stroke of the SysRq
key + x
(I have not tested), but NOT by writing to /proc/sysrq-trigger
(Ubuntu disabled it for this operation). Alternatively, you can disable Secure Boot (in the BIOS or with mokutil
, search for the relevant options on the Internet, and do not forget to check the security implications).
请注意,Linux内核5.4或最新版本具有主线限制bpf()
的a>不会取消激活系统调用,因此Focal/20.04和最新版本不会受到影响. 升级到新内核可能是另一种解决方法.我几天前提交了罚单要回传的更改(而不是停用bpf()
)并且工作正在进行中,因此,当新读者看到答案时,锁定对eBPF的影响可能会得到缓解(应该修复在具有内核5.3.0-43的Ubuntu 19.10上).不确定其他发行版如何处理此问题.不过,它仍然对使用eBPF进行跟踪具有强大的含义.
Note that Linux kernel 5.4 or newest has the mainline restrictions for bpf()
, which do not deactivate the system call, so Focal/20.04 and newest will not be affected. Upgrading to a new kernel might thus be another workaround. I filed a ticket a few days ago to ask for this change to be backported (instead of deactivating bpf()
) and the work is in progress, so by the time new readers look at the answer Lockdown impact on eBPF might well be mitigated ( Should be fixed on Ubuntu 19.10 with kernel 5.3.0-43). Not sure how other distros handle this. And it will still have strong implications for tracing with eBPF, though.
这篇关于XDP程序ip链接错误:Prog部分被拒绝:不允许操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!