Summer of Code
Mai 24th, 2006Juste ce petit billet pour vous faire part de ma joie d'avoir ete selectionne pour faire partie du Google Summer of Code 2006. Comme je le disais dans le precedent post, je travaillerai sur les client et serveur NFS du Hurd, afin de les rendre entierement compatibles avec NFSv2/v3, d'y ajouter des interfaces specifiques au Hurd et de commencer un support NFSv4 (en goodie pour la fin ;-).
L'essentiel de mon temps en informatique cet ete sera donc consacre a NFS. Malheureusement, le jeu des attributions a fait que Google n'a donne cette annee que 10 places au projet GNU, alors que plus de 25 projets avaient soumis des idees de tache. Pour le Hurd, cela se traduit par une place pour 14 propositions (et 12 personnes). Je suis vraiment desole pour les recales dont les projets etaient plus que convaincants et utiles : notamment, j'espere que syn aura le temps de travailler sur le support du son sous GNU/Hurd et que quelqu'un d'autre pourra travailler sur l'implementation d'une nouvelle pile TCP/IP.
Un autre projet tres enthousiasmant en rapport avec le Hurd a ete accepte : le port de debian-installer pour GNU/Hurd. Le but est de faire un installer natif, ce qui permettrait de se dispenser de la seconde phase d'installation (et donc de pas mal de bugs), d'avoir un installer a jour et plus pratique (notamment, un qui soit capable d'installer un bootloader tout seul ;-). Marco Gerards, developpeur du Hurd, bossera lui sur le port de Xen pour Mac Intel, au moins excitant pour moi ;-)
Pour info, 6338 candidatures ont ete proposees, de la part de 3050 personnes. Au final, 629 candidats ont ete pris. Pour les autres, ce n'est que partie remise !
Mais où va le Hurd ? <cc>
Mai 19th, 2006DISCLAIMER: Ce texte n'a pas vocation à être parfaitement objectif. Il se pourrait même qu'il contienne quelques erreurs ou imprécisions. N'hésitez pas à me les communiquer le cas échéant.
Rappel des faits
À l'origine, il y a le système d'exploitation libre GNU, né en 1983 de la volonté de RMS. En 1986, GNU est un ensemble d'applications libres auquel il ne manque plus qu'un composant essentiel : le noyau. Sur ce point, la FSF et RMS tergiverseront bien des années - TRIX, Mach, Sprite, ou sa propre création... La question sera tranchée en 1991 : le Hurd, construit sur Mach, sera le noyau officiel du projet GNU.
Assez vite cependant, l'idée d'utiliser Mach sans modification s'avère très difficile : bugs, code complexe, relativement obsolète... GNU Mach convient, mais tout juste. Thomas Bushnell, créateur du Hurd, le dit lui-même : « All the core hurd hackers are interested in switching to another kernel [...] once we make a fairly stable release. »[0] Plusieurs personnes se montrent interessées, dont des contributeurs majeurs du Hurd (Okuji Yoshinori, Gordon Matzigkeit, ...). L'idée est toujours de faire un port du moindre effort : il ne s'agit pas d'éviter tant que possible de modifier le Hurd, qui est très bien comme ça - seul GNU Mach ne convient pas. Les développeurs s'intéressent particulièrement au micro-noyau L4, né en 1996 et qui présente des performances particulièrement attractives - le principal problème de Mach. Un des objectifs est de rendre le Hurd indépendant du micro-noyau. D'où l'idée d'une émulation de Mach au dessus de L4 (L4Mach) ou encore de "noyaux virtuels" : définir un jeu d'interfaces dont le Hurd a besoin pour fonctionner et implémenter ensuite ces interfaces sur chaque micro-noyau[1]. Une liste de diffusion est créée, ainsi qu'une page Web[2].
Le port sur L4
Fast forward jusqu'à 2002. Neal Walfield, un des développeurs principaux, passe l'été à Karlsruhe, avec l'équipe du projet L4Ka dans le but de commencer un port du Hurd sur L4.
Il faut rappeler un petit peu les différences entre Mach et L4 : Mach est un micro-noyau de première génération, qui inclut tout plein de services (gestion de la mémoire virtuelle, ordonnanceur, pilotes de périphérique, gestion avancée de la communication entre processus) bien qu'il en exporte beaucoup en espace utilisateur (systèmes de fichiers, gestion des utilisateurs, pagers, pile réseau, ...). L4, lui, a pour but d'aller plus loin dans le minimalisme : on ne doit garder dans le noyau que les mécanismes (à opposer aux « policies ») nécessitant des privilèges particuliers (envoi de message entre threads, changement du thread en cours d'exécution, map()/unmap(), ...). Tout le reste doit aller dans l'espace utilisateur.
Porter le Hurd sur L4, ce n'est donc pas simplement une moulinette de sed. Il faut ré-implémenter en espace utilisateur, donc différemment, ce qui est actuellement dans GNU Mach : gestion de la mémoire virtuelle, ordonnanceur avancé, pilotes de périphériques.
Maintenant que l'on sait comment, pourquoi ? Les choses sont claires : le but est d'améliorer les performances. GNU/Hurd est actuellement très lent : si une partie de cette lenteur est probablement due au fait que son code n'est pas optimisé, l'architecture de Mach est aussi en cause[3]. Mais le travail de Neal Walfield sur la gestion de la mémoire virtuelle donne une autre tournure au port du Hurd : la nécessité de réécrire les couches inférieures ouvre le champ des possibles et déjà des nouvelles fonctionnalités émergent - notamment le fait de laisser chaque tâche gérer sa mémoire comme bon lui semble.[4]
Où les problèmes commencent
Cependant un point crucial reste à concevoir : la communication entre processus. L'architecture du Hurd nécessite une isolation importante de chaque composant : les actions d'un serveur ne doivent pas permettre de compromettre un autre serveur, sauf dans les rares cas où la confiance mutuelle est nécessaire. C'est principalement Marcus Brinkmann qui s'en charge.
Le Hurd, contrairement à Unix, est basé sur le concept de « capability », c'est-à-dire qu'un composant A interagit avec un composant B au moyen de références qu'il possède sur un objet fourni par B. À ces références sont associés des droits particuliers - modification, accès aux données associées, etc. Ainsi, lorsque A souhaite accéder à l'objet désigné, il passe à B une capability, qui n'a qu'à vérifier si l'opération est permise par les droits associés à cette capability. Ce modèle est à opposer à celui des ACL. Dans ce dernier, A présente à B une référence sur un objet, référence à laquelle n'est associée aucun droit ; B détermine donc si A le droit d'effectuer l'opération demandée en fonction des droits associés à l'identité de A. Pour être clair, parlons en terme Unix : dans le modèle ACL, A demande à B une opération particulière sur un fichier en lui donnant son chemin ; B voit si A a le droit d'effectuer une telle opération en fonction de son EUID/EGID. À l'inverse, un descripteur de fichiers est une capabiity : il s'agit d'une référence sur un objet (un fichier) à laquelle sont associés des droits (le mode d'ouverture du fichier, précisé via open())[5]. Pour ceux qui se sont déjà intéressés de près au Hurd : en terme Mach, les capabilities sont à rapprocher des « port rights » (droits d'envoi/réception sur un port, auquel est associé un objet).
Une des opérations essentielles dans un système basé sur les capabilities est le transfert de celles-ci. Il s'agit d'un difficile problème de confiance impliquant au moins trois acteurs - un serveur A qui détient une capability sur un objet fourni par un serveur C, et un serveur B à qui A veut donner une copie de sa capability. C'est en concevant ce protocole que les premiers problèmes de L4 sont apparus[6]. Le but de ce billet n'est pas de rentrer dans les détails sur le problème posé : je ferai un prochain billet là-dessus. De façon simple, le problème est que L4 ne fournit pas de primitive pour copier une capability de A à B. À la place, L4 permet de mapper une capability, ce qui signifie que A peut donner le droit à B d'utiliser temporairement une capability dont A dispose sur C - jusqu'à ce que A décide de révoquer ce droit. Évidemment, le but est que B obtienne une capability sur C qui ne dépende pas de A : pour cela, la solution envisagée était d'introduire un serveur de capabilities centralisé. Ainsi, A permettrait à B d'utiliser sa capability sur C pour demander au serveur centralisé de lui délivrer une nouvelle capability sur C, indépendante de celle de A. On a donc implémenté le transfert de capability de A à B.
Cependant, cette approche pose deux problèmes majeurs. Le premier est que ce serveur centralisé de gestion des capabilities doit détenir une copie de toutes les capabilities du système. Ainsi, toute tâche qui crée une capability utilise une fraction de mémoire du serveur. Comme le serveur de capability est une ressource partagée par tous et nécessaire au bon fonctionnement du système, il serait par conception sujet aux DoS.[7][8]
Le second problème, plus important encore, est plus simple : par quel miracle le serveur peut-il donner une copie de la capability sur C à B ? Pour cela, le serveur de capabilities doit disposer d'une primitive qui lui permet d'obtenir une copie d'une capability qu'il détient et de la transmettre à un autre. Mais alors, cette primitive est exactement celle qui manque à L4 et que le serveur de capability est censé « émuler ». Il semble donc que L4 ne permette pas, actuellement, de résoudre ce problème de transfert de capabilities de façon performante - puisque récupérer une copie d'une capability nécessite alors de remonter toute la chaîne jusqu'à l'émetteur original, ce qui pose de plus des problèmes de confiance mutuelle.[9]
Dans la même veine, L4 ne fournit pas de primitive permettant de faire remplir aux capabilities leur second rôle : l'identification (le premier étant l'accès aux ressources d'un objet). En effet, il n'y a pas de moyen simple de dire si deux capabilities sont identiques ou non.
Ces problèmes ont été mis en évidence par le travail de Marcus Brinkmann, Neal Walfield et Jonathan Shapiro. Le dernier est lui-même un des auteurs de EROS et travaille actuellement sur un nouveau micro-noyau : Coyotos. La conception de son micro-noyau profite bien évidemment de ce travail, de même que les discussions présentées précédemment sont largement basées sur son travail : EROS dispose de primitives COPY - pour la copie de capability - et CMP - pour l'identification de celles-ci.[10]
Quid des solutions ?
Maintenant qu'on arrive à la fin de l'histoire, il est temps de répondre à la question : alors le « nouveau Hurd » (nom de code : HurdNG pour... Hurd Next Generation), il utilisera quel micro-noyau ? L4Ka::Pistachio, L4Ka::NextGeneration, L4.Sec, Coyotos, ou son propre noyau ? Ma réponse est simple : who cares ? La vraie question, c'est : qu'est-ce que HurdNG doit être ? De cette définition découlera un design, de ce design découleront des besoins en terme de primitives noyau, et à partir de là le choix du noyau se fera. Actuellement, Coyotos semble plus adapté que les éventuels successeurs de L4, principalement parce que la communication passe mieux entre les développeurs de HurdNG et le développeur de Coyotos. Cela pourrait changer : Jonathan Shapiro et Marcus Brinkmann ont des désaccords importants qui pourraient faire que Coyotos ne soit pas adopté, et les équipes travaillant sur L4 n'ont jamais opposé de refus formel. En bref : wait and see, et en attendant travaillons sur HurdNG.[11][12]
Mais alors, que doit-être HurdNG ? C'est une question extrêmement large à laquelle je n'ai pas de réponse, pas plus que quiconque. Les éléments de réponse se trouvent dans la discussion sur la liste de diffusion l4-hurd[13]. Cependant, une chose est claire : de la même façon que le projet de port du Hurd sur L4 en 2002 ne se limitait plus à "créer une couche de compatibilité sur L4", le projet actuel ne se limite plus à porter l'existant sur L4, en limitant le travail de réécriture/reconception aux couches inférieures. Le port du Hurd sur L4 est apparu comme la chance de revoir les concepts de base du Hurd, en faire une ré-évaluation critique et corriger les problèmes fondamentaux. Ceci se traduit par la définition de nouveaux buts.
Marcus Brinkmann évoquait sa démarche générale dans le port sur L4 dans une interview que j'ai traduite en français[14]. Il évoquait notamment les attaques par déni de service dont souffre actuellement le Hurd : c'est à mon sens un point fondamental. Ce qui rend le Hurd très difficile à debugger actuellement, c'est qu'il n'y a pas de réelle isolation : le plantage du composant que vous développez actuellement entraîne très régulièrement tout le système (et notamment le système de fichiers). Ceci est souvent lié à un problème de conception stricte des protocoles de communication entre composants, mais également à un problème de partage des ressources.
Un exemple simple : une des bibliothèques qui permet d'écrire des translators, libnetfs, nécessite que certaines fonctions rendent les structures qu'elles renvoient avec des mutex dans un certain état. Ne pas le respecter conduit logiquement à un deadlock, et donc à un blocage du processus. Problème : ce blocage du processus entraîne le blocage du système de fichier parent, et souvent, par ricochet, de tout le système.
On pourra ajouter les nombreux cas où l'on assiste à un problème de « resource accounting », c'est à dire quand un processus non privilégié amène un autre processus à allouer de sa mémoire pour lui, créant ainsi la possibilité d'un DoS (ex : auth et la création de jetons[15]) sur un serveur central.
Le travail sur un système de capabilities protégées n'est donc pas déconnecté du Hurd actuel. Il s'agit pas de créer un tout nouveau système from scratch qui n'aurait de rapport avec le Hurd que d'avoir été écrit par les mêmes développeurs. Il s'agit de répondre aux buts originaux du Hurd : isolation, principe de moindre privilège et droits positifs aux utilisateurs, même les moins privilégiés. Il s'agit aussi de corriger à la source les problèmes du Hurd.[16]
Le Hurd et HurdNG
Mais concrètement, quelle relation entre le Hurd d'aujourd'hui et HurdNG ? Il est évident qu'en terme de code, les changements seront énormes. Est-ce que ça veut dire que le projet mettra nécessairement dix ans de plus ? Je ne crois pas. Le principal problème n'est pas de réécrire le code - ça, ça va vite à faire : c'est ce qu'il y a avant et après, c'est à dire la conception et le debugging. Avoir une réévaluation critique des bases du Hurd ne peut qu'aider ce travail de conception, et l'isolation effective qui devrait en résulter aider énormément cette phase de debug.
Doit-on pour autant abandonner le Hurd tel qu'il est actuellement (nom de code : Hurd on Mach) ? Je ne pense pas non plus. D'une part parce que c'est un prototype formidable : il tourne, il permet de montrer beaucoup des avantages d'un système multi-serveurs à micro-noyau, des translators, du système d'authentification, etc[17]. Il permet aussi de comprendre et de montrer les problèmes posés par une telle architecture et les erreurs de conception (outre les exemples déjà cités, quiconque ayant déjà pensé à créer un translator nécessitant une interaction avec l'utilisateur - pour l'entrée d'un mot de passe en FTP, par exemple - se sera déjà cassé les dents sur le problème des translators passifs). Certains[18] pensent qu'il est possible de modifier Hurd on Mach - surtout Mach - de façon à résoudre ces problèmes : à mon avis, ça n'est possible qu'en réécrivant totalement GNU Mach, avec des coûts énormes pour comprendre du code totalement oublié et obsolète, le risque de garder des designs mauvais pour garder la compatibilité - et de toutes façons, on finirait par réinventer la roue, c'est à dire un micro-noyau de seconde génération. En revanche, il est utile de tenter de bosser sur Mach, de corriger des bugs, et même de tenter de corriger les erreurs fondamentales, ne serait-ce que pour distinguer les erreurs de conception (qu'on n'arrivera nécessairement pas à corriger) des erreurs d'implémentation.
Enfin, beaucoup des composants haut niveau de Hurd on Mach pourront, je pense, être réutilisés dans HurdNG : c'est pourquoi je juge encore utile de travailler cet été sur nfs(d), si le Dieu du sel le veut bien.
Je tenterai, comme je l'ai dit, de revenir sur les débats en cours : confinement et DRM[19], persistence[20], etc. En attendant, je pense que les 19 URLs en note vous fourniront un peu de lecture - la plupart ne sont que les points de départ de threads très intéressants que je vous invite à au moins parcourir pour piocher ce qui vous intéresse.
Quelques lectures
Mais comme je sais que vous êtes avides d'encore plus de lecture, je rajoute quelques URLs :
-
La présentation de Marcus Brinkmann aux derniers LSM reprenait de façon résumée le chemin parcouru depuis le début du port sur L4. Il détaille moins l'historique, mais plus les différentes possibilités qui se sont offertes à lui dans la construction d'un système de
capabilities et pourquoi il a dû les abandonner pour choisir la solution actuelle. Les slides sont disponibles, ainsi qu'un enregistrement. - HurdNG a un début de spécification : http://www.marcus-brinkmann.org/hurd-ng.pdf
- Et il y a même une partie HurdNG dans le wiki du Hurd.
-
Marcus Brinkmann a commencé une série de posts dont le but est de détailler la démarche de construction de HurdNG et l'état de ses positions sur les choix à faire. Les deux mails déjà publiés sont très riches, et les threads qui s'en suivent très instructifs :
Mon prochain billet sera probablement politique. À dans quelques semaines pour les billets techniques.
Notes et références
- Hurd Traffic (août 1999) : http://www.kerneltraffic.org/debian-hurd/dh19990817_11.html#2
- Harid Fajji on « Porting the Hurd to L4 » : http://lists.gnu.org/archive/html/bug-hurd/2000-10/msg00112.html
- Page sur L4-Hurd (2000) : http://web.archive.org/web/20020213092049/http://duff.kuicr.kyoto-u.ac.jp/~okuji/l4-hurd.html
- L'état du port sur L4 (2002) : http://kerneltrap.org/node/367/839
- Conférence de Neal Walfield en juillet 2002 : http://web.walfield.org/pub/people/neal/papers/gnu-virtual-memory-management-system-lsm-2002-07-14/html/
- Wikipédia sur les capabilities : http://en.wikipedia.org/wiki/Capability-based_security
- Marcus Brinkmann on changing kernels : http://lists.gnu.org/archive/html/l4-hurd/2005-10/msg00747.html
- Cette remarque vaut également pour tous les protocoles basés sur des sessions, c'est à dire nécessitant que le serveur garde en mémoire des informations d'état pour chaque client / opération. Dans ces protocoles, le serveur doit systématiquement faire confiance aux clients. Il y a deux solutions à ce problème : tenter de faire en sorte que la mémoire associée à ces états, bien qu'accessible qu'aux serveurs, soit comptabilisée dans la mémoire du client, ou utiliser des protocoles session-less. La première approche, bien qu'élégante, est extrêmement difficile à mettre en oeuvre (comment assurer que le client ne compromette pas le serveur par cette mémoire "prêtée" ?). C'est donc la seconde qu'adopte finalement HurdNG.
- MAP vs. COPY : http://lists.gnu.org/archive/html/l4-hurd/2005-10/msg00023.html
- Pourquoi pas COPY sur MAP : http://lists.gnu.org/archive/html/l4-hurd/2005-10/msg00361.html
- La spécification Coyotos : http://coyotos.org/docs/ukernel/spec.html
- Shapiro sur "Changer de micro-noyau ?" : http://lists.gnu.org/archive/html/l4-hurd/2005-10/msg00714.html
- Marcus Brinkmann sur "Quel micro-noyau choisir ?" : http://lists.gnu.org/archive/html/l4-hurd/2006-04/msg00050.html
- Les archives de L4-Hurd : http://lists.gnu.org/archive/html/l4-hurd/
- Interview de Marcus Brinkmann : http://wiki.hurdfr.org/index.php/InterviewMarcusWikiNerds
- Le serveur auth : http://wiki.hurdfr.org/index.php/HIG#auth
- Towards a new strategy in OS design revisited : http://lists.gnu.org/archive/html/l4-hurd/2005-10/msg00651.html
- Conférence et démos du Hurd sur Mach : ftp://ftp.hurdfr.org/hurdfr/events/Kilobug-041023.ogm
- Mach revival project : http://hurd.gnufans.org/bin/view/Mach/GNUMachRevivalProject
- Shapiro sur le débat sur le confinement : http://lists.gnu.org/archive/html/l4-hurd/2006-05/msg00056.html
- Marcus Brinkmann sur la persistence : http://lists.gnu.org/archive/html/l4-hurd/2005-10/msg00081.html
Mon blog à moi que j'ai
Mai 17th, 2006Après avoir (presque) cédé (avec une dizaine d'années de retard) à la mode des pages perso, je cède avec un peu moins de retard à celle du blog.
Au menu, posts techniques et informatifs (principalement sur le développement du Hurd, mais pas seulement), posts politiques et tout ce qui me passera par la tête et que j'aurai envie de partager avec vous. N'hésitez pas à trier par catégorie si seule une de ces catégories vous intéresse : mais promis, je ne parlerai pas de mes vacances en Crête, sauf si j'ai rencontré un coder Hurd génial là-bas.
Ce blog est hébergé par HurdFR. C'est un nouveau service aux adhérents, encore en expérimentation. Il y aura bientôt un Planet regroupant les posts sur ces blogs traitant du Hurd ou de HurdFR. Stay tuned.