windows-drivers-rs - une plateforme qui permet de développer des pilotes Windows en Rust
(github.com/microsoft)- 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-buildpour la configuration de build WDK,wdk-syspour les bindings FFI directs vers l’API WDK,wdkpour des bindings de l’API WDK sûrs et idiomatiques,wdk-panicpour le panic handler,wdk-allocpour la prise en charge dealloc, etwdk-macros, un ensemble de macros facilitant l’utilisation des bindings directs dewdk-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.ione prennent actuellement en charge que KMDF v1.33 ; pour générer des bindings pour d’autres configurations, il faut clonerwindows-drivers-rspuis modifier la configuration debuild.rsdanswdk-sys - Le flux d’utilisation consiste à créer un package Cargo
lib, ajouter les dépendanceswdk-build,wdk,wdk-sys,wdk-alloc,wdk-panic, configurercdylib, définir les métadonnées WDK, appelerwdk_build::configure_wdk_binary_build()dansbuild.rs, ajouterDriverEntry, puis exécutercargo 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
allocde la bibliothèque standard Rust, il faut définirwdk_alloc::WdkAllocatorcomme allocator global
- Les pilotes KMDF et WDM, qui sont des crates en mode noyau, nécessitent la stratégie de panic
- Les prérequis de build sont
libclangpourbindgen,cargo-makepour les tâches post-build, ainsi qu’un environnement WDK valide ; la méthode recommandée consiste à passer par l’eWDK developer prompt cargo makecompile et empaquette les pilotes par défaut, et génère un package de pilotes signé ainsi que le fichierWDRLocalTestCert.cerdanstarget/<Cargo profile>/packageou 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 deWDK_BUILD_ENABLE_SIGNTOOL_VERIFY=truepermet de lancer la vérification de signature des fichiers.syset.catgénérés - La nouvelle extension Cargo
cargo-wdkest en cours de développement en preview afin de remplacercargo-makecomme 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
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 ?
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
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.
C’est sans doute pour cela que MSFT a acquihiré Mark Russinovich et son équipe, non ?
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...
http://farside.link/twitter.com/markrussinovich/status/17057...
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,
}
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*pourbuffer, ces valeurs d’enum ne sont pas définies ni modifiées, seulement lues. Pour NTSTATUS, un blocmatch {}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.
Vous savez ce qui serait mieux ? Écrire des pilotes de périphériques dans un langage à mémoire managée 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.
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.
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.
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.