3 points par GN⁺ 2023-09-25 | 3 commentaires | Partager sur WhatsApp
  • Ensemble de crates Rust permettant de développer des Windows Drivers en Rust, avec pour objectif de prendre en charge les modèles de développement de pilotes WDM et WDF
  • Les principaux composants sont wdk-build pour la configuration de build WDK, wdk-sys pour les bindings FFI directs vers l’API WDK, wdk pour des bindings de l’API WDK sûrs et idiomatiques, wdk-panic pour le panic handler, wdk-alloc pour la prise en charge de alloc, et wdk-macros, un ensemble de macros facilitant l’utilisation des bindings directs de wdk-sys
  • Conçu en tenant compte de la prise en charge des pilotes WDM, KMDF, UMDF et des services Win32, avec support de toutes les versions de WDF incluses dans WDK 22H2 et versions ultérieures
  • Les crates publiées sur crates.io ne prennent actuellement en charge que KMDF v1.33 ; pour générer des bindings pour d’autres configurations, il faut cloner windows-drivers-rs puis modifier la configuration de build.rs dans wdk-sys
  • Le flux d’utilisation consiste à créer un package Cargo lib, ajouter les dépendances wdk-build, wdk, wdk-sys, wdk-alloc, wdk-panic, configurer cdylib, définir les métadonnées WDK, appeler wdk_build::configure_wdk_binary_build() dans build.rs, ajouter DriverEntry, puis exécuter cargo make
    • Les pilotes KMDF et WDM, qui sont des crates en mode noyau, nécessitent la stratégie de panic abort, #![no_std] et la configuration d’un panic handler
    • Pour utiliser le module alloc de la bibliothèque standard Rust, il faut définir wdk_alloc::WdkAllocator comme allocator global
  • Les prérequis de build sont libclang pour bindgen, cargo-make pour les tâches post-build, ainsi qu’un environnement WDK valide ; la méthode recommandée consiste à passer par l’eWDK developer prompt
  • cargo make compile et empaquette les pilotes par défaut, et génère un package de pilotes signé ainsi que le fichier WDRLocalTestCert.cer dans target/<Cargo profile>/package ou sous le chemin correspondant à l’architecture cible
  • La transmission d’arguments comme cargo make default --target <TARGET TRIPLE>, --release, --features <FEATURES>, +<TOOLCHAIN> est prise en charge, et l’activation de WDK_BUILD_ENABLE_SIGNTOOL_VERIFY=true permet de lancer la vérification de signature des fichiers .sys et .cat générés
  • La nouvelle extension Cargo cargo-wdk est en cours de développement en preview afin de remplacer cargo-make comme outil recommandé pour la compilation de pilotes Rust
  • Des exemples minimaux WDM, KMDF et UMDF sont disponibles dans le répertoire examples, et des exemples de création de pilotes sont consultables dans Windows-rust-driver-samples
  • Le projet en est encore à un stade de développement précoce et n’est pas encore recommandé pour un usage en production

