Sdílet prostřednictvím


Zpracování ovládacího prvku systému souborů

Zpracování operace IRP_MJ_FILE_SYSTEM_CONTROL se liší od zpracování vyrovnávací paměti dat vyžadované jinými operacemi v systému souborů. Důvodem je to, že každá operace vytváří svůj specifický mechanismus přenosu dat pro správce vstupně-výstupních operací jako součást řídicího kódu pomocí CTL_CODE makra. Kromě toho řídicí kód určuje přístup k souboru, který vyžaduje volající. Systém souborů by měl být obzvláště obeznámen s tímto problémem při definování řídicího kódu, protože tento přístup je vynucen správcem vstupně-výstupních operací. Některé vstupně-výstupní kontrolní kódy (FSCTL_MOVE_FILE , například) určují FILE_SPECIAL_ACCESS, což je mechanismus umožňující systému souborů indikovat, že zabezpečení operace bude kontrolováno přímo systémem souborů. FILE_SPECIAL_ACCESS je číselně ekvivalentní FILE_ANY_ACCESS, takže správce vstupně-výstupních operací neposkytuje žádné konkrétní kontroly zabezpečení a místo toho ponechává tuto odpovědnost na systému souborů. FILE_SPECIAL_ACCESS hlavně poskytuje dokumentaci, že systém souborů provede dodatečné kontroly.

Několik operací systému souborů určuje FILE_SPECIAL_ACCESS. Operace FSCTL_MOVE_FILE se používá jako součást defragmentačního rozhraní pro systémy souborů a určuje FILE_SPECIAL_ACCESS. Vzhledem k tomu, že chcete mít možnost defragmentovat otevřené soubory, které se aktivně čtou a zapisují, má popisovač, který se má použít, pouze FILE_READ_ATTRIBUTES udělen přístup, aby nedocházelo ke konfliktům přístupu ke sdílení. Tato operace ale musí být privilegovanou operací, protože disk se upravuje na nízké úrovni. Řešením je ověřit, že popisovač použitý k vydání FSCTL_MOVE_FILE je privilegovaný popisovač otevřeného uživatelského svazku na zařízení pro přímý přístup (DASD). Kód systému souborů FASTFAT, který zajišťuje, že se tato operace provádí na uživatelský svazek, který je otevřen, se nachází ve funkci FatMoveFile (viz zdrojový soubor fsctrl.c z ukázky fastfat, kterou WDK obsahuje).

    //
    //  extract and decode the file object and check for type of open
    //

    if (FatDecodeFileObject( IrpSp->FileObject, &Vcb, &FcbOrDcb, &Ccb ) != UserVolumeOpen) {

        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );

        DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

Struktura používaná operací FSCTL_MOVE_FILE určuje přesunutý soubor:

typedef struct {
    HANDLE FileHandle;
    LARGE_INTEGER StartingVcn;
    LARGE_INTEGER StartingLcn;
    ULONG ClusterCount;
} MOVE_FILE_DATA, *PMOVE_FILE_DATA;

Jak bylo již zmíněno, popisovač použitý k zajištění příkazu FSCTL_MOVE_FILE je operací s "otevřením" celého svazku, i když ve skutečnosti se operace týká popisovače souboru zadaného ve vstupní vyrovnávací paměti MOVE_FILE_DATA. Díky tomu jsou kontroly zabezpečení pro tuto operaci poněkud složité. Toto rozhraní například musí převést popisovač souboru na objekt souboru, který představuje přesunutý soubor. To vyžaduje pečlivé zvážení na straně jakéhokoli řidiče. FASTFAT to dělá pomocí ObReferenceObject zabezpečeným způsobem ve funkci FatMoveFile ve zdrojovém souboru fsctrl.c ve vzorovém souboru fastfat, který WDK obsahuje.

    //
    //  Try to get a pointer to the file object from the handle passed in.
    //

    Status = ObReferenceObjectByHandle( InputBuffer->FileHandle,
                                        0,
                                        *IoFileObjectType,
                                        Irp->RequestorMode,
                                        &FileObject,
                                        NULL );

    if (!NT_SUCCESS(Status)) {

        FatCompleteRequest( IrpContext, Irp, Status );

        DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", Status);
        return Status;
    }
    //  Complete the following steps to ensure that this is not an invalid attempt
    //
    //    - check that the file object is opened on the same volume as the
    //      DASD handle used to call this routine.
    //
    //    - extract and decode the file object and check for type of open.
    //
    //    - if this is a directory, verify that it's not the root and that
    //      you are not trying to move the first cluster.  You cannot move the
    //      first cluster because sub-directories have this cluster number
    //      in them and there is no safe way to simultaneously update them
    //      all.
    //
    //  Allow movefile on the root directory if it's FAT32, since the root dir
    //  is a real chained file.
    //    //

Všimněte si použití Irp->RequestorMode k zajištění, že pokud je volající aplikace v uživatelském režimu, popisovač nemůže být popisovač jádra. Požadovaný přístup je 0, aby se soubor mohl během aktivního přístupu přesunout. A nakonec si všimněte, že toto volání musí být provedeno ve správném kontextu procesu, pokud volání pochází z uživatelského režimu. Zdrojový kód ze systému souborů FASTFAT to vynucuje i ve funkci FatMoveFile v fsctrl.c:

    //
    //  Force WAIT to true. There is a handle in the input buffer that can only
    //  be referenced within the originating process.
    //

    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

Tyto sémantické kontroly zabezpečení prováděné systémem souborů FAT jsou typické pro ty, které systém souborů vyžaduje pro jakoukoli operaci, která předává popisovač. Kromě toho musí systém souborů FAT provádět také kontroly sanity specifické pro danou operaci. Tyto kontrolní mechanismy zajišťují, aby byly různorodé parametry kompatibilní (například aby přesunutý soubor byl na svazku, který byl otevřen), aby volající nemohl provádět privilegovanou operaci, pokud by to nemělo být povoleno.

Správné zabezpečení je nezbytnou součástí operací řízení souborového systému, mezi které patří:

  • Ověřování uživatelských jmen odpovídajícím způsobem.

  • Ochrana přístupu k vyrovnávací paměti uživatele

  • Ověřování sémantiky konkrétní operace

V mnoha případech může kód potřebný k provedení správného ověření a zabezpečení představovat podstatnou část kódu v rámci dané funkce.