Непонятное появление синего экрана
От: Kirston  
Дата: 06.06.06 10:13
Оценка:
Пишу драйвер-фильтр файловой системы на базе sfilter (из IFS Kit) и пытаюсь получить имя файла.
Для этого я написал функцию, которая вызывается из обработчиков IRP (Creat, CloseCleanUp, Read, Write, SetFileInformation)/
Она выделяет память под хранения имени файла и заносит туда имя (Код ниже).
Когда ставлю драйвер изапускаю винду, то все работает отлично. 100 тысяч вызовов — работает как часы.
Но стоит попробовать несколько раз откомпилировать что-то компилятором DDK (консольным) — как вылетает синий экран. Синий экран может вылететь тока на 20-ой попытке компиляции. Синий экран с ошибкой PAGE_FAULT_IN_NON_PAGED_AREA.

Вроде все грамотно. Что выделяю — то уничтожаю. С IRQL тоже вроде все ОК. За пределы своего буфера тоже не вылезаю. Не пойму.


Без этой части все работает
      if (FileObject->RelatedFileObject != NULL)
        if ((FileObject->RelatedFileObject)->FileName.Buffer != NULL){
          RtlAppendUnicodeStringToString(&UStr,&FileObject->RelatedFileObject->FileName);
          RtlAppendUnicodeToString(&UStr, L"\\" );
        }
      RtlAppendUnicodeStringToString(&UStr,&FileObject->FileName);




ЛИСТИНГ:

//-----------------Выдает имя файла
UNICODE_STRING SfGetFileName2(IN PFILE_OBJECT FileObject)
{
    USHORT newSize;
    PVOID newBuffer;
    UNICODE_STRING UStr;

    UStr.Buffer = NULL;
    if (FileObject == NULL)
      return UStr;

    if (FileObject->FileName.Buffer == NULL)
      return UStr;

    newSize = FileObject->FileName.Length;
    if (FileObject->RelatedFileObject != NULL)
      if ((FileObject->RelatedFileObject)->FileName.Buffer != NULL)
        newSize = newSize + ((FileObject->RelatedFileObject)->FileName).Length + 4*sizeof(WCHAR);

    newBuffer = ExAllocatePoolWithTag(NonPagedPool,newSize,SFLT_POOL_TAG );
    
    if (newBuffer!=NULL){
      UStr.Buffer = newBuffer;
      UStr.Length=0;
      UStr.MaximumLength=newSize;
      
      if (FileObject->RelatedFileObject != NULL)
        if ((FileObject->RelatedFileObject)->FileName.Buffer != NULL){
          RtlAppendUnicodeStringToString(&UStr,&FileObject->RelatedFileObject->FileName);
          RtlAppendUnicodeToString(&UStr, L"\\" );
        }
      RtlAppendUnicodeStringToString(&UStr,&FileObject->FileName);  
    }
    else{
      UStr.Buffer = NULL;
      UStr.Length=0;
      UStr.MaximumLength=0;
    }

    return UStr;
}




//Вызов
  uu3 = SfGetFileName2(irpSp->FileObject);
   if (uu3.Buffer!=NULL)
     ExFreePool(uu3.Buffer);
Re: Непонятное появление синего экрана
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 06.06.06 10:37
Оценка:
Здравствуйте, Kirston, Вы писали:

K>Вроде все грамотно. Что выделяю — то уничтожаю. С IRQL тоже вроде все ОК. За пределы своего буфера тоже не вылезаю. Не пойму.


Попробуйте для начала не гадать, а зарядить на свой фильтр Driver Verifier и максимальной строгостью проверок I/O. Возможно, он что-нибудь накопает.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Непонятное появление синего экрана
От: Злость Россия  
Дата: 06.06.06 11:54
Оценка:
Злость! пожалуйста следите за объемом цитирования — модератор

Как минимум смотреть RelatedFileObject можно только при обработке IRP_MJ_CREATE.
Правда, Ложь — мне все одно — я имею свое мнение.
Если функция недокументированна — это не значит, что ее не используют все ваши конкуренты в своих продуктах.
Любой строй переходный и отрицать это значит быть закостенелым идиотом.
Re[2]: Непонятное появление синего экрана
От: Kirston  
Дата: 06.06.06 13:37
Оценка:
Здравствуйте, Злость, Вы писали:

пожалуйста следите за объемом цитирования — модератор

З>Как минимум смотреть RelatedFileObject можно только при обработке IRP_MJ_CREATE.


