1 points par GN⁺ 2025-12-14 | 1 commentaires | Partager sur WhatsApp
  • La sécurité mémoire et le sandboxing sont deux concepts de sécurité indépendants, et il faut disposer des deux pour mettre en place une défense robuste
  • Fil-C est une implémentation à sécurité mémoire de C/C++, qui garantit cette sécurité jusqu’au niveau des appels système Linux et peut être utilisée même dans des composants système comme OpenSSH
  • Lors du portage du sandbox basé sur seccomp-BPF d’OpenSSH vers Fil-C, les principaux défis ont porté sur les limites de création de threads et l’ajustement du filtre seccomp
  • Pour la gestion des threads d’arrière-plan du runtime Fil-C, l’API zlock_runtime_threads() a été ajoutée afin de contrôler le comportement des threads à l’intérieur du sandbox
  • Fil-C applique de façon synchronisée les appels prctl à tous les threads du runtime, afin que no_new_privs et le filtre seccomp soient appliqués de manière cohérente à l’ensemble du processus

Relation entre sécurité mémoire et sandboxing

  • La sécurité mémoire et le sandboxing sont deux couches de sécurité distinctes, et l’une seule ne fournit pas une protection complète
    • Exemple de programme sûr en mémoire mais non sandboxé : un programme Java qui peut écraser un fichier via une entrée utilisateur
    • Exemple de programme sandboxé mais non sûr en mémoire : un programme écrit en assembleur avec des privilèges limités
  • En pratique, un sandbox présente des failles structurelles, comme l’autorisation de communication avec un processus broker
  • Il est donc préférable de combiner sécurité mémoire et sandboxing

Combinaison de Fil-C et du sandbox OpenSSH

  • Fil-C est une implémentation à sécurité mémoire de C/C++, qui conserve cette sécurité au niveau des appels système Linux
    • Le runtime Fil-C peut fonctionner même dans des composants système de bas niveau comme init ou udevd
    • OpenSSH fonctionne normalement avec Fil-C et utilise un sandbox seccomp-BPF
  • Sous Linux, OpenSSH construit son sandbox avec les outils suivants
    • chroot pour restreindre l’accès au système de fichiers
    • Exécution sous l’utilisateur/groupe sshd
    • setrlimit pour limiter l’ouverture de fichiers et la création de processus
    • Filtre seccomp-BPF pour n’autoriser que les appels système permis
  • Fil-C prend en charge chroot et le changement d’utilisateur par défaut, mais setrlimit et seccomp-BPF peuvent entrer en conflit avec le fonctionnement du runtime, ce qui demande des ajustements supplémentaires

Contrôle des threads dans le runtime Fil-C

  • Le runtime Fil-C utilise des threads d’arrière-plan pour le garbage collection, qu’il suspend et relance automatiquement si nécessaire
  • Le sandbox setrlimit d’OpenSSH vise à interdire la création de nouveaux processus, et la création de threads par le runtime peut donc enfreindre cette règle
  • Pour résoudre ce problème, l’API zlock_runtime_threads() a été ajoutée à <stdfil.h>
    • Le runtime crée immédiatement les threads dont il a besoin, puis désactive leur arrêt automatique par la suite
    • L’appel est effectué dans la fonction ssh_sandbox_child d’OpenSSH avant setrlimit ou seccomp-BPF

Ajustement du filtre seccomp d’OpenSSH

  • Après l’application de zlock_runtime_threads(), la plupart des fonctions du sandbox continuent de fonctionner telles quelles
  • Les changements suivants ont été apportés au filtre seccomp
    • En cas de violation, réglage sur SECCOMP_RET_KILL_PROCESS afin de terminer aussi les threads d’arrière-plan de Fil-C
    • Ajout de MAP_NORESERVE à la liste des autorisations, pour permettre l’utilisation de l’allocateur mémoire de Fil-C
    • Autorisation de l’appel sched_yield, utilisé dans l’implémentation des verrous de Fil-C
  • Les appels futex utilisés par Fil-C pour la synchronisation étaient déjà autorisés, donc aucun changement supplémentaire n’était nécessaire