3 commentaires

 
GN⁺ 2023-09-25
Avis de Hacker News
  • Pour ceux qui ne s’en souviennent pas, Mark Russinovich, avant de prendre la place de son patron et d’être évoqué comme possible prochain CEO de MSFT, dirigeait une société d’outils logiciels et de conseil autour du noyau NT, où les ingénieurs de Redmond allaient apprendre le développement du noyau NT.
    Il a aussi découvert des fonctionnalités de protection de fichiers comme le rootkit DRM de Sony et le rootkit de Symantec, et a également pris Best Buy la main dans le sac pour le piratage d’ERD Commander.
    Je regrette un peu d’avoir supprimé LinkedIn en 2014. C’était le compte où toute la Valley et Mark étaient des relations de premier niveau, mais il y a quand même une forme de liberté et d’agilité dans l’anonymat relatif. C’était quoi déjà, cette chanson reggae de Desmond Dekker qui dit qu’il ne sert à rien de raconter tout ce qu’on a fait, gagné, et qui on connaît ?

    • Apple semble avoir fait quelque chose de similaire. Les documents internes d’Apple n’étaient pas grand-chose comparés aux livres de Jonathan Levin, si bien qu’Apple en achetait souvent pour ses ingénieurs OS.
      C’est assez intéressant que des entreprises de cette taille, alors qu’elles disposent d’un avantage bien plus grand avec le code source réel et l’accès aux ingénieurs, n’arrivent pas vraiment à bien faire ce travail elles-mêmes. Ces tiers, au moins Levin, ont dû s’appuyer en grande partie sur la rétro-ingénierie.
      https://newosxbook.com
    • On ne peut pas parler de lui sans mentionner Sysinternals. Je dépends de cette suite d’outils tous les jours au travail.
      Quand on pense que presque toutes les entreprises dans le monde qui utilisent Windows se servent d’au moins un outil Sysinternals, l’influence de Sysinternals a peut-être même été plus grande que celle d’Azure lui-même.
    • Les outils Sysinternals devraient être inclus par défaut dans chaque installation de Windows. Ils sont indispensables dans mon environnement, et ils me manquent vraiment quand je répare ou débogue l’ordinateur d’un ami.
      C’est sans doute pour cela que MSFT a acquihiré Mark Russinovich et son équipe, non ?
    • C’est un bon programmeur, mais à lire son livre, je ne pense pas qu’il ferait un bon CEO.
      L’impression que m’a laissée son premier livre, c’est qu’il voit le monde de façon extrêmement manichéenne.
  • Tweet d’origine : https://twitter.com/markrussinovich/status/17057307039574058...

  • Joli /s, mais ce n’est pas très Rust-like :
    pub struct QueueContext {
    buffer: PVOID,
    length: usize,
    timer: wdf::Timer,
    current_request: WDFREQUEST,
    current_status: NTSTATUS,
    spin_lock: wdf::SpinLock,
    }

    • La plupart de ces éléments finissent par désigner des types entiers FFI. C’est ainsi que l’API des pilotes Windows les utilise.
      On rencontre un problème similaire avec les pilotes Rust dans le noyau Linux, et c’est pareil pour d’autres projets qui interopèrent avec du C.
      Des types comme NTSTATUS sont assez largement documentés. Contrairement à C ou C++, Rust ne permet pas d’assigner simplement une valeur entière à une valeur d’enum. On pourrait créer des classes wrapper pour forcer un cast à chaque fois, mais alors la moitié du code deviendrait des .into(), et cela risquerait aussi d’ajouter de l’overhead dans le pilote.
      À vue d’œil, à part peut-être le void* pour buffer, ces valeurs d’enum ne sont pas définies ni modifiées, seulement lues. Pour NTSTATUS, un bloc match {} devrait suffire. WDFREQUEST est un handle, donc à part le remplacer par un autre handle du même type, il n’y a pas grand-chose qu’on puisse faire avec.
      Timer et SpinLock ont été transformés en objets idiomatiques Rust qui encapsulent en interne des appels de bibliothèque unsafe. Pour le reste, je ne vois pas vraiment comment rendre ce code plus idiomatique Rust sans imposer une charge de performance importante.
    • Pour se débarrasser de ça, il faudrait probablement tout réécrire.
  • Vous savez ce qui serait mieux ? Écrire des pilotes de périphériques dans un langage à mémoire managée comme C#.

    • Microsoft pousse de plus en plus de code vers l’espace utilisateur. Parmi les changements récents, les fabricants d’imprimantes doivent utiliser des apps d’impression UWP, et non des pilotes, pour ajouter des fonctionnalités personnalisées à leurs imprimantes. Ces apps sont généralement écrites dans des langages comme C#.
      Je suis d’accord avec le jugement de Microsoft : plutôt que de rendre le noyau plus facilement accessible, il vaut mieux exécuter moins de code constructeur dans le noyau. C# n’est pas adapté à des situations du genre « je veux accéder à un buffer, mais il n’a pas encore été paginé en mémoire, et je suis dans un gestionnaire d’interruption », donc faire tourner un garbage collector dans le noyau sans bugs semble presque impossible.
    • Je ne sais pas si ce serait vraiment mieux. Je n’ai pas d’expérience en développement de pilotes, mais les pilotes de périphériques sont des composants essentiels bas niveau d’un système d’exploitation en fonctionnement, et cela ne semble pas très compatible avec une garbage collection qui interrompt l’exécution selon son propre calendrier.
    • Je n’ai pas envie que ma souris saccade parce que le pilote s’est arrêté pour faire tourner le garbage collector.
    • Microsoft a déjà essayé, et cela a été un échec cuisant. Je crois qu’ils n’en ont pas donné la raison, mais sur le matériel du début des années 2000, je pense que la garbage collection aurait provoqué beaucoup trop de pauses.
    • Même en C++, il est très difficile d’écrire des pilotes de périphériques tout en conservant la capacité à écrire des pilotes noyau paginables.
      Les pilotes peuvent avoir besoin d’accéder à la mémoire à des moments où une faute de page est impossible, par exemple dans un gestionnaire d’interruption, ce qui impose un contrôle très strict de la disponibilité de la mémoire. Le langage et le runtime C# devraient au minimum ajouter des mécanismes explicites pour gérer cela.
 
bungker 2023-11-30

Je pense que c’est un peu sous-estimé, donc j’ajoute ceci. Russinovich est quelqu’un qui a créé une multitude de ressources et d’outils en lien avec le noyau Windows. Parmi les développeurs travaillant sur le noyau Windows (y compris ceux qui ont créé des rootkits), il n’y a sans doute personne qui n’ait pas étudié en s’appuyant sur les ressources ou la documentation de Russinovich.

 
botplaysdice 2023-12-01

On entendait dire que le noyau Windows était en cours de réécriture en Rust, et voilà enfin que le SDK pour les pilotes arrive. Il y aura sans doute bientôt une annonce indiquant qu’à partir de 20XX, il faudra créer les pilotes en Rust.