I am using PREFast to check some driver code build for Windows7. The following line of code
stackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
Gives the warning:
warning 28107: The Memory 'deviceObject' must be held when calling 'IoAttachDeviceToDeviceStack'.
deviceObject is obtained with an earlier call to IoCreateDevice. Does anyone know what this warning means and how to get rid of it?
The PREfast help says "A resource that the program must acquire before calling the function was not acquired when the function was called. As a result, the function call will fail."
The example that the help page provides surrounds a pair of calls to ExAcquireResourceLite and ExReleaseResourceLite (which gives this warning) between calls to KaEnterCriticalRegion and KaLeaveCriticalRegion, which then supposedly gets rid of the warning, but I don't know how to apply this info to my call to IoAttachDeviceToDeviceStack.
Any advice would be appreciated.
I believe I have an answer to my own question. The call to IoCreateDevice was in a separate function which was called from this one. I think this was stopping PREfast from seeing that this function was being called and deviceObject was being correctly initialised before the call to IoAttachDeviceToDeviceStack was called.
I have moved the IoCreateDevice call into the same function as IoAttachDeviceToDeviceStack and the warning went away.
Thanks to anyone that spent time reading this and trying to find an answer.
Related
So i've been trying to write a pintool that monitors call/ret instructions but i've noticed that threre was a significant inconsistency between the two. For example ret instructions without previous call.
I've run the tool in a console application from which i got the following logs showing this inconsistency (this is an example, there are more inconsistencies like the one listed below in the other call/ret instructions):
1. Call from ntdll!LdrpCallInitRoutine+0x69, expected to return to 7ff88f00502a
2. RETURN to 7ff88f00502a
//call from ntdll!LdrpInitializeNode+0x1ac which is supposed to return at 7ff88f049385 is missing (the previous instruction)
3. RETURN to 7ff88f049385 (ntdll!LdrpInitializeNode+0x1b1)
The above are the first 3 log entries for the call/ret instructions. As one can see, the monitoring started a bit late, at the call found at ntdll!LdrpCallInitRoutine+0x69, it returned to the expected address but then returned to 7ff88f049385 without first tracking the call found in the previous instruction.
Any ideas of what could be the fault?
The program is traced with INS_AddInstrumentFunction with a callback that more or less does:
if INS_IsCall(ins) INS_InsertCall(ins,...
if INS_IsRet(ins) INS_InsertCall(ins,...
I've tried the same program on Linux which worked as expected, without any mismatch.
Any ideas of the reason behind this behavior?
I'm running into a deadlock during static initialization in Solaris. The situation strongly resembles that of this user's problem.
My environment is:
solaris 10
gcc 5.4 installed to a non-standard location
all relevant shared libraries are linked against the libstdc++ and/or libgcc_s libraries from that installation
boost 1.45 (we're moving away from it soon, but for the moment that cannot change)
I see this problem when linking dynamically or statically against boost libraries
The symptoms:
Deadlocks while executing boost::system::generic_category()
generic_category() is being called to initialize global static references in boost/system/error_code.hpp
If I shuffle link order, putting -lboost_system ahead of other libraries being linked in, the problem goes away.
If I set a breakpoint in generic_category() then attempt to step over the 1st line after the first time the breakpoint gets hit, the breakpoint gets hit again when executing the same function in a different shared library's _init() -- that is, it never stops on the 2nd line of generic_category() from when I told it to step over the 1st line.
Since stepping over the 1st line didn't work, I stepped into it then stepped out & again the breakpoint got hit.
I restarted the process & stepped in after the breakpoint got hit then began stepping. Stepping over the call to boost::system::error_category::error_category() I ran into the same problem.
I tried again, this time stepping an instruction at a time when I got to the error_category() call. It attempts to call it through the PLT which calls elf_rtbndr() which is supposed to return the real function's address in %o0, but when I step over the call to elf_rtbndr() it again hits the breakpoint instead of resuming where it left off.
When the breakpoint gets hit for the 2nd time it's calling generic_category() in some other shared library's _init(); that's when the deadlock occurs.
Thanks in advance for your time & help.
This has been reported several times (see this post in Boost and another in GCC). This seems to be a circular dependency issue during Boost initialization which, for some reason, only manifests on Solaris. The usual advice is to work around this by messing with library initialization (e.g. by shuffling the library order as you did with -lboost_system).
Another option is to disable thread-safe guards (-fno-threadsafe-statics flag) which would get rid of the deadlock but would keep the buggy nested constructor call which is undesirable.
This is my code:
UNICODE_STRING symbol;
WCHAR ntNameBuffer[128];
swprintf(ntNameBuffer, L"\\Device\\Harddisk1\\Partition1");
RtlInitUnicodeString(&symbol, ntNameBuffer);
KdPrint(("OSNVss:symbol is %ws\n",symbol.Buffer));
status = IoGetDeviceObjectPointer(&symbol,
FILE_READ_DATA,
&pDiskFileObject,
&pDiskDeviceObject);
My driver is next-lower-level of \\Device\\Harddisk1\\Partition1.
When I call IoGetDeviceObjectPointer it will fail and no status returns and it not continue do remaining code.
When I use windbg debug this, it will break with a intelpm.sys;
If I change the objectname to "\\Device\\Harddisk1\\Partition2" (the partition2 is really existing), it will success call
If I change objectname to "\\Device\\Harddisk1\\Partition3", (the partition3 is not existing), it failed and return status = 0xc0000034, mean objectname is not existing.
Does anybody know why when I use object "\\Device\\Harddisk1\\Partition1" it fails and no return status? thanks very much!
First and foremost: what are you trying to achieve and what driver model are you using? What bitness, what OS versions are targeted and on which OS version does it fail? Furthermore: you are at the correct IRQL for the call and is running inside a system thread, right? From which of your driver's entry points (IRP_MJ_*, DriverEntry ...) are you calling this code?
Anyway, was re-reading the docs on this function. Noting in particular the part:
The IoGetDeviceObjectPointer routine returns a pointer to the top object in the named device object's stack and a pointer to the
corresponding file object, if the requested access to the objects can
be granted.
and:
IoGetDeviceObjectPointer establishes a "connection" between the caller
and the next-lower-level driver. A successful caller can use the
returned device object pointer to initialize its own device objects.
It can also be used as as an argument to IoAttachDeviceToDeviceStack,
IoCallDriver, and any routine that creates IRPs for lower drivers. The
returned pointer is a required argument to IoCallDriver.
You don't say, but if you are doing this on a 32bit system, it may be worthwhile tracking down what's going on with IrpTracker. However, my guess is that said "connection" or rather the request for it gets somehow swallowed by the next-lower-level driver or so.
It is also hard to say what kind of driver you are writing here (and yes, this can be important).
Try not just breaking at a particular point before or after the fact but rather follow the stack that the IRP would travel downwards in the target device object's stack.
But thinking about it, you probably aren't attached to the stack at all (for whatever reason). Could it be that you actually should be using IoGetDiskDeviceObject instead, in order to get the actual underlying device object (at the bottom of the stack) and not a reference to the top-level object attached?
Last but not least: don't forget you can also ask this question over on the OSR mailing lists. There are plenty of seasoned professionals there who may have run into the exact same problem (assuming you are doing all of the things correct that I asked about).
thanks everyone , I solve this problem; what cause this problem is it becoming synchronous; when I
call IoGetDeviceObjectPointer , it will generate an new Irp IRP_MJ_WRITER which pass though from high level, when this irp reach my driver, my thread which handle IRP is the same thread whilch call IoGetDeviceObjectPointer ,so it become drop-dead halt;
My program can be started in 2 ways:
the START OF SELECTION event that calls a MAIN function from one of my local classes.
the ZAVGTTA4 transaction that calls the same method.
at PAI, for the BACK event, when calling LEAVE TO SCREEN '0'., my program behaves in 2 ways according to how it was started. I want to get back to the selection screen (1000).
I thought about querying the stack, where i'm sure to find how my program was called. I can see that the stack trace is different, but i don't know how to acces my stack from the program. I've heard about the RTTI that i think might be able to help me.
You may try SYSTEM_CALLSTACK.
DATA:
abap_callstack_line TYPE abap_callstack_line,
callstack TYPE abap_callstack.
CALL FUNCTION 'SYSTEM_CALLSTACK'
EXPORTING
max_level = 4
IMPORTING
callstack = callstack.
But in your case I would prefer an additional parameter and the calling place can fill this entry. I would not call the parameter called_by but something like behaviour or mode.
I am trying to figure out a crash in my application.
WinDbg tells me the following: (using dashes in place of underscores)
LAST-CONTROL-TRANSFER: from 005f5c7e to 6e697474
DEFAULT-BUCKET-ID: BAD_IP
BUGCHECK-STR: ACCESS-VIOLATION
It is obvious to me that 6e697474 is NOT a valid address.
I have three questions:
1) Does the "BAD_IP" bucket ID mean "Bad Instruction Pointer?"
2) This is a multi-threaded application so one consideration was that the object whose function I was attempting to call went out of scope. Does anyone know if that would lead to the same error message?
3) What else might cause an error like this? One of my co-workers suggested that it might be a stack overflow issue, but WinDBG in the past has proven rather reliable at detecting and pointing these out. (not that I'm sure about the voodoo it does in the background to diagnose that).
Bad-IP is Bad Instruction Pointer. From the description of your problem, I would assume it is a stack corruption instead of a stack overflow.
I can think of the following things that could cause a jump to invalid address, in decreasing order of likelyhood:
calling a member function on a deallocated object. (as you suspect)
calling a member function of a corrupted object.
calling a member function of an object with a corrupted vtable.
a rouge pointer overwriting code space.
I'd start debugging by finding the code at 005f5c7e and looking at what objects are being accessed around there.
It may be helpful to ask, what could have written the string 'ttie' to this location? Often when you have bytes in the 0x41-0x5A, 0x61-0x7A ([a-zA-Z]) range, it indicates a string buffer overflow.
As to what was actually overwritten, it could be the return address, some other function pointer you're using, or occasionally that a virtual function table pointer (vfptr) in an object got overwritten to point to the middle of a string.