1 points par GN⁺ 2 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Exclure Rust du simple fait de l’existence de unsafe et considérer Fil-C comme seul sûr passe à côté du champ réel d’application des logiciels et des compromis techniques
  • Fil-C transforme les accès mémoire invalides en panique dans les programmes C/C++, mais au prix d’une incompatibilité ABI, de ralentissements pouvant aller jusqu’à plusieurs fois dans certains cas, et de l’introduction d’un GC
  • Dans Android, avec environ 5 millions de lignes de code Rust, un seul cas potentiel de vulnérabilité de sûreté mémoire corrigé avant la sortie a été trouvé, soit une estimation de 0,2 cas par million de lignes, contre environ 1 000 pour les anciennes données en C/C++
  • Il n’est pas nécessaire de choisir entre une technologie qui bloque 99,9 % des problèmes dans tous les programmes et une autre qui en bloque 100 % dans 90 % des programmes ; pour les logiciels qui acceptent mal les contraintes de Fil-C, des alternatives comme Rust sont adaptées
  • La sûreté mémoire doit être évaluée avec les performances, l’ABI, le GC et la prévention des courses de données ; si l’on critique Rust comme insuffisant, il faut au moins appliquer le même critère au C/C++ classique et à Zig hors Fil-C

Rust et le modèle de responsabilité des langages systèmes traditionnels

  • Le débat sur la sûreté mémoire dans les langages de programmation système sans GC s’est surtout articulé autour de la différence de modèle de responsabilité entre Rust et C/C++/Zig
    • Rust cherche à empêcher la compilation de programmes susceptibles de provoquer des problèmes de sûreté mémoire, au prix de rejeter aussi certains programmes qui pourraient pourtant être sûrs
    • unsafe est une porte de sortie qui permet de contourner certaines garanties, par exemple pour déréférencer des pointeurs bruts
    • Les langages de la famille C confient l’essentiel des garanties de sûreté mémoire au programmeur
  • Même s’il existe des différences de niveau de support selon les langages, comme le RAII et les smart pointers en C++, ou defer en Zig, ils ne bloquent pas par principe les accès mémoire invalides eux-mêmes

L’option supplémentaire apportée par Fil-C

  • Fil-C propose une nouvelle approche pour exécuter du code C et C++ en sûreté mémoire
    • Lorsqu’un accès mémoire invalide survient, comme un accès hors limites ou un use-after-free, il déclenche une panique
    • Il combine un GC et InvisiCaps, qui suit la mémoire accessible par les pointeurs
  • Un nouveau mode de compilation inspiré de Fil-C a aussi été proposé pour Zig
  • Si certains projets C/C++ populaires proposaient des releases compilées avec Fil-C, cela pourrait offrir une option supplémentaire pour réduire les vulnérabilités de sûreté mémoire

Le critère selon lequel Rust ne serait pas sûr

  • Le développeur de Fil-C affirme sur Twitter que Rust n’est pas un langage sûr du point de vue mémoire, au motif que unsafe permet de contourner certaines garanties
  • Le développeur de Zig Andrew Kelley a lui aussi qualifié, dans le titre d’une issue liée, un mode inspiré de Fil-C de mode de compilation “réellement memory-safe, contrairement à Rust”
  • Certaines discussions vont jusqu’à exiger que les utilisateurs de Rust, s’ils se soucient vraiment de sûreté mémoire, abandonnent Rust et fassent la promotion de Fil-C, jugé plus sûr
  • Ce critère compare Rust et Fil-C sans tenir compte du coût concret de Fil-C et adopte une posture proche des critiques accusant parfois la communauté Rust de fanatisme

Les contraintes d’application de Fil-C

  • Fil-C n’est pas un remplaçant drop-in sans coût
    • Il n’est pas compatible au niveau ABI avec les programmes compilés sans Fil-C
    • Il peut être plusieurs fois plus lent dans certaines situations
    • Il introduit un GC
  • Pour des programmes comme de petits utilitaires, où la baisse de performance est peu perceptible ou où le lien dynamique n’est pas nécessaire, ces contraintes peuvent ne pas être décisives
  • À l’inverse, de nombreux projets populaires ne peuvent pas accepter un GC ni une incompatibilité ABI, et les programmes auxquels Fil-C, dans sa forme actuelle, s’applique mal sont souvent bien adaptés à Rust

Les données réelles sur les vulnérabilités dans le code Rust

  • Il existe encore peu de données pour juger la sécurité réelle de Rust, mais on n’a pas observé beaucoup de vulnérabilités de sûreté mémoire exploitables dans des logiciels Rust
  • Dans les plus de 5 millions de lignes de code Rust d’Android, un seul cas potentiel de vulnérabilité de sûreté mémoire a été découvert, puis corrigé avant la sortie
    • La densité estimée est de 0,2 cas par million de lignes
    • Les anciennes données C/C++ d’Android étaient d’environ 1 000 cas par million de lignes
    • La densité du code Rust est donc suivie à un niveau plus de 1 000 fois inférieur à celui du C/C++
  • Les chiffres peuvent varier selon les projets, mais ils appuient l’idée qu’en environnement réel, Rust réduit fortement le risque d’introduire des problèmes de sûreté mémoire

