Comment compiler le compilateur C à partir de zéro, puis compiler Unix / Linux à partir de zéro


64

Disons que je travaille pour une grande organisation de services en dehors des États-Unis et du Royaume-Uni. Nous utilisons beaucoup les serveurs UNIX et Linux.

En lisant cet article, il est mentionné qu'il serait facile d'insérer une porte dérobée dans un compilateur C, puis tout code compilé avec ce compilateur contiendrait également une porte dérobée. Maintenant, étant donné les récentes fuites concernant le mandat de la NSA / GCHQ de corriger les faiblesses des méthodes de chiffrement, du matériel et des logiciels, le compilateur est maintenant un point de défaillance critique. Toutes les distributions UNIX / Linix standard pourraient potentiellement être compromises. Nous ne pouvons pas nous permettre de faire compromettre nos systèmes, nos données et les données de nos clients par des gouvernements voyous.

Compte tenu de ces informations, je souhaite créer un compilateur de confiance à partir de rien, puis je dispose d’une base sécurisée sur laquelle je peux construire le système d’exploitation et les applications à partir du code source utilisant ce compilateur.

Question

Quelle est la manière correcte (et sécurisée) de compiler un compilateur à partir du code source (un scénario apparemment surprenant) puis de compiler une distribution Unix / Linux sécurisée à partir de zéro?

Vous pouvez supposer que moi-même ou d'autres personnes ont la capacité de lire et de comprendre le code source pour détecter les failles de sécurité, le code source sera donc vérifié avant la compilation. Ce que je cherche vraiment, c’est un guide de travail permettant de produire ce compilateur à partir de zéro en toute sécurité et pouvant être utilisé pour compiler le noyau, d’autres parties du système d’exploitation et des applications.

La pile de sécurité doit commencer au niveau de base si nous voulons avoir confiance dans le système d'exploitation ou les applications qui s'exécutent sur cette pile. Oui, je comprends qu'il peut y avoir des backdoors matériels qui peuvent insérer du microcode dans le compilateur au cours de sa construction. Nous ne pouvons pas grand-chose à ce sujet pour le moment, sauf peut-être utiliser des puces non conçues aux États-Unis. Faisons en sorte que cette couche soit triée au début et supposons que je puisse la construire sur un vieil ordinateur avant d’introduire des portes dérobées.

Comme le dit Bruce Schneier: "Aux ingénieurs, je dis ceci: nous avons construit Internet et certains d'entre nous ont contribué à le subvertir. Maintenant, ceux d'entre nous qui aiment la liberté doivent le réparer."

Liens supplémentaires:


7
Zut, c'est une question très intéressante et je ne veux pas la migrer mais je ne pense pas vraiment que c'est le sujet ici. Il convient mieux à stackoverflow.com puisque votre question de base concerne la compilation d’un compilateur à partir de zéro, qui est à peu près indépendante de tout système d’exploitation et qui constitue une question de programmation. Si vous n'obtenez pas de réponse après un moment, utilisez le lien "drapeau" sous les balises de votre question et demandez à un modérateur de le déplacer vers un SO.
Terdon

2
@terdon Cela conviendrait peut-être mieux à Programmers.SE puisqu'il s'agit davantage de problèmes de programmation généraux que d'un problème de développement spécifique. En fait, il pourrait y avoir un doublon .
un CVn

2
GCC est open source, comment n'importe quelle porte dérobée serait insérée?
Michael Pankov

2
Gardez à l'esprit que l'exploit de Thompson stable nécessite un code pouvant reconnaître le moment où le programme de connexion ou le compilateur est en cours de compilation. Si vous pouvez transformer manuellement la source en un formulaire que le compilateur ne reconnaît pas comme l'un de ces programmes, la porte dérobée ne sera pas propagée.
Russell Borogove

2
@Constantius - lisez l'article de Thompson lié à la première ligne. Qui compile le compilateur?
Russell Borogove

Réponses:


30

Autant que je sache, le seul moyen d’être totalement sûr de la sécurité serait d’écrire un compilateur en langage assembleur (ou de modifier le disque directement vous-même ). C'est seulement à ce moment-là que vous pourrez vous assurer que votre compilateur n'insère pas de porte dérobée - cela fonctionne car vous éliminez complètement le compilateur.

À partir de là, vous pouvez utiliser votre compilateur "from-scratch" pour amorcer, par exemple, la chaîne d'outils GNU. Vous pouvez ensuite utiliser votre chaîne d’outils personnalisée pour compiler un système Linux From Scratch .

Notez que pour vous simplifier la tâche, vous pourriez avoir un deuxième compilateur intermédiaire, écrit en C (ou dans une autre langue). Ainsi, vous écririez le compilateur A en assembleur, puis réécrivriez ce compilateur en C / C ++ / Python / Brainfuck / quoique ce soit pour obtenir le compilateur B, que vous compileriez à l'aide du compilateur A. Vous utiliseriez ensuite le compilateur B pour compiler gcc et amis.


