failed to attach eBPF: invalid instruction — Ошибка eBPF fentry/kprobe
Архитектура ошибки и симптомы сбоя
Ошибка «fentry/kprobe: failed to attach eBPF program: invalid instruction» (сопровождающаяся кодом возврата -EINVAL) возникает при попытке загрузить или прикрепить программу eBPF (BCC, bpftrace, Cilium, Falco, Datadog/Tetragon) к точкам трассировки ядра fentry / fexit или kprobes. Ошибка означает, что загружаемый eBPF байткод содержит инструкции ISA (например, 32-bit atomics, bswap, jump bounds), не поддерживаемые текущей версией ядра, либо ядро собрано без поддержки BTF (BPF Type Format) и CONFIG_DYNAMIC_FTRACE_WITH_REGS.
Диагностическая таблица параметров сбоя
| Параметр | Значение | Инженерный смысл сбоя |
|---|---|---|
| fentry / fexit | BPF Direct Call Trampoline | Быстрый интерфейс перехвата вызовов функций ядра через BPF-трамплины (без overhead kprobes). |
| BTF (/sys/kernel/btf/vmlinux) | Type Information Metadata | Встроенная в ядро база метаданных типов C для поддержки переносимости CO-RE. |
| BPF ISA Version | v1, v2, v3, v4 | Набор инструкций виртуальной машины eBPF, заданный при компиляции в Clang/LLVM. |
Пошаговое дерево решений и сценарии траблшутинга
Сценарий 1: Проверка поддержки BTF и трамплинов в текущем ядре
# Проверка наличия файла vmlinux BTF в sysfs:
ls -lh /sys/kernel/btf/vmlinux
# Проверка обязательных флагов конфигурации ядра:
zgrep -E "(CONFIG_DEBUG_INFO_BTF|CONFIG_BPF_JIT|CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS)" /proc/config.gz || grep -E "(CONFIG_DEBUG_INFO_BTF|CONFIG_BPF_JIT)" /boot/config-$(uname -r)Если CONFIG_DEBUG_INFO_BTF не равен y, интерфейсы fentry/fexit работать не могут.
Сценарий 2: Перекомпиляция eBPF программы под совместимую версию ISA
Если компилятор Clang сгенерировал инструкции BPF v4, не поддерживаемые старыми ядрами (ниже Linux 6.0):
# Укажите флаг совместимости -mcpu=v2 или -mcpu=v3 при компиляции:
clang -O2 -target bpf -mcpu=v2 -g -c my_ebpf_prog.c -o my_ebpf_prog.oСценарий 3: Откат с fentry на стандартные kprobe точки перехвата
Если ядро хоста не поддерживает fentry (требуется Linux 5.5+ и x86_64), переключите тип программы в исходном коде или bpftrace:
# Вместо синтаксиса fentry:
# fentry:do_unlinkat { ... }
# Используйте совместимый синтаксис kprobe:
kprobe:do_unlinkat { ... }Сценарий 4: Включение JIT-компилятора eBPF
# Включение BPF JIT в ядре:
sudo sysctl -w net.core.bpf_jit_enable=1
sudo sysctl -w net.core.bpf_jit_harden=0ITSTM проводит аудит совместимости ядер Linux, сборку кастомных ядер с поддержкой BTF/CO-RE и развертывание eBPF-мониторинга.
Частые вопросы (FAQ)
Чем fentry быстрее и лучше классического kprobe?
fentry использует прямой вызов BPF-программы через трамплин (nop-инструкцию в начале функции), тратя всего несколько тактов CPU. kprobe использует программное прерывание (int3 / breakpoint), что вызывает тяжелое переключение контекста и падение производительности.
Что такое BPF CO-RE (Compile Once – Run Everywhere)?
Это технология, позволяющая скомпилировать eBPF программу один раз и запускать ее на любых версиях ядер без перекомпиляции на целевом хосте, используя метаданные типов BTF и релокации libbpf.
Почему bpftrace выдает ошибку invalid instruction на старых CentOS 7/8?
В ядрах CentOS 7 (ядро 3.10) подсистема eBPF находится в зачаточном состоянии, а в RHEL 8 ядро 4.18 не имеет встроенной поддержки BTF по умолчанию, что делает невозможным запуск современных fentry скриптов.
Как сгенерировать vmlinux.h для CO-RE программ?
Используйте утилиту bpftool: bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h.