Pourquoi il n’est pas nécessaire de n’en choisir qu’un seul

  • L’exemple hypothétique d’un choix entre une technologie qui bloque 99,9 % des problèmes dans tous les programmes et une autre qui en bloque 100 % dans 90 % des programmes montre que le périmètre d’application comme le niveau de prévention comptent tous deux
  • Même si les proportions exactes sont inconnues, il n’est pas nécessaire de choisir un seul des deux approches
    • Les projets C/C++/Zig capables d’accepter ces compromis peuvent proposer des binaires Fil-C
    • Les logiciels qui ne peuvent pas utiliser Fil-C peuvent être écrits dans des langages qui éliminent totalement ou en grande partie le risque de vulnérabilités de sûreté mémoire

Pourquoi choisir Rust même si l’on peut utiliser un GC

  • Il reste légitime de choisir Rust même s’il existe des options à GC comme Go ou Fil-C
  • Les programmes pouvant être écrits dans un langage à GC n’ont souvent pas besoin de unsafe, tandis que ceux qui ont besoin de unsafe ne peuvent souvent pas utiliser de GC
  • On peut juger plus importantes que ce faible risque de sûreté mémoire d’autres garanties et fonctionnalités du langage, comme la prévention des courses de données
  • Fil-C transforme les vulnérabilités de sûreté mémoire du C/C++ existant en crashs
    • C’est préférable à une vulnérabilité de sécurité, mais si la densité historique d’environ 1 000 cas par million de lignes reste la même, il restera beaucoup de crashs à corriger
    • Par le passé, certaines vulnérabilités de sécurité reposaient justement sur la capacité d’un attaquant à faire planter un programme

Un critère cohérent de sûreté mémoire

  • Si même les 0,2 cas par million de lignes de Rust sont inacceptables, alors il faut appliquer une critique équivalente ou plus stricte au C/C++ classique et à Zig hors Fil-C
  • Tolérer des alternatives moins sûres que Rust tout en excluant Rust uniquement à cause de unsafe revient à appliquer de manière incohérente un absolutisme de la sûreté mémoire

