DeadLock в CcPurgeCacheSection

Тема в разделе "WASM.NT.KERNEL", создана пользователем Koshak, 25 окт 2006.

  1. Koshak

    Koshak New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2006
    Сообщения:
    31
    Адрес:
    Russia
    Здравствуйте все.
    В двух словах задача такова: есть зашифрованный файл и есть фильтр, который этот файл расшифровывает. Фильтр может произвольно включаться и отключаться пользователем.
    Ситуация первая: фильтр отключён, произведено чтение зашифрованного файла. Файл попадает в кэш. Пользователь Включает фильтр, открывает файл в каком-либо редакторе (notepad или F3/F4 в ФАР) - данные в редактор попадают из кэша - т.е. в зашифрованном виде.
    Ситуация вторая: фильтр включён, произведено чтение зашифрованного файла. Файл расшифровывается и попадает в кэш. Пользователь ОТключает фильтр, открывает файл в каком-либо редакторе (notepad или F3/F4 в ФАР) - данные в редактор попадают из кэша - т.е. в РАСшифрованном виде, что не допустимо.
    Аналогичная ситуация описана у PavPS http://www.wasm.ru/forum/viewtopic.php?id=7455. PavPS пишет, что нашёл решение в функциях IoSynchronousPageWrite / IoPageRead, что меня озадачивает, т.к. в IFS сказано, что это функции системные и вообще пользуйтесь CcCopyWrite, CcPrepareMdlWrite, IoBuildSynchronousFsdRequest, CcCopyRead and CcMdlRead. В Инете путного описания этих функций не нашёл, а у Руссиновича во "Внутреннем устройстве W2k" упоминание о них есть только 1 раз на схеме прохождения запроса NtReadFile/NtWriteFile. Из этой схемы следует, что IoSynchronousPageWrite / IoPageRead вызываются CCManager'ом если запрошенных данных из читаемого/записываемого файла нет в кэшированных страницах. Отсюда вывод - надо их перехватить. Перехват через SST или сплайсинг в драйвере-фильтре - это по-моему извращение. Вызов CcCopyRead не помогает - данные в буфере кэша не обновляются.
    Исходя из вышесказанного решил очищать кэш. очистку буферов должен выполнять следующий код:
    Код (Text):
    1. // Определение того, что открывается именно тот файл,
    2. // который надо расшифровывать.....
    3. if(CcIsFileCached(irpSp->FileObject)){
    4.     pFCB = (PFSRTL_COMMON_FCB_HEADER)(irpSp->FileObject->FsContext);
    5.  
    6.     DbgPrint("pFCB->PagingIoResource");
    7.     AAA=(DWORD)(pFCB->PagingIoResource);
    8.     B2H(buf1,AAA);
    9.     DbgPrint(buf1);
    10.  
    11.     DbgPrint("pFCB->Resource");
    12.     AAA=(DWORD)(pFCB->Resource);
    13.     B2H(buf1,AAA);
    14.     DbgPrint(buf1);
    15.        
    16.     DbgPrint("irpSp->FileObject->SectionObjectPointer");
    17.     AAA=(DWORD)(irpSp->FileObject->SectionObjectPointer);
    18.     B2H(buf1,AAA);
    19.     DbgPrint(buf1);
    20.  
    21.     KeEnterCriticalRegion();
    22.  
    23.     DbgPrint("ExAcquireResourceExclusiveLite(pFCB->PagingIoResource, FALSE);");
    24.         ExclusiveOk=ExAcquireResourceExclusiveLite(pFCB->PagingIoResource, FALSE);
    25.     AAA=(DWORD)(ExclusiveOk);
    26.     B2H(buf1,AAA);
    27.     DbgPrint(buf1);
    28.  
    29.     DbgPrint("ExAcquireResourceExclusiveLite(pFCB->Resource, FALSE);");
    30.         ExclusiveOk=ExAcquireResourceExclusiveLite(pFCB->Resource, FALSE);
    31.     AAA=(DWORD)(ExclusiveOk);
    32.     B2H(buf1,AAA);
    33.     DbgPrint(buf1);
    34.  
    35.     DbgPrint("CcPurgeCacheSection(irpSp->FileObject->SectionObjectPointer, NULL, 0, FALSE);");
    36.         ExclusiveOk=CcPurgeCacheSection(irpSp->FileObject->SectionObjectPointer, NULL, 0, FALSE);
    37.     AAA=(DWORD)(ExclusiveOk);
    38.     B2H(buf1,AAA);
    39.     DbgPrint(buf1);
    40.  
    41.     DbgPrint("ExReleaseResourceLite(pFCB->PagingIoResource);");
    42.         ExReleaseResourceLite (pFCB->PagingIoResource);
    43.     DbgPrint("ExReleaseResourceLite (pFCB->Resource);");
    44.         ExReleaseResourceLite(pFCB->Resource);
    45.  
    46.     KeLeaveCriticalRegion();
    47.  
    48.     DbgPrint("=========== PurgeCache end =============");
    49. }
    Этот код будучи вставленным в обработчик IRP_MJ_CREATE не вызывается никогда - т.е. файл, типа, не кэширован, но при попытке его открыть через Explorer данные вытаскиваются именно из кэша, причём во многих случаях файл открывается, а вызова IRP_MJ_READ не происходит. А если этот код вставить в IRP_MJ_READ, то происходит DeadLock в CcPurgeCacheSection. При этом тот поток в контексте которого это выполнялось виснет намертво (обычно это поток Explorer'а), а система начинает вести себя странно - некоторые приложения начинают тормозить, Еxplorer вообще глючит безбожно, короче через 5 минут требуется перезагрузка, даже в том случае, если я выгружаю свой драйвер-фильтр. Вот что отображается в DbgView (который продолжает на удивление стабильно работать):
    Код (Text):
    1. 00000000    0.00000000  ------ Loading begin ------
    2. 00000001    0.00004749  ------ DeviceObject ------ 
    3. 00000002    0.00005112  81 ea 90 20
    4. 00000003    0.00005476  ------ pdoex->AttachedTo ------
    5. 00000004    0.00005839  00 00 00 00
    6. 00000005    0.01261641  ------ SystemID ------ 
    7. 00000006    0.01262535  80 00 03 e0
    8. 00000007    0.01262926  ------ HarddiskVolume3 PDO ------  
    9. 00000008    0.01263289  81 ea 90 20
    10. 00000009    0.01263764  ------ Loading end ------  
    11. 00000010    11.71699333 pFCB->PagingIoResource 
    12. 00000011    11.71700382 81 7b 3f 08
    13. 00000012    11.71700859 pFCB->Resource 
    14. 00000013    11.71701050 81 d8 a2 68
    15. 00000014    11.71701527 irpSp->FileObject->SectionObjectPointer
    16. 00000015    11.71701908 81 7d ad 54
    17. 00000016    11.71702290 ExAcquireResourceExclusiveLite(pFCB->PagingIoResource, FALSE); 
    18. 00000017    11.71702766 00 00 00 00
    19. 00000018    11.71703148 ExAcquireResourceExclusiveLite(pFCB->Resource, FALSE); 
    20. 00000019    11.71703529 00 00 00 01
    21. 00000020    11.71704006 CcPurgeCacheSection(irpSp->FileObject->SectionObjectPointer, NULL, 0, FALSE);
    Вопрос такой: кто знает как вызывать CcPurgeCacheSection без дэдлока, или каким-либо образом обработать чтение / запись в кэш откликнитесь пожалуйста....
    Здесь более логичной мне видится обработка чтения / записи в кэш, но скудность познаний не позволяет её реализовать... Ещё вопрос: как может быть так, что открывается файл, а вызова IRP_MJ_READ нет. Какие функции отрабатывают в этом случае?
    Хэлп, плиз.
     
  2. Zufyxe

    Zufyxe New Member

    Публикаций:
    0
    Регистрация:
    13 авг 2004
    Сообщения:
    137
    Адрес:
    Russia
    IRP_MJ_READ конечно же вызывается. Но только один раз, для фрагмента не помещенного в кэш.
    Я отлавливал подобную ситуацию следующим образом:
    ставил 2 хука:
    IoCreateFile
    IoCompleteRequest
    при открытии файла, ПОСЛЕ выполнения
    IoCreateFile проверял, мой ли это файлик и делал CcPurgeCacheSection
    затем в обработчике IoCompleteRequest начинал отлавливать выполненные IRP_MJ_READ
    и расшифровывал загружаемые фрагменты непосредственно в буфере\MDL
     
  3. Zufyxe

    Zufyxe New Member

    Публикаций:
    0
    Регистрация:
    13 авг 2004
    Сообщения:
    137
    Адрес:
    Russia
    Вот, я поднимал уже тему. Давно правда :)
    http://www.wasm.ru/forum/viewtopic.php?id=6794