L’eBPF (extended Berkeley Packet Filter) permet d’exécuter des programmes sandboxés dans un contexte privilégié du noyau Linux, sans jamais modifier son code source ni charger de module noyau traditionnel. On peut la comparer, dans son rôle, à ce que JavaScript est au HTML : là où le noyau était statique une fois compilé, eBPF permet d’y écrire de mini-programmes qui s’exécutent dynamiquement lors d’événements spécifiques — une entrée-sortie disque, un appel système.
Architecture et cycle de vie
eBPF est fondamentalement une architecture de jeu d’instructions (ISA), exécutée par une machine virtuelle interne au noyau, dotée de ses propres registres, instructions et pile.
Un programme eBPF se développe dans un sous-ensemble restreint du langage C, compilé en bytecode via Clang/LLVM. Il est ensuite chargé dans le noyau via l’appel système bpf(), où un vérificateur l’analyse avant toute autorisation : absence de boucle infinie, validité des accès mémoire, respect de limites de complexité strictes. Une fois validé, il subit une compilation JIT (Just-In-Time) vers des instructions natives du processeur, pour approcher une vitesse d’exécution native. Il s’attache enfin à des points d’entrée précis — des hooks — qu’il s’agisse de points de trace (tracepoints), de sondes noyau (kprobes) ou utilisateur (uprobes), ou de points spécifiques de la pile réseau comme XDP (eXpress Data Path). La communication entre espace noyau et espace utilisateur transite par des maps (stockage clé-valeur partagé) ou des tampons circulaires (ring buffers).
Où eBPF s’emploie
Initialement conçue pour le filtrage réseau, eBPF a étendu ses usages à trois domaines principaux. En observabilité et tracing, elle permet une analyse de performance très fine avec un surcoût minimal (des outils comme tcplife ou opensnoop), la rendant utilisable en production continue. En réseautage, XDP traite ou redirige des paquets dès les premiers étages de la pile réseau, permettant une atténuation efficace des attaques DDoS. En sécurité, elle surveille l’ensemble des appels système et le trafic réseau pour bâtir des systèmes de détection d’intrusion sophistiqués.
Frameworks
Programmer directement en bytecode eBPF reste peu praticable au quotidien ; deux frameworks du projet iovisor simplifient l’accès. BCC (BPF Compiler Collection) permet d’écrire le programme en C et de l’orchestrer avec des scripts Python, Lua ou C++. bpftrace propose un langage de haut niveau, suffisamment simple pour créer des outils de diagnostic en une seule ligne de commande.
Limites et risques de sécurité
Les programmes eBPF restent volontairement contraints : taille limitée à 4096 instructions, profondeur de pile plafonnée à 512 octets, absence d’accès direct aux fonctions de synchronisation du noyau — ce qui peut d’ailleurs créer des problèmes de TOCTTOU. Contrairement à une idée reçue, eBPF n’a pas été conçue à l’origine pour la sécurité : ses sondes peuvent parfois échouer à se déclencher sans avertissement, ce qui complique son usage comme brique de confiance exclusive.
Un vecteur de malware à part entière
Des attaquants peuvent détourner eBPF pour construire des rootkits particulièrement furtifs. La fonction
bpf_probe_write_userpermet de modifier la mémoire d’un processus utilisateur pendant un appel système ;bpf_override_returnpermet de bloquer des actions de sécurité indésirables — deux primitives qui, entre de mauvaises mains, contournent directement les défenses qu’eBPF sert par ailleurs à renforcer.
L’installation d’un programme eBPF exige en principe les pleins pouvoirs root, ou des capacités spécifiques comme CAP_BPF. Pour cette raison même, de nombreuses distributions — Ubuntu en tête — désactivent par défaut eBPF pour les utilisateurs non privilégiés, afin de fermer un vecteur d’escalade de privilèges qui, sans cela, resterait ouvert par défaut.
En résumé
eBPF permet à un utilisateur d’installer dynamiquement du code exécuté dans le contexte du noyau, tout en restant orchestré depuis l’espace utilisateur — un pouvoir considérable, qui appelle une vigilance proportionnée.