Injecteur de fautes pour application distribuée
24 mars 2008 – 15:10Dans le cadre d’un projet scolaire, je travaille sur un projet concernant la sécurité des grilles de calcul. Rappelons qu’une grille de calcul désigne un ensemble d’ordinateurs interconnectés et qui ne sont pas nécessairement homogènes. Ce type d’architecture est utilisé majoritairement pour faire tourner des applications nécessitant une très grande puissance de calculs. Avec le temps, la taille de ces application tend à augmenter, donc les besoins en matière de sécurité également. Le but du projet sur lequel je travaille en ce moment est de concevoir un injecteur de fautes pour application distribuée. Cet injecteur doit permettre en quelque sorte de faire planter une application tournant en parallèle sur plusieurs machines, afin de mettre à l’épreuve sa tolérance aux fautes. Ce billet présente rapidement l’architecture de notre logiciel, qui est toujours en développement.
Pour concevoir une application parallèle, on utilise assez souvent la programmation par messages. Dans le cadre de notre projet, nous utilisons la bibliothèque LAM/MPI qui fournit toute une API permettant d’envoyer des messages à des processus tournant sur des machines distantes. De plus, le but étant d’injecter des fautes, nous avons choisit de provoquer ces fautes lors des envois et réceptions de messages. Ainsi nous pouvons facilement simuler aussi bien les pannes logicielles (déni de service) et matérielles (coupure de lien d’un réseau, paquet perdu ou corrompu). Pour détourner les fonctions fournies par la bibliothèque LAM/MPI, nous utilisons la variable d’environnement LD_PRELOAD. Cette variable des systèmes UNIX/Linux permet de charger dynamiquement une bibliothèque au lancement d’une application. Le point intéressant est que cette bibliothèque peut redéfinir des fonctions qui existent déjà dans les autres bibliothèques, donc peut potentiellement les appeler tout en modifiant leur comportement.
LD_PRELOAD permet alors de modifier le comportement d’une application tout en n’ayant pas besoin de la recompiler ! Il est toutefois important de préciser que cette technique ne permet de détourner (hooker) que les fonctions définies dans des librairies dynamiques. C’est un point crucial et qui nous a posé quelques problèmes. En effet nous utilisions au départ la librairie MPICH 1, et il se trouve que lorsqu’une application est compilée avec, les appels MPI sont liés de manière statique. Un simple appel à la commande ldd permet de le voir. C’est pourquoi nous avons choisis d’utiliser LAM/MPI à la place.
Ainsi, nous avons développé une bibliothèque dynamique (fichier .so) dont le but est de venir d’interposer entre l’application parallèle et LAM/MPI. Cette bibliothèque (que nous avons nommé bibliothèque d’interposition) redéfinit les fonctions MPI_Send() et MPI_Recv() en injectant des fautes comme des corruptions de données et des dénis de service. Les fautes ne sont pas générées de manière permanentes ; nous utilisons en plus un processus qui tourne en tâche de fond (démon) qui communique avec la librairie par l’intermédiaire d’un segment de mémoire partagé. Ce démon est en réalité un serveur utilisant CORBA. Son rôle est de rester en attente de requêtes et de dialoguer avec la librairie pour déclencher l’injection de fautes. Il surveille également l’application ainsi que le système par l’intermédiaire de sondes logicielles afin de suivre en temps réel les valeurs de quelques variables, comme la charge CPU, l’occupation mémoire, etc. Ces valeurs sont sauvegardées dans une base de données pour être retraitées plus tard par un module de statistiques.
Sur chaque machine tournent donc : une instance de l’application distribuée, une instance de la bibliothèque d’interposition, et une instance du démon. Mais en plus de tout cela, il faut être capable de déployer l’application parallèle. Nous avons donc conçu un module dédié à cela, le simulateur. Il est contrôlable en ligne de commande ou via une interface graphique. Son but est de lancer l’application parallèle, les démons et activer le détournement de fonction en exportant la variable LD_PRELOAD sur toutes les machines.
Ce projet, bien que relativement complexe, se révèle très intéressant. Cela nous a permis de découvrir et d’utiliser des libraires et des technologies très utiles, comme CORBA, MPI, Boost, MySQL++. Nous utilisons également Flex et Bison pour la conception de l’interpréteur de commandes du simulateur.
Au fut et à mesure du développement, je mettrai sans doute en ligne quelques billets exposant de façon plus détaillée la conception de certains des modules.
Désolé, les commentaires sont fermés pour le moment.