13
Même dans ce cas, cela ne protège toujours que contre un compilateur malveillant. Vous devez toujours faire confiance au système sur lequel le compilateur s'exécute. Aucun logiciel n'existe isolément.
un CVn

3
Tout ce qui est autonome est intrinsèquement dangereux. Vous proposez effectivement un compilateur (bien qu'étrange) de chaîne d'outils, ce qui signifie qu'il peut probablement être modifié exactement de la manière que vous essayez d'éviter. Mieux encore, il pourrait être modifié en transit via MitM.
Strugee

1
Vous devez comprendre que cette réponse vient d'un jeune de 15 ans. Continuez en tant que membre!
mardi

3
Il ne faut pas oublier d’écrire aussi un éditeur de code à partir de rien - qui sait si votre <code> vim </ code> précompilé ou le <code> vim </ code> que vous compilez avec votre bon compilateur depuis la source que vous n’avez audité qu’en utilisant infecté <code> vim </ code> est digne de confiance?
Hagen von Eitzen

1
N'oubliez jamais que, sauf si vous avez personnellement écrit ce premier code machine (pas d'assemblage. Code machine réel), et que vous êtes un expert en reconnaissance des failles de sécurité sournoises, vous avez lu et vérifié chaque ligne de code que vous compilez… ou du moins que vous connaissez. la personne qui l' a fait personnellement , et lui faire confiance pour le faire .... rien de tout cela ne va aider du tout. C'est pourquoi essayer de Kickstarter cela ruine tout le problème. Qui est: haute fiabilité.
Evi1M4chine

22

Un moyen possible, même si cela prendrait très longtemps dans la pratique, serait de retourner aux sources. Le développement de GNU a commencé en 1984, et la version originale de Minix (utilisée au début du développement de Linux pour l’amorçage) a été publiée en 1987.

Toute votre réponse repose sur votre prémisse selon laquelle "vous ou d'autres personnes avez la capacité de lire et de comprendre le code source pour détecter les failles de sécurité, le code source sera donc préalablement vérifié avant la compilation", et vous pouvez faire confiance au résultat d'une telle analyse. . Sans cela, cette réponse est probablement pire que sans valeur, car vous passerez énormément de temps sans aucun bénéfice.

Si vous pouvez trouver une copie du livre Minix original avec le code source, vous pouvez la saisir à partir du livre. Compilez-le, puis utilisez un décompilateur différent sur un système différent pour vérifier que le compilateur génère la sortie binaire attendue en langage machine. (Le code ne contient que 12 000 lignes, probablement C, cela prend donc beaucoup de temps mais reste raisonnable si vous êtes sérieux au sujet d'un tel projet.) Vous pouvez même écrire votre propre désassembleur; cela ne devrait pas être très difficile.

Prenez les versions les plus anciennes des utilitaires GNU sur lesquels vous pouvez éventuellement mettre la main (car celles-ci ont probablement moins de code et moins de dépendances vis-à-vis de bibliothèques externes), parcourez le code, compilez-le pour Minix (cela pourrait prendre du travail, cependant; Ce que vous voulez absolument éviter, c’est d’apporter des ajustements au code source, car cela rendrait l’ajout de correctifs très sujet aux erreurs par la suite) et suivrait un cycle de désassemblage-vérification similaire pour les outils GNU. À ce stade, vous faites confiance au système d’exploitation et à la chaîne d’outils, il vous suffit donc de consulter le code source du patchset (tout ce qui n’est pas dans le patchset est déjà approuvé), mais les outils seront toujours très primitifs et rudimentaires par rapport à ce que vous avez utilisé. À aujourd'hui. Par exemple, n'espérez rien de plus que les fonctionnalités les plus élémentaires des outils système.Lire beaucoup de XKCD.

À un moment donné, vous disposerez d’un système capable de compiler et d’amorcer une première version du noyau Linux, un peu comme ce fut le cas au début des années 90, lorsque Linux commença à gagner du terrain parmi les pirates. À ce stade, je suggèrerais de migrer vers Linux (reconstruire les bibliothèques système et la chaîne d’outils contre Linux, compiler le noyau Linux, démarrer sous Linux et éventuellement reconstruire le noyau Linux et la chaîne d’outils GNU sous Linux; le dernier prouve que le système est maintenant autonome. hébergement), mais c’est à vous de décider. Continuez à vérifier les correctifs, à patcher le noyau, les bibliothèques et les outils GNU de base, et à reconstruire jusqu’à ce que vous obteniez les versions modernes.

Vous disposez alors d’un système d’exploitation de base et d’un compilateur fiables qui peuvent être utilisés pour créer des logiciels modernes. D'ici là, vous pouvez suivre, par exemple, les guides Linux From Scratch pour créer un système capable d'exécuter des tâches utiles .

À aucun moment, le système "compilateur" ne peut jamais être connecté à un réseau (y compris en tant que VM sur un hôte en réseau); vous risqueriez de pénétrer dans tout composant compatible réseau, y compris le noyau. Si vous craignez une attaque du compilateur Thompson , vous devez vous attendre à ce que tout hôte de machine virtuelle puisse également être compromis. Utilisez sneakernet pour obtenir le code source et les fichiers binaires de l'hôte physique sur lequel vous compilez des éléments. Attendez-vous à rencontrer des problèmes pour obtenir des fichiers sur et hors du système au moins avant d'arriver au point où la prise en charge du stockage de masse USB a été mise en œuvre. Si vous êtes vraiment paranoïaque, des listes de code source d'impression et saisissez - les à la main (et nous espérons que le pilote d'imprimante et l' imprimante ne sont pas un code similaire dans les), ou lisez le code sur l’écran d’un ordinateur et saisissez-le dans un autre ordinateur physiquement à côté, mais non connecté.

Oui, cela prendra beaucoup de temps. Mais l’avantage de cette approche est que chaque étape est incrémentielle, ce qui signifie qu’il serait beaucoup plus difficile de faire passer tout ce qui est malfaisant à moins de l’introduire très progressivement sur une période de plusieurs versions; ceci parce que l'ensemble des modifications à chaque étape est relativement petit et donc beaucoup plus facile à examiner. Comparez le patch avec le journal des modifications et assurez-vous que vous pouvez déterminer exactement quelle entrée du journal des modifications correspond à chaque modification du code source. Encore une fois, cela suppose que vous avez la possibilité (éventuellement par l’intermédiaire de quelqu'un de confiance) de vérifier que de tels changements n’ont pas été insérés dans le code, mais cela devrait vous rapprocher d’un système de confiance, à l’exception du logiciel uniquement. approche du firmware peut.


