Je suis en train d'étudier le développement de logiciels critiques pour la sécurité, et en particulier l'impact du choix du langage de programmation sur ce développement.
Veuillez expliquer en détail quelles langues sont couramment utilisées et pourquoi.
Ada et SPARK (qui est un dialecte Ada avec quelques crochets pour la vérification statique) est utilisé dans les milieux de l'aérospatiale pour la construction de logiciels à haute fiabilité tels que les systèmes avioniques. Il existe une sorte de écosystème d’outils de vérification de code pour ces langues , bien que cette technologie existe aussi pour plus de langues grand public également .
Erlang était conçu à partir de la base pour écriture de haute fiabilité code de télécommunication. Il est conçu pour faciliter la séparation des problèmes de récupération d’erreur (c’est-à-dire que le sous-système générant l’erreur est différent de celui qui traite l’erreur). Il peut également être soumis à des preuves formelles bien que cette capacité n'ait pas vraiment quitté les milieux de la recherche.
Langages fonctionnels tels que Haskell peuvent être soumis à des preuves formelles par des systèmes automatisés en raison de la nature déclarative du langage. Cela permet de contenir du code avec des effets secondaires dans des fonctions monadiques. Pour une preuve d'exactitude formelle, on peut supposer que le reste du code ne fait que ce qui est spécifié.
Cependant, ces langues sont collectées et la collecte est transparente pour le code, elle ne peut donc pas être raisonnée de cette manière. Les langages collectés avec les ordures ménagères ne sont normalement pas assez prévisibles pour les applications en temps réel difficiles, bien qu'il existe un corpus de recherches en cours dans les éboueurs incrémentiels limités dans le temps.
Eiffel et ses descendants prennent en charge une technique appelée Design By Contract qui fournit un mécanisme d’exécution robuste pour l’intégration de pré-contrôles et de post-contrôles pour invariants . Tandis que Eiffel n’a jamais vraiment compris, le développement de logiciels très fiables consiste généralement à écrire des vérifications et des gestionnaires pour les modes de défaillance en amont avant d’écrire les fonctionnalités.
Bien que C et C++ n'aient pas été spécifiquement conçus pour ce type d'application, ils sont largement utilisés pour les logiciels intégrés et critiques pour la sécurité. plusieurs raisons. Les principales propriétés de note sont le contrôle de la gestion de la mémoire (ce qui vous permet d'éviter d'avoir à nettoyer, par exemple), des bibliothèques d'exécution simples, bien déboguées et un support pour les outils développés. Un grand nombre des chaînes d'outils de développement intégrées utilisées aujourd'hui ont été développées pour la première fois dans les années 1980 et 1990, alors qu'il s'agissait de la technologie actuelle. Elles proviennent de la culture Unix qui prévalait à cette époque. Ces outils restent donc populaires pour ce type de travail.
Le code de gestion manuelle de la mémoire doit être soigneusement vérifié pour éviter les erreurs, mais il permet un contrôle des temps de réponse des applications qui n’est pas disponible avec les langues qui dépendent de garbage collection. The durée d’exécution de base). bibliothèques des langages C et C++ sont relativement simples, matures et bien compris, ils figurent donc parmi les plates-formes les plus stables disponibles. La plupart des outils d’analyse statique utilisés pour Ada, sinon tous, prennent également en charge C et C++, et il existe de nombreux d’autres outils similaires disponibles pour C . Il y a aussiplusieurslargementtiliséC/C++baséoutilchaînes ; la plupart des chaînes d'outils utilisées pour Ada sont également disponibles dans des versions prenant en charge C et/ou C++.
méthodes formelles tel que sémantique axiomatique (PDF), notation Z ou processus séquentiels en communication permet à la logique du programme d'être mathématique vérifiées et sont souvent utilisées dans la conception de logiciels critiques pour la sécurité lorsque l’application est suffisamment simple pour les appliquer (généralement des systèmes de contrôle intégrés). Par exemple, n de mes anciens professeurs a fait la preuve formelle de l’exactitude d’un système de signalisation pour le réseau ferroviaire allemand.
Le principal inconvénient des méthodes formelles est leur tendance à croître de manière exponentielle en complexité par rapport au système sous-jacent à prouver. Cela signifie qu’il existe un risque important d’erreurs dans la preuve, elles sont donc pratiquement limitées à des applications relativement simples. Les méthodes formelles sont assez largement utilisées pour vérifier l'exactitude du matériel, car les bugs matériels sont très coûteux à corriger, en particulier pour les produits grand public. Depuis le bug de Pentium FDIV , les méthodes formelles ont beaucoup attiré l'attention et ont été utilisées tilisées pour vérifier l'exactitude de la FP sur tous les processeurs Intel depuis le Pentium Pro.
De nombreux autres langages ont été utilisés pour développer des logiciels hautement fiables. Beaucoup de recherches ont été effectuées sur le sujet. On peut raisonnablement soutenir que la méthodologie est plus importante que la plate-forme bien qu'il existe des principes tels que la simplicité et la sélection et le contrôle des dépendances qui pourrait exclure l'utilisation de certaines plates-formes .
Comme plusieurs autres l'ont noté, certaines plates-formes O/S possèdent des fonctionnalités favorisant la fiabilité et un comportement prévisible, telles que des minuteries de surveillance et des temps de réponse garantis. La simplicité est également un facteur important de fiabilité. De nombreux systèmes RT sont délibérément conservés très simples et compacts. QNX ( seul celui que je connais bien, ayant déjà travaillé avec un système de traitement par lots à partir de celui-ci) est très petit et ne peut tenir que sur une seule disquette. OpenBSD - qui est connu pour sa sécurité robuste et son audit de code approfondi - permet également de garder le système simple.
EDIT: This post contient des liens vers de bons articles sur les logiciels critiques pour la sécurité, en particulier Ici et ici . Les accessoires à S.Lott et Adam Davis pour la source. L'histoire de la THERAC-25 est un peu un travail classique dans ce domaine.
Pour C++, la norme de codage C++ de Joint Strike Fighter (F-35) est une bonne lecture:
Je crois que Ada est toujours utilisé dans certains projets gouvernementaux critiques pour la sécurité et/ou les missions. Je n'ai jamais utilisé la langue, mais c'est sur ma liste de "apprendre", avec Eiffel. Eiffel propose Design By Contract, censé améliorer la fiabilité et la sécurité.
Premièrement, les logiciels critiques pour la sécurité adhèrent aux mêmes principes que ceux que l'on pourrait observer dans les domaines classiques de l'ingénierie mécanique et électrique. Redondance, tolérance aux pannes et sécurité en cas de défaillance.
En passant, et comme l'a déjà dit l'affiche précédente (et pour une raison quelconque, le vote a été rejeté), le facteur le plus important pour y parvenir est que votre équipe ait une compréhension sans faille de tout ce qui se passe. Il va sans dire qu'une bonne conception logicielle de votre part est la clé. Mais cela implique aussi un langage accessible, mature, bien soutenu, pour lequel il existe de nombreuses connaissances communes et des développeurs expérimentés.
De nombreuses affiches ont déjà fait remarquer que le système d'exploitation est un élément clé à cet égard, ce qui est très vrai surtout parce qu'il doit être déterministe (voir QNX ou VxWorks). Cela exclut la plupart des langages interprétés qui font les choses dans les coulisses pour vous.
L'ADA est une possibilité, mais il y a moins d'outils et de soutien, et plus important encore, les gens stellaires ne sont pas aussi facilement disponibles.
C++ est une possibilité, mais seulement si vous appliquez strictement un sous-ensemble. À cet égard, c’est l’outil du diable, qui promet de nous rendre la vie plus facile, mais qui en fait souvent trop,
C est idéal. Il est très mature, rapide, dispose d’un ensemble diversifié d’outils et d’un support, de nombreux développeurs expérimentés, multiplate-forme et extrêmement flexible, pouvant travailler à proximité du matériel.
De tout ce que j'ai développé, de Smalltalk à Ruby), j'apprécie et j'apprécie tout ce que les autres langues ont à offrir. Mais lorsque je développe des systèmes critiques, je mords avec C. mon expérience (défense et de nombreux dispositifs médicaux de classe II et III) est moins, plus.
Je choisirais haskell si la sécurité était primordiale. Je propose haskell car il comporte une vérification de type statique très rigide et favorise la programmation dans laquelle vous construisez des pièces de manière à ce qu'elles soient très faciles à tester.
Mais alors, je ne me soucierais pas beaucoup de la langue. Vous pouvez obtenir beaucoup plus de sécurité sans compromettre autant en gardant votre projet globalement en état et en respectant les délais. Globalement, il faut que toute la gestion de projet de base soit en place. Je pourrais peut-être me concentrer sur des tests approfondis pour vérifier que tout fonctionne comme il se doit, des tests couvrant tous les cas critiques et plus.
La langue et le système d'exploitation sont importants, mais le design aussi. Essayez de le garder nu, simple comme bonjour.
Je commencerais par disposer du minimum d'informations d'état (données d'exécution), afin de minimiser les risques d'incohérence. Ensuite, si vous souhaitez bénéficier d'une redondance à des fins de tolérance aux pannes, assurez-vous de disposer de moyens à toute épreuve pour récupérer les données incohérentes. Redondance sans moyen de remédier à l'incohérence, c'est simplement demander des ennuis.
Ayez toujours une solution de rechange lorsque les actions demandées ne sont pas terminées dans un délai raisonnable. Comme ils le disent dans le contrôle du trafic aérien, une autorisation non reconnue n'est pas une autorisation.
N'ayez pas peur des méthodes de vote. Ils sont simples et fiables, même s’ils risquent de perdre quelques cycles. Évitez les traitements qui reposent uniquement sur des événements ou des notifications, car ils peuvent facilement être supprimés, dupliqués ou mal ordonnés. En plus des scrutins, ils vont bien.
Un de mes amis du projet APOLLO a un jour fait remarquer qu'il savait qu'ils devenaient sérieux quand ils ont décidé de recourir à des sondages plutôt qu'à des événements, même si l'ordinateur était extrêmement lent.
P.S. Je viens de lire les normes relatives aux véhicules aériens C++. Ils sont OK, mais ils semblent supposer qu’il y aura beaucoup de classes, de données, de pointeurs et d’allocation dynamique de mémoire. C’est exactement ce qu’il ne faut pas plus qu’absolument nécessaire. Il devrait y avoir un tsar de structure de données avec une grosse faux.
Le système d'exploitation est plus important que la langue. Utilisez un noyau en temps réel tel que VxWorks ou QNX. Nous avons examiné les deux pour contrôler les robots industriels et avons décidé d’utiliser VxWorks. Nous utilisons C pour le contrôle du robot.
Pour les logiciels réellement critiques, tels que les systèmes d'autoland d'avions, vous souhaitez que plusieurs processeurs s'exécutent indépendamment pour vérifier les résultats.
Les environnements en temps réel ont généralement des exigences "critiques pour la sécurité". Pour ce genre de chose, vous pouvez regarder VxWorks , un système d’exploitation en temps réel populaire. Il est actuellement utilisé dans de nombreux domaines tels que les avions Boeing, les composants internes BMW iDrive, les contrôleurs RAID et divers engins spatiaux. ( Check it out .)
Le développement pour la plate-forme VxWorks peut être fait avec plusieurs outils, parmi lesquels Eclipse , Workbench , SCORE , et d'autres. C, C++, Ada et Fortran (oui, Fortran) sont pris en charge, ainsi que d'autres.
Voici quelques mises à jour pour certains outils que je n'avais pas encore vus, avec lesquels j'ai joué récemment et qui sont assez bons.
L'infrastructure de compilateur LLVM , un bref texte de présentation sur leur page principale (inclut les interfaces clientes pour C et C++. Des interfaces clientes pour Java, Scheme et d'autres langages sont en développement);
Une infrastructure de compilateur - LLVM est également un ensemble de code source qui implémente le langage et la stratégie de compilation. Les principaux composants de l’infrastructure LLVM sont un front-end C & C++ basé sur GCC, un cadre d’optimisation du temps de liaison avec un ensemble croissant d’analyses et de transformations globales et interprocédurales, des back-end statiques pour X86, X86-64, PowerPC. 32/64, architectures ARM, Thumb, IA-64, Alpha, SPARC, MIPS et CellSPU, un back-end émettant du code C portable et un compilateur Just-In-Time pour X86, X86-64, PowerPC 32/64 processeurs, et un émetteur pour MSIL.
VCC ;
VCC est un outil qui prouve l'exactitude des programmes C concurrents annotés ou trouve des problèmes en eux. VCC étend C avec des fonctionnalités de conception par contrat, telles que les pré-et post-conditions ainsi que les invariants de type. Les programmes annotés sont convertis en formules logiques à l'aide de l'outil Boogie, qui les transmet à un solveur SMT Z3 automatisé pour vérifier leur validité.
VCC utilise la version récemment publiée Common Compiler Infrastructure .
Ces deux outils, LLVM ou VCC, sont conçus pour prendre en charge plusieurs langages et architectures. Je pense qu’il s’agit d’une hausse du codage par contrat et d’autres pratiques de vérification formelle.
WPF (pas le framework MS :), est un bon point de départ si vous essayez d’évaluer quelques-uns des travaux de recherche récents et des outils de validation du programme. espace.
WG2 est la ressource principale pour les détails critiques du langage de développement de systèmes assez actuels et spécifiques . Celles-ci couvrent tous les domaines (Ada, C, C++, Java, C #, Scripts, etc.) et disposent au minimum d’un ensemble de références et de conseils judicieux pour la mise à jour des informations sur les failles et les vulnérabilités spécifiques au langage.
Puisque vous ne donnez pas de plate-forme, je devrais dire C/C++. Sur la plupart des plates-formes temps réel, les options sont relativement limitées.
Les inconvénients de la tendance de C à vous laisser vous tirer dans le pied sont compensés par le nombre d'outils permettant de valider le code et par la stabilité et l'adressage direct du code aux capacités matérielles de la plate-forme. De plus, vous ne pourrez pas vous fier à des logiciels tiers qui n’ont pas fait l’objet d’un examen approfondi - cela inclut la plupart des bibliothèques - même beaucoup de ceux fournis par les fournisseurs de matériel.
Puisque tout sera votre responsabilité, vous voulez un compilateur stable, un comportement prévisible et une correspondance étroite avec le matériel.
Il y a beaucoup de bonnes références sur http://www.dwheeler.com ("logiciel à haute assurance").
Pour les véhicules, voir la norme MISRA C. C mais vous ne pouvez pas utiliser plus de deux niveaux de pointeurs, et quelques autres choses comme ça.
adahome.com a de bonnes informations sur Ada. J'ai aimé ce tutoriel C++ to Ada: http://adahome.com/Ammo/cpp2ada.html
Tom Hawkins a réalisé quelques trucs intéressants sur Haskell. Voir: ImProve (le langage intègre un solveur SMT pour vérifier les conditions de vérification) et Atom (EDSL pour la programmation simultanée en temps réel sans utiliser de tâches ou de threads réels).
Une nouvelle norme de sécurité critique pour Java est en cours de développement - JSR 302: Sécurité critique Java Technologie .
Le Java critique (SCJ) est basé sur un sous-ensemble de RTSJ. L'objectif est de disposer d'un cadre approprié pour le développement et l'analyse de programmes critiques pour la sécurité pour la certification en matière de sécurité (DO-178B, niveau A et autres normes critiques pour la sécurité).
SCJ, par exemple, supprime le tas, qui est toujours présent dans RTSJ, il définit également 3 niveaux de conformité auxquels application et VM implémentation peuvent se conformer. Les niveaux de conformité sont définis pour faciliter la certification d'applications très complexes.
Ressources:
N'importe quel produit logiciel peut passer le processus de certification DO-178b en utilisant n'importe quel outil, mais la question est de savoir à quel point ce serait difficile. Si le compilateur n'est pas certifié, vous devrez peut-être démontrer que votre code est traçable au niveau de l'assembly. Il est donc utile que votre compilateur soit certifié. Nous avons utilisé C dans nos projets, mais nous devions vérifier au niveau de Assembly et utiliser une norme de code qui incluait la désactivation de l'optimiseur, l'utilisation limitée de la pile, l'utilisation limitée des interruptions, des bibliothèques certifiables transparentes, etc. Le plan de l'AFPC semble plus réalisable.
À mesure que les applications grossissent, le code d'assemblage devient un choix moins viable. Le processeur ARM invite simplement le C++, mais si vous demandez à des entreprises comme Kiel si leur outil est certifié, elles reviendront avec un "hein?". Et n'oubliez pas que les outils de vérification doivent également être Essayez de vérifier un programme de test LabView.
Un langage qui impose des modèles soigneux peut aider, mais vous pouvez imposer des modèles soigneux en utilisant n’importe quel langage, même un assembleur. Chaque hypothèse sur chaque valeur a besoin d'un code qui teste l'hypothèse. Par exemple, testez toujours le diviseur à zéro avant de le diviser.
Plus vous pouvez faire confiance aux composants réutilisables, plus la tâche est facile, mais les composants réutilisables sont rarement certifiés pour une utilisation critique et ne vous feront pas passer à travers les processus de sécurité réglementaires. Vous devez utiliser un petit noyau de système d'exploitation, puis construire de minuscules modules testés avec une entrée aléatoire. Une langue comme Eiffel pourrait aider, mais il n’ya pas de solution miracle.
HAL/S est utilisé pour la navette spatiale.
Je ne sais pas quelle langue utiliser, mais je sais quelle langue je ne voudrais pas:
NOTE ON Java SUPPORT. LE PRODUIT LOGICIEL PEUT CONTENIR UN SUPPORT POUR LES PROGRAMMES ÉCRITS EN Java. Java TECHNOLOGIE IS PAS DE TOLÉRANT PAR DÉFAUT AND IS NON CONÇU, FABRIQUÉ, OR DESTINÉ À ÊTRE UTILISÉ OR REVENDU EN TANT QUE MATÉRIEL DE COMMANDE EN LIGNE DANS DES ENVIRONNEMENTS DANGEREUX EXIGEANT DES PERFORMANCES FAVORABLES, TELLES QUE DANS L’EXPLOITATION DES INSTALLATIONS NUCLÉAIRES, DE LA NAVIGATION AÉRONAUTIQUE OR SYSTÈMES DE COMMUNICATION, CONTRÔLE DE LA CIRCULATION AÉRIENNE, MACHINES DE SOUTIEN DIRECTE À LA VIE, OR SYSTÈMES D’ARMES À FEU , DANS LEQUEL L'ÉCHEC DE Java LA TECHNOLOGIE PEUT ENGAGER DIRECTEMENT À LA MORT, BLESSURE PERSONNELLE, OR PHYSIQUE GRAVE OR DOMMAGES À L'ENVIRONNEMENT .