Перехват системных вызовов и интеграция 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 Map, размещаемых в разделяемой памяти. Вместе с 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-программ расширений к ФС для кэширования или управления доступом).
Источник: http://www.opennet.ru/opennews/art.shtml?num=60477