SysadminNews

Linux 7.3 ajoute FailFS et retire deux vieux systèmes

Sur cette page
  1. Un système de fichiers qui refuse tout
  2. fchroot(), et pourquoi chroot() ne suffisait pas
  3. L'opposé de nullfs, par le même auteur
  4. Ce qui casse, et ce que cela coûte
  5. Deux systèmes de fichiers à la retraite
  6. Quoi en faire
  7. Sources et pour aller plus loin

Linux 7.3 a gagné un système de fichiers qui refuse tout, et perdu deux systèmes que plus personne n'utilisait depuis vingt ans. Dans les premières demandes d'intégration fusionnées par Linus Torvalds le 17 août 2026, le pilote EFS de SGI IRIX et le pilote FreeVxFS pour Veritas VxFS ont été supprimés, environ trois mille sept cents lignes à eux deux. À la place arrive FailFS, neuf cent trente et une lignes documentation comprise, où chaque opération renvoie EOPNOTSUPP et où la racine ne peut pas être ouverte du tout. Il arrive avec un nouvel appel système fchroot() et une sentinelle FD_FAILFS_ROOT.

The short answer

Les premières demandes d'intégration pour Linux 7.3, fusionnées le 17 août 2026, ajoutent FailFS, un pseudo système de fichiers où chaque opération renvoie EOPNOTSUPP et où la racine ne peut pas être ouverte, avec un nouvel appel système fchroot() et une sentinelle FD_FAILFS_ROOT. L'objectif est de permettre à un processus d'abandonner entièrement son système de fichiers ambiant, de sorte que les seuls chemins encore résolus soient ceux ancrés sur un descripteur qu'il détient déjà. La même fusion supprime EFS, le format d'avant XFS chez SGI IRIX, et FreeVxFS, le pilote Veritas en lecture seule.

EOPNOTSUPPrenvoyé par chaque opération FailFS, statfs() compris
931 lignesla totalité de FailFS, documentation comprise
~3 700 lignessupprimées avec les pilotes EFS et FreeVxFS
Carte réponse : Linux 7.3 intègre FailFS, 931 lignes documentation comprise, où chaque opération renvoie EOPNOTSUPP et où la racine ne peut pas être ouverte même avec O_PATH, avec le nouvel appel système fchroot et la sentinelle FD_FAILFS_ROOT, tandis que les pilotes EFS et FreeVxFS sont supprimés, soit environ 3700 lignes en moins.
Un système de fichiers arrive qui ne fait rien, deux partent que personne n'utilisait. PNG

L'actualité des systèmes de fichiers du noyau parle d'ordinaire d'aller plus vite ou de stocker davantage. Ici, il s'agit d'un pilote dont le métier entier consiste à dire non, et c'est plus intéressant que cette description ne le laisse croire.

Un système de fichiers qui refuse tout

FailFS renvoie EOPNOTSUPP pour chaque opération qui l'atteint. C'est déjà inhabituel. Ce qui en fait une véritable primitive d'isolation, c'est la minutie avec laquelle il se retire de la vue. Selon le RFC, statfs() échoue aussi, vous ne pouvez donc pas identifier le système de fichiers via un descripteur. La racine ne peut pas être ouverte même avec O_PATH, et elle décline le rappel de revalidation faible que le VFS utilise pour les terminaux sautés, ce qui, selon les mots de Christian Brauner dans la publication, ferme tout moyen restant de la référencer.

Vient ensuite le modèle de propriété. Une seule instance est montée très tôt au démarrage via kern_mount(), ce qui la rend logiquement distincte de tous les espaces de noms de montage du système. Elle ne peut pas être clonée, l'espace utilisateur ne peut pas la monter, et rien ne peut être monté par dessus. Il en existe exactement une, elle n'appartient à personne, et vous ne pouvez jamais qu'être à l'intérieur.

Le bénéfice se lit dans ce qui arrive ensuite à la résolution des chemins. Avec la racine ou le répertoire courant placés dans FailFS, les chemins absolus échouent, les liens symboliques absolus échouent, et les recherches relatives à AT_FDCWD échouent. La seule chose qui fonctionne encore est une recherche ancrée sur un descripteur explicite. L'accès au système de fichiers bascule d'ambiant à explicite : au lieu d'avoir toute l'arborescence et d'être retenu par les permissions, le processus n'a rien et détient exactement les descripteurs qu'on lui a donnés.

Liste comparant ce qui fonctionne encore et ce qui échoue lorsqu'un processus a sa racine ou son répertoire courant dans FailFS : openat avec un descripteur déjà détenu fonctionne, tandis que les chemins absolus, les liens symboliques absolus, les recherches relatives à AT_FDCWD, l'ouverture de la racine FailFS et l'exécution de binaires liés dynamiquement échouent tous.
Une fois dans FailFS, un descripteur déjà détenu est la seule porte de sortie. PNG

fchroot(), et pourquoi chroot() ne suffisait pas

