Le Berkeley Packet Filter (BPF) ou Berkeley-Filter est in­té­res­sant pour tous les systèmes d’ex­ploi­ta­tion unixoïdes tels que Linux. L’action prin­ci­pale de la « machine virtuelle à usage spécial », dé­ve­lop­pée en 1992, est de filtrer les paquets de données des réseaux et les intégrer dans le noyau du système d’ex­ploi­ta­tion. Le BPF constitue une interface pour la sau­ve­garde des couches d’unités de données ou de pro­grammes. Les couches de sécurité ont pour tâche d’assurer la trans­mis­sion fiable des paquets de données et de contrôler l’accès à ces paquets.

Lorsqu’un de ces paquets de données parvient au des­ti­na­taire, le BPF lit les données des couches de sau­ve­garde du paquet et recherche les erreurs, par exemple. Cela permet au des­ti­na­taire de les corriger. Il peut également comparer les données avec les dé­fi­ni­tions des filtres et ainsi accepter ou rejeter un paquet qui n’est pas considéré comme pertinent. Ceci peut permettre d’éco­no­mi­ser beaucoup de capacité de calcul.

Comment fonc­tionne le Berkeley Packet Filter?

Pour intégrer ses fonctions, le Berkeley Packet Filter a été intégré comme in­ter­prète de langage machine au sein d’une machine virtuelle. En con­sé­quence, le BPF exécute un format prédéfini d’ins­truc­tions. En tant qu’in­ter­prète, le filtre de Berkeley lit les fichiers sources, les analyses et exécute ins­truc­tion par ins­truc­tion. Il traduit ensuite les ins­truc­tions en code machine pour une exécution directe.

Le filtre de Berkeley utilise les SysCalls, qui sont des appels à des fonctions spé­ci­fiques du système, prêtes à l’emploi, afin de faire des requêtes au noyau. Le noyau vérifie les droits d’accès avant d’accepter ou rejeter la demande. Les quelques 330 Linux SysCalls sont les suivants :

  • read : au­to­ri­sa­tion de lecture, avec laquelle un fichier peut être lu
  • write : au­to­ri­sa­tion d’écrire, afin qu’un dossier puisse être écrit
  • open : les fichiers ou les dis­po­si­tifs peuvent être ouverts
  • close : les fichiers ou les dis­po­si­tifs peuvent être fermés
  • stat : le statut d’un dossier est récupéré
Note

Le Berkeley-Filter peut fonc­tion­ner à la fois en mode noyau (accès maximal aux res­sources de la machine) et en mode uti­li­sa­teur (accès limité aux res­sources in­for­ma­tiques)

Avantages du Berkeley-Filter

Avec eBPF, vous pouvez filtrer les paquets de données pour éviter que des données non per­ti­nentes ne ra­len­tis­sent les per­for­mances de votre PC. Les en­re­gis­tre­ments de données inu­ti­li­sables ou in­cor­rects peuvent ainsi être rejetés ou réparés dès le départ. En outre, le BPF étendu offre une sécurité accrue grâce aux SysCalls (appels sys­té­ma­tiques) - vous pouvez fa­ci­le­ment mesurer vos per­for­mances ou les suivre grâce aux appels du système.

En 2007 déjà, la mise en œuvre du BPF a été étendue par les « Zero copy buffer ex­ten­sions ». Grâce à ces ex­ten­sions, les pilotes de pé­ri­phé­riques peuvent en­re­gis­trer les paquets de données capturés di­rec­te­ment dans le programme sans avoir à copier les données au préalable.

Pro­gram­mer des filtres avec BPF

En mode uti­li­sa­teur, vous pouvez définir des filtres in­di­vi­duels pour l'in­ter­face du Berkeley-Filter à tout moment. Dans le passé, les codes cor­res­pon­dants étaient écrits ma­nuel­le­ment et traduits en un bytecode BPF. Au­jour­d'hui, grâce au LLVM Clang Compiler, il est possible de traduire di­rec­te­ment les bytecodes.

Les bi­blio­thèques du noyau d'ex­ploi­ta­tion con­tien­nent également des exemples de pro­grammes qui sim­pli­fient la dé­fi­ni­tion des pro­grammes eBPF. Diverses fonctions d’aide vous sim­pli­fient le travail.

Les vé­ri­fi­ca­teurs de sécurité de l'eBPF

L’exécution d’appels système dans le noyau est toujours associée à certains risques de sécurité et de stabilité. Avant qu’un eBPF SysCall ne se charge, il doit passer un certain nombre de contrôles :

  1. On vérifie tout d’abord si l’appel système a été in­ter­rompu et ne contient pas de boucles. Cela pourrait conduire à un crash du noyau. Le graphique de flux de contrôle du programme est vérifié pour trouver les dé­cla­ra­tions inac­ces­sibles qui ne sont pas chargées par la suite.
  2. Avant et après l’exécution d’une ins­truc­tion, l’état de l’appel au système eBPF est vérifié. Cela permet de garantir que le BPF étendu ne fonc­tionne que dans les limites au­to­ri­sées et n'accède pas aux données en dehors de la Sandbox. Il n’est pas né­ces­saire de vérifier chaque voie in­di­vi­duel­le­ment. Un sous-ensemble est gé­né­ra­le­ment suffisant pour cela.
  3. Enfin, le type de SysCall est également défini. Cette étape est im­por­tante pour limiter les fonctions du noyau qui peuvent être appelées depuis le SysCall et les struc­tures de données aux­quelles on peut accéder. Par exemple, vous pouvez utiliser des appels système qui accèdent di­rec­te­ment aux données par paquets du réseau.

Les types SysCall traitent en gros quatre fonctions : où le programme peut être joint, quelles fonctions d'aide du noyau peuvent être appelées, si les données par paquets du réseau sont ac­ces­sibles di­rec­te­ment ou non et quel type d’objet est transmis avec priorité dans un appel système.

Ac­tuel­le­ment, les types de SysCall eBPF suivants sont pris en charge par le noyau :

  • BPF_PROG_TYPE_SOCKET_FILTER
  • BPF_PROG_TYPE_KPROBE
  • BPF_PROG_TYPE_SCHED_CLS
  • BPF_PROG_TYPE_SCHED_ACT
  • BPF_PROG_TYPE_TRA­CE­POINT
  • BPF_PROG_TYPE_XDP
  • BPF_PROG_TYPE_PERF_EVENT
  • BPF_PROG_TYPE_CGROUP_SKB
  • BPF_PROG_TYPE_CGROUP_SOCK
  • BPF_PROG_TYPE_LWT_ *
  • BPF_PROG_TYPE_SOCK_OPS
  • BPF_PROG_TYPE_SK_SKB
  • BPF_PROG_CGROUP_DEVICE
Aller au menu principal