Есть драйвер который становится в стек логического диска C:\. Становится то он хорошо, а вот IRP плохо обрабытавает - после нескоторого времени работы WinDbg говорит следующие: Код (Text): Access violation - code c0000005 (!!! second chance !!!) nt!NtWriteFile+0x321: 8057a29f ff530c call dword ptr [ebx+0xc] Функция обработки IRP такая: Код (Text): NTSTATUS DtdHookRoutine( PDEVICE_OBJECT HookDevice, IN PIRP Irp ) { PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); PHOOK_EXTENSION hookExt; // // Point at the device extension, which contains information on which // file system this IRP is headed for // hookExt = HookDevice->DeviceExtension; switch (currentIrpStack->MajorFunction) { case IRP_MJ_CREATE: DbgPrint("dtd!DtdHookRoutine: currentIrpStack->MajorFunction = IRP_MJ_CREATE\n"); break; case IRP_MJ_SET_INFORMATION: DbgPrint("dtd!DtdHookRoutine: currentIrpStack->MajorFunction = IRP_MJ_SET_INFORMATION\n"); break; default: DbgPrint("dtd!DtdHookRoutine: currentIrpStack->MajorFunction = other\n"); break; } IoCopyCurrentIrpStackLocationToNext(Irp); return IoCallDriver( hookExt->FileSystem, Irp ); } В чем может быть проблема проблема???
Возможно прямого отношения к багу это и не имеет, но IoCopyCurrentIrpStackLocationToNext без последующего IoSetCompletionRoutine - это баг по-любому. Когда IRP будет завершаться, то будет вызвана IO_STACK_LOCATION.CompletionRoutine, но у тебя там мусор. В общем случае, либо так: IoCopyCurrentIrpStackLocationToNext IoSetCompletionRoutine IoCallDriver либо так IoSkipCurrentIrpStackLocation IoCallDriver
Пробовал и IoSkipCurrentIrpStackLocation, тот же баг. Только когда используешь эту функцию что-то странное происходит с IRP. Код (Text): // Сейчас Irp->StackCount == 9 // Irp->CurrentLocation == 9 IoSkipCurrentIrpStackLocation(Irp); // После вызова IoSkipCurrentIrpStackLocation // Irp->CurrentLocation == 10 return IoCallDriver( hookExt->FileSystem, Irp ); // А после IoCallDriver() // Irp->CurrentLocation == 11 Мне кажется это както неправильно, или я ошибаюсь?
Ну значит баг не в этом, но это тоже баг А с IRP всё нормально. Если мы делаем скип, то не ставим CompletionRoutine и таким образом после вызова IoCallDriver полностью теряем IRP... "мы его теряем" (с) )) Т.е. после того как IoCallDriver вернётся, IRP уже может быть завершён, а может ещё нет. Если нет, то в Irp->CurrentLocation может быть все что угодно от 0 до Irp->StackCount+1, если да, то память под IRP уже могла быть передана кому-то другому и там вообще мусор. А приращение на единицу после IoSkipCurrentIrpStackLocation нормальное. Подробности можно глянуть тут: http://www.wasm.ru/article.php?article=drvw2k15
да, я читал твою статью... очень хорошо написанно, хотя и очень много сразу потому еще не все стало на свои места А в чем может быть баг... может есть какие мысли? вот кстати стек вызовов при виалюшене: Код (Text): STACK_TEXT: f7d93d38 804df06b 00000890 00000000 00000000 nt!NtWriteFile+0x321 f7d93d38 7c90eb94 00000890 00000000 00000000 nt!KiFastCallEntry+0xf8 0184f6c8 7c90e9ff 7c81100e 00000890 00000000 ntdll!KiFastSystemCallRet 0184f6cc 7c81100e 00000890 00000000 00000000 ntdll!ZwWriteFile+0xc 0184f72c 50042018 00000890 0184f768 0000004d kernel32!WriteFile+0xf7 0184fb6c 50041e81 0184fba0 0000004d 01a41238 wuaueng!Trace::CTraceCategory::WriteToFile+0xf8 0184fda4 500418f0 00000003 00000000 5004c2e8 wuaueng!Trace::CTraceCategory::Trace+0x131 0184fdc8 5004c2d2 0184fdf0 00000004 00000003 wuaueng!Trace::CDebugTrace::Trace+0x4b 0184fdf8 5004417a 00000010 01a40e98 01a40e98 wuaueng!CSusAgent::DispatchEvent+0x1a4 0184fe10 500440f7 00000001 00000010 01a40f6c wuaueng!CSusEventSystem::DispatchEvent+0x47 0184fe3c 5004461d 00000001 01a40e98 00000000 wuaueng!CSusEventSystem::ProcessRewaitHandle+0x68 0184fe5c 50044596 00000000 00000000 00000003 wuaueng!CSusEventSystem::ProcessTimeout+0x7d 0184fe80 50066898 50002000 7c80ac28 00000000 wuaueng!CSusEventSystem::Run+0x6d 0184ff18 500013f0 00000001 000e4ce0 500012a7 wuaueng!ServiceMain+0x20c 0184ff6c 010011cc 00000001 000e4ce0 00000000 wuauserv!ServiceMain+0xaf 0184ffa0 77deb48b 00000001 000e4ce0 0007e898 svchost!ServiceStarter+0x9e 0184ffb4 7c80b50b 000e4cd8 00000000 0007e898 ADVAPI32!ScSvcctrlThreadA+0x12 0184ffec 00000000 77deb479 000e4cd8 00000000 kernel32!BaseThreadStart+0x37 Как видно ошибку провацирует wuauserv, т.е автоапдейт виндовс. В стеке нет моего фильтра.
отключил службу автоапдейта... все равно падает. Но заметил особенность, что в стеке перед вызовом есть следующие функции: ntdll!KiFastSystemCallRet и nt!KiFastCallEntry. Как я понимаю это функции быстрого ввода/вывода. Я их никак не обрабатываю, но в FileMon'е Руссиновича они перехватываются. Может и мне надо перехватывать. Или это не то???
Нет. Это шлюзы в ядро. Если камень поддерживает инструкции sysenter/sysexit (или как их там), то, видимо, испльзуются эти функции при переходе ring3->ring0 и обратно. У меня камень без sysenter, поэтому точно сказать не могу, но судя по именам ничего другого они делать и не могут. Т.е. они исползуются при вызове любой функции переходящей в ядро и прямого отношения к багу тоже не имеют. Падает фдерная NtWriteFile при попытке обращения к какому-то параметру/полю структуры. Дизасмни свой ntoskrnl.exe. Разберись что происходит в районе NtWriteFile+0x321 и посмотри в отладчике.
вообще поидее то что мой драйвер становиться в стек никак не должно влиять на NtWriteFile, т.к. насколько я понимаю NtWriteFile шлет запрос к девайсу логического диска, и как раз там начинает работать мой фильтр. Единственное что может падать (если придерживаться этой схемы), так это код который обрабатывает ответ от драйвера.
DeeoniS а у тебя hookExt->FileSystem точно правильный? вообще, если в твоем драйвере что-то происходит, то это наверняка не в том куске кода, который ты запостил
По одной строчке call dword ptr [ebx+0xc] сложно ориентироваться, но я таки попробую. Почти 100% падает при попытке вызвать Fast I/O Dispatch Routine. Вот очень сильно (на 99% ) упрощённый код NtWriteFile: Код (Text): NTSTATUS NtWriteFile( IN HANDLE FileHandle, ... ) { ... status = ObReferenceObjectByHandle( FileHandle, 0L, IoFileObjectType, requestorMode, (PVOID *) &fileObject, &handleInformation); ... deviceObject = IoGetRelatedDeviceObject( fileObject ); ... fastIoDispatch = deviceObject->DriverObject->FastIoDispatch; ... if (...) { ... if (...) { ... if ( fastIoDispatch->FastIoWrite( ... ) ) { <<<<-----!!!!!!!! ... } ... } ... } ... return status; }
Four-F т.е. получается что всетаки надо перехватывать функции быстрого ввода/вывода. Просто я писал драйвер ориентируясь на FileMon Руссиновича. Там он в DriverEntry перехватывает быстрый в/в: Код (Text): // // This Filemon's Fast I/O dispatch table. Note that NT assumes that // file system drivers support some Fast I/O calls, so this table must // be present for an file system filter driver // FAST_IO_DISPATCH FastIOHook = { sizeof(FAST_IO_DISPATCH), FilemonFastIoCheckifPossible, FilemonFastIoRead, FilemonFastIoWrite, FilemonFastIoQueryBasicInfo, //.... }; NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { //.... DriverObject->FastIoDispatch = &FastIOHook; //.... } а я этого не делаю, т.к. хотел для начала все максимально упростить.
Nouzui hookExt->FileSystem точно правильный, если конечно где-то не затирается чем-нибудь, но это маловероятно
Да. Вот тут список того, что может влетать в драйверы томов: http://msdn2.microsoft.com/en-us/library/ms790755.aspx Но перехватывать нужно всё и просто редиректить в оригинальный драйвер. Это стандартный подход, как для "честных" фильтров, так и для хукающих.
весело.. всегда думал, что fast io опционально, типа, SizeOfFastIoDispatch=0, и никаких проблем мда..
а как вообще определяется, можно ли использовать fast io по флагу FO_FILE_FAST_IO_READ в объекте файла? и в чем вообще смысл этих функций? почему они используются только для синхронных операций и при наличии кеширования?
Потому, что это и есть чтение/запись кешированного файла, т.е. просто копируются данные из кеша, который суть буфер в памяти. Смысл в том, что это гораздо быстрее чем создавать IRP, прогонять его через цепочку драйверов, заставляя их дергать данные с диска. Можно ли использовать fast io, определяет диспетчер ввода/вывода. И так как я сам про это мало что знаю , подробнее можно глянуть в IFS Kit в разделах "Introduction to File System Filter Drivers" и "OSR Technical Articles", а также в журнале "The NT Insider" на osronline.com.