Le mécanisme a besoin d'une entrée qui ne dépende pas des chemins, puisque tout l'objet est que les chemins cessent de fonctionner. C'est fchroot(), un nouvel appel système qui change la racine à partir d'un descripteur de fichier plutôt que d'une chaîne de caractères. À côté, le noyau expose FD_FAILFS_ROOT, une valeur de descripteur sentinelle comprise à la fois par fchdir() et fchroot(), de sorte qu'une tâche peut déplacer sa racine et son répertoire courant dans le système de fichiers défaillant sans jamais le nommer.

La demande d'intégration précise qu'une tâche non privilégiée peut faire un chroot vers FailFS à condition d'avoir positionné le drapeau no new privileges. C'est la condition standard pour confier une primitive de confinement à un processus non privilégié, le même arrangement qui rend praticables les filtres seccomp non privilégiés et les espaces de noms utilisateur, et c'est ce qui empêche cette fonctionnalité de rester réservée à root et aux seuls moteurs de conteneurs.

Il vaut la peine d'être précis sur ce que c'est et ce que ce n'est pas. Un chroot classique déplace le point de départ de la résolution des chemins absolus, et le processus dispose encore d'une arborescence, résout encore un chemin comme /etc/passwd vers quelque chose. FailFS supprime l'arborescence. Ce sont deux garanties différentes, et la seconde est bien plus facile à raisonner quand vous relisez ce qu'un processus auxiliaire peut atteindre.

L'opposé de nullfs, par le même auteur

FailFS ne prend son sens qu'à côté de NULLFS, que Christian Brauner a fait entrer dans Linux 7.0 et qui se trouve sous le chemin de démarrage du noyau publié en 7.2 le 16 août. NULLFS est un répertoire vide et immuable en permanence, dont les recherches échouent avec ENOENT. Il n'y a rien ici, mais le répertoire lui-même est un objet normal : ouvrable, lisible, utilisable comme point de montage. Il existe surtout pour rendre le démarrage moins pénible, puisque pivot_root() peut alors placer la racine définitive sous la racine temporaire au lieu d'imposer un nettoyage manuel du ramfs initial, et pour donner aux fils noyau une racine sans aucun accès au système de fichiers. Brauner a été direct sur la motivation, décrivant le déport du travail de système de fichiers vers des fils noyau comme un concept cassé.

FailFS est l'autre moitié. NULLFS dit qu'il n'y a rien ici. FailFS dit que rien n'est supporté ici. Entre les deux, vous pouvez décrire à peu près n'importe quel degré de privation de système de fichiers qu'un processus pourrait souhaiter, vocabulaire réellement utile pour qui construit des bacs à sable, et compagnon naturel du travail d'outillage de conteneurs que nous avons couvert dans Podman 6.1.

Ce qui casse, et ce que cela coûte

Une limite est structurante : les binaires liés dynamiquement ne peuvent plus être exécutés une fois dans FailFS, car le chargeur dynamique résout des chemins absolus et tout chemin absolu échoue désormais. Si vous voulez utiliser ce mécanisme, soit votre programme est lié statiquement, soit vous faites vos exécutions avant de basculer dans FailFS et vous traitez la transition comme une porte à sens unique. Ce n'est pas une discipline nouvelle. C'est la même forme de contrainte que celle déjà imposée par les filtres seccomp stricts et le drapeau no new privileges, et elle pousse les conceptions à faire toute la préparation délicate en amont.

Côté coût, c'est modeste. Neuf cent trente et une lignes documentation comprise, avec un pilote sous les deux cents lignes dans le RFC, cela revient presque à rien pour une fonctionnalité noyau.

Deux systèmes de fichiers à la retraite

La même fenêtre de fusion supprime des pilotes qui ont le problème inverse : beaucoup d'histoire, aucun utilisateur.

FreeVxFS était le pilote libre en lecture seule pour le format Veritas VxFS utilisé par HP-UX et SCO UnixWare. La demande de suppression est directe sur son raisonnement : assurer la compatibilité avec de vieux systèmes Unix des années 1990 était amusant il y a vingt cinq ans, aujourd'hui cela sert surtout de matière première aux vérificateurs de bogues automatisés, avec un seul utilisateur et contributeur connu ces quinze dernières années. Ce dernier point est l'argument moderne en faveur du retrait, et il est plus récent qu'il n'en a l'air : les pilotes non maintenus génèrent désormais un flux régulier de rapports issus d'outils automatisés et de chasseurs de bogues pilotés par modèle, et quelqu'un doit trier chacun d'eux. C'est la même question de temps de mainteneur que le projet Debian met aux voix pour son propre outillage, abordée par le côté code.

EFS a suivi le même chemin. C'était le pilote en lecture seule du format sur disque utilisé par SGI sur IRIX avant XFS, non maintenu depuis plus de vingt ans. Les deux suppressions retirent ensemble environ trois mille sept cents lignes.

Toujours dans les demandes VFS, NILFS2 a basculé ses lectures O_DIRECT vers l'infrastructure iomap, la même consolidation que la plupart des systèmes de fichiers suivent depuis des années.

