Share via


Erstellen einer Verarbeitung

Für ein Dateisystem tritt der größte Teil der interessanten Sicherheitsarbeit während IRP_MJ_CREATE Verarbeitung auf. Es ist dieser Schritt, der die eingehende Anforderung analysieren, bestimmen muss, ob der Aufrufer über die entsprechenden Rechte zum Ausführen des Vorgangs verfügt, und den Vorgang nach Bedarf erteilen oder verweigern. Glücklicherweise wird für Dateisystementwickler der größte Teil des Entscheidungsmechanismus im Sicherheitsreferenzmonitor implementiert. Daher muss das Dateisystem in den meisten Fällen nur die entsprechenden Sicherheitsreferenzmonitorroutinen aufrufen, um den Zugriff ordnungsgemäß zu bestimmen. Das Risiko für ein Dateisystem tritt auf, wenn es diese Routinen nicht bei Bedarf aufruft und einem Aufrufer unangemessen Zugriff gewährt.

Bei einem Standarddateisystem, z. B. dem FAT-Dateisystem, sind die überprüfungen, die als Teil von IRP_MJ_CREATE in erster Linie semantische Überprüfungen sind. Beispielsweise verfügt das FAT-Dateisystem über zahlreiche Überprüfungen, um sicherzustellen, dass IRP_MJ_CREATE Verarbeitung basierend auf dem Status der Datei oder des Verzeichnisses zulässig ist. Diese vom FAT-Dateisystem durchgeführten Überprüfungen umfassen Überprüfungen auf schreibgeschützte Medien (z. B. Versuche, destruktive "Erstellungsvorgänge", z. B. Überschreiben oder Ersetzen, auf schreibgeschützten Medien sind nicht zulässig), Freigabezugriffsprüfungen und Oplock-Überprüfungen. Einer der schwierigsten Teile dieser Analyse besteht darin, zu erkennen, dass ein Vorgang auf einer Ebene (z. B. auf Dateiebene) aufgrund des Zustands einer anderen Ressourcenebene (z. B. der Volumeebene) nicht zulässig ist. Beispielsweise kann eine Datei nicht geöffnet werden, wenn ein anderer Prozess das Volume ausschließlich gesperrt hat. Zu den gängigen Zu überprüfenden Fällen gehören:

  • Ist die geöffnete Dateiebene mit dem Zustand der Volumeebene kompatibel? Die Sperrung auf Volumeebene muss eingehalten werden. Wenn also ein Prozess eine exklusive Sperre auf Volumeebene enthält, können nur Threads innerhalb dieses Prozesses Dateien öffnen. Threads aus anderen Prozessen dürfen dateien nicht öffnen.

  • Ist die geöffnete Dateiebene mit dem Medienzustand kompatibel? Bestimmte "Create"-Vorgänge ändern die Datei im Rahmen des Vorgangs "create". Dies umfasst das Überschreiben, Ablösen und sogar das Aktualisieren des letzten Zugriffs auf die Datei. Diese "Erstellungsvorgänge" sind auf schreibgeschützten Medien nicht zulässig, und der Zeitpunkt des letzten Zugriffs wird nicht aktualisiert.

  • Ist die geöffnete Volumeebene mit dem Zustand auf Dateiebene kompatibel? Ein exklusives Öffnen eines Volumes ist nicht zulässig, wenn dateien auf dem Volume geöffnet sind. Dies ist ein häufiges Problem für neue Entwickler, da sie versuchen, das Volume zu öffnen und feststellen, dass es fehlschlägt. Wenn dies fehlschlägt, können FSCTL_DISMOUNT_VOLUME verwendet werden, um geöffnete Handles zu ungültig zu machen und eine Aufhebung der Bereitstellung zu erzwingen, sodass exklusiver Zugriff auf das neu bereitgestellte Volume gewährt wird.

Darüber hinaus müssen Dateiattribute kompatibel sein. Eine Datei mit dem schreibgeschützten Attribut kann nicht für den Schreibzugriff geöffnet werden. Beachten Sie, dass der gewünschte Zugriff überprüft werden sollte, nachdem die Erweiterung der generischen Rechte erweitert wurde. Diese Überprüfung innerhalb des FASTFAT-Dateisystems befindet sich beispielsweise in der FatCheckFileAccess-Funktion (siehe die Acchksup.c-Quelldatei aus den fastfat-Beispielen, die das WDK enthält).

