Ошибка IP-связи программы XDP: раздел программы отклонен: операция не разрешена - PullRequest
3 голосов
/ 20 февраля 2020

Я пытаюсь войти в 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 объект xdpsock_kern.o раздел xdp_sock

раздел программы '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 + echo x > /proc/sysrq-trigger + Alt+SysRq+x действительно решает проблему - наконец-то я могу загрузить программу XDP! Забавное пасхальное яйцо. Спасибо @Qeole!

1 Ответ

3 голосов
/ 20 февраля 2020

eBPF: операция не разрешена

Существует несколько возможных причин ошибки разрешения (-EPERM, возвращаемой bpf(), которую можно наблюдать с помощью strace -e bpf <command>) при работе с eBPF. Но не так много. Обычно они подпадают под один из следующих пунктов:

  • У пользователя нет необходимых возможностей (CAP_SYS_ADMIN, CAP_NET_ADMIN, ... обычно в зависимости от о типах используемых программ). Обычно это решается с помощью под именем root, который обладает всеми необходимыми возможностями. В вашем случае вы используете sudo, так что вы покрыты.

  • Создание объекта BPF (новая карта или загрузка программы) будет превышать ограничение на сумму памяти, которая может быть заблокирована в ядре пользователем. Обычно это решается (для root) с помощью ulimit -l <something_big> в терминале или setrlimit() в C программе . Очень маловероятно, что в вашем случае ваша программа очень мала, и вы не упомянули, что в вашей системе загружено много объектов BPF.

  • Есть еще несколько возможностей, например пытается писать на картах, которые «заморожены» или доступны только для чтения et c., или , пытаясь использовать вызовы функций для не root пользователей . Как правило, они предназначены для более сложных случаев использования и не должны затрагивать такую ​​простую программу, как ваша.

Блокировка, безопасная загрузка, EFI и (неудачные) бэкпорты для ограничений bpf()

Но проблема, которую вы, похоже, бьете, может быть связана с чем-то другим. «Lockdown» - это модуль безопасности, который был объединен с ядром Linux 5.5. Он направлен на то, чтобы запретить пользователям изменять работающий образ Linux. Оказывается, несколько дистрибутивов решили перенести Lockdown в свои ядра, и иногда они выбирали патчи, предшествовавшие финальной версии, которая была объединена с основной веткой Linux.

Например, в Ubuntu и Fedora есть набор пользовательских патчей для бэкпорта, которые используются в ядрах, используемых в Disco / 19.04 и Eoan / 19.10 (ядро 5.3 для последних не помню для диско). Он включает в себя патч, который полностью отключает системный вызов bpf() при активации блокировки, что означает, что создание карт или загрузка программ BPF невозможны. Кроме того, они включили блокировку по умолчанию при активации Secure Boot , что, я думаю, является значением по умолчанию для машин, загружающихся с EFI.

См. Также это сообщение в блоге Хороший способ проверить, влияет ли блокировка на использование BPF, - это попробовать загрузить минимальные программы или запустить dmesg | grep Lockdown, чтобы проверить, что-то вроде:

Lockdown: systemd: BPF is restricted; see man kernel_lockdown.7

Так что для Ubuntu 19.04 и 19.10, например , вы должны отключить блокировку для работы с eBPF . Это может быть сделано с помощью физического нажатия клавиши SysRq + x (я не проверял), но НЕ путем записи в /proc/sysrq-trigger (Ubuntu отключил его для эта операция). Кроме того, вы можете отключить безопасную загрузку (в B IOS или с помощью mokutil найдите соответствующие опции в Inte rnet и не забудьте проверить последствия для безопасности).

Примечание что Linux ядро ​​5.4 или новее имеет ограничения магистрали для bpf(), которые не деактивируют системный вызов, поэтому Focal / 20.04 и новее не будут затронуты. Обновление до нового ядра может, таким образом, стать другим обходным путем . Я подал билет через несколько дней go, чтобы попросить перенести это изменение (вместо деактивации bpf()), и работа продолжается, так что к тому времени новые читатели будут смотреть на ответ Влияние блокировки на eBPF вполне можно смягчить ( Редактировать: Должно быть исправлено в Ubuntu 19.10 с ядром 5.3.0-43). Не уверен, как другие дистрибутивы справляются с этим. И он все равно будет иметь сильных последствий для трассировки с помощью eBPF .

...