Проект bpftime развивает реализацию eBPF, работающую в пространстве пользователя

Представлен проект bpftime, развивающий runtime и виртуальную машину для выполнения обработчиков eBPF в пространстве пользователя. Bpftime позволяет создавать eBPF-сценарии трассировки и вмешательства в работу процессов, реализующие такие возможности, как uprobe и программный перехват всех системных вызовов, работающие целиком в пространстве пользователя. Отмечается, что благодаря исключению лишних переключений контекста bpftime позволяет добиться десятикратного снижения накладных расходов по сравнению с использованием функциональности uprobe и uretprobe, предоставляемой ядром Linux. Кроме того, bpftime значительно упрощает отладку, потенциально может применяться на системах без ядра Linux и не требует расширенных привилегий, необходимых для загрузки eBPF-приложения в ядро. Код проекта написан на языках С/C++ и распространяется под лицензией MIT.

Перехват системных вызовов и интеграция uprobe-проверок реализована с использованием техники перезаписи исполняемого кода (binary
rewriting), при которой обращения к системным вызовам, точкам входа и локальным функциям подменяются на переход к отладочным обработчикам через модификацию машинного кода выполняемого приложения, что значительно эффективнее организации перехвата с использованием uprobe на уровне ядра Linux.

Поддерживаются операции замены или изменения функций, прикрепления обработчиков (hook-ов) и фильтров, перенаправления, блокировки или замены параметров системных вызовов, перехвата точек входа и выхода из функций, а также подстановки обработчика по произвольному смещению в коде. Bpftime может быть прикреплён к любому работающему процессу в системе без необходимости их перезапуска или пересборки. Подстановка bpftime в процессы может осуществляться для работающих процессов через ptrace, а для загружаемых через LD_PRELOAD.

В составе bpftime развивается runtime, позволяющий прикреплять eBPF-программы к точкам трассировки системных вызовов и uprobe; виртуальная машина eBPF с JIT для обособленного выполнения программ eBPF на уровне пользовательского процесса (дополнительно поддерживается AOT-компиляция); фоновый процесс для взаимодействия с ядром и организации совместимости с uprobe-подсистемой ядра (bpftime поддерживает режим загрузки eBPF в пространство пользователя из ядра для организации совместной работы с eBPF-программами в ядре, используемыми, например, для обработки kprobe или выставляющими сетевые фильтры).

Виртуальная машина eBPF оформлена в форме подключаемой библиотеки и предоставляет API, похожий на ubpf, что позволяет использовать её для интеграции функциональности eBPF в другие проекты. Для суммарного агрегирования данных из нескольких процессов поддерживается создание совместных eBPF Maps, размещаемых в разделяемой памяти. Вместе с bpftime могут использоваться типовые обработчики eBPF, написанные для использования в ядре, а для сборки могут применяться стандартные инструменты на базе clang и libbpf.

C bpftime в пространстве пользователя могут выполняться такие системы трассировки, как BCC, bpftrace и Deepflow. Например, продемонстрировано применение скрипта sslsniff из фреймворка BCC для анализа и сохранения шифрованного трафика в nginx. Производительность nginx при выполнении sslsniff на стороне ядра снизилась на 58%, а при выносе обработчика в пространство пользователя на 12.3%.

Архитектура трассировки процессов с использованием оригинального eBPF в ядре:


Архитектура трассировки в пространстве пользователя с использованием bpftime:


Гибридный режим, в котором bpftime работает совместно с eBPF в ядре, например, для установки сетевых фильтров или выноса отдельных обработчиков в пространство пользователя:


Из планов на будущее отмечается реализация возможности подстановки исключений (Fault Injection); горячего наложения патчей (Hot Patching) для изменения логики работы или исправлении ошибок в бинарных сборках;
создание модуля к Nginx, позволяющего создавать расширения при помощи программ eBPF (например, для динамического выбора маршрутов, кэширования, применения политик безопасности и балансировки нагрузки); расширение возможностей подсистемы FUSE через использование eBPF (например, создание расширений к ФС для кэширования или управления доступом).

Release. Ссылка here.