Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTFSD
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


fltReadFile fails only on windows 10 with status_invalid_device_request

Ehsan_TaheriEhsan_Taheri Member Posts: 187

Hi,
I have this code in a routine that I try to open and read a file on drive C: that my minifilter is not attached to.
I am doing this in instancesetup for attaching minifilter to another drive, namely E:

The code runs fine on windows 8.1 and windows 7 and i am able to obtain the file content but on windows 10 fltReadFile fails.

Am I not allowed to access that file using fltmgr functions on windows 10 or there is some parameters that can fix this?

InitializeObjectAttributes(&oa,
    &filePath,
    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
    NULL,
    NULL);

status = FltCreateFileEx(FltObjects->Filter,
    NULL,
    &fileHandle,
    &fileObject,
    GENERIC_READ,
    &oa,
    &iOSB,
    0,
    0,
    FILE_SHARE_READ,
    FILE_OPEN,
    0,
    NULL,
    0,
    0);

if (NT_SUCCESS(status))
{
    status = FltReadFile(FltObjects->Instance,
        fileObject,
        &byteOffset,
        MAX_ACCESS_FILE_SIZE,
        fileContent,
        FLTFL_IO_OPERATION_NON_CACHED |
        FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
        &bytesRead,
        NULL,
        NULL);

    if (NT_SUCCESS(status))
    {
        ...
    }

}