Огромное спасибо за ответ, что хоть прочитал человек.
Сам разобрался буквально за 3 часа до того как прочитал твой ответ.
В документации нарыл.
Re[3]: Непонятное появление синего экрана
От: Kirston  
Дата: 06.06.06 16:02
Оценка:
А каким иным образом можно узнать имя файла, если это не запрос IRP_MJ_CREAT?
Re[4]: Непонятное появление синего экрана
От: Злость Россия  
Дата: 06.06.06 16:46
Оценка: 1 (1)
Здравствуйте, Kirston, Вы писали:

K>А каким иным образом можно узнать имя файла, если это не запрос IRP_MJ_CREAT?


1. Спросить у файловой системы.
2. Взять из своего кеша имен, открытых файлов (который строим на этапе IRP_MJ_CREAT).

В IFS kit — есть оба примера.

1. это sfilter.
2. это filespy.
Правда, Ложь — мне все одно — я имею свое мнение.
Если функция недокументированна — это не значит, что ее не используют все ваши конкуренты в своих продуктах.
Любой строй переходный и отрицать это значит быть закостенелым идиотом.
Re[5]: Непонятное появление синего экрана
От: Kirston  
Дата: 10.06.06 15:29
Оценка:
Здравствуйте, Злость, Вы писали:

З>Здравствуйте, Kirston, Вы писали:


K>>А каким иным образом можно узнать имя файла, если это не запрос IRP_MJ_CREAT?


З>1. Спросить у файловой системы.

З>2. Взять из своего кеша имен, открытых файлов (который строим на этапе IRP_MJ_CREAT).

З>В IFS kit — есть оба примера.


З>1. это sfilter.

З>2. это filespy.

Я вот спрашиваю у фаловой системы, с помощью IRP_MJ_QUERY_INFORMATION FileNameInformation.
Работает. Но при загрузке или выключении компьютер в 30% случаях зависает. Но без появления синего экрана.
Механизм посылки IRP я полностью списал из FileMon Русиновича.
В чем ботва?
Re[6]: Непонятное появление синего экрана
От: Kirston  
Дата: 10.06.06 18:18
Оценка:
Вот приложил код.



NTSTATUS
SfPassThrough (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{  
  UNICODE_STRING uu;
  UNICODE_STRING uu3;
  PUNICODE_STRING uu2=&uu;
  PIO_STACK_LOCATION irpSp;
  PSFILTER_DEVICE_EXTENSION devExtS = DeviceObject->DeviceExtension;

    PIRP MiMi;
    PVOID BufferName;
    PIO_STACK_LOCATION MiMiSp;
    KEVENT Ev;
    IO_STATUS_BLOCK io_Block;

  VALIDATE_IRQL(Irp);


  if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) {
    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    return STATUS_INVALID_DEVICE_REQUEST;
  }

  irpSp = IoGetCurrentIrpStackLocation( Irp );

 
  if ((irpSp->MajorFunction!=IRP_MJ_SET_INFORMATION) && (irpSp->MajorFunction!=IRP_MJ_WRITE) && (irpSp->MajorFunction!=IRP_MJ_READ)){
    IoSkipCurrentIrpStackLocation( Irp );
    return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  }


  DbgPrint ("SW11_BETA037\n");

  BufferName = ExAllocatePoolWithTag( NonPagedPool, 2000, SFLT_POOL_TAG);
  if (BufferName == NULL){
    IoSkipCurrentIrpStackLocation( Irp );
    return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  }

 
  KeInitializeEvent(&Ev, SynchronizationEvent,FALSE);
  MiMi = IoAllocateIrp(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject->StackSize,FALSE);
  if (MiMi == NULL){
    ExFreePool(BufferName);
    IoSkipCurrentIrpStackLocation( Irp );
    return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  }


  MiMi->AssociatedIrp.SystemBuffer = BufferName; 
  MiMi->UserEvent = &Ev;
  MiMi->UserIosb = &io_Block;
  MiMi->Tail.Overlay.Thread = PsGetCurrentThread();
  MiMi->Tail.Overlay.OriginalFileObject = irpSp->FileObject;
  MiMi->RequestorMode = KernelMode;
  MiMi->Flags = 0;            

  MiMiSp = IoGetNextIrpStackLocation(MiMi);
  MiMiSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;
  MiMiSp->DeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
  MiMiSp->FileObject = irpSp->FileObject;
  MiMiSp->Parameters.QueryFile.Length  = 2000;
  MiMiSp->Parameters.QueryFile.FileInformationClass = FileNameInformation;
  IoSetCompletionRoutine(MiMi, DeleteIrpRoutine, NULL, TRUE, TRUE, TRUE);


  IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, MiMi); 
        
  KeWaitForSingleObject(&Ev,Executive, KernelMode, FALSE, 0);

  DbgPrint ("SW8_BETA038\n");

  if (!NT_SUCCESS(io_Block.Status)){
    ExFreePool(BufferName);
    IoSkipCurrentIrpStackLocation( Irp );
    return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );    
    DbgPrint ("SW8_NO\n");
  }
  
    
  uu3.MaximumLength = (USHORT)((PFILE_NAME_INFORMATION)BufferName)->FileNameLength;
  uu3.Length = uu3.MaximumLength;
  uu3.Buffer = ((PFILE_NAME_INFORMATION)BufferName)->FileName;


  ExFreePool(BufferName);
  IoSkipCurrentIrpStackLocation( Irp );
  return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );

}



