eBPF расшифровывается как extended Berkeley Packet Filter. Когда вы работаете с Linux и хотите взаимодействовать с ядром, вам необходим такой фреймворк, как eBPF. eBPF - это фреймворк, который призван помочь разработчикам беспрепятственно запускать низкоуровневые программы ядра.
С помощью eBPF можно быстро загружать и запускать программы с минимальными накладными расходами на настройку. Если вы новичок в eBPF и работаете с программами ядра, это руководство поможет вам разобраться в eBPF и понять, как его использовать. Мы представим несколько примеров инъекции кода в ядро с использованием eBPF.
Что такое eBPF
eBPF - это аббревиатура расширенного фильтра Berkeley Packer Filter. Он выступает в качестве интерфейса в ядре Linux, позволяющего разработчикам внедрять код для взаимодействия с ядром, например, изменять его поведение или наблюдать за ним.
Впервые eBPF был выпущен как трассировщик пакетов, но в 2014 году был расширен и интегрирован в ядро Linux. Хотя в основном он помогает решать задачи трассировки, у него есть множество функциональных возможностей, в том числе он позволяет приложениям пользовательского пространства выполнять программы в пространстве ядра.
В памяти компьютера есть пространство пользователя и пространство ядра. В пространстве пользователя выполняются пользовательские программы, а пространство ядра отведено для работы драйверов и ядра. Пользовательские программы не могут выполняться в пространстве ядра. Это делается для того, чтобы исключить возможность внедрения в ядро небезопасных программ или других уязвимостей и его разрушения.
Однако eBPF предоставляет возможность запускать пользовательские программы в пространстве ядра в виде байткода. Поскольку байт-коды сложны в написании, для написания eBPF-программ необходимы фреймворки разработки, такие как BCC или Bpftrace. Эти фреймворки имеют открытый исходный код, и любой желающий может их использовать. Вы можете установить фреймворки BCC или Bpftrace и создавать программы eBPF.
Установка BCC
BCC - это набор инструментов компилятора BPF, которые помогают при написании и выполнении программ eBPF.
Начните с обновления репозитория apt:
1 | sudo apt-get update |
Установите инструменты коллекции компиляторов BPF с помощью следующей команды:
1 | sudo apt-get install bpfcc-tools linux-headers-$(uname -r) |
Будут найдены и установлены инструменты BCC, соответствующие архитектуре вашего ядра. Нажмите "y" для подтверждения установки.
Убедиться в том, что BCC установлен и работает, можно, запустив одну из его утилит для получения PID любой команды, выполняемой в терминале.
Откройте два окна терминала. В первом терминале выполните следующую команду bpfcc:
1 | sudo /usr/sbin/bashreadline-bpfcc |
На втором терминале выполните несколько команд, как показано на следующем рисунке:
Если BCC и eBPF работают на первом терминале, то во втором окне вы увидите PID команд, которые вы ввели, и временные метки.
Ваш BCC установлен. Теперь вы можете выполнять различные программы eBPF для внедрения кода в ядро для различных целей.
Установка Bpftrace
Помимо использования фреймворка BCC, вы можете использовать фреймворк Bpftrace. Он идеально подходит для решения различных задач и представляет собой утилиту командной строки, позволяющую напрямую выполнять команды eBPF.
Установите ее с помощью следующей команды:
1 | sudo apt install bpftrace |
Установив Bpftrace, вы можете развернуть свои программы eBPF. Рассмотрим несколько примеров развертывания различных программ с помощью утилиты командной строки.
Из репозитория Bpftrace GitHub можно развернуть различные "однострочные" программы. Например, можно вывести список потребления диска различными процессами, запустив следующую программу:
1 | sudo bpftrace -e 'tracepoint:block:block_rq_issue { printf("%s %d\n", comm, args->bytes); }' |
Из вывода можно заметить, что в столбцах отображаются имя процесса, размер диска и размер диска.
В выводе отображаются все процессы в ядре.
Если вы также хотите проверить количество системных вызовов по процессам, вы можете воспользоваться программой Bpftrace one-liners, выполнив следующую команду:
1 | sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter {@[comm] = count(); }' |
Вывод системных вызовов осуществляется после нажатия Ctrl + C для завершения команды. На выходе отображается имя процесса, а отчет, содержащий карту, отображается как ассоциативный массив.
В count() заносится счетчик частоты вызовов системы для каждого процесса. Если необходимо вывести список всех зондов, можно воспользоваться командой bpftrace -l, как показано ниже:
1 | sudo bpftrace -l 'tracepoint:syscalls:sys_enter_*' |
Вот так можно работать с программой eBPF в Linux.
Заключение
eBPF - это способ вставки кода в ядро Linux. Для создания и запуска eBPF-программ можно использовать такие фреймворки, как BCC и Bpftrace. В этой заметке были представлены eBPF и фреймворк для написания и выполнения eBPF-программ. Кроме того, мы привели несколько примеров программ eBPF, которые можно запустить.