Comments

  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,152
    edited August 7

    You are giving the read the wrong instance. I can’t remember whether it is optional or nowt, but if it isn’t you will need to find an instance or use Zw... (which night be easier for all your calls if you are never going to be attached)

  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    well it doesn't matter if minifilter is attached to c: or not. the call to fltReadFile fails with the same error code.

  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,152

    Yes, butthe fact remains that unless FltObjects->Instance is for C: (which means that the callback is for a file on c:) thats just not going to work.

    I see that this is not an optional parameter, so you are left with

    • Finding one of your instances on C:
    • Using ZwRead (and probably ZwCreateFileZwClose)
  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    Thanks for response.
    But the documentation for instance parameter said:
    "Opaque instance pointer for the minifilter driver instance that is initiating the read request"
    So i did not expect it to be a problem.
    This works fine on win 7 and 8.1 too. But not on win 10. I wonder how that is possible
    Anyways thanks.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335
    via Email
    It isn't supposed to work on any Windows, as Rod explained.
    Either switch to Zw or open the file on E, only after you already have
    some instance for the C drive.
  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,152

    I'm constructing a PR for the documentation

  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    It isn't supposed to work on any Windows, as Rod explained.

    But it works as I said(win 8.1 and 7). Care to do a simple check to confirm if you need to.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335
    via Email
    Lots of things arent supposed to work but do often.
    However you need it to always work.
  • Sergey_PisarevSergey_Pisarev Member - All Emails Posts: 259
    edited August 7

    @Ehsan_Taheri said:

    It isn't supposed to work on any Windows, as Rod explained.

    But it works as I said(win 8.1 and 7). Care to do a simple check to confirm if you need to.

    It was a bug in 7 and 8.
    Instance can only initiate io on the same volume, below itself.
    You need an instance for volume c: to fltreadfile from volume c:
    Instance for e: won’t do in this case

  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    Then what about fltCreateFileEx?
    documentation for parameter instance says:
    "An opaque instance pointer for the minifilter driver instance that the create request is to be sent to. The instance must be attached to the volume where the file or directory resides. This parameter is optional and can be NULL. If this parameter is NULL, the request is sent to the device object at the top of the file system driver stack for the volume. If it is non-NULL, the request is sent only to minifilter driver instances that are attached below the specified instance."
    It means they consider the scenario that the target file is not in the same volume as minifilter instance.
    What use such FltCreateFile has?
    fltcreatefileEx succeeds in windows 10 when I issue it for a file on another volume, my minifilter is not attached too.
    why they consider allowing fltCreateFile(in that specific scenario) while you can't issue a FltReadFile or maybe something else after?
    They could just "send the request to the device object at the top of the file system driver stack" just like create file document says.
    At least they could do some deadlock check in fltReadFile which can't be done in zwReadFile, if they allowed it.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335
    via Email
    You make a good point. You can't even use FltPerform(a)SynchronousIo
    with such an opened handle.
    Other than FltMgr keeping a reference count (and bugchecking/asserting
    when Verifier is enabled on the filter), I don't directly see a
    purpose.
  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,152

    I do not really understand the problem.

    The instance is the location in the mini filter stack where the io is initiated. That’s all (and indeed everything)

    It doesn’t matter what sort of io. It is not at all unusual to not want to send operations to the top of the stack particularly after an open.

    Flt create allows null (probably as has been said to allow file object leakage detection by verifier); other operations don’t. So you either don’t use them or if altitude does matter, summon up an instance.

    But the instance has to be relevant to the underlying device. If it didn’t then there is no meaning to the io. Sounds like there was a major bug prior to win 10 which thankfully has been plugged.

    I suspect that if you went back 15 years you might be able to persuade Neal to allow null instances on other operations, but I see little value in it....

  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    Flt create allows null (probably as has been said to allow file object leakage detection by verifier);

    The point is: will such fileObjects ever be used actually? to leak after and then be detected?

  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    And if not, and since we are not 15 yours back. maybe they consider do not allowing NULL on FltCreateFile as well instead?

  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,152

    The point is: will such fileObjects ever be used actually? to leak after and then be detected?

    Yes,
    1. They are referenced so if you references are wrong they will leak and use memory
    2. They can (and often are) passed to other subsystems. Think Oplocks amongst many others.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335
    via Email
    You can use FltEnumerateInstances and get an instance at the top of the
    stack for a given volume.
  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    Thanks for pointing it.
    Ofc that is correct in case my filter is attached to the target volume which was not my case.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335
    via Email
    You don't have to be attached to it!
  • Ehsan_TaheriEhsan_Taheri Member Posts: 187

    Let's assume my minifilter(A) is not attached to volume X(which is my scenarion and this desscusion is based on it).
    I call FltEnumerateInstances for volume X and get a list of instance poiters non of which belong to my minifilter.
    Then I use a random instance from the list and call FltReadFile from minifilter A using an instance pointer of minifilter B?
    Is that safe?
    And is there any benefit to doing it this way instead of going with zwreadfile and zwcreatefile. since it seems to be a bit more complicated than just using zw...files.

  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,152

    If you are never going to be involved on that volume my suggestion would be to use Zw...

    As for your proposed method, do not use a random instance, rather use the top instance (there is a call to give you that).... There are several classes of filters which will cause a crash in the FSD if you skip them....

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335
    via Email
    This is safe. You can place the read anywhere you want in the stack.
    You might break some encryption or AV filters, perhaps :)

    But they must be able to handle such cases! No read is guaranteed to
    be never from the top of a minifilter stack (as opposed to a top of
    the whole FS filter stack), nor are they guaranteed to pass through
    their filters.

    This is not a suggestion, as in "do that". It was only a comment that
    it is possible to do that.\
  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,152

    This is safe. You can place the read anywhere you want in the stack.

    With the greatest respect, you cannot. This is not safe.

    You might break some encryption or AV filters, perhaps :)

    No, you run a real risk of causing on a crash if the filter is making use of shadow file objects (see NT Insiders passim). The Microsoft Windows FSD's react with great hostility to file objects they did not create.

    I am also aware of at least one Microsoft sourced filter which might also cause issues because it demands to be in the way if it has seen the create.

    If you issue a create at a certain level then you HAVE to respect that ordering. Sending a create with an Instance NULL means you send the create at the top of the stack which means that you need to send reads and writes to the top of the stack.

    This is not breaking some filter. This is causing a crash because you have broken the architectural constraints.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 335
    via Email
    Filters will NOT see all file objects' create, e.g. Stream file objects.
    The shadow FOs still have issues with MUP.

    It should not be so, but FILTERS must be ready for FOs they did not see.
    Several large scale deployed AVs do this sometimes.

    What must NOT be done is the opposite: create at a position, but read at a
    higher position. Create on top and read elsewhere is not an issue that you
    describe - the filter WILL have seen an open request in this case.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Internals & Software Drivers 30 Nov 2020 LIVE ONLINE
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Developing Minifilters Early 2021 LIVE ONLINE