Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results
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/
I was looking at this Microsoft sample:
And saw this:
// // Stack file objects are never scanned. // IoGetStackLimits( &stackLow, &stackHigh ); if (((ULONG_PTR)FltObjects->FileObject > stackLow) && ((ULONG_PTR)FltObjects->FileObject < stackHigh)) { return FLT_PREOP_SUCCESS_NO_CALLBACK; }
And this:
// // Stack file objects are never scanned. // PFILE_OBJECT FileObject = Data->Iopb->TargetFileObject; IoGetStackLimits( &stackLow, &stackHigh ); if (((ULONG_PTR)FileObject > stackLow) && ((ULONG_PTR)FileObject < stackHigh)) { return FLT_PREOP_SUCCESS_NO_CALLBACK; }
So my question is, what does it mean for the FltObjects->FileObject
or for Data->Iopb->TargetFileObject
to be on the stack? What does that have to do anything with scanning the file?
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! | ||
Kernel Debugging | 16-20 October 2023 | Live, Online |
Developing Minifilters | 13-17 November 2023 | Live, Online |
Internals & Software Drivers | 4-8 Dec 2023 | Live, Online |
Writing WDF Drivers | 10-14 July 2023 | Live, Online |
Comments
Back in the days of XP (or possibly even NT4 SP2 - maybe even 3.7) someone thought it would be a cute way of saving nanoseconds and NPP(*) to allocate a FO on the stack to streamline some operations (I am sure someone out there will remember which but I would guess it was in a fastio path equivalent to the stat(3) callbacks we now have).
This worked really well until file system filters (no mini filters in those days) started doing real object manipulations on them like referencing them, and dereferencing them later. At that stage the dereference would turn into a decrement of a random bit of stack which would usually cause a series of difficult to diagnose crashes.
So people got into the habit of saying ‘if this FO is on the stack keep clear’. Hence that code. I haven’t seen that since Vista or maybe Win7 but, given the difficulty of debugging this sort of crash, the code hangs around.
It might be interesting to put in a PR to pull that code and see if it gets accepted- that would be a pretty clear indication of whether the code really has been expunged.
R
(*) Remember NT had to boot in 64Mb of physical memory and run on what now would appear to be slow processors so allocating pool had a real and (critically) measurable cost. Hence tricks like this had real value and were done within a reasonably ‘rigorous’ engineering process (his initials were DC and it might even have been his idea) so it’s not a daft as it might sound now -certainly les strange than some things you see in an active kernel these days.
But should I also add this check in my minifilter callbacks? Because so far I have never used it and never got any problems, which makes me wonder why would Microsoft write this code in their new projects considering the problem seems to have existed pre vista, and minifilter is vista+? Why would I put a workaround code for a pre vista problem in a vista+ project?
I’d imagine cut and paste programming. Me? I’d add it, but I’d also put in a PR to remove it from the sample and base my behavior on whether the PR was accepted.
There are two things that came to mind:
I only recently noticed that a ZwCreateFile call can use up as much as ~6KB of kernel stack space in a pretty common call path (i.e. not in a corner case, but in everyday use) on Win 11, and none of the calls in that path, until FltMgr/NTFS check for how much kernel stack is left.
Cheers, Deja.