Instruction — le grain du profil seccomp
Objet. Question restée ouverte après la décision sur la largeur des enveloppes (
instruction-largeur-enveloppes-defaut-fr.md§10). Elle bloque la part seccomp d’AirSandboxManager: il n’existe aucun chemin entre « l’octroi accorde ceci » et « voici l’allow-list de syscalls ».TRANCHÉ le 2026-08-10 (BDFL) : grain A (catégories nommées) et égalité stricte pour les profils d’
air-sshd— redériver ne doit rien élargir sur le composant le plus exposé. Mise en œuvre :crates/air-sandbox/src/profile.rs(catégories) etcrates/air-bundle/src/ceiling.rs(dérivation depuis l’octroi).Les §1 à §6 sont conservés tels qu’ils ont servi à décider.
1. Ce que le code pratique déjà, sans le nommer
air-sandbox expose deux profils figés, taillés pour air-sshd. Mesurés :
| Profil | Syscalls |
|---|---|
pre_auth | 34 |
sftp_worker | 58 |
Et le rapport entre les deux n’est pas quelconque :
sftp_workercontient exactementpre_auth— vérifié, l’inclusion est totale ;- il ajoute 24 syscalls, et ces 24 forment une catégorie cohérente :
openat,openat2,lseek,fstat,newfstatat,statx,getdents64,fcntl,dup,dup3,pread64,pwrite64,ftruncate,mkdirat,unlinkat,renameat2,symlinkat,readlinkat,faccessat,fchmod,fchmodat,fchownat,utimensat,getcwd.
La structure « socle + catégorie » existe donc déjà. Elle n’est simplement pas nommée, et elle est écrite par duplication manuelle : les 34 entrées du socle sont recopiées dans le second profil.
C’est le principal apport de cette instruction. La question n’est pas « quel grain inventer » mais « faut-il nommer celui qu’on emploie déjà ».
2. La duplication est une dette, pas un détail
Ajouter un syscall au socle demande aujourd’hui de le faire à deux endroits, et rien ne
le vérifie. Un oubli ne se voit pas à la relecture — il se voit quand un worker meurt d’un
KILL_PROCESS en production, sur un chemin rarement pris.
Le dépôt a déjà payé ce genre d’erreur ailleurs (le socle de relecture d’identité, dont le
commentaire dans profile.rs raconte qu’il manquait et tuait la vérification défensive de
drop_privileges).
3. Ce que le socle n’est pas
pre_auth n’est pas un socle universel : il contient recvmsg, qui n’y est que pour un
besoin propre au montage privsep d’air-sshd — recevoir le tuyau clair post-auth par
SCM_RIGHTS. Le commentaire du code le dit lui-même : « le seul syscall de la famille
socket de ce profil ».
Un socle générique serait donc pre_auth moins ce qui relève d’un montage particulier.
Le distinguer est un travail à faire, pas une évidence.
4. Les deux grains possibles
Grain A — catégories nommées, dérivées des entitlements (recommandé)
Un socle obligatoire, plus des catégories additives que l’octroi active :
profil = socle ∪ ⋃ { catégorie(f) | f ∈ familles non vides de l'octroi }
- Pour : c’est ce que le code fait déjà ; une catégorie se relit, une liste de 58 syscalls non ; la duplication disparaît ; la dérivation depuis l’octroi devient mécanique — donc testable, et non plus un jugement humain à chaque profil.
- Contre : une catégorie est forcément plus large que le besoin exact d’un service
donné.
air-sshdreçoit aujourd’hui 58 syscalls choisis un par un ; avec des catégories, il en recevrait peut-être quelques-uns de plus. - Précédent :
pledged’OpenBSD, dont c’est exactement le pari — et le pari a tenu.
Grain B — profil étroit unique, plus dérogations explicites
Un seul profil minimal, et chaque service déclare les syscalls supplémentaires dont il a besoin.
- Pour : le plus étroit possible, service par service.
- Contre : ce sont les profils figés d’aujourd’hui, avec leur duplication et leur illisibilité, simplement déplacés dans les manifestes. Et cela demanderait à un développeur d’application de raisonner en numéros de syscalls — ce que le vocabulaire des entitlements existe précisément pour éviter.
5. Ce qui reste à trancher, si le grain A est retenu
- La frontière du socle. Que garde-t-on ?
recvmsgen sort-il ? Un socle trop large annule le bénéfice ; trop étroit, il tue des processus sur des chemins rares. - La liste des catégories, et leur correspondance aux quatre familles d’entitlements.
La famille
filesystema sa catégorie toute trouvée (les 24 ci-dessus). Les trois autres n’ont pas d’applicateur (décision du 2026-08-10) — leur catégorie seccomp doit-elle exister d’avance, ou naître avec l’applicateur ? - Le sort des deux profils existants.
air-sshdtourne en production avec eux. Les redériver depuis des catégories doit donner un résultat au moins aussi étroit, et c’est vérifiable par un test qui compare les deux ensembles.
6. Questions au BDFL
- Grain A ou grain B ? (Recommandation : A — c’est déjà la pratique, il ne reste qu’à la nommer et à supprimer la duplication.)
- Les catégories des familles sans applicateur — créées d’avance, ou avec l’applicateur ? (Recommandation : avec l’applicateur, par cohérence avec la décision sur les enveloppes : on ne déclare pas ce qu’on ne sait pas appliquer.)
- Élargissement toléré pour
air-sshd? Redériver ses profils depuis des catégories peut lui accorder quelques syscalls de plus qu’aujourd’hui. Acceptable, ou exige-t-on l’égalité stricte — quitte à garder une catégorie sur mesure pour lui ?
7. Ce qui a été fait (2026-08-10)
- Trois catégories nommées dans
air-sandbox:Baseline(33),FdPassing(1),Filesystem(24).compose()les assemble, socle compris d’office — un profil qui l’omettrait ne serait pas plus étroit, il serait mort. recvmsgsort du socle. Il n’était danspre_authque pour le montage privsep d’air-sshd; le laisser dans le socle donnerait à tout processus confiné le droit de recevoir des descripteurs — donc n’importe quel objet ouvert que son pair veut bien lui remettre.- Les profils figés ne sont pas réécrits :
air-sandboxest couche 1, sa surface est scellée. Un test vérifie qu’ils valent exactement la composition de leurs catégories. Prouvé mordant : ajouter un syscall au socle sans le porter dans les profils fait tomber le test, en nommant le syscall en trop. - La dérivation vit en couche 2 (
syscall_categories_for), parce que les entitlements y vivent :air-sandboxpose la cage, il ne lit pas de manifeste. - Une seule famille produit une catégorie — le filesystem. Les trois autres n’ont pas d’applicateur ; leur catégorie naîtra avec lui, par cohérence avec la décision sur les enveloppes.
Landlock v4 est fait (2026-08-10) : la catégorie Network existe, et elle exigeait au
passage treize syscalls socket absents du vocabulaire AirSyscall. Les ajouter a révélé que
les 62 numéros d’air-sandbox n’étaient vérifiés par rien — check-syscalls les couvre
désormais (265 numéros au lieu de 203).
Reste sans applicateur : AirCom et les périphériques.
Licence du document : MPL 2.0