DocumentationSandbox et garde-fous

Sandbox et garde-fous

Le runner installe de vraies frontières noyau autour de chaque processus fournisseur, et refuse de lancer ce qu’il ne peut pas borner.

Ce qui n’est pas borné ne démarre pas

Avant de lancer un processus fournisseur, Automonique vérifie sa frontière d’exécution. Une sonde de capacités en lecture seule indique quels mécanismes l’hôte peut appliquer, et un sélecteur de mode refuse ou se dégrade bruyamment, jamais en silence.

Les couches de confinement

CoucheCe qu’elle garantit
cgroup v2Confinement de tous les descendants. Le placement est sans course, les plafonds sont posés avant que le cgroup contienne un processus, cgroup.kill termine tout le sous-arbre, y compris un petit-enfant échappé par setsid, et un cgroup non supprimable est signalé comme résidu.
Fermeture des descripteursTout ce qui sort d’une liste explicite est fermé, puis /proc/self/fd est relu pour le confirmer.
Landlock, fichiersUne liste d’autorisation avec des intentions distinctes : lecture, lecture-écriture, lecture-exécution. Un jeu de règles appliqué partiellement est refusé.
Landlock, TCPPolitique ABI 4 qui refuse bind et connect par défaut.
seccomp, socketsPar défaut, aucun socket ne peut être créé. Un plan peut accorder seulement AF_UNIX (stream, datagram, seqpacket) et TCP IPv4/IPv6. Les appels io_uring sont refusés, les numéros d’appel x32 sont couverts, et toute architecture autre que x86_64 est refusée.
seccomp, processusToujours refusés : ptrace, process_vm_*, pidfd_getfd, unshare et setns, ainsi que clone avec des drapeaux de namespace ; clone3 répond ENOSYS.

Un test de bout en bout lance une charge réelle sous ces frontières à la fois : la sonde TCP est refusée par Landlock à connect (EACCES) tandis que la sonde UDP meurt plus tôt, à socket (EPERM). Deux erreurs distinctes prouvent deux couches distinctes.

Le plan de lancement

Un superviseur encode un LaunchPlan typé et borné (programme, arguments, droits sur les fichiers, exceptions TCP, formes de sockets), transmis par stdin, jamais en argument. Un helper de confiance :

  • rejoint le cgroup de l’exécution et confirme son appartenance auprès du noyau ;
  • scelle l’image du programme et, si le plan le demande, bascule sur un uid subordonné ;
  • remplace stdin par le memfd scellé du prompt, ou par /dev/null s’il n’y a pas de prompt ;
  • ferme et vérifie les descripteurs, applique les limites de ressources ;
  • installe les deux domaines Landlock et le filtre seccomp ;
  • puis seulement exécute la charge, avec un environnement vide hors liste explicite.

Les variables d’environnement passent par une liste explicite, validée par grammaire et par taille. Le prompt n’est nommé par aucun chemin et n’apparaît jamais dans les arguments. Un plan contradictoire, par exemple une exception de port TCP sans droit de socket TCP, est refusé plutôt que résolu en silence.

Supervision des exécutions

Chaque tentative enregistre ses événements de démarrage et de fin dans un journal chaîné par hachage. Une annulation ou un dépassement de délai tue tout l’arbre via le cgroup.

Un socket de contrôle privé et versionné authentifie le pair par ses identifiants noyau avant de lire le moindre octet, et propose inspect, subscribe (paginé, à l’octet près), heartbeat et cancel, dont la répétition répond already_delivered.

Écoute et sortie réseau

Le seul port réseau que le processus daemon ouvre est celui du broker de sortie, attribué par le noyau en loopback, propre à une exécution et jamais réutilisé. Le broker n’autorise que les destinations listées dans egress-destinations et refuse tout le reste.

Les autres composants qui écoutent sont des services distincts, eux aussi limités à la machine : le tableau de bord web (127.0.0.1:18082), l’adaptateur AG-UI (127.0.0.1:18083) et le propriétaire du stockage temporaire, sur un socket Unix privé.

Ce qui reste hors de portée

  • UDP, sockets bruts, AF_UNIX et sockets déjà connectés hérités échappent à Landlock : c’est pourquoi la politique TCP n’est pas présentée comme une coupure réseau, et pourquoi le filtre seccomp ferme la création de sockets.
  • Les descripteurs hérités avant l’application et le passage SCM_RIGHTS sur un socket unix accordé restent hors d’atteinte, et les tests le consignent.
  • Un binaire fournisseur est admis par empreinte épinglée et par le registre du workspace, pas par une signature vérifiée.