Sparse repasse à l'attaque

Posté par (page perso) . Modéré par Nÿco.
Tags :
31
26
oct.
2009
Technologie
Sparse est, comme Git et Linux, un bébé de Linus Torvalds qui a commencé à l'écrire en 2003.
Ce logiciel est un analyseur statique de code et il a pour but de détecter les bugs éventuels du noyau Linux, notamment les erreurs portant sur les types des variables.
Linus avait transmis le contrôle de Sparse à Josh Triplett en 2006 mais, après une grosse version 0.4 en septembre 2007 et une petite version de correction 0.4.1 en novembre 2007, le projet s'était gentiment endormi. Plus aucune version pendant presque deux ans... jusqu'au 16 octobre dernier ! Après Josh Triplett (qui a ajouté dans Sparse des vérifications des primitives de read-copy-update), c'est maintenant Christopher Li qui est le nouveau mainteneur de Sparse et cette transmission du flambeau s'est donc accompagnée de la sortie de la version 0.4.2.

Pour utiliser Sparse, il faut lancer une commande de type make C=1 quand on compile son noyau. Cette commande va lancer Sparse et examiner tous les fichiers sources en C pour détecter les erreurs. Bien entendu, si le développeur s'intéresse à une classe particulière d'erreurs, il peut passer une option à Sparse pour lui dire d'afficher les warnings sur ce type d'erreurs. Ainsi l'option -Wdo-while affiche les alertes concernant les boucles de type do..while.
Sparse fonctionne à l'aide d'annotations spéciales qui sont ajoutées dans les codes sources par les développeurs du noyau. Ainsi, pour se prémunir des erreurs portant sur l'endianness (ou le "boutisme") de l'ordre des octets on peut ajouter des annotations spécifiques. Un entier non signé pourra avoir l'annotation __be32 pour signifier qu'il est de type big endian 32 bits. Sparse s'occupera alors de vérifier que du code noyau n'essaye pas de mélanger, quelque part, cette variable avec un autre type, etc.
On peut également utiliser l'annotation __user pour indiquer un pointeur mémoire de l'espace utilisateur (user-space pointers). Cette annotation est ignorée par le compilateur GCC (qui définit __user comme une chaîne vide) alors que Sparse s'en sert pour marquer le pointeur comme relevant de l'espace utilisateur et comme étant interdit de déréferencer. Plus de confusion entre les pointeurs et plus d'erreurs de déréférencement des pointeurs user-space !
Sparse permet ainsi de vérifier les pointeurs mémoires, les opérations de lock/unlock, les opérations sur les bits, les troncatures lors des changements de type, les déréférencements de pointeurs nuls et une multitude d'autres problèmes potentiels (voir la page de man).

La version 0.4.2 de Sparse, la première depuis près de deux ans, incorpore beaucoup d'améliorations extrêmement techniques car le logiciel lui-même est un outil très spécialisé à la disposition des kernel hackers.
Un œil non averti peut tout de même remarquer l'annonce de la compatibilité avec l'architecture Sparc64, la prise en charge préliminaire d'OpenBSD, la compatibilité avec l'option de sécurité FORTIFY_SOURCE, un nettoyage des warnings et une réduction des faux positifs, la gestion de la technique de programmation Thread-local storage, une meilleure compatibilité avec les options récentes de GCC, etc.

