Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Étude — Surface d’administration et placement de la configuration

Statut : note de travail, conversation en cours. Ne fait autorité sur rien. Aucune décision n’est prise ici — elle est versée pour être reprise et poursuivie.

Pourquoi. L’étude « Le chemin » a établi qu’il manquait des Managers pour orchestrer un démarrage. En tirant sur ce fil sont apparues deux questions qu’elle ne traitait pas : quels outils d’administration Air doit fournir, et où vit la configuration dans un système à racine immuable. La seconde a fait apparaître un trou réel dans la conception du modèle A/B.


1. Les Managers : ce qui existe, ce qui manque

État relevé dans l’arbre le 2026-08-02, corrigé et précisé le 2026-08-03 après un audit méthodique — la première rédaction était juste sur le compte, trop grossière sur la nature de l’écart. L’état faisant autorité vit désormais dans l’amendement d’ADR-077 (« Managers de domaine en couche 1 ») ; ce qui suit en est le résumé.

Huit Managers existentAirTaskManager (processus et threads), AirFileManager, AirMemoryManager, AirSignalManager, AirNetworkManager (sockets, pas configuration), AirEnvironmentManager, AirSystemManager, AirLogManager — mais exister n’est pas jouer le rôle. Le renommage AirProcessManagerAirTaskManager (ADR-088) est allé au bout dans le code ; il reste des mentions périmées dans les ADR et les manifestes.

Trois domaines mûrs n’ont pas de Manager — mais aucun n’est pour autant un tas de fonctions libres, et les trois cas ne sont pas de même gravité :

DomaineCe qu’il expose réellementNature de l’écart
air-deviceAirDevice, AirDeviceEnumerator, AirDeviceMonitor, AirBlockDevicesurface objet, aucune fonction libreFaible : il manque le point d’entrée médiateur unique, pas les objets
air-sandboxAirSandbox (poseur de profil, apply()), AirSandboxProfile, AirLandlockPolicy + deux fonctions de compilationMoyen — et ADR-112 nomme AirSandboxManager dans son propre titre alors que le code livre AirSandbox
air-terminalAirTerminal, PtyPair, AnsiCodec mais l’essentiel en fonctions libres (openpty, pty_*, tcgetpgrp…)Fort : ADR-077 exige nommément un AirTerminalManager

ADR-077 pose que les toits consomment une surface médiatrice. Le lanceur sera un toit, et ces trois domaines sont exactement ceux dont il aura besoin.

1.1 Managers manquants pour orchestrer un démarrage

ManagerCe qu’il porteJalon
AirMountManagermount/umount, pivot_root1 — sans lui PID 1 ne monte ni /proc, ni /sys, ni /dev
AirPowerManagerreboot(2) : redémarrer, éteindre, arrêter1
AirDeviceManagerpeupler /dev, suivre le branchement à chaud1–2
AirClockManagerrégler l’horloge système au démarrage2
AirSandboxManagerposer une cage avant exec — ce que le lanceur consulte2–3
AirCgroupManagercréer un cgroup, y placer un processus, cgroup.kill, cgroup.events3
AirLinkManagernetlink : lien haut/bas, adresse, route3
AirServiceManagersuperviser N services : dépendances, ordre, redémarrage3
AirVolumeManagerdevice-mapper, dm-verity4
AirSessionManagerles fonctions dissoutes de logindaprès 3

L’AirCgroupManager mérite qu’on s’y arrête : c’est ce qui rend l’arrêt d’un service fiable et l’attribution des journaux infalsifiable. Sans lui, air-launchd supervise comme les scripts SysV — en traquant des PID et en les perdant.

1.2 Deux pièges

Le nom AirNetworkManager est déjà pris, et il désigne les sockets. Le manager de configuration réseau ne peut pas s’appeler ainsi — collision que ADR-029 est censé prévenir. AirLinkManager est un candidat, le nom reste à arbitrer.

ADR-077 est appliqué inégalement, et l’audit du 2026-08-03 a montré que l’écart est plus large que « trois domaines sans Manager ». Il porte dans les deux sens : trois domaines mûrs n’ont pas de Manager, et à l’inverse quatre Managers existent sans que la doctrine les nomme (AirEnvironmentManager, AirSignalManager, AirMemoryManager, AirSystemManager). Plus grave, exister ne suffit pas à jouer le rôle : AirNetworkManager porte quatre méthodes — le codec sockaddr et deux options de socket — pendant que les toits consomment AirSocket directement pour tout le reste. La médiation n’est pas violée (aucun toit ne touche la couche 0), mais elle ne passe pas par le Manager.

Il faudra soit compléter, soit acter que certains domaines s’en passent — mais pas laisser la doctrine dire une chose et le code une autre. L’état complet, domaine par domaine, est consigné dans l’amendement d’ADR-077.


