Apresentado o projeto bpftime, que desenvolve runtime e máquina virtual para executar manipuladores eBPF no espaço do usuário. O bpftime permite a execução completa de programas eBPF de rastreamento e interferência nos processos, utilizando recursos como uprobe e interceptação de chamadas de sistema. Destaca-se que, ao eliminar mudanças de contexto desnecessárias, o bpftime possibilita uma redução de dez vezes nas sobrecargas em comparação com a funcionalidade uprobe e uretprobe fornecida pelo núcleo do Linux. Além disso, o bpftime simplifica significativamente a depuração, podendo ser aplicado em sistemas sem núcleo do Linux e não requer permissões elevadas necessárias para carregar aplicações eBPF no núcleo. O código do projeto é escrito em C/C++ e é distribuído sob a licença MIT.
A interceptação de chamadas de sistema e a integração de verificações uprobe são implementadas utilizando a técnica de reescrita de código executável (binary rewriting), onde as chamadas de sistema, pontos de entrada e funções locais são substituídos por saltos para manipuladores de depuração através da modificação do código de máquina da aplicação em execução, o que é consideravelmente mais eficiente do que a organização de interceptação utilizando uprobe no nível do núcleo Linux.
São suportadas operações de substituição ou alteração de funções, anexação de manipuladores (hooks) e filtros, redirecionamento, bloqueio ou substituição de parâmetros de chamadas de sistema, interceptação de pontos de entrada e saída de funções, assim como a substituição de manipuladores em qualquer deslocamento no código. O bpftime pode ser anexado a qualquer processo em execução no sistema sem a necessidade de reiniciar ou recompilar. A inserção do bpftime em processos pode ser realizada para processos em execução através do ptrace, e para processos carregados através do LD_PRELOAD.
Dentro do bpftime, está em desenvolvimento um runtime que permite anexar programas eBPF a pontos de rastreamento de chamadas de sistema e uprobe; máquina virtual eBPF com JIT para execução isolada de programas eBPF no nível do processo do usuário (suporte adicional para compilação AOT); um processo em segundo plano para interagir com o núcleo e organizar a compatibilidade com o subsistema uprobe do núcleo (bpftime suporta o modo de carregar eBPF no espaço do usuário a partir do núcleo para trabalhar em conjunto com programas eBPF no núcleo, utilizados, por exemplo, para processamento de kprobe ou para aplicar filtros de rede).
A máquina virtual eBPF é estruturada como uma biblioteca plugável e fornece uma API semelhante ao ubpf, permitindo sua utilização para integrar funcionalidades eBPF em outros projetos. Para agregação de dados de vários processos, é suportada a criação de eBPF Maps compartilhados, alocados na memória compartilhada. Juntamente com bpftime, podem ser utilizados manipuladores eBPF padrão, escritos para uso no núcleo, e ferramentas padrão baseadas em clang e libbpf podem ser aplicadas para compilação.
Com bpftime no espaço do usuário, podem ser executados sistemas de rastreamento como BCC, bpftrace e Deepflow. Por exemplo, foi demonstrado o uso do script sslsniff do framework BCC para análise e armazenamento de tráfego criptografado em nginx. Nos testes realizados, o desempenho do nginx ao executar sslsniff no lado do núcleo diminui em 58%, enquanto a execução do manipulador no espaço do usuário reduz em 12,3%.
Arquitetura de rastreamento de processos com uso do eBPF original no núcleo:

Arquitetura de rastreamento no espaço do usuário utilizando bpftime:

Modo híbrido, onde bpftime opera juntamente com eBPF no núcleo, por exemplo, para estabelecer filtros de rede ou deslocar manipuladores específicos para o espaço do usuário:

Entre os planos futuros, destaca-se: a possibilidade de injeção de falhas (Fault Injection); a sobreposição de patches (Hot Patching) para alterar a lógica de operação ou corrigir erros em compilações binárias; criação de um módulo para Nginx, permitindo a construção de extensões usando programas eBPF (por exemplo, para seleção dinâmica de rotas, cache, aplicação de políticas de segurança e balanceamento de carga); ampliação das capacidades do subsistema FUSE (por exemplo, a criação de extensões em forma de programas eBPF para cache ou controle de acesso).
Fonte: opennet.ru
