• Aucun résultat trouvé

Chapitre VI : Validation expérimentale 107

VI.2 Technique d’injection de fautes utilisée 112

Notre objectif est d’évaluer la tolérance aux fautes de notre architecture, en d’autres termes l’efficacité du logiciel de défense ajouté. Les hypothèses de fautes que nous considérons sont les fautes physiques et logicielles décrites en section I.2.

Même si nous voulons vérifier le logiciel de défense, la cible d’injection de fautes est en réalité les applications. En effet, le logiciel de défense vise à éviter des défaillances applicatives. Il s’agit donc de perturber la partie fonctionnelle du logiciel pour évaluer les capacités de la tolérance aux fautes du logiciel de défense.

Les modes de défaillances considérés sont alors différents des modes de défaillance d’un système d’exploitation (échelle CRASH, section VI.1.1).

Les 3 modes de défaillances étudiés sont :

 Les défaillances applicatives. Nos mécanismes réflexifs ont pour but d’éviter ces défaillances et permettre au système de rester opérationnel, en dépit de la présence d’erreurs. Ce mode de défaillance est spécifique et doit être décrit plus précisément pour un cas d’étude donné.

 Le crash ou erreur de segmentation. En général, il est difficile de remédier à ce type de défaillance avec l’architecture de tolérance aux fautes proposée, à moins d’introduire de la redondance matérielle. Nous nous intéressons donc peu aux tests conduisant à ce type de défaillance.

 La tolérance aux fautes (TaF) ou pas d’observation. L’application fonctionne correctement, son comportement respecte les spécifications. Cela signifie soit que l’erreur injectée est latente, soit que les mécanismes de tolérance aux fautes ont traité correctement l’erreur injectée. Le temps de réponse est plus long (mais acceptable selon les contraintes temporelles imposée), lorsque les mécanismes de tolérance aux fautes ont été activés.

Les défaillances du logiciel embarqué peuvent affecter globalement les flots de données et/ou de contrôle, selon les catégories de référence que nous avons définies au chapitre III (cf. Tab.9). L’injection de fautes consiste donc à provoquer de

façon contrôlée ces défaillances, peu importe la manière. En effet, les mécanismes

de tolérance aux fautes mis en œuvre ciblent les défaillances, indifféremment de leur origine physique ou logicielle.

Les erreurs que nous injectons correspondent donc à l’ajout dans le code « d’actionneurs logiciels », tels que nous les avons définis en section IV.4.3. En effet, les actionneurs logiciels, qui permettent d’agir sur les flots de données et de contrôle, peuvent être considérés soit comme des outils de correction de l’exécution par le logiciel de défense, soit comme des outils de perturbation de l’exécution pour l’injection de fautes.

Le flot de contrôle étant principalement contrôlé par l’exécutif temps réel, une méthode relativement simple pour le perturber consiste à utiliser les services de

l’exécutif temps réel. Une connaissance fine des appels système utilisés par l’application permet même une inhibition ciblée du comportement attendu, conduisant à une défaillance particulière. Par exemple, la demande explicite d’une activation de tâche, peut être perturbée par un service de terminaison de tâche.

Pour le flot de données, une démarche analogue peut être menée en utilisant des services de communication qui inhibent ou perturbent le comportement prévu. Cela dit, dans l’état de l’art de nombreuses techniques existent pour corrompre les données (Software-In-the-Loop, Bit-Flip, etc.).

Nous nous plaçons au niveau de l’intégrateur qui maîtrise le code glue entre les applications et le logiciel de base, dont il ne dispose que des interfaces. La technique d’injection de fautes que nous utilisons consiste à utiliser des services fonctionnels du logiciel de base (services exécutifs et de communication), pour provoquer des erreurs au niveau du code glue, et entraîner des défaillances applicatives.

Le réalisme des erreurs injectées n’est pas fondamental dans notre approche orientée par les défaillances. Notons que la probabilité d’occurrence de telles erreurs de programmation dans le code est certainement très faible, pour des développeurs expérimentés ou des générateurs de codes matures ou certifiés. Cela dit, le déploiement du standard d’architecture logicielle AUTOSAR favorise l’utilisation d’outils de génération automatique de code, développé par des tiers. Malgré les nombreux avantages de cette méthode, l’utilisation d’outils commerciaux limite la maîtrise du code produit, et déplace les efforts manuels au niveau de la configuration des outils. La complexité des paramétrages, ajoutée à une connaissance limitée des outils de génération de code, augmentent le risque d’erreurs de concurrence, d’entrelacement ou d’inhibition de services de support d’exécution.

L’injection de fautes par ajout d’appels à des services exécutifs ou de communication est donc finalement représentative d’erreurs de configuration et de génération de code. Ces erreurs lorsqu’elles apparaissent réellement dans un système sont généralement permanentes. Pour notre technique d’injection de fautes, il est possible d’injecter les erreurs de manière transitoires ou permanentes. Dans le cas d’une erreur permanente, il s’agit d’insérer avant la compilation, dans une tâche, une ligne de code contenant un appel de service, qui sera appelé chaque fois que la tâche est appelée. Une erreur transitoire consiste à associer l’appel de service à un compteur qui détermine à quel moment déclencher l’appel une seule fois. Notre logiciel de défense traite a priori aussi bien les défaillances transitoires que permanentes, comme il est conçu pour traiter une défaillance chaque fois qu’elle apparaît en ligne. Il n’est donc pas réducteur de tester son efficacité seulement pour des erreurs permanentes.

La matrice de traçabilité des exigences structure notre technique d’injection de fautes. Nous définissons pour chaque type de défaillance une stratégie de vérification (cf. Tab.13). Elle consiste à déterminer les éléments du système à perturber. Elle est proche de la stratégie de détection d’erreur (cf. Tab.11, Chap.IV), à la seule différence que les éléments qui étaient tracés sont maintenant les cibles d’injections d’erreurs.

1- Type de Défaillance spécifique 7- Stratégie de Vérification Flot de données : Valeur échangée invalide (/non voulue)

L’assertion exprime les conditions dans lesquelles la valeur d’une donnée est interdite (/nominale).

Il s’agit de corrompre les éléments de la condition ou la donnée considérée. Flot de données : Temps d’échange de donnée trop long (/ trop court)

L’assertion exprime les conditions dans lesquelles le temps d’échange d’une donnée est interdit.

Il s’agit de corrompre les éléments de la condition ou la donnée considérée.

Flot de contrôle : Transition invalide

(/ non voulue)

L’assertion exprime les conditions dans lesquelles un évènement de contrôle ne doit pas (/doit) se produire.

Il s’agit de corrompre les éléments de la condition ou l’évènement de contrôle considéré.

Flot de contrôle : Séquence d’exécution invalide

(/ non voulue)

L’assertion exprime les conditions dans lesquelles une séquence d’algorithmes de calcul ou d’évènements de contrôle sont interdites (/nominale).

Il s’agit de corrompre les éléments de la condition ou l’algorithme de calcul ou l’évènement de contrôle considéré.

Flot de contrôle : Temps d’exécution

trop long (/ trop court)

L’assertion exprime les conditions dans lesquelles le temps d’exécution d’un algorithme de calcul est interdit.

Il s’agit de corrompre les éléments de la condition ou l’algorithme de calcul considéré.

Table 13 : Stratégie de vérification