2. Les outils d’administration

2.1 Le patron existe déjà

air-account et air-keystore sont livrés comme binaires autonomes ; air-sshd et air-ssh ont leur sous-commande config. La doctrine fixe la forme : artefact binaire (ADR-073), CLI get/set, export/import JSON pour les agents et le versionnement, porte admin sur les mutations (ADR-101), validation à l’écriture — pas au démarrage. Une configuration invalide doit être refusée par la CLI, au bureau, pas découverte à trois heures du matin quand la machine ne remonte pas.

2.2 « Un Manager = une commande » ne tient pas

Trois cas le cassent :

  • des Managers n’ont rien à configurerAirMemoryManager, AirSignalManager, AirTaskManager sont des APIs, pas des sous-systèmes paramétrables ;
  • une configuration traverse plusieurs Managers — un « profil réseau », c’est le lien, l’adressage, la résolution, demain le filtrage ;
  • certaines configurations n’appartiennent pas au poste — les profils de confinement d’une application sont déclarés dans son manifeste.

Le bon découpage n’est pas la liste des Managers, c’est la liste des domaines de configuration : un corps d’état persistant qu’un administrateur doit pouvoir écrire, inspecter, valider et exporter.

2.3 Clarification : les Managers ne lisent pas de configuration

Qui monte les systèmes de fichiers au démarrage ? Pas AirMountManager — c’est une API, elle ne décide rien, elle exécute une opération typée. C’est air-launchd qui lit « quoi monter, où, dans quel ordre » et appelle le Manager.

La configuration appartient donc aux orchestrateurs, pas aux Managers. Si les Managers lisaient de la configuration, la politique redescendrait en couche 1 — exactement ce qu’ADR-077 refuse. La couche 1 exécute, elle ne décide pas.

2.4 Les outils, par domaine de configuration

Déjà là : air-account, air-keystore, air-sshd config, air-ssh config.

OutilDomaineJalon
air-mountQuoi monter, où, dans quel ordre, options, politique d’échec1
air-systemNom d’hôte, fuseau, locale, source de temps2
air-serviceServices, ordre, dépendances, profil de confinement, redémarrage3
air-netProfils réseau : sélection d’interfaces, adressage, routes, DNS3
air-logDestination, niveau, rotation, quotas3
air-sandboxProfils de confinement nommés, plafond du poste3
air-pkg / air-sysupdateApplications, mise à jour système4+

Deux points de conception :

air-mount — l’ordre est un graphe, pas une liste. On ne monte pas /var/log avant /var. Une liste ordonnée à la main casse dès qu’on insère une entrée : il faut exprimer des dépendances, laisser l’outil calculer l’ordre, et refuser les cycles à l’écriture. Il faut aussi une politique d’échec par entrée (bloquante ou non), sans quoi un disque absent empêche la machine de démarrer.

air-net — les noms d’interface ne sont pas stables. « Toutes les cartes ou seulement quelques-unes » appelle un sélecteur (par nom, adresse MAC, type, motif), pas une liste de noms — sinon la configuration d’une machine ne vaut que pour elle, et une image générique ne peut rien contenir d’utile.

2.5 Trois choix transverses

N binaires plutôt qu’un air à sous-commandes. Pas par goût : chaque outil devient confinable séparément, avec son profil et son octroi. air-net n’a aucune raison de pouvoir écrire la base de comptes. La granularité de l’outil épouse celle du privilège — c’est déjà le choix fait pour air-account et air-keystore.

Chaque outil doit savoir travailler hors ligne, pour produire un artefact au moment de la construction de l’image, pas seulement sur une machine vivante. Cela impose dès la conception un mode « produire vers tel arbre » en plus du mode « modifier ce système » — facile à prévoir, très pénible à rétrofitter.

Validation à l’écriture, jamais au démarrage (cf. §2.1).


3. Le placement de la configuration

C’est la partie qui a fait apparaître un trou.

3.1 Le mécanisme envisagé, et pourquoi il ne tient pas

Piste explorée : /etc sur la partition racine en lecture seule ; une partition inscriptible montée à la demande (par exemple sur /air) contenant les vrais fichiers modifiables sous /air/etc ; une commande d’administration monte /air, modifie, génère une version signée, remonte /etc en écriture, y copie l’artefact, remonte /etc en lecture seule, démonte /air.

Obstacle dur : on ne remonte pas une racine dm-verity en écriture. Ce n’est pas une politique de montage, c’est la nature de la cible : le périphérique bloc est vérifié page par page contre un arbre de Merkle dont la racine est signée et passée au démarrage. L’écriture invaliderait l’arbre, et la cible ne la prend pas en charge. L’étape « remonter /etc en écriture » est donc impossible si la racine est protégée. Et si elle ne l’est pas, tout l’édifice d’intégrité tombe.