NTSTATUS
DeleteIrpRoutine(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
{
    UNREFERENCED_PARAMETER( DeviceObject );
    UNREFERENCED_PARAMETER( Context );

    *Irp->UserIosb = Irp->IoStatus;

    KeSetEvent(Irp->UserEvent,0,FALSE);
    IoFreeIrp(Irp);
    return STATUS_MORE_PROCESSING_REQUIRED;
}
Re[2]: Непонятное появление синего экрана
От: Valery A. Boronin Россия linkedin.com/in/boronin
Дата: 10.06.06 23:19
Оценка:
Здравствуйте, Злость, Вы писали:

З>Как минимум смотреть RelatedFileObject можно только при обработке IRP_MJ_CREATE.

не то.
точнее не совсем то.

плюс некорректная формулировка ответа в любом случае — обработка ГДЕ, в dispatch or completion? конечно, понятно что тут имелось ввиду время ДО, но тем не менее лучше быть точным

PS но ничего этого я бы не написал если бы не было оверквотинга! пожалуйста, будь внимательнее — время же не казенное...
... << RSDN@Home 1.2.0 alpha rev. 648>>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re: Непонятное появление синего экрана
От: Valery A. Boronin Россия linkedin.com/in/boronin
Дата: 10.06.06 23:19
Оценка:
Здравствуйте, Kirston, Вы писали:

давайте попробуем разобраться

итак, у нас PAGE_FAULT_IN_NON_PAGED_AREA

это чаще всего означает что где-то что-то конкретно и безвозвратно повреждено

потому что процессор попросил нас удовлетворить его a page fault для отсутствующей в памяти странички. причем оказывается что виртуальный адрес лежит в адресах ядра, которые ОС отвела под non-paged pool! соотв. эти данные НЕ могут быть выгружены на диск! таким образом, такая ошибка может означать в принципе что угодно, например выход за границы a non-paged pool allocation. но в Вашем случае все ясно сразу и без дампа.

ниже я покажу что именно было испорчено и почему

K>Пишу драйвер-фильтр файловой системы на базе sfilter (из IFS Kit) и пытаюсь получить имя файла.

K>Для этого я написал функцию, которая вызывается из обработчиков IRP (Creat, CloseCleanUp, Read, Write, SetFileInformation)/
K>Она выделяет память под хранения имени файла и заносит туда имя (Код ниже).
K>Когда ставлю драйвер изапускаю винду, то все работает отлично. 100 тысяч вызовов — работает как часы.
K>Но стоит попробовать несколько раз откомпилировать что-то компилятором DDK (консольным) — как вылетает синий экран. Синий экран может вылететь тока на 20-ой попытке компиляции. Синий экран с ошибкой PAGE_FAULT_IN_NON_PAGED_AREA.
нагруженная машина сразу свалится, как только имя файла, до которого Вы упорно пытаетесь добраться (я даже не говорю про FileObject->RelatedFileObject->FileName. Достаточно и FileObject->FileName), окажется давно уже не в памяти, например из-за интенсивного своппинга. Или еще хуже на что-то другое изменено, т.к. никто не гарантирует валидность буфера с именем файла (которое Вы видите в IRP_MJ_CREATE) ПОСЛЕ того как Вы отправили вызов вниз (т.е. в completion routine уже не стоит трогать. И более того "спрашивать" это имя там тоже чревато, ибо completion может быть вызвана на DISPATCH_LEVEL)

А гарантированно валидно в памяти имя соотв. до отправки вниз — надо спросить\построить и наконец запомнить его у себя, так наверное проще всего Вам решить проблему будет.

ну и по тем же причинам НИКОГДА НЕ ТРОГАЙТЕ FileObject->RelatedFileObject->RelatedFileObject — I/O manager держит ссылки только на FileObject и FileObject->RelatedFileObject — делая их использование надежным ДО отправки пакета вниз. А вот дальше, на то что торчит из FileObject->RelatedFileObject уже никаких гарантий нет.

Короче материал по теме:
Q65 When can I rely upon the file name in the FileObject structure?

41 Can I rely upon the RelatedFileObject field in the FileObject? How should I use this information?

K>Вроде все грамотно. Что выделяю — то уничтожаю. С IRQL тоже вроде все ОК. За пределы своего буфера тоже не вылезаю. Не пойму.

неграмотно. так как было сделано просто делать нельзя. в принципе.

поздно падало только из-за незагруженности. Вообще разработчикам драйверов я бы рекомендовал всегда вести разработку на очень слабеньких по ресурсам машинках — чтобы быстрее такие ошибки провоцировать, выявлять и устранять. Например всегда можно 128 или даже 96 МБ сделать в виртуалке (или с помощью boot.ini опции /MAXMEM=xx) — большого падения скорости не будет ибо вся вирт. машина будет в памяти хоста почти всегда целиком, а вот ошибочки такие внутри ловиться будут гораздо раньше и не придется ждать нужного IRP_MJ_CLOSE сутками.
... << RSDN@Home 1.2.0 alpha rev. 648>>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[6]: Непонятное появление синего экрана
От: Valery A. Boronin Россия linkedin.com/in/boronin
Дата: 10.06.06 23:19
Оценка:
Здравствуйте, Kirston, Вы писали:

K>>>А каким иным образом можно узнать имя файла, если это не запрос IRP_MJ_CREAT?


З>>1. Спросить у файловой системы.

З>>2. Взять из своего кеша имен, открытых файлов (который строим на этапе IRP_MJ_CREAT).
да, но на каждом пути масса нюансов. Впрочем, это лишь вопрос дисциплины и понимания того, что делаем
конкретно нюансы были перечислены мной чуть выше

З>>В IFS kit — есть оба примера.


З>>1. это sfilter.

З>>2. это filespy.
не рекомендуется писать production code на базе filespy

K>Я вот спрашиваю у фаловой системы, с помощью IRP_MJ_QUERY_INFORMATION FileNameInformation.

слишком расплывчато: спрашиваете пользуясь каким FileObject и в какой момент (dispatch or completion)?
впроче, ответа не требую — тут все ясно.
K>Работает. Но при загрузке или выключении компьютер в 30% случаях зависает. Но без появления синего экрана.
читайте про нюансы в ссылках на OSR FAQ — они в пред. сообщ.

K>Механизм посылки IRP я полностью списал из FileMon Русиновича.

K>В чем ботва?
в том что filemon бесплатен и как следствие является "решением на соплях"
Автор: Maxim S. Shatskih
Дата: 21.05.04
(с)
... << RSDN@Home 1.2.0 alpha rev. 648>>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[2]: Непонятное появление синего экрана
От: Valery A. Boronin Россия linkedin.com/in/boronin
Дата: 10.06.06 23:19
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Попробуйте для начала не гадать, а зарядить на свой фильтр Driver Verifier и максимальной строгостью проверок I/O. Возможно, он что-нибудь накопает.

это вряд ли (с)
почему — объяснил рядом
... << RSDN@Home 1.2.0 alpha rev. 648>>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[7]: Непонятное появление синего экрана
От: Kirston  
Дата: 11.06.06 06:56
Оценка:
K>>Я вот спрашиваю у фаловой системы, с помощью IRP_MJ_QUERY_INFORMATION FileNameInformation.
VAB>слишком расплывчато: спрашиваете пользуясь каким FileObject и в какой момент (dispatch or completion)?
VAB>впроче, ответа не требую — тут все ясно.

Я ж код приложил его хоть и страничка, но читается просто.
Re[7]: Непонятное появление синего экрана
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.06.06 15:18
Оценка: :)
Здравствуйте, Valery A. Boronin, Вы писали:

VAB>в том что filemon бесплатен и как следствие является "решением на соплях"
Автор: Maxim S. Shatskih
Дата: 21.05.04
(с)


Импликация неуместна Бесплатность filemon никак не коррелирует с принципом его работы
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.