I'm currently performing a kernel debug with liveKD.
In all the cases where my blocking happens ( a ::CloseHandle()
function call which never returns ) I happen to have a stacktrace which blocks in the kernel on a synchronisationEvent
.
But when I do !object 12345678
if 123456789 is my synchronisationEvent
as reported in the thread information of the process, it says Not a valid object (ObjectType invalid).
I'm worrying if corruptions at our application level in user mode could corrupt the kernel ? Does windows guarantee anything like a seperation of the memory spaces that would prevent from something like that ?
The code of the application uses C++, COM/DCOM, and Win32 intensively.
THREAD 856a2d48 Cid 0660.0350 Teb: 7ff25000 Win32Thread: ffaaedd8 WAIT: (Executive) KernelMode Non-Alertable 860c6f9c SynchronizationEvent IRP List: babea5d8: (0006,01d8) Flags: 00000404 Mdl: 00000000 Not impersonating DeviceMap 89809fc8 Owning Process 86212d40 Image: DataCaptorIS.exe Attached Process N/A Image: N/A Wait Start TickCount 27315407 Ticks: 6067021 (1:02:17:26.134) Context Switch Count 2259 IdealProcessor: 0 UserTime 00:00:04.976 KernelTime 00:00:02.184 Win32 Start Address 0x775c03e9 Stack Init 8aa0dfd0 Current 8aa0da98 Base 8aa0e000 Limit 8aa0b000 Call 0 Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5 ChildEBP RetAddr Args to Child 8aa0dab0 824bfced 856a2d48 00000000 8ab00120 nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4]) 8aa0dae8 824beb4b 856a2e08 856a2d48 860c6f9c nt!KiSwapThread+0x266 8aa0db10 824b856f 856a2d48 856a2e08 00000000 nt!KiCommitThreadWait+0x1df 8aa0db88 914539fb 860c6f9c 00000000 00000000 nt!KeWaitForSingleObject+0x393 8aa0dbcc 82478c1e 860c6f98 babea5d8 babea73c serial!SerialClose+0x332 (FPO: [Non-Fpo]) 8aa0dbe4 886206b9 babea5d8 861986d0 bc859308 nt!IofCallDriver+0x63 8aa0dc08 82478c1e 861986d0 860c6890 00000800 serenum!Serenum_CreateClose+0x77 (FPO: [Non-Fpo]) 8aa0dc20 82673be6 84aa7a00 bc8592f0 00000000 nt!IofCallDriver+0x63 8aa0dc64 826647c9 bc859308 bc859308 bc8592f0 nt!IopDeleteFile+0x10c 8aa0dc7c 824ba1e0 00000000 856a2d48 bc8592f0 nt!ObpRemoveObjectRoutine+0x59 8aa0dc90 824ba150 bc859308 82687556 960a5578 nt!ObfDereferenceObjectWithTag+0x88 (FPO: [0,0,3]) 8aa0dc98 82687556 960a5578 856a2d48 00000c80 nt!ObfDereferenceObject+0xd (FPO: [0,1,0]) 8aa0dcdc 8268727c 960a5578 a7d21900 86212d40 nt!ObpCloseHandleTableEntry+0x21d 8aa0dd0c 82687616 86212d40 856a2d01 0763f3b4 nt!ObpCloseHandle+0x7f 8aa0dd28 8247f8a6 00000c80 0763f3b8 775d7094 nt!NtClose+0x4e 8aa0dd28 775d7094 00000c80 0763f3b8 775d7094 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame @ 8aa0dd34) WARNING: Frame IP not in any known module. Following frames may be wrong. 0763f3b8 00000000 00000000 00000000 00000000 0x775d7094
This stacktrace states that the thread is waiting on synchronisationEvent
860c6f9c.
The command kd> !object 860c6f9c
returns Not a valid object (ObjectType invalid)
.
I don't know if this does mean that the synchronisationEvent
is corrupted in the Kernel. When I apply the command on other synchronisationEvent of the process I get an output rather like:
0: kd> !object 95369c68 Object: 95369c68 Type: (84aa6378) Event ObjectHeader: 95369c50 (new version) HandleCount: 1 PointerCount: 2
At the application level, in usermode, this happens after that kind of code that should have canceled and purged any IRP:
::CancelIoEx(m_handle_to_serial_port_com);
WaitForRequestToComplete(); // our function calls ::GetOverlappedResult(..., bWait) for any OVERLAPPED that was pending, with bWait == TRUE
::PurgeComm(m_handle_to_serial_port_com);
WaitForRequestToComplete(); // our function calls ::GetOverlappedResult(..., bWait) for any OVERLAPPED that was pending, with bWait == TRUE
::CloseHandle(m_handle_to_serial_port_com); // the closeHandle which never returns
The problems occurs really randomly. Sometimes it takes days before it reproduces.
0: kd> dp 86184f9c - @@c++(sizeof(nt!_object_header) - #RTL_FIELD_SIZE(nt!_object_header, Body)) 86184f84 00000006 00000000 00000000 00000000 86184f94 00000000 00000001 00040001 00000000 86184fa4 85917420 85917420 00000000 00000000 86184fb4 00000000 00000000 00000000 0000000d 86184fc4 86184890 00000040 00000000 00000800 86184fd4 00000000 85747a68 00000000 00000000 86184fe4 00000000 00000000 86184fec 86184fec 86184ff4 86184ff4 86184ff4 96d4c000 040d0000
and trying to display the object header:
0: kd> dt nt!_object_header 86184f9c - @@c++(sizeof(nt!_object_header) - #RTL_FIELD_SIZE(nt!_object_header, Body)) Cannot find specified field members.
It's definitely supposed to be. If the kernel were corruptable from user mode, you would have a security flaw that would potentially impact all users on the machine. You could deny service by making the kernel crash. You could elevate privileges by taking advantage of a kernel buffer overrun. You could steal someone else's data by using a kernel information disclosure flaw.
Just because you feed the kernel bad data does not mean it has such a vuln. The kernel may be smart enough to detect and prevent such issues, or it may execute any code that could suffer from corrupt userland input in userland.
If you have actually found a bug that lets you crash the kernel, read someone else's data that was passed to the kernel, or something similar, then you should report it to Microsoft. If you suspect that you have found something, try contacting MS support and see if they can help. They are the experts on the OS and most likely to be able to identify if your suspected flaw is a real flaw.