Deux conséquences en cascade.

Le modèle A/B. La racine est ce qu’on bascule atomiquement. Si la configuration vit dedans et mute, la racine n’est plus immuable, son empreinte verity change à chaque modification, et il faut re-signer la racine sur la machine — exactement la clé qu’on ne veut pas y mettre.

La signature locale ne vaut pas ce qu’elle semble valoir. Signée par quelle clé ? Si la machine détient une clé dont le système accepte les signatures, une machine compromise signe ce qu’elle veut. Sans coffre matériel — l’OTP du Pi n’en est pas un, et il n’y a pas de TPM — une clé locale est un fichier. Elle protège contre l’altération hors ligne ; pas contre un système compromis en marche, qui est la menace qui nous intéresse.

3.2 Le critère de découpage

Cette configuration décide-t-elle quel code s’exécute ?

  • Oui → table de montage (on pourrait monter un autre /usr), liste des services, profils de confinement. Ces configurations sont du code du point de vue de la sécurité.
  • Non → nom d’hôte, adresse réseau, fuseau, known_hosts de l’utilisateur. Leur compromission est ennuyeuse ; elle n’ouvre pas la porte à l’exécution de code arbitraire.
ProtectionModifier
Critiquedans l’image, couverte par verityintégrité complète, signée hors machine= nouvelle image, donc chemin A/B
Exploitationpartition inscriptible montée sur /etc/airLandlock + porte adminimmédiat, par la CLI

La seconde ligne n’est pas signée, et ce n’est pas un renoncement : ce qui la protège est que seuls les outils d’administration peuvent écrire ce chemin. La propriété fondatrice — un attaquant corrompt des applications, jamais le système — est préservée, une application n’étant ni root ni autorisée par Landlock. Et si l’attaquant est root, une signature locale ne l’aurait pas arrêté non plus.

3.3 Réduire le problème avant de le résoudre

Beaucoup de ce qui ressemble à de la configuration n’en est pas. Le disque externe est le cas d’école : il ne demande aucune configuration, mais une politique (dans l’image) plus un événementair-device voit apparaître un bloc amovible, la politique dit « les amovibles se montent sous /media/<uuid>, toujours en nosuid,nodev,noexec, propriété de l’utilisateur de la session », c’est monté. Rien n’a été modifié, rien signé, aucun redémarrage.

Première étape : reclasser. Une bonne moitié de ce qu’on croit devoir rendre mutable est une politique fixe plus des événements d’exécution.

3.4 Pour le reste : la délégation bornée

L’image ne fixe pas les valeurs, elle fixe l’enveloppe ; la partie mutable remplit à l’intérieur ; le lanceur refuse tout ce qui dépasse.