Quoi en faire

Si vous exploitez des systèmes en production, rien cette semaine. Linux 7.3 est dans sa fenêtre de fusion, et ni les suppressions ni FailFS ne vous atteindront avant que vous ne passiez délibérément à ce noyau, avec les changements d'ordonnancement et d'équilibrage déjà en file pour cette version.

Si vous maintenez quoi que ce soit qui lance des processus auxiliaires et leur remet des descripteurs de fichiers, FailFS mérite d'être lu maintenant plutôt que plus tard. La question de conception à laquelle il répond est celle que la plupart des bacs à sable traitent mal : non pas comment restreindre ce que ce processus peut ouvrir, mais comment garantir qu'il ne peut ouvrir que ce que je lui ai donné. Et si vous gardez encore une bande IRIX ou un volume VxFS que vous comptiez lire un jour, faites-le sur un noyau antérieur à la 7.3.

Sources et pour aller plus loin

Questions fréquentes

Que fait FailFS, concrètement ?

Il échoue. Chaque opération qui atteint FailFS renvoie EOPNOTSUPP, le code d'erreur que Linux utilise pour opération non supportée, et cela inclut statfs(), si bien que le système de fichiers ne peut même pas être identifié via un descripteur. Le répertoire racine ne peut pas être ouvert, pas même avec O_PATH, et il refuse le rappel de revalidation faible que le VFS utilise pour les terminaux sautés, ce qui ferme le dernier moyen indirect d'obtenir une référence vers lui. Une instance unique est montée très tôt au démarrage avec kern_mount(), elle existe donc en dehors de tout espace de noms de montage. Elle ne peut pas être clonée, l'espace utilisateur ne peut pas la monter, et rien ne peut être monté par dessus.

Pourquoi vouloir un système de fichiers qui ne renvoie que des erreurs ?

Pour permettre à un processus d'abandonner complètement son état de système de fichiers. Une fois que votre racine ou votre répertoire courant est FailFS, tout chemin absolu, tout lien symbolique absolu et toute recherche relative à AT_FDCWD échouent immédiatement. Les seuls chemins qui se résolvent sont ceux ancrés sur un descripteur de fichier que vous détenez déjà, avec openat() et ses variantes. L'accès au système de fichiers cesse d'être ambiant pour devenir explicite : le processus atteint exactement les descripteurs qu'on lui a remis, et rien d'autre. À comparer avec un chroot classique, où le processus dispose encore d'une arborescence complète en dessous de lui et résout toujours les chemins absolus, simplement depuis un autre point de départ.

Qu'est-ce que fchroot() et en quoi diffère-t-il de chroot() ?

chroot() prend un chemin. fchroot() prend un descripteur de fichier, ce qui fait du changement de racine une opération de descripteur de plein droit plutôt qu'une opération de chemin, et cela compte quand l'objectif est justement qu'aucun chemin ne fonctionne plus. Le noyau expose aussi une sentinelle FD_FAILFS_ROOT comprise par fchdir() et fchroot(), de sorte qu'une tâche peut placer sa racine et son répertoire courant dans le système de fichiers défaillant sans avoir besoin d'un chemin vers lui. Selon la demande d'intégration, une tâche non privilégiée peut faire un chroot vers FailFS à condition d'avoir le drapeau no new privileges, condition habituelle pour confier une primitive de confinement à un processus non privilégié.

Quel est le rapport avec nullfs ?

Ce sont des opposés assumés, tous deux signés Christian Brauner. NULLFS, intégré à Linux 7.0, est un répertoire vide et immuable en permanence : les recherches échouent avec ENOENT, autrement dit il n'y a rien ici, mais le répertoire lui-même peut être ouvert, lu, inspecté avec stat et servir de point de montage. FailFS dit que rien n'est supporté ici, et refuse même d'être regardé. NULLFS existe surtout pour rendre le démarrage plus propre, en permettant à pivot_root() de placer la racine définitive sous la racine temporaire, et pour donner aux fils noyau une racine sans accès au système de fichiers. FailFS est la version que l'on pointe vers un processus utilisateur quand on veut qu'il n'ait aucun système de fichiers ambiant.

Peut-on s'en servir aujourd'hui, et qu'est-ce qui casse ?

Pas encore sur un noyau stable. Il s'agit de matériau de fenêtre de fusion pour Linux 7.3, la première version sur laquelle vous pourrez l'exécuter est donc 7.3 elle-même, et la sentinelle ainsi que la plomberie fchroot() sont arrivées en travaux de suite du RFC initial que Christian Brauner a publié sur linux-fsdevel le 23 juillet 2026. La limite connue mérite d'être anticipée : les binaires liés dynamiquement ne peuvent pas être exécutés depuis FailFS, car le chargeur résout des chemins absolus et tout chemin absolu échoue désormais. En pratique cela signifie des binaires statiques, ou bien faire ses exécutions avant de basculer dans FailFS, la même discipline que celle qu'imposent déjà les bacs à sable seccomp stricts.