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/
No matter what I do I seem to get PAGE_FAULT_IN_NONPAGED_AREA
in my kernel driver. I've read everything I could about linked lists but I'm no closer to the solution.
Do I also need to do a memory copy of the handle (ProcessId) returned by PsSetLoadImageNotifyRoutine
?
Is if (!pointer)
the same as if (pointer == NULL)
?
Any clues to why I get PAGE_FAULT_IN_NONPAGED_AREA
?
BOOLEAN ListContainsProcess(PSINGLE_LIST_ENTRY listHead, HANDLE ProcessId) { PSINGLE_LIST_ENTRY entry = listHead->Next; if (entry == NULL) { return false; } while (entry != listHead) { PPROCESS_LIST list = (PPROCESS_LIST)CONTAINING_RECORD(entry, PROCESS_LIST, LinkField); DbgPrint("Handle is %d", ProcessId); if (list->ProcessId == ProcessId) { return true; } entry = entry->Next; } return false; } VOID ImageCallback( IN PUNICODE_STRING FullImageName, IN HANDLE ProcessId, IN PIMAGE_INFO ImageInfo ) { UNREFERENCED_PARAMETER(ImageInfo); PDEVICE_EXTENSION extension; // // Assign extension variable // extension = (PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension; if (ProcessId == NULL) { DbgPrint("ProcessID is NULL"); return; } if (ListContainsProcess(&ProcessListSingleHead, ProcessId)) { DbgPrint("Process found in process list\n"); } else { UNICODE_STRING path = RTL_CONSTANT_STRING(L"\\System32\\app.exe"); if (RtlxSuffixUnicodeString(&path, FullImageName, TRUE)) { DbgPrint("App started\n"); PPROCESS_LIST list = (PPROCESS_LIST)ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESS_LIST), 1); if (!list) { DbgPrint("STATUS_INSUFFICIENT_RESOURCES"); return; } list->ProcessId = ProcessId; PushEntryList(&ProcessListSingleHead, &(list->LinkField)); } } ... } ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* PAGE_FAULT_IN_NONPAGED_AREA (50) Invalid system memory was referenced. This cannot be protected by try-except. Typically the address is just plain bad or it is pointing at freed memory. Arguments: Arg1: fffffffffffffff8, memory referenced. Arg2: 0000000000000000, value 0 = read operation, 1 = write operation. Arg3: fffff8800c3ee7dc, If non-zero, the instruction address which referenced the bad memory address. Arg4: 0000000000000000, (reserved) Debugging Details: ------------------ KEY_VALUES_STRING: 1 STACKHASH_ANALYSIS: 1 TIMELINE_ANALYSIS: 1 DUMP_CLASS: 1 DUMP_QUALIFIER: 401 DUMP_TYPE: 1 BUGCHECK_P1: fffffffffffffff8 BUGCHECK_P2: 0 BUGCHECK_P3: fffff8800c3ee7dc BUGCHECK_P4: 0 READ_ADDRESS: fffffffffffffff8 FAULTING_IP: Driver!ListContainsProcess+5c [main.cpp @ 228] fffff880`0c3ee7dc 483908 cmp qword ptr [rax],rcx MM_INTERNAL_CODE: 0 DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT BUGCHECK_STR: 0x50 PROCESS_NAME: taskhost.exe CURRENT_IRQL: 0 TRAP_FRAME: fffff880095754d0 -- (.trap 0xfffff880095754d0) NOTE: The trap frame does not contain all registers. Some register values may be zeroed or incorrect. rax=fffffffffffffff8 rbx=0000000000000000 rcx=0000000000000d08 rdx=000000000000000e rsi=0000000000000000 rdi=0000000000000000 rip=fffff8800c3ee7dc rsp=fffff88009575660 rbp=fffff80003c760f0 r8=0000000000000065 r9=0000000000000003 r10=0000000000000000 r11=fffff88009575280 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei ng nz na pe nc Driver!ListContainsProcess+0x5c: fffff880`0c3ee7dc 483908 cmp qword ptr [rax],rcx ds:ffffffff`fffffff8=???????????????? Resetting default scope LAST_CONTROL_TRANSFER: from fffff80003bc8562 to fffff80003aeeba0 STACK_TEXT: fffff880`09575378 fffff800`03bc8562 : 00000000`00000050 ffffffff`fffffff8 00000000`00000000 fffff880`095754d0 : nt!KeBugCheckEx fffff880`09575380 fffff800`03afac96 : 00000000`00000000 ffffffff`fffffff8 00000000`00000000 00000000`00000001 : nt!MmAccessFault+0x2322 fffff880`095754d0 fffff880`0c3ee7dc : fffff880`0c3eece0 00000000`00000d08 00000000`00000065 00000000`00000003 : nt!KiPageFault+0x356 fffff880`09575660 fffff880`0c3ee62d : fffff880`0c3f0098 00000000`00000d08 00000000`00000000 00000000`00000000 : Driver!ListContainsProcess+0x5c [main.cpp @ 228] fffff880`095756a0 fffff800`03d3a6f8 : fffffa80`0a398c18 00000000`00000d08 fffff880`09575858 00000000`00000000 : Driver!ImageCallback+0x4d [main.cpp @ 273] fffff880`09575700 fffff800`03e8d262 : fffffa80`0a398bc0 fffffa80`0bc46278 fffffa80`0a3a8a50 00000000`00000000 : nt!PsCallImageNotifyRoutines+0xdc fffff880`09575760 fffff800`03d4fcc7 : fffffa80`0a3a8a10 fffffa80`0bc46060 fffff880`09575a10 fffff880`09575a08 : nt!MiMapViewOfImageSection+0x9b2 fffff880`095758b0 fffff800`03d5541d : ffffe6be`00000004 fffffa80`0bc46060 fffff880`09575a10 00000000`00000000 : nt!MiMapViewOfSection+0x367 fffff880`095759a0 fffff800`03afcbd3 : 00000000`00000404 fffffa80`0b9f7060 00000000`0291f148 00000000`0291f301 : nt!NtMapViewOfSection+0x2bd fffff880`09575a70 00000000`77849b0a : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 00000000`0291f128 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x77849b0a THREAD_SHA1_HASH_MOD_FUNC: 9a8c01c8d3d816fc81b482c5ab85d8bc45900d22 THREAD_SHA1_HASH_MOD_FUNC_OFFSET: a008a686f51c9886a95257dfb15374e4ddc4cfd7 THREAD_SHA1_HASH_MOD: c792971b158a39e417c8371a54cd46baa3e9df9b FOLLOWUP_IP: Driver!ListContainsProcess+5c [main.cpp @ 228] fffff880`0c3ee7dc 483908 cmp qword ptr [rax],rcx FAULT_INSTR_CODE: 75083948 FAULTING_SOURCE_LINE_NUMBER: 228 FAULTING_SOURCE_CODE: 224: while (entry != listHead) 225: { 226: PPROCESS_LIST list = (PPROCESS_LIST)CONTAINING_RECORD(entry, PROCESS_LIST, LinkField); 227: DbgPrint("Handle is %d", ProcessId);
228: if (list->ProcessId == ProcessId) {
229: return true; 230: } 231: entry = entry->Next; 232: } 233: return false; SYMBOL_STACK_INDEX: 3 SYMBOL_NAME: Driver!ListContainsProcess+5c
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 | 9-13 Sept 2024 | Live, Online |
Developing Minifilters | 15-19 July 2024 | Live, Online |
Internals & Software Drivers | 11-15 Mar 2024 | Live, Online |
Writing WDF Drivers | 20-24 May 2024 | Live, Online |
Comments
Well, you don't show us 'ProcessListSingleHead' declaration in your code, but it seems to be an uniitialised variable with a random and undefined value. You are passing its address to ListContainsProcess() function, which treats its value as a valid pointer. Look at the line below
Once you have passed the address of unitialised variable to a function, 'entry' points to the middle of nowhere at the moment. Therefore, you are lucky enough to crash the very first time you try to access an address that it points to. If you were not so lucky and 'entry' was pointing to a random but valid address, you would end up with memory corruption, i.e.finding a bug would not be as easy as it is now.....
Anton Bassov
According to MSDN
ProcessListSingleHead.Next = NULL;
should be enough to initialize the linked list? Did I miss something?Well, you did not show us this part in your original post,did you.....
Indeed...
What you are missing is that,in order to be in a position to help you, we have to see ALL your code, rather than just separate
fragments of it ....
Anton Bassov
Here we go.
....
Look how PushEntryList() works
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-pushentrylist
[begin quote]
PushEntryList sets ListHead->Next to Entry, and Entry->Next to point to the old first entry of the list.
[end quote]
Yo have initialised ProcessListSingleHead.Next to NULL. What do you think is going to happen when you reach the last entry in the list? Its "Next' field is going to be NULL, rather than point to the list head, because of the way you have initialised it.
Therefore, you just dereference NULL pointer on the final iteration of the loop. Have you got anymore questions why you crash????
In order to make it work the way you expect it to you have to initialize it like "ProcessListSingleHead.Next = &ProcessListSingleHead;"
Anton Bassov
>
> In order to make it work the way you expect it to you have to initialize it like "ProcessListSingleHead.Next = &ProcessListSingleHead;"
Or, alternatively, use the function that was SPECIFICALLY designed for
this purpose: InitializeSListHead.
Tim Roberts, [email protected]
Software Wizard Emeritus
True, but my point was that, after having been initialised to NULL, the first list entry is obviously never going to point to the list head, i.e. to itself. To be honest, it really amazes me that someone had to go the NTDEV in order to find a bug like that - it seems to be laying right on the surface, don't you think. I know we were all inexperienced once, but in this particular case the OP obviously did not even try to do his"homework"....
Anton Bassov