Das folgende Codebeispiel ist spezifisch für die FAT-Semantik. Ein Dateisystem, das auch DACLs implementiert, würde eine zusätzliche Sicherheitsüberprüfung mithilfe der Sicherheitsreferenzmonitorroutinen (z. B. SeAccessCheck) durchführen.

    //
    //  check for a read-only Dirent
    //

    if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {

        //
        //  Check the desired access for a read-only Dirent
        // Don't allow 
        //  WRITE, FILE_APPEND_DATA, FILE_ADD_FILE,
        //  FILE_ADD_SUBDIRECTORY, and FILE_DELETE_CHILD
        //

        if (FlagOn(*DesiredAccess, ~(DELETE |
                                     READ_CONTROL |
                                     WRITE_OWNER |
                                     WRITE_DAC |
                                     SYNCHRONIZE |
                                     ACCESS_SYSTEM_SECURITY |
                                     FILE_READ_DATA |
                                     FILE_READ_EA |
                                     FILE_WRITE_EA |
                                     FILE_READ_ATTRIBUTES |
                                     FILE_WRITE_ATTRIBUTES |
                                     FILE_EXECUTE |
                                     FILE_LIST_DIRECTORY |
                                     FILE_TRAVERSE))) {

            DebugTrace(0, Dbg, "Cannot open readonly\n", 0);

            try_return( Result = FALSE );
        }

Eine subtilere Überprüfung, die von FASTFAT implementiert wird, besteht darin, sicherzustellen, dass der vom Aufrufer angeforderte Zugriff etwas ist, das dem FAT-Dateisystem bekannt ist (in der FatCheckFileAccess-Funktion in Acchksup.c aus dem fastfat-Beispiel, das das WDK enthält):

Im folgenden Codebeispiel wird ein wichtiges Konzept für die Dateisystemsicherheit veranschaulicht. Überprüfen Sie, ob das, was an Ihr Dateisystem übergeben wird, nicht außerhalb der erwarteten Grenzen liegt. Der konservative und richtige Ansatz aus Sicherheitssicht besteht darin, dass Sie diese Anforderung ablehnen sollten, wenn Sie eine Zugriffsanforderung nicht verstehen.

    //
    // Check the desired access for the object. 
    // Reject what we do not understand.
    // The model of file systems using ACLs is that
    // they do not type the ACL to the object that the 
    // ACL is on. 
    // Permissions are not checked for consistency vs.
    // the object type - dir/file.
    //

    if (FlagOn(*DesiredAccess, ~(DELETE |
                                 READ_CONTROL |
                                 WRITE_OWNER |
                                 WRITE_DAC |
                                 SYNCHRONIZE |
                                 ACCESS_SYSTEM_SECURITY |
                                 FILE_WRITE_DATA |
                                 FILE_READ_EA |
                                 FILE_WRITE_EA |
                                 FILE_READ_ATTRIBUTES |
                                 FILE_WRITE_ATTRIBUTES |
                                 FILE_LIST_DIRECTORY |
                                 FILE_TRAVERSE |
                                 FILE_DELETE_CHILD |
                                 FILE_APPEND_DATA))) {

        DebugTrace(0, Dbg, "Cannot open object\n", 0);

        try_return( Result = FALSE );
    }

Glücklicherweise werden bei Dateisystemen, nachdem die Sicherheitsüberprüfung während der ersten Erstellungsverarbeitung durchgeführt wurde, nachfolgende Sicherheitsüberprüfungen vom E/A-Manager durchgeführt. So stellt der E/A-Manager beispielsweise sicher, dass Anwendungen im Benutzermodus keinen Schreibvorgang für eine Datei ausführen, die nur für den Lesezugriff geöffnet wurde. Tatsächlich sollte ein Dateisystem nicht versuchen, schreibgeschützte Semantik für das Dateiobjekt zu erzwingen, selbst wenn es nur für den Lesezugriff geöffnet wurde, während der IRP_MJ_WRITE Dispatchroutine. Dies liegt daran, wie der Speicher-Manager einem bestimmten Abschnittsobjekt ein bestimmtes Dateiobjekt zuordnet. Das nachfolgende Schreiben durch diesen Abschnitt wird als IRP_MJ_WRITE Vorgänge für das Dateiobjekt gesendet, obwohl die Datei schreibgeschützt geöffnet wurde. Anders ausgedrückt: Die Zugriffserzwingung erfolgt, wenn ein Dateihandle von ObReferenceObjectByHandle an Nt-Systemdiensteinstiegspunkten in das entsprechende Dateiobjekt konvertiert wird.

Es gibt zwei zusätzliche Stellen innerhalb eines Dateisystems, an denen semantische Sicherheitsüberprüfungen ähnlich wie bei der "Erstellen"-Verarbeitung durchgeführt werden müssen:

  • Während der Verarbeitung von Umbenennung oder harter Verknüpfung.

  • Beim Verarbeiten von Dateisystemsteuerungsvorgängen.

In den nachfolgenden Abschnitten wird die Umbenennungsverarbeitung und die Verarbeitung der Dateisystemsteuerung erläutert.

Beachten Sie, dass dies keine vollständige Liste der semantischen Probleme im Zusammenhang mit der "Erstellen"-Verarbeitung ist. In diesem Abschnitt sollen Dateisystementwickler auf diese Probleme hingewiesen werden. Alle semantischen Probleme müssen für ein bestimmtes Dateisystem identifiziert, implementiert werden, um die spezifische Semantik zu erfüllen, und getestet werden, um sicherzustellen, dass die Implementierung die verschiedenen Fälle behandelt.