La méthode de désassemblage-vérification est très imparfaite, car elle présume encore que la machine de vérification est totalement fiable. À moins de construire cette machine et son logiciel à partir de rien, ou de connaître la personne qui l'a fait personnellement et de lui faire confiance, cela ne se produira pas. Donc, cela n'est toujours pas sûr. Pardon. …… En outre, dans ces affaires, «aussi proche de…» signifie toujours «peu sûr», car il ne nécessite qu'un seul point indigne de confiance pour tout gâcher.
Evi1M4chine

9

Si vous avez besoin d'un compilateur de confiance, vous pouvez consulter des travaux universitaires, comme le projet compcert . C'est un compilateur construit par l'INRIA (un laboratoire public français) conçu pour être '' certifié '', c'est-à-dire pour produire un exécutable sémantiquement parfaitement équivalent au code (et bien sûr, il a été prouvé mathématiquement).


1
Tout le monde a besoin d'un compilateur de confiance. Comment les maths peuvent-ils produire un compilateur "de confiance"?
David J

@DavidJ Bootstrapping, le plus probable. Construisez un petit morceau que vous pouvez complètement vérifier et prouver que vous êtes correct, puis utilisez-le comme base pour créer des compilateurs plus complexes.
un CVn

1
"" "Ce qui distingue CompCert C de tout autre compilateur de production, c'est qu'il est formellement vérifié, à l'aide de preuves mathématiques assistées par machine, qu'il est exempt de problèmes de mauvaise compilation ." "" Compcert.inria.fr/compcert-C.html Compilation n’est plus aussi empirique qu’avant.
lgeorget

1
@ MichaelKjörling qui ne tient probablement pas compte du fait que le noyau peut être compromis pour inclure une porte dérobée dans la source du compilateur lors de la lecture par un compilateur
fratchet freak le

1
J'ai aussi trouvé ce lien qui pourrait fonctionner aussi.
David J

2

Bien que la création manuelle de votre propre compilateur comme point de départ soit la solution la plus sécurisée, une autre option consiste à installer un système à partir d’un CD d’installation datant de 5 (ou de 10) ans, qui, selon vous, a été créé avant l’existence de ces exploits. Puis utilisez-le comme base pour compiler la nouvelle source auditée.


5
L’attaque est connue du public depuis 1984. Thompson n’a probablement pas été le premier à penser à cette possibilité. Revenir aussi loin signifie que la plupart des choses que nous prenons pour acquis aujourd'hui n'étaient pas présentes. réfléchissez à ce que les ordinateurs étaient capables de faire il y a 20 ans et comparez-le à leur état actuel. Même le système de démarrage Linux Minix n’est sorti qu’en 1987 et le développement de GNU a commencé en 1984. Donc, si en théorie cela peut répondre à la question, dans la pratique, c'est en grande partie une réponse inutile.
un CVn

2
Le premier ordinateur sur lequel je pourrais potentiellement mettre la main serait un 286. Il me faudra voir si mes grands-parents l’ont toujours.
David J

1
Des points bonus pour réellement considérer cela :-). @DavidJ
11684

@ MichaelKjörling: Pas vraiment. car cela ne fait que rallonger votre chaîne de démarrage. Mais peut-être pas aussi longtemps que d'écrire votre propre compilateur à partir de zéro en langage machine.
Evi1M4chine
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.