Aracılığıyla paylaş


Dosya Sistemi Denetimi İşleme

IRP_MJ_FILE_SYSTEM_CONTROL işleminin işlenmesi, dosya sistemindeki diğer işlemlerin gerektirdiği veri arabelleği işlemesinden farklıdır. Bunun nedeni, her işlemin CTL_CODE makro yoluyla denetim kodunun bir parçası olarak G/Ç yöneticisi için kendi özel veri aktarım mekanizmasını oluşturmasıdır. Buna ek olarak, denetim kodu çağıranın gerektirdiği dosya erişimini belirtir. G/Ç yöneticisi tarafından bu erişim uygulandığından, bir dosya sistemi denetim kodunu belirlerken bu sorun konusunda özellikle farkında olmalıdır. Bazı G/Ç denetim kodları (örneğin FSCTL_MOVE_FILE) FILE_SPECIAL_ACCESS belirtir. Bu, dosya sisteminin işlemin güvenliğinin doğrudan dosya sistemi tarafından denetleneceğini belirtmesine olanak tanıyan bir mekanizmadır. FILE_SPECIAL_ACCESS sayısal olarak FILE_ANY_ACCESS ile eşdeğerdir, bu nedenle G/Ç yöneticisi herhangi bir özel güvenlik denetimi sağlamaz ve bu sorumluluğu dosya sistemine devreder. FILE_SPECIAL_ACCESS temelde dosya sistemi tarafından ek denetimler yapılacağına ilişkin belgeler sağlar.

Çeşitli dosya sistemi işlemleri FILE_SPECIAL_ACCESS'i tanımlar. FSCTL_MOVE_FILE işlemi, dosya sistemleri için birleştirme arabiriminin bir parçası olarak kullanılır ve FILE_SPECIAL_ACCESS belirtir. Açık dosyaları aktif olarak okunan ve yazılan durumlarda birleştirebilmek istediğiniz için, kullanılacak tanımlayıcıya yalnızca FILE_READ_ATTRIBUTES erişim izni verilmiştir; bu da paylaşım erişimi çatışmalarını önlemeye yöneliktir. Ancak, disk düşük düzeyde değiştirildiği için bu işlemin ayrıcalıklı bir işlem olması gerekir. Çözüm, FSCTL_MOVE_FILE komutunu vermek için kullanılan tanıtıcının, ayrıcalıklı bir tanıtıcı olan bir doğrudan erişimli depolama cihazı (DASD) kullanıcı biriminde açık olduğundan emin olmaktır. Bu işlemin bir kullanıcı birimi açıkken gerçekleştirilmesini sağlayan FASTFAT dosya sistemi kodu, FatMoveFile işlevindedir (WDK'nin içerdiği fastfat örneğinden fsctrl.c kaynak dosyasına bakın):

    //
    //  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;
    }

FSCTL_MOVE_FILE işlemi tarafından kullanılan yapı taşınan dosyayı belirtir:

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

Daha önce belirtildiği gibi, FSCTL_MOVE_FILE işleminin gerçekleştirilmesi için kullanılan tanıtıcı, tüm birimin "açık" bir operasyonu olarak ele alınır, ancak işlem, gerçekte, MOVE_FILE_DATA giriş arabelleğinde belirtilen dosya tanıtıcısı için geçerlidir. Bu, bu işlem için güvenlik denetimlerini biraz karmaşık hale getirir. Örneğin, bu arabirimin dosya tutamacını taşınan dosyayı temsil eden bir dosya nesnesine dönüştürmesi gerekir. Her sürücünün dikkatli düşünmesi gerekir. FASTFAT bunu, WDK'nin içerdiği fastfat örneğindeki fsctrl.c kaynak dosyasındaki FatMoveFile işlevinde korunan bir şekilde ObReferenceObject kullanarak yapar:

    //
    //  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.
    //    //

Çağıran bir kullanıcı modu uygulamasıysa tanıtıcının çekirdek tanıtıcısı olamayacağından emin olmak için Irp->RequestorMode kullanımına dikkat edin. Dosyaya etkin bir şekilde erişilirken taşınabilmesi için gerekli erişim 0'dır. Son olarak, çağrı kullanıcı modundan kaynaklanıyorsa bu çağrının doğru işlem bağlamında yapılması gerektiğini unutmayın. FASTFAT dosya sistemindeki kaynak kodu, fsctrl.c dosyasındaki FatMoveFile işlevinde de bunu zorlar:

    //
    //  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 );

FAT dosya sistemi tarafından gerçekleştirilen bu anlam güvenliği denetimleri, tanıtıcı kullanan herhangi bir işlem için dosya sistemi tarafından gerektirilir ve bunlara tipik bir örnektir. Buna ek olarak, FAT dosya sisteminin işleme özgü akıl sağlığı denetimleri de gerçekleştirmesi gerekir. Bu uygunluk denetimleri, farklı parametrelerin uyumlu olduğundan emin olmak için yapılmaktadır (örneğin, taşınan dosya açılan birimdedir), böylece çağıranın izin verilmemesi gerektiğinde ayrıcalıklı bir işlem gerçekleştirmesi önlenir.

Herhangi bir dosya sistemi için doğru güvenlik, aşağıdakiler dahil olmak üzere dosya sistemi denetim işlemlerinin önemli bir parçasıdır:

  • Kullanıcı tanıtıcıları uygun şekilde doğrulanıyor.

  • Kullanıcı arabelleği erişimini koruma.

  • Belirli bir işlemin semantiğini doğrulama.

Çoğu durumda, doğru doğrulama ve güvenlik gerçekleştirmek için gereken kod, verilen işlev içindeki kodun önemli bir bölümünü oluşturabilir.