L’idée-clé : rendre la configuration mutable incapable d’exprimer un énoncé dangereux, plutôt que de la protéger cryptographiquement — protection qui ne tient pas sans coffre matériel.

  • Montages : l’image déclare la table système et une politique de délégation — « sous /media/** et /mnt/**, des montages sont permis, obligatoirement en nosuid,nodev,noexec, jamais par-dessus un chemin système ». Un attaquant qui réécrit la partie mutable monte un disque inutile ; il ne monte rien par-dessus /usr et ne rend rien exécutable. Ça règle aussi le disque interne permanent, sans image nouvelle.
  • Services : l’image déclare les services système et le plafond de privilège de chaque emplacement délégable. Une application enregistre un service d’arrière-plan dans les limites de son octroi ; elle ne s’accorde pas CAP_NET_ADMIN en écrivant un fichier.
  • Réseau : catégorie inoffensive — une adresse IP n’exécute pas de code.

Ce qui reste vraiment structurel — modifier le privilège d’un service système, changer la table de montage système — est rare, et le redémarrage y est souhaitable : c’est le moment où la nouvelle configuration est vérifiée avant d’être active. Tous les systèmes comparables font ainsi ; ChromeOS et Android l’interdisent purement, Silverblue et MicroOS l’autorisent au prix d’un redémarrage. On ne peut pas à la fois vérifier au démarrage et modifier à chaud.

Le coût, sans le cacher : la difficulté se déplace vers le choix des enveloppes. Trop étroites, l’utilisateur se heurte à des murs ; trop larges, elles ne protègent plus rien. Et les élargir exige une nouvelle image. C’est un vrai travail de conception, mais fini et anticipable, là où la signature locale était une impasse.

Pourquoi c’est le bon mécanisme : c’est déjà le nôtre. L’enveloppe déclarée par l’image que la partie mutable ne peut dépasser, c’est exactement la « policy du poste » qui plafonne ce qu’un manifeste d’application peut demander. Même structure : une déclaration immuable qui borne, une déclaration mutable qui demande, un arbitre qui calcule l’intersection. Un seul concept à comprendre, implémenter et auditer.

3.5 Un avantage propre à Air

Sur un Linux classique, /etc est un zoo de fichiers texte écrits par des dizaines de paquets, dont beaucoup exigent l’écriture à l’exécution — d’où les surcouches et les tmpfs peuplés au démarrage des systèmes à racine immuable. Air n’a pas ce problème : la configuration est binaire et le projet contrôle qui écrit quoi. /etc peut être quasi vide dans l’image, et /etc/air un simple point de montage. C’est un bénéfice direct de la doctrine de configuration binaire, qui n’avait pas été anticipé pour cela.


4. Le cas de la base de comptes

Elle met le critère du §3.2 à l’épreuve : elle est critique, et pourtant elle ne peut pas être dans l’image.

4.1 Elle décide bel et bien quel code s’exécute

Qui écrit la base de comptes peut créer un compte d’UID 0, s’ajouter à un groupe privilégié, poser un mot de passe qu’il connaît, changer le shell d’un compte, ou pointer le répertoire personnel d’un utilisateur privilégié vers un répertoire qu’il contrôle — dont les fichiers d’initialisation s’exécuteront sous cette identité.

C’est donc, avec les profils de confinement, l’état mutable le plus critique de la machine. Et elle doit rester modifiable : on ne reconstruit pas une image pour changer un mot de passe.

Il existe donc une catégorie non nommée au §3.2 : critique et nécessairement mutable. Elle est peu peuplée — la base de comptes en est le cas principal.

4.2 Ce qui la protège

Quatre mesures, dont trois existent déjà :

  1. Monopole d’écriture — seul air-account écrit ces artefacts (Landlock), et air-account est lui-même un binaire signé de l’image. Aucun éditeur, aucun shell, même sous root.
  2. Porte admin sur toute mutation (ADR-101).
  3. L’enveloppe, et c’est l’ajout qui compte : l’image déclare les UID et GID système réservés. air-account ne peut alors créer ni un second UID 0, ni ajouter quelqu’un à un groupe privilégié réservé. La délégation bornée appliquée aux comptes — elle retire le pire scénario, l’escalade par création de compte.
  4. Journalisation de chaque mutation via air-log. On n’empêche pas root ; on le rend bruyant.

4.3 Le point rassurant, spécifique à Air

Sur un Linux classique, compromettre la base de comptes équivaut à tout perdre : on devient root, et root exécute ce qu’il veut.

Dans Air, non. Si le lanceur refuse d’exécuter un binaire non signé, compromettre la base de comptes donne une identité, pas du code arbitraire : l’attaquant devient root et ne peut lancer que ce que le système accepte déjà. C’est une position sensiblement plus faible, et cela justifie a posteriori d’avoir mis l’arbitre de lancement au cœur du modèle.

4.4 Où exactement

Sur la partition inscriptible montée sur /etc/air, avec des permissions différenciées — ce que la structure actuelle permet, les schémas étant trois artefacts distincts (Passwd, Group, Shadow).

À conserver impérativement au passage en binaire : passwd et group doivent rester lisibles (la résolution de noms en a besoin), shadow ne l’être que par air-account. Fondre les trois obligerait à tout mettre en 0600 et casserait la résolution.

4.5 Là où l’absence de chiffrement mord

shadow est un actif de confidentialité, pas seulement d’intégrité. Sur une machine sans chiffrement de disque — décision actée pour le Raspberry Pi, ADR-014 amendé — les empreintes sont lisibles par quiconque a un accès physique. Argon2id rend l’attaque coûteuse, il ne l’empêche pas.

C’est le premier endroit concret où cette décision a un coût identifiable. Elle n’est pas remise en cause — l’accès physique est hors du modèle de menace du Pi — mais c’est l’argument le plus solide pour chiffrer au moins cette partition le jour où un ancrage matériel existera.


5. Questions ouvertes

  1. Comment naît le premier compte ? À l’installation la base est vide : l’installeur crée le premier administrateur, donc il détient l’espace d’un instant le pouvoir d’écrire la base sans porte admin, puisqu’aucun administrateur n’existe pour l’ouvrir. Qui a ce droit, quand la fenêtre se referme, et comment on prouve qu’elle s’est refermée.
  2. Quelles enveloppes exactement, pour les montages et pour les services ? C’est le travail de conception que le §3.4 déplace, et il n’est pas fait.
  3. AirLinkManager : le nom. AirNetworkManager est pris par les sockets.
  4. Complète-t-on ADR-077 pour les trois domaines sans Manager, ou acte-t-on l’exception ?
  5. Chiffrement de la partition de configuration : différé, ou instruit dès qu’un ancrage matériel existe ?

Licence du document : MPL 2.0 Statut : note de travail, conversation en cours.