1 commentaires

 
GN⁺ 2 시간 전
Avis sur Lobste.rs
  • Le propos d’Andrew Kelly, que l’OP semble avoir mal pris, est que Zig peut compiler, y compris l’ensemble des dépendances C/C++, en exécutable entièrement memory-safe, sans échappatoire, avec un coût en performances d’environ 1 à 6× selon la fréquence du suivi des pointeurs
    L’auteur y voit une attaque contre Rust et finit par attaquer Zig, mais Fil-C et le nouveau mode de build de Zig sont des contributions positives à l’écosystème, offrant des choix de conception et des compromis différents de Rust
    J’interprète aussi cela comme signifiant qu’en suivant la programmation orientée données privilégiée par l’équipe Zig, on peut ramener le coût de performance près de 1×

    • L’auteur réagissait au titre « inspiré de Fil-C, introduction d’un mode de compilation réellement memory-safe, contrairement à Rust » et à un post Twitter du développeur de Fil-C
      Ce n’est pas absurde d’y voir une provocation inutile, et Andrew a ensuite remplacé le titre par quelque chose de moins agressif
  • À l’inverse de d’habitude, quand une légère moquerie du type « votre langage n’est pas memory-safe » a été dirigée vers Rust, l’ampleur de la réaction des développeurs Rust a été notable
    J’aime beaucoup Rust moi aussi, mais il faut le prendre avec équité

    • Dire que « Rust est plutôt memory-safe, mais Fil-C l’est davantage sur cet aspect » ne me semble ni très polémique ni faux
      D’ailleurs, le C formellement vérifié de seL4 est encore plus sûr
    • Comme j’accorde de l’importance aux programmes corrects et essaie autant que possible de ne pas écrire de code qui ne l’est pas, je préfère paradoxalement Rust à Zig
      Zig a pour atouts de faciliter une terminaison correcte en cas d’échec d’allocation mémoire et de compiler rapidement
      Je ne sais pas si Fil-C est plus memory-safe que Rust, mais pour mes usages, le garbage collector et l’incompatibilité avec l’ABI C sont des obstacles décisifs
      On peut éviter les race conditions en restant monothread et obtenir la memory safety avec un garbage collector, mais j’aime que Rust fournisse les deux sans ces compromis
  • Comme j’accorde énormément d’importance à la memory safety, Fil-C et l’implémentation de l’ABI Fil-C dans Zig sont des choix naturels
    Un projet Rust avec des dépendances C voit ses garanties de sûreté affaiblies, et n’utiliser que du Rust pur est possible mais peu pratique
    Rust devrait lui aussi implémenter l’ABI Fil-C pour pouvoir construire en toute sécurité des dépendances C et les lier à Rust, et je ne vois pas pourquoi ce serait polémique

    • Rust dispose déjà de l’interpréteur Miri, qui vérifie si du code Rust unsafe respecte bien les garanties du Rust sûr
      Si on implémente quelque chose de similaire, j’aimerais que ce soit un outil auxiliaire servant seulement à améliorer le code FFI en build de debug
      Avoir un garbage collector et vérifier toutes les opérations à l’exécution ne convient pas à tous les usages
  • Avant de réduire Fil-C à un simple utilitaire, il faut voir la présentation de Fil-C à la conférence Software Should Work
    L’intervenant a fait sa présentation sur un portable Linux dont tout l’espace utilisateur, jusqu’à OpenOffice Impress, tournait en Fil-C
    Ce ne sera sans doute pas adapté à certains programmes C/C++, mais cela ne ressemble pas à une technologie gadget autant que l’auteur le pense

  • Venant de Python, la memory safety était pour moi un prérequis, et j’ai choisi Rust pour trois raisons
    Premièrement, son système de types puissant permet d’assurer la correction à la compilation, et la memory safety obtenue avec #![forbid(unsafe_code)] et l’audit des dépendances via cargo-geiger est l’expression la moins intéressante de cela
    Deuxièmement, il offre un écosystème qui facilite l’écriture sûre d’un code qu’on peut ensuite partager entre plusieurs langages et environnements d’exécution
    Troisièmement, il a du sucre syntaxique qui rend agréable l’écriture de code de haut niveau, comme try!(x) à l’époque
    Zig et Fil-C ne semblent pas offrir cette capacité à faire attraper les erreurs logiques par le compilateur en encodant dans le système de types des invariants via le pattern typestate ou les newtypes
    L’incompatibilité ABI de Fil-C pose aussi problème pour écrire des modules compilés de façon sûre pour des runtimes existants, comme le CPython d’un hébergement web mutualisé

    • Dans Zig aussi, le pattern typestate et l’encodage dans les types de diverses contraintes sont possibles, et sous certains aspects comptime est plus expressif que Rust
      Il y a des compromis en temps de compilation, en verbosité, et le fait que la majeure partie de l’écosystème ne pousse pas jusque-là, mais c’est réellement possible et assez amusant
  • Je me demande pourquoi une technologie comme Fil-C n’est pas apparue il y a 20 ans

    • Dans le monde du mainframe, on met en garde depuis des décennies contre les problèmes de sécurité liés au partage et au marquage des pointeurs et des permissions fondées sur des capacités
      Mais personne ne voulait en payer le prix en CPU ou en mémoire, autrement dit en coût
    • J’ai posé une question similaire à Filip il y a quelques mois et j’ai reçu la réponse suivante
      Entre 2004 et 2018, l’idée existait, mais il pensait que le concept même de C memory-safe était absurde ; entre 2018 et 2023, il a changé d’avis, mais sans trouver comment atteindre une compatibilité extrême
      Le Fil-C du début, entre 2023 et 2024, avait une compatibilité et des performances bien inférieures ; à la fin 2024, la percée d’InvisiCaps a permis d’obtenir le haut niveau actuel de compatibilité et des performances correctes
      Ce qui lui a fait changer d’avis vers 2018, c’est l’observation que les variantes de C utilisées sur GPU sont une forme simple de C memory-safe
    • Il y a 20 ans, les ordinateurs étaient plus lents et on était bien plus sensible au coût de la sûreté
  • Si on interprète de la façon la plus charitable l’idée selon laquelle « si le camp Rust se souciait vraiment de memory safety, il devrait soutenir Fil-C, plus sûr, et abandonner Rust », cela signifie qu’à présent que Fil-C existe, il faudrait cesser les efforts pour réécrire le monde en Rust, revenir à C/C++ et conserver l’écosystème unifié de bibliothèques d’autrefois
    Même si les bibliothèques Rust peuvent être utilisées depuis C/C++, certains développeurs ne le souhaitent pas, donc si les utilisateurs de Rust reconnaissaient qu’il existe une meilleure solution et abandonnaient, la fragmentation disparaîtrait, selon cette logique
    Mais Fil-C implique des compromis que Rust n’a pas, notamment un garbage collector et un support limité à x86-64 Linux
    Au-delà de la memory safety, Cargo et l’absence d’espace de noms global sont des raisons majeures d’utiliser Rust, et il est regrettable que les divisions entre camps de langage soient mêlées à une guerre culturelle plus large
    On veut juste construire des bibliothèques que tout le monde aura envie d’utiliser

    • Je me demande si C et C++ ne constituent pas déjà un écosystème fragmenté à eux seuls
      Certains développeurs C peuvent ne pas vouloir de bibliothèques C++, et avec Zig et Odin en plus, la fragmentation restera même si Rust disparaît
      Je me demande si Rust crée vraiment une fragmentation d’une nature particulière
    • Moi aussi, je voudrais un monde où tout le monde utiliserait les bibliothèques avec satisfaction, et je développe un transpileur haut niveau Rust→Zig qui préserve les génériques via comptime
      Rust encode davantage de contraintes, ce qui en fait un langage source idéal