windows-drivers-rs - Plattform für die Entwicklung von Windows-Treibern in Rust
(github.com/microsoft)- Eine Sammlung von Rust-Crates, die die Entwicklung von Windows-Treibern in Rust ermöglicht und die Unterstützung der Treibermodelle WDM und WDF zum Ziel hat
- Zu den Hauptbestandteilen gehören
wdk-buildfür die WDK-Build-Konfiguration,wdk-sysfür direkte FFI-Bindings der WDK-API,wdkfür sichere und idiomatische Bindings der WDK-API,wdk-panicfür den Panic-Handler,wdk-allocfüralloc-Unterstützung sowiewdk-macros, eine Makro-Sammlung zur Unterstützung bei der Nutzung direkterwdk-sys-Bindings - Es wurde mit Blick auf die Unterstützung von WDM-, KMDF- und UMDF-Treibern sowie Win32-Services entwickelt und umfasst die Unterstützung aller in WDK 22H2 oder neuer enthaltenen WDF-Versionen
- Die auf
crates.ioveröffentlichten Crates unterstützen derzeit nur KMDF v1.33; Bindings für andere Konfigurationen können erzeugt werden, indemwindows-drivers-rsgeklont und anschließend diebuild.rs-Konfiguration vonwdk-sysangepasst wird - Der typische Ablauf besteht aus dem Erstellen eines Cargo-
lib-Pakets, dem Hinzufügen der Abhängigkeitenwdk-build,wdk,wdk-sys,wdk-allocundwdk-panic, dem Setzen voncdylib, dem Konfigurieren der WDK-Metadaten, dem Aufruf vonwdk_build::configure_wdk_binary_build()inbuild.rs, dem Hinzufügen vonDriverEntryund dem Ausführen voncargo make- Für Kernel-Mode-Crates wie KMDF- und WDM-Treiber sind die Panic-Strategie
abort,#![no_std]und die Einrichtung eines Panic-Handlers erforderlich - Um das
alloc-Modul der Rust-Standardbibliothek zu verwenden, muss der globale Allocatorwdk_alloc::WdkAllocatorgesetzt werden
- Für Kernel-Mode-Crates wie KMDF- und WDM-Treiber sind die Panic-Strategie
- Zu den Build-Anforderungen gehören
libclangfürbindgen,cargo-makefür Post-Build-Aufgaben sowie eine gültige WDK-Umgebung; empfohlen wird der Einstieg über den eWDK Developer Prompt cargo makebaut und paketiert Treiber standardmäßig, wobei als Ergebnis ein signiertes Treiberpaket und die DateiWDRLocalTestCert.ceruntertarget/<Cargo profile>/packageoder unter dem Pfad der Zielarchitektur erzeugt werden- Unterstützt werden die Übergabe von Argumenten wie
cargo make default --target <TARGET TRIPLE>,--release,--features <FEATURES>und+<TOOLCHAIN>; außerdem kann mitWDK_BUILD_ENABLE_SIGNTOOL_VERIFY=truedie Signaturprüfung der erzeugten.sys- und.cat-Dateien aktiviert werden - Die neue Cargo-Erweiterung
cargo-wdkbefindet sich in der Entwicklung und im Preview-Status, umcargo-makeals empfohlenes Werkzeug für den Build von Rust-Treibern zu ersetzen - Minimale Beispiele für WDM, KMDF und UMDF finden sich im
examples-Verzeichnis; Beispiele für die Treibererstellung gibt es unter Windows-rust-driver-samples - Das Projekt befindet sich noch in einer frühen Entwicklungsphase und wird für den Production-Einsatz noch nicht empfohlen
3 Kommentare
Meinungen auf Hacker News
Zur Erinnerung: Mark Russinovich betrieb, bevor er den Posten seines Chefs übernahm und als möglicher nächster MSFT-CEO gehandelt wurde, eine Firma für Software-Tools und NT-Kernel-Consulting, zu der Redmond-Ingenieure gingen, um die Entwicklung am NT-Kernel zu lernen.
Außerdem entdeckte er Sonys DRM-Rootkit und Symantecs rootkitartige Dateischutzfunktion und deckte auf, dass Best Buy ERD Commander illegal kopiert hatte.
Heute bedauere ich ein wenig, dass ich 2014 LinkedIn gelöscht habe. Es war ein Account, bei dem praktisch das ganze Valley und Mark Kontakte ersten Grades waren, aber in relativer Unbekanntheit liegen auch Freiheit und Wendigkeit. Wie hieß noch mal dieser Reggae-Song von Desmond Dekker darüber, dass es sinnlos ist, herumzuerzählen, was man alles gemacht und verdient hat und wen man kennt?
Es ist ziemlich interessant, dass Unternehmen dieser Größenordnung, obwohl sie mit echtem Source Code und Zugang zu Ingenieuren eine viel bessere Ausgangsposition haben, so etwas selbst nicht besonders gut hinbekommen. Diese Drittanbieter, zumindest Levin, mussten sich zu einem großen Teil auf Reverse Engineering stützen.
https://newosxbook.com
Wenn man bedenkt, dass nahezu jedes Unternehmen weltweit, das Windows nutzt, mindestens ein Sysinternals-Tool verwendet, war der Einfluss von Sysinternals vielleicht sogar größer als der von Azure selbst.
Vermutlich hat MSFT Mark Russinovich und sein Team genau deshalb per Acquihire übernommen.
Mein Eindruck aus dem ersten Buch war, dass er die Welt extrem schwarz-weiß sieht.
Original-Tweet: https://twitter.com/markrussinovich/status/17057307039574058...
http://farside.link/twitter.com/markrussinovich/status/17057...
Nettes /s, aber das ist nicht sehr Rust-typisch:
pub struct QueueContext {
buffer: PVOID,
length: usize,
timer: wdf::Timer,
current_request: WDFREQUEST,
current_status: NTSTATUS,
spin_lock: wdf::SpinLock,
}
Beim Schreiben von Rust-Treibern für den Linux-Kernel gibt es ähnliche Probleme, und dasselbe gilt für andere Projekte, die mit C interoperieren.
Typen wie NTSTATUS sind ziemlich umfangreich dokumentiert. Anders als in C oder C++ kann man in Rust Integer-Werte nicht einfach Enum-Werten zuweisen. Man könnte Wrapper-Klassen erzeugen und jedes Mal casten lassen, aber dann bestünde die Hälfte des Codes aus
.into(), und vermutlich entstünde auch Overhead im Treiber.So wie es aussieht, werden diese Enum-Werte, abgesehen vielleicht von einem
void*fürbuffer, nicht gesetzt oder verändert, sondern nur gelesen. Für NTSTATUS dürfte einmatch {}-Block ausreichen. WDFREQUEST ist ein Handle; außer es gegen ein anderes Handle desselben Typs auszutauschen, kann man damit ohnehin nicht viel machen.Timer und SpinLock sind in Rust-typische Objekte umgewandelt, die unsichere Library-Aufrufe intern kapseln. Darüber hinaus sehe ich keine gute Möglichkeit, diesen Code ohne erhebliche Performance-Kosten Rust-typischer zu machen.
Weißt du, was besser wäre? Gerätetreiber in einer speicherverwalteten Sprache wie C# zu schreiben.
Ich stimme Microsofts Einschätzung zu, dass es besser ist, weniger Herstellercode im Kernel auszuführen, statt den Kernel leichter zugänglich zu machen. C# eignet sich nicht für Situationen wie „Ich möchte auf irgendeinen Buffer zugreifen, aber er ist noch nicht eingepaged, und ich befinde mich in einem Interrupt-Handler“, daher erscheint es nahezu unmöglich, im Kernel einen Garbage Collector fehlerfrei laufen zu lassen.
Treiber können zu Zeitpunkten auf Speicher zugreifen, zu denen Page Faults nicht möglich sind, etwa in einem Interrupt-Handler, weshalb die Speicherverfügbarkeit extrem strikt kontrolliert werden muss. Die C#-Sprache und -Runtime müssten zumindest Funktionen hinzufügen, um damit explizit umzugehen.
Ich füge das hinzu, weil mir das etwas unterschätzt zu werden scheint. Russinovich ist jemand, der unzählige Materialien und Tools rund um den Windows-Kernel erstellt hat. Unter den Entwicklern, die mit dem Windows-Kernel gearbeitet haben – einschließlich der Entwickler von Rootkits –, gibt es wohl niemanden, der nicht anhand von Russinovichs Materialien oder Dokumenten gelernt hat.
Es hieß zwar, dass der Windows-Kernel in Rust neu geschrieben werde, und nun kommt endlich das Treiber-SDK heraus. Wahrscheinlich erscheint bald eine Ankündigung, dass man ab 20XX Treiber in Rust entwickeln soll.