Mise en œuvre de prctl dans Fil-C

  • OpenSSH utilise deux appels prctl lors de l’installation du filtre seccomp
    • PR_SET_NO_NEW_PRIVS pour empêcher l’acquisition de privilèges supplémentaires
    • PR_SET_SECCOMP, SECCOMP_MODE_FILTER pour activer le filtre
  • Le problème est que prctl ne s’applique qu’au thread appelant, ce qui laisse le risque que d’autres threads du runtime Fil-C restent sans filtre
  • Pour éviter cela, Fil-C utilise l’API filc_runtime_threads_handshake() afin d’appliquer la configuration de manière synchronisée à tous les threads du runtime
    • Elle garantit que chaque thread exécute le même appel prctl
    • En présence de plusieurs threads utilisateur, elle déclenche une erreur de sûreté Fil-C pour renforcer la protection

Conclusion

  • La combinaison de la sécurité mémoire et du sandboxing constitue l’approche de sécurité la plus solide
  • Fil-C intègre complètement le sandbox basé sur seccomp d’OpenSSH tout en préservant la sécurité mémoire sans réduire le niveau de protection
  • Dans un environnement Linux, Fil-C permet d’obtenir à la fois une sécurité au niveau système et une sûreté au niveau du langage

1 commentaires

 
GN⁺ 2025-12-14
Commentaires sur Hacker News
  • Je me demande pourquoi il n’y a aucune mention de landlock

  • Il existe une approche de compilation hybride C → WASM → C
    Cela permet de contrôler entièrement les interactions avec l’OS, tout en sandboxant les accès mémoire comme avec WASM, tout en restant techniquement du code C
    Voir RLBox pour plus d’informations

    • Les sandboxs WASM ne garantissent pas la correction (soundness) du programme
      Elles peuvent corrompre la mémoire, mais l’étendue des dégâts reste confinée à l’intérieur de la sandbox
      Des systèmes comme SECCOMP sont bureaucratiques, car il faut définir très finement toutes les politiques d’interaction
      Fil-C, au contraire, adopte une approche où le langage et le runtime eux-mêmes cherchent à garantir le bon fonctionnement du programme
      Les binaires Fil-C sont des exécutables ordinaires, donc ils peuvent aussi être utilisés avec des sandboxs comme SECCOMP
      Linux a mis 20 ans à créer l’interface prctl, donc pour voir quelque chose de similaire dans WASI, il faudra sans doute attendre 10 ans
    • RLBox est une technologie de sandboxing, pas une technologie de sûreté mémoire
      On peut toujours produire des flux d’exécution étranges à l’intérieur de la sandbox
  • L’auteur de Fil-C est doué pour les inventions techniquement intéressantes, mais je m’inquiète du niveau réel de validation de l’implémentation
    Il a dit qu’on pouvait compiler des programmes setuid avec Fil-C, mais la partie modifiée de ld.so peut être risquée
    Les applications setuid doivent être écrites de façon extrêmement défensive vis-à-vis des variables d’environnement, des descripteurs de fichiers, de rlimit, des signaux, etc.
    Ces aspects semblent encore inachevés, donc il y a un risque à l’utiliser dans une vraie infrastructure
    Cela dit, tester une base de code avec Fil-C pourrait permettre de découvrir des bugs intéressants

    • Je suis justement en train de tester s’il existe un moyen de casser Fil-C
    • Si cela vous inquiète vraiment, il faut expérimenter vous-même et partager les résultats
    • L’objectif est de rendre le runtime transparent afin de permettre l’audit
      La modification de ld.so est mineure et sert essentiellement à lui apprendre la disposition de libc
      Le bug getenv lié à setuid a déjà été corrigé avec secure_getenv
      Dans ces critiques, il y a une part de vérité et une part de FUD
    • Je regrette l’attitude peu coopérative de l’auteur de Fil-C face aux critiques
      Avec Fil-C, en situation de data race, les pointeurs et les capabilities peuvent devenir incohérents
      Cela peut provoquer une violation de la sûreté mémoire
      L’auteur le nie, mais la comparaison avec Java n’est pas appropriée
      La technologie est excellente, mais l’attitude de l’auteur nuit à la confiance
  • WASM est à la fois une sandbox et un environnement d’exécution, et selon la façon dont on l’utilise, on peut obtenir un certain niveau de sûreté mémoire
    Si l’on compile du C en WASM, les bugs existent toujours, mais leur portée est limitée
    Il est donc juste de classer WASM comme une technologie de sandboxing, mais en tant qu’environnement d’exécution il offre davantage de possibilités

    • WASM reste au fond une technologie de sandboxing
      Un bug dans le module B peut permettre de lire les données du module A
      En d’autres termes, WASM n’est qu’un remplaçant léger des sandboxs de processus
    • Dire « cela dépend de la façon dont on l’utilise » est en soi une preuve que WASM n’est pas totalement sûr
      On pourrait dire la même chose de C : « c’est sûr selon la façon dont on l’utilise »
    • WASM ne comprend pas le modèle mémoire du C, donc il ne peut pas implémenter des protections comme Fil-C
      WASM empêche de s’échapper du runtime, mais n’empêche pas de s’échapper de la mémoire du programme interne
  • Demande de comparaison entre Fil-C et Rust

    • Les deux technologies sont excellentes, mais leurs approches diffèrent
      Fil-C convient pour renforcer des programmes C existants en mettant l’accent sur la compatibilité et la sécurité
      Rust est mieux adapté aux nouvelles bases de code pour obtenir sûreté statique et performances
      Fil-C implique une légère perte de performances, mais il est utile pour du code C existant (ffmpeg, nginx, sudo, etc.)
      Rust se distingue par le multithreading et son système de types
    • Fil-C introduit un GC, ce qui peut dégrader les performances
      Son objectif n’est pas d’améliorer la conception du langage, mais d’apporter la sûreté mémoire
      Ses concurrents sont plus proches de D, Nim ou Go que de Rust
    • Fil-C utilise des vérifications à l’exécution pour détecter les accès mémoire non sûrs et arrêter le programme
      Rust les prévient à la compilation
      Les deux approches sont orthogonales, et on pourrait ajouter à Rust des vérifications à l’exécution dans le style de Fil-C
  • Les MicroVM gagnent progressivement en popularité
    Je me demande comment Fil-C pourrait en tirer parti

    • Cela demanderait un peu de portage, mais on pourrait aussi remonter certaines fonctionnalités des microVM dans le userland à sûreté mémoire de Fil-C
  • J’espère que ce projet recevra davantage d’attention
    Ce serait bien que des outils critiques comme sudo ou polkit soient distribués avec sûreté mémoire

  • J’aimerais qu’on utilise davantage le sandboxing, même avec des langages sûrs en mémoire
    C’est dommage que Rust ou Go utilisent si peu les sandboxs au niveau OS

    • Seccomp a une portabilité et une composabilité limitées
      Il est difficile à configurer au niveau d’une bibliothèque, et il est sensible à la version du noyau ou à l’implémentation de libc
      Il ne peut pas filtrer les entrées derrière des pointeurs comme les chemins de fichiers, ce qui montre ses limites
      C’est pourquoi il faut généralement le configurer directement au niveau de l’application
    • Rust a très peu de runtime, ce qui le rend bien adapté au sandboxing
      En revanche, le runtime de Go est plus lourd, donc il est plus difficile à sécuriser comme Fil-C
  • Je me demande en quoi Fil-C diffère de l’Address Sanitizer (ASan) de clang
    Si cela se limite à produire une panic à l’exécution, peut-on vraiment appeler cela de la « sûreté mémoire » ?

    • ASan détecte bien les bugs, mais ne garantit pas une sûreté mémoire complète
      Certains bugs lui échappent
      Son approche consiste à placer des « red zones » autour de la mémoire, donc la détection dépend parfois de la chance
    • Si une erreur mémoire est bloquée par une panic avant de produire des effets, on peut aussi considérer cela comme de la sûreté mémoire
      La sûreté mémoire ne signifie pas « ne jamais planter », mais « empêcher qu’un accès invalide produise un effet »
  • Question sur les raisons pour lesquelles on n’utiliserait pas une VM complète comme sandbox

    • Une VM est une excellente sandbox, mais des applications comme Chrome ou OpenSSH ont besoin de séparation de privilèges
      Un processus analyse les entrées sans privilèges, tandis qu’un autre fonctionne avec des privilèges élevés
      Les deux communiquent via IPC
      Utiliser une VM augmente la sécurité, mais ajoute beaucoup d’overhead, et complique des fonctions comme l’accès au GPU ou aux fichiers
      C’est pourquoi, en général, le sandboxing au niveau OS est plus propre
    • Les VM résolvent la plupart des problèmes, mais l’accélération graphique sur desktop reste difficile
      Il faut attribuer le GPU de manière dédiée, et même Qubes ne se connecte que via du forwarding X11, donc sans accélération