Cette hyper-spécialisation et cette technicité de la liste des nouveautés expliquent la relative obscurité de Sparse, même s'il est assez étonnant que le monde du libre ne consacre pas plus d'efforts et de publicité à cet outil très puissant. En ce qui concerne la concurrence libre, les outils qui se rapprochent le plus de Sparse sont :
  • Splint (dérivé de l'antique Lint) qui fonctionne lui-aussi avec des annotations. Cette technique nécessite donc une adaptation du code source pour laquelle il faudrait atteindre une masse critique de développeurs désireux de faire ce travail. Le projet, au vu des commits, semble complètement mort.

  • Clang qui est le frontal d'analyse de code du compilateur modulaire LLVM. Bien entendu qui dit analyse de code dit possibilité de détection d'erreurs. Une fonction d'analyse statique et de rapport d'erreurs est donc disponible quand on utilise Clang. On peut également utiliser des annotations dans le code source avec Clang, mais là aussi il faut faire un travail d'adaptation. À ce sujet il faut noter que comme LLVM/Clang est largement financé (et donc indirectement contrôlé) par Apple, il existe beaucoup d'annotations qui sont spécifiques à MacOS X.
Dans le monde propriétaire, l'analyseur statique le plus connu est celui de la société Coverity qui est issu du projet académique Stanford Checker. Coverity est notamment financé par le département américain de la sécurité intérieure pour détecter les bugs de plusieurs projets open source (Linux, FreeBSD, Postfix, Python, Samba, etc). Les résultats ne sont pas publics puisqu'ils ne sont diffusés qu'aux développeurs enregistrés, mais il existe une page qui donne le taux de bugs moyen par projet (au potentiel assez trollifère donc).

On voit donc que, au moins dans le monde du libre, la voie est relativement dégagée pour Sparse qui pourrait peut-être devenir l'outil d'analyse statique libre de référence.
Sur la liste de diffusion du noyau on voit souvent passer des patchs ajoutant ces annotations spécifiques à Sparse. Son utilisation est également listée parmi les actions obligatoires à dérouler avant de soumettre un nouveau patch pour le noyau (point 9 de la liste officielle SubmitChecklist).
Si Sparse n'est actuellement utilisé que par le noyau Linux, cette situation n'a rien d'inéluctable et des logiciels en espace utilisateur pourraient également en faire un usage précieux. Certes le projet se restreint au code C, mais il existe de nombreux projets libres dans ce langage et ces derniers pourraient commencer à utiliser les annotations de Sparse afin de profiter de ses avantages en terme de fiabilité et de sécurité.
Bien entendu, Sparse n'atteindra sans doute jamais la popularité de Linux ou même de Git. Contrairement au célèbre noyau libre, c'est un outil réservé au développeurs et, contrairement au célèbre gestionnaire de version décentralisé, c'est un outil très spécialisé... mais Linus peut quand même être fier de son rejeton !

PS : À noter que, contrairement à Linux et Git qui sont sous GPLv2, Linus a choisi la licence Open Software License pour Sparse. Cela est sans doute dû au fait que Linus travaillait à l'époque pour l'entreprise Transmeta comme le prouve l'attribution de copyright du code original. Bien entendu la licence OSL est libre (et même copyleft) au sens de la Free Software Foundation mais il faut noter que la licence OSL incorpore une clause de terminaison des droits en cas d'attaque judiciaire basée sur un brevet logiciel.
Cette clause est considérée comme non compatible avec les DFSG (Debian Free Software Guidelines) par le projet Debian qui distribue donc Sparse dans sa branche non free.
  • # Précision

    Posté par (page perso) . Évalué à 5.

    Tu dis que l'on doit utiliser des annotations dans le code source, mais est-ce que Sparse fait quand même des checks basiques comme coverity si ces annotations ne sont pas présentes? Genre vérifier qu'on ne va pas trop loin dans un tableau statique, ce que fait Coverity en fait.

    Sinon, c'est bien dommage que ça ne gère que le langage C. Ce langage est parfait pour du code low level comme le kernel, mais il faut avouer que l'orienté objet apporte beaucoup de souplesse pour les applications plus haut niveau comme les interfaces graphiques. Peut-être qu'un jour...
  • # Coccinelle, userland

    Posté par . Évalué à 2.

    > Si Sparse n'est actuellement utilisé que par le noyau Linux,

    En fait il est déjà utilisé par quelques projets en espace utilisateur. A ma connaissance, qemu et xfsprogs intègrent des vérifications basées sur sparse. Le fait que ces deux projets soient fréquentés par des devs kernel n'est peut-être pas fortuit : pour avoir essayé sans succès d'utiliser sparse à partir de la "documentation" disponible, j'ai supposé qu'il fallait être soit super doué, soit déjà introduit par la connaissance de cas d'utilisations concrets (comme on en trouve dans le noyau). D'autre part les en-têtes de la glibc (et en pratique tout le /usr/include) produisent de copieux warnings, ce qui rends l'utilisation en espace utilisateur laborieuse. Bref, avec un peu plus de doc et d'exemples, et un solide système de filtres, sparse serait plus simple d'accès pour les "non kernel-hackers".

    Je profite de ce poste pour signaler Coccinelle, un analyseur statique mignon tout plein et oublié dans l'inventaire de la dépêche. Il est très facile à utiliser (il suffit généralement d'écrire des "patches sémantiques" de quelques lignes adaptés à ses besoins, cf. les exemples plus bas), et il ne nécessite pas d'annotations spécifiques dans le code cible.

    Coccinelle est un projet universitaire (franco-suédois), mais il a déjà donné des résultats très concrets, sous la forme idéale de nombreux patchs envoyés sur LKML corrigeant de vrais bugs (exemples : http://lkml.indiana.edu/hypermail/linux/kernel/0806.3/0094.h(...) , http://lkml.org/lkml/2009/9/22/198 , ...).

    Deux obstacles au succès de Coccinelle cependant : il est écrit en Objective Caml (sans jugement sur la pertinence technique de ce choix de langage, mais les utilisateurs de l'outil sont des développeurs C), et il incorpore son propre parseur C (ce qui l'expose à des problèmes de compatibilité en traitant des sources prévues pour gcc), à la différence de sparse, qui se branche facilement sur gcc ou llvm.

    # le site de Coccinelle
    http://coccinelle.lip6.fr

    # une introduction à Coccinelle par Val Aurora (anciennement Valerie Henson)
    http://lwn.net/Articles/315686/


    p.s.: en ce qui concerne la question de la licence de sparse :
    - Linus Torvalds donne une motivations spécifique sur le choix d'une licence incompatible avec la GPL, dans la FAQ de sparse. Il y explique qu'il souhaite (souhaitait) ainsi prendre le contrepied du parti prix monolithique de gcc (« I like the GPL, but as rms says, "Linus is just an engineer". I refuse to use a license if that license causes bad engineering decisions. I want the front-end to be considered a separate project ».
    cf.
    http://git.kernel.org/?p=linux/kernel/git/torvalds/sparse.gi(...)
    - Mais il reconnait que l'OSL n'est pas le meilleur choix :
    http://www.mail-archive.com/linux-sparse@vger.kernel.org/msg(...)
    - De toutes façons, Novafora (qui a hérité de la propriété intellectuelle de Transmeta) a accepté de re-licencer sous MIT il y a quelques mois :
    http://markmail.org/message/qijmu2cu4gbi74te

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.