Erstellen zuverlässiger Kernel-Mode-Treiber

Treiber machen einen erheblichen Prozentsatz des gesamten Codes aus, der im Kernelmodus ausgeführt wird. Ein Kernelmodustreiber ist tatsächlich eine Komponente des Betriebssystems. Daher tragen zuverlässige und sichere Treiber erheblich zur Allgemeinen Vertrauenswürdigkeit des Betriebssystems bei. Befolgen Sie die folgenden Richtlinien, um einen zuverlässigen Kernelmodustreiber zu erstellen:

  • Schützen Sie Geräteobjekte ordnungsgemäß.

    Der Benutzerzugriff auf die Treiber und Geräte eines Systems wird durch Sicherheitsbeschreibungen gesteuert, die das System Geräteobjekten zuweist. In den meisten Fällen legt das System Gerätesicherheitsparameter fest, wenn ein Gerät installiert wird. Weitere Informationen finden Sie unter Erstellen sicherer Geräteinstallationen. Manchmal ist es angebracht, dass ein Treiber eine Rolle bei der Steuerung des Zugriffs auf sein Gerät spielt. Weitere Informationen finden Sie unter Sichern von Geräteobjekten.

  • Überprüfen Sie Geräteobjekte ordnungsgemäß.

    Wenn ein Treiber mehrere Typen von Geräteobjekten erstellt, muss er überprüfen, welchen Typ er in jedem IRP empfängt. Weitere Informationen finden Sie unter Fehler beim Überprüfen von Geräteobjekten.

  • Verwenden Sie "sichere Zeichenfolgen"-Funktionen.

    Beim Bearbeiten von Zeichenfolgen sollte ein Treiber sichere Zeichenfolgenfunktionen anstelle der Zeichenfolgenfunktionen verwenden, die mit C/C++-Sprachlaufzeitbibliotheken bereitgestellt werden. Weitere Informationen finden Sie unter Verwenden sicherer Zeichenfolgenfunktionen.

  • Überprüfen von Objekthandles.

    Treiber, die Objekthandles als Eingabe empfangen, müssen überprüfen, ob die Handles gültig sind, darauf zugegriffen werden kann und vom erwarteten Typ sind. Weitere Informationen zur Verwendung von Objekthandles finden Sie in den folgenden Themen:

    Objektverwaltung

    Fehler beim Überprüfen von Objekthandles

  • Unterstützen Sie Multiprozessoren ordnungsgemäß.

    Gehen Sie niemals davon aus, dass Ihr Treiber nur auf Einzelprozessorsystemen ausgeführt wird. Informationen zu Programmiertechniken, die Sie verwenden können, um sicherzustellen, dass Ihr Treiber auf Multiprozessorsystemen ordnungsgemäß funktioniert, finden Sie in den folgenden Themen:

    Synchronisierungstechniken

    Fehler in einer Multiprozessorumgebung

  • Behandeln Sie den Treiberzustand ordnungsgemäß.

    Es ist wichtig, immer zu überprüfen, ob sich Ihr Treiber in dem Zustand befindet, von dem Sie annehmen, dass er sich befindet. Wenn der Treiber beispielsweise eine IRP empfängt, wird dann bereits ein IRP desselben Typs gewartet? Wenn der Treiber nicht auf diese Situation überprüft, kann die erste IRP verloren gehen. Weitere Informationen finden Sie unter Fehler beim Überprüfen des Treiberstatus.

  • Überprüfen Sie IRP-Eingabewerte.

    Aus Zuverlässigkeits- und Sicherheitssicht ist es wichtig, alle Werte zu überprüfen, die einem IRP zugeordnet sind, z. B. Pufferadressen und Längen. Die folgenden Themen enthalten Informationen zum Überprüfen von IRP-Eingabewerten:

    DispatchReadWrite mit gepufferten E/A-Vorgängen

    Fehler in gepufferten E/A-Vorgängen

    DispatchReadWrite mit direkter E/A

    Fehler in der direkten E/A

    Sicherheitsprobleme für E/A-Kontrollcodes

    Fehler beim Verweisen auf User-Space Adressen

  • Behandeln Sie den E/A-Stapel ordnungsgemäß.

    Beim Übergeben von IRPs im Treiberstapel ist es wichtig, dass Treiber IoSkipCurrentIrpStackLocation oder IoCopyCurrentIrpStackLocationToNext aufrufen, um den E/A-Stapelspeicherort des nächsten Treibers einzurichten. Schreiben Sie keinen Code, der einen E/A-Stapelspeicherort direkt in den nächsten kopiert.

  • Behandeln Sie IRP-Vervollständigungsvorgänge ordnungsgemäß.

    Ein Treiber darf niemals eine IRP mit dem status Wert STATUS_SUCCESS abschließen, es sei denn, er unterstützt und verarbeitet das IRP tatsächlich. Informationen zu den richtigen Methoden zum Verarbeiten von IRP-Vervollständigungsvorgängen finden Sie unter Abschließen von IRPs.

  • Behandeln Sie IRP-Abbruchvorgänge ordnungsgemäß.

    Abbrechen von Vorgängen kann schwierig sein, ordnungsgemäß zu codieren, da sie in der Regel asynchron ausgeführt werden. Probleme im Code, der Abbruchvorgänge verarbeitet, können lange Zeit unbemerkt bleiben, da dieser Code in einem ausgeführten System in der Regel nicht häufig ausgeführt wird.

    Lesen und verstehen Sie unbedingt alle Informationen unter Abbrechen von IRPs. Achten Sie besonders auf die Synchronisierung des IRP-Abbruchs und punkte, die beim Abbrechen von IRPs berücksichtigt werden sollten.

    Eine Möglichkeit, die mit Abbruchvorgängen verbundenen Synchronisierungsprobleme zu vermeiden, besteht darin, eine abbruchsichere IRP-Warteschlange zu implementieren. Eine abbruchsichere IRP-Warteschlange ist eine vom Treiber verwaltete Warteschlange, die für Windows XP und höhere Betriebssystemversionen eingeführt wurde, aber auch abwärtskompatibel zu früheren Versionen ist.

  • Behandeln Sie IRP-Bereinigungs- und -Schließvorgänge ordnungsgemäß.

    Stellen Sie sicher, dass Sie den Unterschied zwischen IRP_MJ_CLEANUP und IRP_MJ_CLOSE Anforderungen verstehen. Bereinigungsanforderungen gehen ein, nachdem eine Anwendung alle Handles für ein Dateiobjekt geschlossen hat, manchmal jedoch, bevor alle E/A-Anforderungen abgeschlossen sind. Schließen von Anforderungen nach Abschluss oder Abbruch aller E/A-Anforderungen für das Dateiobjekt. Weitere Informationen finden Sie in den folgenden Themen:

    DispatchCreate, DispatchClose und DispatchCreateCloseClose Routinen

    DispatchCleanup-Routinen

    Fehler beim Behandeln von Bereinigungs- und Schließenvorgängen

Weitere Informationen zur ordnungsgemäßen Behandlung von IRPs finden Sie unter Zusätzliche Fehler bei der Behandlung von IRPs.

Verwenden der Treiberüberprüfung

Driver Verifier ist das wichtigste Tool, das Sie verwenden können, um die Zuverlässigkeit Ihres Treibers sicherzustellen. Driver Verifier kann auf eine Vielzahl von häufig auftretenden Treiberproblemen überprüfen, einschließlich einiger der in diesem Abschnitt erläuterten Probleme. Die Verwendung von Driver Verifier ersetzt jedoch nicht den sorgfältigen, durchdachten Softwareentwurf.